mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
fix(node): better detection for when to surface node resolution errors (#24653)
This commit is contained in:
parent
445e05a39d
commit
52ababc4bf
35 changed files with 678 additions and 519 deletions
|
@ -446,15 +446,14 @@ impl<TGraphContainer: ModuleGraphContainer>
|
|||
specifier: &str,
|
||||
referrer: &ModuleSpecifier,
|
||||
) -> Result<ModuleSpecifier, AnyError> {
|
||||
if let Some(result) = self.shared.node_resolver.resolve_if_in_npm_package(
|
||||
specifier,
|
||||
referrer,
|
||||
NodeResolutionMode::Execution,
|
||||
) {
|
||||
return match result? {
|
||||
Some(res) => Ok(res.into_url()),
|
||||
None => Err(generic_error("not found")),
|
||||
};
|
||||
if self.shared.node_resolver.in_npm_package(referrer) {
|
||||
return Ok(
|
||||
self
|
||||
.shared
|
||||
.node_resolver
|
||||
.resolve(specifier, referrer, NodeResolutionMode::Execution)?
|
||||
.into_url(),
|
||||
);
|
||||
}
|
||||
|
||||
let graph = self.graph_container.graph();
|
||||
|
|
|
@ -12,7 +12,8 @@ use deno_core::serde_json;
|
|||
use deno_package_json::PackageJsonDepValue;
|
||||
use deno_runtime::deno_fs::FileSystem;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveError;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveErrorKind;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveIoError;
|
||||
use deno_runtime::deno_node::errors::PackageNotFoundError;
|
||||
use deno_runtime::deno_node::load_pkg_json;
|
||||
use deno_runtime::deno_node::NodePermissions;
|
||||
use deno_runtime::deno_node::NpmResolver;
|
||||
|
@ -198,7 +199,7 @@ impl NpmResolver for ByonmCliNpmResolver {
|
|||
}
|
||||
|
||||
Err(
|
||||
PackageFolderResolveErrorKind::NotFoundPackage {
|
||||
PackageNotFoundError {
|
||||
package_name: name.to_string(),
|
||||
referrer: referrer.clone(),
|
||||
referrer_extra: None,
|
||||
|
@ -209,7 +210,7 @@ impl NpmResolver for ByonmCliNpmResolver {
|
|||
|
||||
let path = inner(&*self.fs, name, referrer)?;
|
||||
self.fs.realpath_sync(&path).map_err(|err| {
|
||||
PackageFolderResolveErrorKind::Io {
|
||||
PackageFolderResolveIoError {
|
||||
package_name: name.to_string(),
|
||||
referrer: referrer.clone(),
|
||||
source: err.into_io_error(),
|
||||
|
|
|
@ -21,7 +21,7 @@ use deno_npm::NpmResolutionPackage;
|
|||
use deno_npm::NpmSystemInfo;
|
||||
use deno_runtime::deno_fs::FileSystem;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveError;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveErrorKind;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveIoError;
|
||||
use deno_runtime::deno_node::NodePermissions;
|
||||
use deno_runtime::deno_node::NpmResolver;
|
||||
use deno_semver::package::PackageNv;
|
||||
|
@ -549,7 +549,7 @@ impl NpmResolver for ManagedCliNpmResolver {
|
|||
.resolve_package_folder_from_package(name, referrer)?;
|
||||
let path =
|
||||
canonicalize_path_maybe_not_exists_with_fs(&path, self.fs.as_ref())
|
||||
.map_err(|err| PackageFolderResolveErrorKind::Io {
|
||||
.map_err(|err| PackageFolderResolveIoError {
|
||||
package_name: name.to_string(),
|
||||
referrer: referrer.clone(),
|
||||
source: err,
|
||||
|
|
|
@ -15,7 +15,8 @@ use deno_npm::NpmPackageId;
|
|||
use deno_npm::NpmSystemInfo;
|
||||
use deno_runtime::deno_fs::FileSystem;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveError;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveErrorKind;
|
||||
use deno_runtime::deno_node::errors::PackageNotFoundError;
|
||||
use deno_runtime::deno_node::errors::ReferrerNotFoundError;
|
||||
use deno_runtime::deno_node::NodePermissions;
|
||||
|
||||
use super::super::cache::NpmCache;
|
||||
|
@ -84,7 +85,7 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver {
|
|||
.resolve_package_folder_id_from_specifier(referrer)
|
||||
else {
|
||||
return Err(
|
||||
PackageFolderResolveErrorKind::NotFoundReferrer {
|
||||
ReferrerNotFoundError {
|
||||
referrer: referrer.clone(),
|
||||
referrer_extra: None,
|
||||
}
|
||||
|
@ -98,7 +99,7 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver {
|
|||
Ok(pkg) => match self.maybe_package_folder(&pkg.id) {
|
||||
Some(folder) => Ok(folder),
|
||||
None => Err(
|
||||
PackageFolderResolveErrorKind::NotFoundPackage {
|
||||
PackageNotFoundError {
|
||||
package_name: name.to_string(),
|
||||
referrer: referrer.clone(),
|
||||
referrer_extra: Some(format!(
|
||||
|
@ -112,7 +113,7 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver {
|
|||
},
|
||||
Err(err) => match *err {
|
||||
PackageNotFoundFromReferrerError::Referrer(cache_folder_id) => Err(
|
||||
PackageFolderResolveErrorKind::NotFoundReferrer {
|
||||
ReferrerNotFoundError {
|
||||
referrer: referrer.clone(),
|
||||
referrer_extra: Some(cache_folder_id.to_string()),
|
||||
}
|
||||
|
@ -122,7 +123,7 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver {
|
|||
name,
|
||||
referrer: cache_folder_id_referrer,
|
||||
} => Err(
|
||||
PackageFolderResolveErrorKind::NotFoundPackage {
|
||||
PackageNotFoundError {
|
||||
package_name: name,
|
||||
referrer: referrer.clone(),
|
||||
referrer_extra: Some(cache_folder_id_referrer.to_string()),
|
||||
|
|
|
@ -33,7 +33,9 @@ use deno_npm::NpmResolutionPackage;
|
|||
use deno_npm::NpmSystemInfo;
|
||||
use deno_runtime::deno_fs;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveError;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveErrorKind;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveIoError;
|
||||
use deno_runtime::deno_node::errors::PackageNotFoundError;
|
||||
use deno_runtime::deno_node::errors::ReferrerNotFoundError;
|
||||
use deno_runtime::deno_node::NodePermissions;
|
||||
use deno_semver::package::PackageNv;
|
||||
use serde::Deserialize;
|
||||
|
@ -185,14 +187,14 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver {
|
|||
) -> Result<PathBuf, PackageFolderResolveError> {
|
||||
let maybe_local_path = self
|
||||
.resolve_folder_for_specifier(referrer)
|
||||
.map_err(|err| PackageFolderResolveErrorKind::Io {
|
||||
.map_err(|err| PackageFolderResolveIoError {
|
||||
package_name: name.to_string(),
|
||||
referrer: referrer.clone(),
|
||||
source: err,
|
||||
})?;
|
||||
let Some(local_path) = maybe_local_path else {
|
||||
return Err(
|
||||
PackageFolderResolveErrorKind::NotFoundReferrer {
|
||||
ReferrerNotFoundError {
|
||||
referrer: referrer.clone(),
|
||||
referrer_extra: None,
|
||||
}
|
||||
|
@ -220,7 +222,7 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver {
|
|||
}
|
||||
|
||||
Err(
|
||||
PackageFolderResolveErrorKind::NotFoundPackage {
|
||||
PackageNotFoundError {
|
||||
package_name: name.to_string(),
|
||||
referrer: referrer.clone(),
|
||||
referrer_extra: None,
|
||||
|
|
335
cli/resolver.rs
335
cli/resolver.rs
|
@ -25,15 +25,17 @@ use deno_runtime::deno_fs;
|
|||
use deno_runtime::deno_fs::FileSystem;
|
||||
use deno_runtime::deno_node::errors::ClosestPkgJsonError;
|
||||
use deno_runtime::deno_node::errors::NodeResolveError;
|
||||
use deno_runtime::deno_node::errors::ResolvePkgSubpathFromDenoModuleError;
|
||||
use deno_runtime::deno_node::errors::NodeResolveErrorKind;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveErrorKind;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveIoError;
|
||||
use deno_runtime::deno_node::errors::PackageNotFoundError;
|
||||
use deno_runtime::deno_node::errors::PackageResolveErrorKind;
|
||||
use deno_runtime::deno_node::errors::UrlToNodeResolutionError;
|
||||
use deno_runtime::deno_node::is_builtin_node_module;
|
||||
use deno_runtime::deno_node::parse_npm_pkg_name;
|
||||
use deno_runtime::deno_node::NodeModuleKind;
|
||||
use deno_runtime::deno_node::NodeResolution;
|
||||
use deno_runtime::deno_node::NodeResolutionMode;
|
||||
use deno_runtime::deno_node::NodeResolver;
|
||||
use deno_runtime::deno_node::NpmResolver as DenoNodeNpmResolver;
|
||||
use deno_runtime::deno_node::PackageJson;
|
||||
use deno_runtime::fs_util::specifier_to_file_path;
|
||||
use deno_semver::npm::NpmPackageReqReference;
|
||||
|
@ -47,7 +49,6 @@ use crate::args::JsxImportSourceConfig;
|
|||
use crate::args::DENO_DISABLE_PEDANTIC_NODE_WARNINGS;
|
||||
use crate::colors;
|
||||
use crate::node::CliNodeCodeTranslator;
|
||||
use crate::npm::ByonmCliNpmResolver;
|
||||
use crate::npm::CliNpmResolver;
|
||||
use crate::npm::InnerCliNpmResolverRef;
|
||||
use crate::util::sync::AtomicFlag;
|
||||
|
@ -102,17 +103,77 @@ impl CliNodeResolver {
|
|||
self.node_resolver.get_closest_package_json(referrer)
|
||||
}
|
||||
|
||||
pub fn resolve_if_in_npm_package(
|
||||
pub fn resolve_if_for_npm_pkg(
|
||||
&self,
|
||||
specifier: &str,
|
||||
referrer: &ModuleSpecifier,
|
||||
mode: NodeResolutionMode,
|
||||
) -> Option<Result<Option<NodeResolution>, NodeResolveError>> {
|
||||
) -> Result<Option<NodeResolution>, AnyError> {
|
||||
let resolution_result = self.resolve(specifier, referrer, mode);
|
||||
match resolution_result {
|
||||
Ok(res) => Ok(Some(res)),
|
||||
Err(err) => {
|
||||
let err = err.into_kind();
|
||||
match err {
|
||||
NodeResolveErrorKind::RelativeJoin(_)
|
||||
| NodeResolveErrorKind::PackageImportsResolve(_)
|
||||
| NodeResolveErrorKind::UnsupportedEsmUrlScheme(_)
|
||||
| NodeResolveErrorKind::DataUrlReferrer(_)
|
||||
| NodeResolveErrorKind::TypesNotFound(_)
|
||||
| NodeResolveErrorKind::FinalizeResolution(_)
|
||||
| NodeResolveErrorKind::UrlToNodeResolution(_) => Err(err.into()),
|
||||
NodeResolveErrorKind::PackageResolve(err) => {
|
||||
let err = err.into_kind();
|
||||
match err {
|
||||
PackageResolveErrorKind::ClosestPkgJson(_)
|
||||
| PackageResolveErrorKind::InvalidModuleSpecifier(_)
|
||||
| PackageResolveErrorKind::ExportsResolve(_)
|
||||
| PackageResolveErrorKind::SubpathResolve(_) => Err(err.into()),
|
||||
PackageResolveErrorKind::PackageFolderResolve(err) => {
|
||||
match err.as_kind() {
|
||||
PackageFolderResolveErrorKind::Io(
|
||||
PackageFolderResolveIoError { package_name, .. },
|
||||
)
|
||||
| PackageFolderResolveErrorKind::PackageNotFound(
|
||||
PackageNotFoundError { package_name, .. },
|
||||
) => {
|
||||
if self.in_npm_package(referrer) {
|
||||
// we're in an npm package, so use node resolution
|
||||
Some(self.resolve(specifier, referrer, mode))
|
||||
} else {
|
||||
None
|
||||
return Err(err.into());
|
||||
}
|
||||
if let Some(byonm_npm_resolver) =
|
||||
self.npm_resolver.as_byonm()
|
||||
{
|
||||
if byonm_npm_resolver
|
||||
.find_ancestor_package_json_with_dep(
|
||||
package_name,
|
||||
referrer,
|
||||
)
|
||||
.is_some()
|
||||
{
|
||||
return Err(anyhow!(
|
||||
concat!(
|
||||
"Could not resolve \"{}\", but found it in a package.json. ",
|
||||
"Deno expects the node_modules/ directory to be up to date. ",
|
||||
"Did you forget to run `npm install`?"
|
||||
),
|
||||
specifier
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
PackageFolderResolveErrorKind::ReferrerNotFound(_) => {
|
||||
if self.in_npm_package(referrer) {
|
||||
return Err(err.into());
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,18 +182,18 @@ impl CliNodeResolver {
|
|||
specifier: &str,
|
||||
referrer: &ModuleSpecifier,
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<Option<NodeResolution>, NodeResolveError> {
|
||||
) -> Result<NodeResolution, NodeResolveError> {
|
||||
let referrer_kind = if self.cjs_resolutions.contains(referrer) {
|
||||
NodeModuleKind::Cjs
|
||||
} else {
|
||||
NodeModuleKind::Esm
|
||||
};
|
||||
|
||||
let maybe_res =
|
||||
let res =
|
||||
self
|
||||
.node_resolver
|
||||
.resolve(specifier, referrer, referrer_kind, mode)?;
|
||||
Ok(self.handle_node_resolution(maybe_res))
|
||||
Ok(self.handle_node_resolution(res))
|
||||
}
|
||||
|
||||
pub fn resolve_req_reference(
|
||||
|
@ -159,16 +220,15 @@ impl CliNodeResolver {
|
|||
let package_folder = self
|
||||
.npm_resolver
|
||||
.resolve_pkg_folder_from_deno_module_req(req, referrer)?;
|
||||
let maybe_resolution = self
|
||||
.maybe_resolve_package_sub_path_from_deno_module(
|
||||
let resolution_result = self.resolve_package_sub_path_from_deno_module(
|
||||
&package_folder,
|
||||
sub_path,
|
||||
Some(referrer),
|
||||
mode,
|
||||
)?;
|
||||
match maybe_resolution {
|
||||
Some(resolution) => Ok(resolution),
|
||||
None => {
|
||||
);
|
||||
match resolution_result {
|
||||
Ok(resolution) => Ok(resolution),
|
||||
Err(err) => {
|
||||
if self.npm_resolver.as_byonm().is_some() {
|
||||
let package_json_path = package_folder.join("package.json");
|
||||
if !self.fs.exists_sync(&package_json_path) {
|
||||
|
@ -178,12 +238,7 @@ impl CliNodeResolver {
|
|||
));
|
||||
}
|
||||
}
|
||||
Err(anyhow!(
|
||||
"Failed resolving '{}{}' in '{}'.",
|
||||
req,
|
||||
sub_path.map(|s| format!("/{}", s)).unwrap_or_default(),
|
||||
package_folder.display()
|
||||
))
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -195,32 +250,7 @@ impl CliNodeResolver {
|
|||
maybe_referrer: Option<&ModuleSpecifier>,
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<NodeResolution, AnyError> {
|
||||
self
|
||||
.maybe_resolve_package_sub_path_from_deno_module(
|
||||
package_folder,
|
||||
sub_path,
|
||||
maybe_referrer,
|
||||
mode,
|
||||
)?
|
||||
.ok_or_else(|| {
|
||||
anyhow!(
|
||||
"Failed resolving '{}' in '{}'.",
|
||||
sub_path
|
||||
.map(|s| format!("/{}", s))
|
||||
.unwrap_or_else(|| ".".to_string()),
|
||||
package_folder.display(),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn maybe_resolve_package_sub_path_from_deno_module(
|
||||
&self,
|
||||
package_folder: &Path,
|
||||
sub_path: Option<&str>,
|
||||
maybe_referrer: Option<&ModuleSpecifier>,
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<Option<NodeResolution>, ResolvePkgSubpathFromDenoModuleError> {
|
||||
let maybe_res = self
|
||||
let res = self
|
||||
.node_resolver
|
||||
.resolve_package_subpath_from_deno_module(
|
||||
package_folder,
|
||||
|
@ -228,7 +258,7 @@ impl CliNodeResolver {
|
|||
maybe_referrer,
|
||||
mode,
|
||||
)?;
|
||||
Ok(self.handle_node_resolution(maybe_res))
|
||||
Ok(self.handle_node_resolution(res))
|
||||
}
|
||||
|
||||
pub fn handle_if_in_node_modules(
|
||||
|
@ -267,13 +297,13 @@ impl CliNodeResolver {
|
|||
|
||||
fn handle_node_resolution(
|
||||
&self,
|
||||
maybe_resolution: Option<NodeResolution>,
|
||||
) -> Option<NodeResolution> {
|
||||
if let Some(NodeResolution::CommonJs(specifier)) = &maybe_resolution {
|
||||
resolution: NodeResolution,
|
||||
) -> NodeResolution {
|
||||
if let NodeResolution::CommonJs(specifier) = &resolution {
|
||||
// remember that this was a common js resolution
|
||||
self.cjs_resolutions.insert(specifier.clone());
|
||||
}
|
||||
maybe_resolution
|
||||
resolution
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -458,39 +488,6 @@ impl CliGraphResolver {
|
|||
bare_node_builtins_enabled: self.bare_node_builtins_enabled,
|
||||
}
|
||||
}
|
||||
|
||||
// todo(dsherret): update this and the surrounding code to handle the structured errors from NodeResolver
|
||||
fn check_surface_byonm_node_error(
|
||||
&self,
|
||||
specifier: &str,
|
||||
referrer: &ModuleSpecifier,
|
||||
original_err: AnyError,
|
||||
resolver: &ByonmCliNpmResolver,
|
||||
) -> Result<(), AnyError> {
|
||||
if let Ok((pkg_name, _, _)) = parse_npm_pkg_name(specifier, referrer) {
|
||||
match resolver.resolve_package_folder_from_package(&pkg_name, referrer) {
|
||||
Ok(_) => {
|
||||
return Err(original_err);
|
||||
}
|
||||
Err(_) => {
|
||||
if resolver
|
||||
.find_ancestor_package_json_with_dep(&pkg_name, referrer)
|
||||
.is_some()
|
||||
{
|
||||
return Err(anyhow!(
|
||||
concat!(
|
||||
"Could not resolve \"{}\", but found it in a package.json. ",
|
||||
"Deno expects the node_modules/ directory to be up to date. ",
|
||||
"Did you forget to run `npm install`?"
|
||||
),
|
||||
specifier
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Resolver for CliGraphResolver {
|
||||
|
@ -523,6 +520,18 @@ impl Resolver for CliGraphResolver {
|
|||
}
|
||||
|
||||
let referrer = &referrer_range.specifier;
|
||||
|
||||
// Use node resolution if we're in an npm package
|
||||
if let Some(node_resolver) = self.node_resolver.as_ref() {
|
||||
if referrer.scheme() == "file" && node_resolver.in_npm_package(referrer) {
|
||||
return node_resolver
|
||||
.resolve(specifier, referrer, to_node_mode(mode))
|
||||
.map(|res| res.into_url())
|
||||
.map_err(|e| ResolveError::Other(e.into()));
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to resolve with the workspace resolver
|
||||
let result: Result<_, ResolveError> = self
|
||||
.workspace_resolver
|
||||
.resolve(specifier, referrer)
|
||||
|
@ -535,7 +544,19 @@ impl Resolver for CliGraphResolver {
|
|||
let result = match result {
|
||||
Ok(resolution) => match resolution {
|
||||
MappedResolution::Normal(specifier)
|
||||
| MappedResolution::ImportMap(specifier) => Ok(specifier),
|
||||
| MappedResolution::ImportMap(specifier) => {
|
||||
// do sloppy imports resolution if enabled
|
||||
if let Some(sloppy_imports_resolver) = &self.sloppy_imports_resolver {
|
||||
Ok(sloppy_imports_resolve(
|
||||
sloppy_imports_resolver,
|
||||
specifier,
|
||||
referrer_range,
|
||||
mode,
|
||||
))
|
||||
} else {
|
||||
Ok(specifier)
|
||||
}
|
||||
}
|
||||
MappedResolution::WorkspaceNpmPackage {
|
||||
target_pkg_json: pkg_json,
|
||||
sub_path,
|
||||
|
@ -552,8 +573,6 @@ impl Resolver for CliGraphResolver {
|
|||
)
|
||||
.map_err(ResolveError::Other)
|
||||
.map(|res| res.into_url()),
|
||||
// todo(dsherret): for byonm it should do resolution solely based on
|
||||
// the referrer and not the package.json
|
||||
MappedResolution::PackageJson {
|
||||
dep_result,
|
||||
alias,
|
||||
|
@ -604,44 +623,6 @@ impl Resolver for CliGraphResolver {
|
|||
Err(err) => Err(err),
|
||||
};
|
||||
|
||||
// check if it's an npm specifier that resolves to a workspace member
|
||||
if let Some(node_resolver) = &self.node_resolver {
|
||||
if let Ok(specifier) = &result {
|
||||
if let Ok(req_ref) = NpmPackageReqReference::from_specifier(specifier) {
|
||||
if let Some(pkg_folder) = self
|
||||
.workspace_resolver
|
||||
.resolve_workspace_pkg_json_folder_for_npm_specifier(req_ref.req())
|
||||
{
|
||||
return Ok(
|
||||
node_resolver
|
||||
.resolve_package_sub_path_from_deno_module(
|
||||
pkg_folder,
|
||||
req_ref.sub_path(),
|
||||
Some(referrer),
|
||||
to_node_mode(mode),
|
||||
)?
|
||||
.into_url(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do sloppy imports resolution if enabled
|
||||
let result =
|
||||
if let Some(sloppy_imports_resolver) = &self.sloppy_imports_resolver {
|
||||
result.map(|specifier| {
|
||||
sloppy_imports_resolve(
|
||||
sloppy_imports_resolver,
|
||||
specifier,
|
||||
referrer_range,
|
||||
mode,
|
||||
)
|
||||
})
|
||||
} else {
|
||||
result
|
||||
};
|
||||
|
||||
// When the user is vendoring, don't allow them to import directly from the vendor/ directory
|
||||
// as it might cause them confusion or duplicate dependencies. Additionally, this folder has
|
||||
// special treatment in the language server so it will definitely cause issues/confusion there
|
||||
|
@ -654,76 +635,62 @@ impl Resolver for CliGraphResolver {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(resolver) =
|
||||
self.npm_resolver.as_ref().and_then(|r| r.as_byonm())
|
||||
{
|
||||
match &result {
|
||||
let Some(node_resolver) = &self.node_resolver else {
|
||||
return result;
|
||||
};
|
||||
|
||||
let is_byonm = self
|
||||
.npm_resolver
|
||||
.as_ref()
|
||||
.is_some_and(|r| r.as_byonm().is_some());
|
||||
match result {
|
||||
Ok(specifier) => {
|
||||
if let Ok(npm_req_ref) =
|
||||
NpmPackageReqReference::from_specifier(specifier)
|
||||
NpmPackageReqReference::from_specifier(&specifier)
|
||||
{
|
||||
let node_resolver = self.node_resolver.as_ref().unwrap();
|
||||
// check if the npm specifier resolves to a workspace member
|
||||
if let Some(pkg_folder) = self
|
||||
.workspace_resolver
|
||||
.resolve_workspace_pkg_json_folder_for_npm_specifier(
|
||||
npm_req_ref.req(),
|
||||
)
|
||||
{
|
||||
return Ok(
|
||||
node_resolver
|
||||
.resolve_package_sub_path_from_deno_module(
|
||||
pkg_folder,
|
||||
npm_req_ref.sub_path(),
|
||||
Some(referrer),
|
||||
to_node_mode(mode),
|
||||
)?
|
||||
.into_url(),
|
||||
);
|
||||
}
|
||||
|
||||
// do npm resolution for byonm
|
||||
if is_byonm {
|
||||
return node_resolver
|
||||
.resolve_req_reference(&npm_req_ref, referrer, to_node_mode(mode))
|
||||
.map(|res| res.into_url())
|
||||
.map_err(|err| err.into());
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
if referrer.scheme() == "file" {
|
||||
if let Some(node_resolver) = &self.node_resolver {
|
||||
let node_result =
|
||||
node_resolver.resolve(specifier, referrer, to_node_mode(mode));
|
||||
match node_result {
|
||||
Ok(Some(res)) => {
|
||||
return Ok(res.into_url());
|
||||
}
|
||||
Ok(None) => {
|
||||
self
|
||||
.check_surface_byonm_node_error(
|
||||
specifier,
|
||||
referrer,
|
||||
anyhow!("Cannot find \"{}\"", specifier),
|
||||
resolver,
|
||||
)
|
||||
.map_err(ResolveError::Other)?;
|
||||
|
||||
Ok(node_resolver.handle_if_in_node_modules(specifier)?)
|
||||
}
|
||||
Err(err) => {
|
||||
self
|
||||
.check_surface_byonm_node_error(
|
||||
specifier,
|
||||
referrer,
|
||||
err.into(),
|
||||
resolver,
|
||||
)
|
||||
// If byonm, check if the bare specifier resolves to an npm package
|
||||
if is_byonm && referrer.scheme() == "file" {
|
||||
let maybe_resolution = node_resolver
|
||||
.resolve_if_for_npm_pkg(specifier, referrer, to_node_mode(mode))
|
||||
.map_err(ResolveError::Other)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if referrer.scheme() == "file" {
|
||||
if let Some(node_resolver) = &self.node_resolver {
|
||||
let node_result = node_resolver.resolve_if_in_npm_package(
|
||||
specifier,
|
||||
referrer,
|
||||
to_node_mode(mode),
|
||||
);
|
||||
if let Some(Ok(Some(res))) = node_result {
|
||||
if let Some(res) = maybe_resolution {
|
||||
return Ok(res.into_url());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let specifier = result?;
|
||||
match &self.node_resolver {
|
||||
Some(node_resolver) => node_resolver
|
||||
.handle_if_in_node_modules(specifier)
|
||||
.map_err(|e| e.into()),
|
||||
None => Ok(specifier),
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,15 +151,14 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
|||
})?
|
||||
};
|
||||
|
||||
if let Some(result) = self.shared.node_resolver.resolve_if_in_npm_package(
|
||||
specifier,
|
||||
&referrer,
|
||||
NodeResolutionMode::Execution,
|
||||
) {
|
||||
return match result? {
|
||||
Some(res) => Ok(res.into_url()),
|
||||
None => Err(generic_error("not found")),
|
||||
};
|
||||
if self.shared.node_resolver.in_npm_package(&referrer) {
|
||||
return Ok(
|
||||
self
|
||||
.shared
|
||||
.node_resolver
|
||||
.resolve(specifier, &referrer, NodeResolutionMode::Execution)?
|
||||
.into_url(),
|
||||
);
|
||||
}
|
||||
|
||||
let mapped_resolution =
|
||||
|
@ -250,14 +249,12 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
|||
Err(err)
|
||||
if err.is_unmapped_bare_specifier() && referrer.scheme() == "file" =>
|
||||
{
|
||||
// todo(dsherret): return a better error from node resolution so that
|
||||
// we can more easily tell whether to surface it or not
|
||||
let node_result = self.shared.node_resolver.resolve(
|
||||
let maybe_res = self.shared.node_resolver.resolve_if_for_npm_pkg(
|
||||
specifier,
|
||||
&referrer,
|
||||
NodeResolutionMode::Execution,
|
||||
);
|
||||
if let Ok(Some(res)) = node_result {
|
||||
)?;
|
||||
if let Some(res) = maybe_res {
|
||||
return Ok(res.into_url());
|
||||
}
|
||||
Err(err.into())
|
||||
|
|
|
@ -30,6 +30,8 @@ use deno_graph::GraphKind;
|
|||
use deno_graph::Module;
|
||||
use deno_graph::ModuleGraph;
|
||||
use deno_graph::ResolutionResolved;
|
||||
use deno_runtime::deno_node::errors::NodeJsErrorCode;
|
||||
use deno_runtime::deno_node::errors::NodeJsErrorCoded;
|
||||
use deno_runtime::deno_node::NodeModuleKind;
|
||||
use deno_runtime::deno_node::NodeResolution;
|
||||
use deno_runtime::deno_node::NodeResolutionMode;
|
||||
|
@ -756,13 +758,21 @@ fn resolve_graph_specifier_types(
|
|||
.as_managed()
|
||||
.unwrap() // should never be byonm because it won't create Module::Npm
|
||||
.resolve_pkg_folder_from_deno_module(module.nv_reference.nv())?;
|
||||
let maybe_resolution =
|
||||
let res_result =
|
||||
npm.node_resolver.resolve_package_subpath_from_deno_module(
|
||||
&package_folder,
|
||||
module.nv_reference.sub_path(),
|
||||
Some(referrer),
|
||||
NodeResolutionMode::Types,
|
||||
)?;
|
||||
);
|
||||
let maybe_resolution = match res_result {
|
||||
Ok(res) => Some(res),
|
||||
Err(err) => match err.code() {
|
||||
NodeJsErrorCode::ERR_TYPES_NOT_FOUND
|
||||
| NodeJsErrorCode::ERR_MODULE_NOT_FOUND => None,
|
||||
_ => return Err(err.into()),
|
||||
},
|
||||
};
|
||||
Ok(Some(NodeResolution::into_specifier_and_media_type(
|
||||
maybe_resolution,
|
||||
)))
|
||||
|
@ -805,8 +815,7 @@ fn resolve_non_graph_specifier_types(
|
|||
referrer_kind,
|
||||
NodeResolutionMode::Types,
|
||||
)
|
||||
.ok()
|
||||
.flatten(),
|
||||
.ok(),
|
||||
)))
|
||||
} else if let Ok(npm_req_ref) = NpmPackageReqReference::from_str(specifier) {
|
||||
debug_assert_eq!(referrer_kind, NodeModuleKind::Esm);
|
||||
|
@ -817,13 +826,20 @@ fn resolve_non_graph_specifier_types(
|
|||
let package_folder = npm
|
||||
.npm_resolver
|
||||
.resolve_pkg_folder_from_deno_module_req(npm_req_ref.req(), referrer)?;
|
||||
let maybe_resolution = node_resolver
|
||||
.resolve_package_subpath_from_deno_module(
|
||||
let res_result = node_resolver.resolve_package_subpath_from_deno_module(
|
||||
&package_folder,
|
||||
npm_req_ref.sub_path(),
|
||||
Some(referrer),
|
||||
NodeResolutionMode::Types,
|
||||
)?;
|
||||
);
|
||||
let maybe_resolution = match res_result {
|
||||
Ok(res) => Some(res),
|
||||
Err(err) => match err.code() {
|
||||
NodeJsErrorCode::ERR_TYPES_NOT_FOUND
|
||||
| NodeJsErrorCode::ERR_MODULE_NOT_FOUND => None,
|
||||
_ => return Err(err.into()),
|
||||
},
|
||||
};
|
||||
Ok(Some(NodeResolution::into_specifier_and_media_type(
|
||||
maybe_resolution,
|
||||
)))
|
||||
|
|
|
@ -687,7 +687,7 @@ impl CliMainWorkerFactory {
|
|||
return Ok(None);
|
||||
}
|
||||
|
||||
let Some(resolution) = self
|
||||
let resolution = self
|
||||
.shared
|
||||
.node_resolver
|
||||
.resolve_package_subpath_from_deno_module(
|
||||
|
@ -695,10 +695,7 @@ impl CliMainWorkerFactory {
|
|||
sub_path,
|
||||
/* referrer */ None,
|
||||
NodeResolutionMode::Execution,
|
||||
)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
)?;
|
||||
match &resolution {
|
||||
NodeResolution::BuiltIn(_) => Ok(None),
|
||||
NodeResolution::CommonJs(specifier) | NodeResolution::Esm(specifier) => {
|
||||
|
|
|
@ -49,6 +49,8 @@ pub enum NodeJsErrorCode {
|
|||
ERR_UNKNOWN_FILE_EXTENSION,
|
||||
ERR_UNSUPPORTED_DIR_IMPORT,
|
||||
ERR_UNSUPPORTED_ESM_URL_SCHEME,
|
||||
/// Deno specific since Node doesn't support TypeScript.
|
||||
ERR_TYPES_NOT_FOUND,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for NodeJsErrorCode {
|
||||
|
@ -70,6 +72,7 @@ impl NodeJsErrorCode {
|
|||
ERR_UNKNOWN_FILE_EXTENSION => "ERR_UNKNOWN_FILE_EXTENSION",
|
||||
ERR_UNSUPPORTED_DIR_IMPORT => "ERR_UNSUPPORTED_DIR_IMPORT",
|
||||
ERR_UNSUPPORTED_ESM_URL_SCHEME => "ERR_UNSUPPORTED_ESM_URL_SCHEME",
|
||||
ERR_TYPES_NOT_FOUND => "ERR_TYPES_NOT_FOUND",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -122,65 +125,98 @@ impl NodeJsErrorCoded for InvalidModuleSpecifierError {
|
|||
}
|
||||
}
|
||||
|
||||
kinded_err!(LegacyResolveError, LegacyResolveErrorKind);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum LegacyMainResolveError {
|
||||
pub enum LegacyResolveErrorKind {
|
||||
#[error(transparent)]
|
||||
PathToDeclarationUrl(PathToDeclarationUrlError),
|
||||
TypesNotFound(#[from] TypesNotFoundError),
|
||||
#[error(transparent)]
|
||||
ModuleNotFound(#[from] ModuleNotFoundError),
|
||||
}
|
||||
|
||||
impl NodeJsErrorCoded for LegacyMainResolveError {
|
||||
impl NodeJsErrorCoded for LegacyResolveError {
|
||||
fn code(&self) -> NodeJsErrorCode {
|
||||
match self {
|
||||
Self::PathToDeclarationUrl(e) => e.code(),
|
||||
match self.as_kind() {
|
||||
LegacyResolveErrorKind::TypesNotFound(e) => e.code(),
|
||||
LegacyResolveErrorKind::ModuleNotFound(e) => e.code(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kinded_err!(PackageFolderResolveError, PackageFolderResolveErrorKind);
|
||||
|
||||
impl NodeJsErrorCoded for PackageFolderResolveError {
|
||||
fn code(&self) -> NodeJsErrorCode {
|
||||
match self.as_kind() {
|
||||
PackageFolderResolveErrorKind::NotFoundPackage { .. }
|
||||
| PackageFolderResolveErrorKind::NotFoundReferrer { .. }
|
||||
| PackageFolderResolveErrorKind::Io { .. } => {
|
||||
NodeJsErrorCode::ERR_MODULE_NOT_FOUND
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PackageFolderResolveErrorKind {
|
||||
#[error(
|
||||
"Could not find package '{}' from referrer '{}'{}.",
|
||||
package_name,
|
||||
referrer,
|
||||
referrer_extra.as_ref().map(|r| format!(" ({})", r)).unwrap_or_default()
|
||||
)]
|
||||
NotFoundPackage {
|
||||
package_name: String,
|
||||
referrer: ModuleSpecifier,
|
||||
pub struct PackageNotFoundError {
|
||||
pub package_name: String,
|
||||
pub referrer: ModuleSpecifier,
|
||||
/// Extra information about the referrer.
|
||||
referrer_extra: Option<String>,
|
||||
},
|
||||
pub referrer_extra: Option<String>,
|
||||
}
|
||||
|
||||
impl NodeJsErrorCoded for PackageNotFoundError {
|
||||
fn code(&self) -> NodeJsErrorCode {
|
||||
NodeJsErrorCode::ERR_MODULE_NOT_FOUND
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error(
|
||||
"Could not find referrer npm package '{}'{}.",
|
||||
referrer,
|
||||
referrer_extra.as_ref().map(|r| format!(" ({})", r)).unwrap_or_default()
|
||||
)]
|
||||
NotFoundReferrer {
|
||||
referrer: ModuleSpecifier,
|
||||
pub struct ReferrerNotFoundError {
|
||||
pub referrer: ModuleSpecifier,
|
||||
/// Extra information about the referrer.
|
||||
referrer_extra: Option<String>,
|
||||
},
|
||||
pub referrer_extra: Option<String>,
|
||||
}
|
||||
|
||||
impl NodeJsErrorCoded for ReferrerNotFoundError {
|
||||
fn code(&self) -> NodeJsErrorCode {
|
||||
NodeJsErrorCode::ERR_MODULE_NOT_FOUND
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error("Failed resolving '{package_name}' from referrer '{referrer}'.")]
|
||||
Io {
|
||||
package_name: String,
|
||||
referrer: ModuleSpecifier,
|
||||
pub struct PackageFolderResolveIoError {
|
||||
pub package_name: String,
|
||||
pub referrer: ModuleSpecifier,
|
||||
#[source]
|
||||
source: std::io::Error,
|
||||
},
|
||||
pub source: std::io::Error,
|
||||
}
|
||||
|
||||
impl NodeJsErrorCoded for PackageFolderResolveIoError {
|
||||
fn code(&self) -> NodeJsErrorCode {
|
||||
NodeJsErrorCode::ERR_MODULE_NOT_FOUND
|
||||
}
|
||||
}
|
||||
|
||||
impl NodeJsErrorCoded for PackageFolderResolveError {
|
||||
fn code(&self) -> NodeJsErrorCode {
|
||||
match self.as_kind() {
|
||||
PackageFolderResolveErrorKind::PackageNotFound(e) => e.code(),
|
||||
PackageFolderResolveErrorKind::ReferrerNotFound(e) => e.code(),
|
||||
PackageFolderResolveErrorKind::Io(e) => e.code(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PackageFolderResolveErrorKind {
|
||||
#[error(transparent)]
|
||||
PackageNotFound(#[from] PackageNotFoundError),
|
||||
#[error(transparent)]
|
||||
ReferrerNotFound(#[from] ReferrerNotFoundError),
|
||||
#[error(transparent)]
|
||||
Io(#[from] PackageFolderResolveIoError),
|
||||
}
|
||||
|
||||
kinded_err!(PackageSubpathResolveError, PackageSubpathResolveErrorKind);
|
||||
|
@ -189,10 +225,8 @@ impl NodeJsErrorCoded for PackageSubpathResolveError {
|
|||
fn code(&self) -> NodeJsErrorCode {
|
||||
match self.as_kind() {
|
||||
PackageSubpathResolveErrorKind::PkgJsonLoad(e) => e.code(),
|
||||
PackageSubpathResolveErrorKind::PackageFolderResolve(e) => e.code(),
|
||||
PackageSubpathResolveErrorKind::Exports(e) => e.code(),
|
||||
PackageSubpathResolveErrorKind::LegacyMain(e) => e.code(),
|
||||
PackageSubpathResolveErrorKind::LegacyExact(e) => e.code(),
|
||||
PackageSubpathResolveErrorKind::LegacyResolve(e) => e.code(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -202,13 +236,9 @@ pub enum PackageSubpathResolveErrorKind {
|
|||
#[error(transparent)]
|
||||
PkgJsonLoad(#[from] PackageJsonLoadError),
|
||||
#[error(transparent)]
|
||||
PackageFolderResolve(#[from] PackageFolderResolveError),
|
||||
#[error(transparent)]
|
||||
Exports(PackageExportsResolveError),
|
||||
#[error(transparent)]
|
||||
LegacyMain(LegacyMainResolveError),
|
||||
#[error(transparent)]
|
||||
LegacyExact(PathToDeclarationUrlError),
|
||||
LegacyResolve(LegacyResolveError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
|
@ -254,7 +284,7 @@ impl NodeJsErrorCoded for PackageTargetResolveError {
|
|||
PackageTargetResolveErrorKind::InvalidPackageTarget(e) => e.code(),
|
||||
PackageTargetResolveErrorKind::InvalidModuleSpecifier(e) => e.code(),
|
||||
PackageTargetResolveErrorKind::PackageResolve(e) => e.code(),
|
||||
PackageTargetResolveErrorKind::PathToDeclarationUrl(e) => e.code(),
|
||||
PackageTargetResolveErrorKind::TypesNotFound(e) => e.code(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -270,7 +300,7 @@ pub enum PackageTargetResolveErrorKind {
|
|||
#[error(transparent)]
|
||||
PackageResolve(#[from] PackageResolveError),
|
||||
#[error(transparent)]
|
||||
PathToDeclarationUrl(#[from] PathToDeclarationUrlError),
|
||||
TypesNotFound(#[from] TypesNotFoundError),
|
||||
}
|
||||
|
||||
kinded_err!(PackageExportsResolveError, PackageExportsResolveErrorKind);
|
||||
|
@ -293,16 +323,23 @@ pub enum PackageExportsResolveErrorKind {
|
|||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PathToDeclarationUrlError {
|
||||
#[error(transparent)]
|
||||
SubPath(#[from] PackageSubpathResolveError),
|
||||
#[error(
|
||||
"[{}] Could not find types for '{}'{}",
|
||||
self.code(),
|
||||
self.0.code_specifier,
|
||||
self.0.maybe_referrer.as_ref().map(|r| format!(" imported from '{}'", r)).unwrap_or_default(),
|
||||
)]
|
||||
pub struct TypesNotFoundError(pub Box<TypesNotFoundErrorData>);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TypesNotFoundErrorData {
|
||||
pub code_specifier: ModuleSpecifier,
|
||||
pub maybe_referrer: Option<ModuleSpecifier>,
|
||||
}
|
||||
|
||||
impl NodeJsErrorCoded for PathToDeclarationUrlError {
|
||||
impl NodeJsErrorCoded for TypesNotFoundError {
|
||||
fn code(&self) -> NodeJsErrorCode {
|
||||
match self {
|
||||
PathToDeclarationUrlError::SubPath(e) => e.code(),
|
||||
}
|
||||
NodeJsErrorCode::ERR_TYPES_NOT_FOUND
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -441,6 +478,7 @@ impl NodeJsErrorCoded for PackageResolveError {
|
|||
match self.as_kind() {
|
||||
PackageResolveErrorKind::ClosestPkgJson(e) => e.code(),
|
||||
PackageResolveErrorKind::InvalidModuleSpecifier(e) => e.code(),
|
||||
PackageResolveErrorKind::PackageFolderResolve(e) => e.code(),
|
||||
PackageResolveErrorKind::ExportsResolve(e) => e.code(),
|
||||
PackageResolveErrorKind::SubpathResolve(e) => e.code(),
|
||||
}
|
||||
|
@ -454,37 +492,49 @@ pub enum PackageResolveErrorKind {
|
|||
#[error(transparent)]
|
||||
InvalidModuleSpecifier(#[from] InvalidModuleSpecifierError),
|
||||
#[error(transparent)]
|
||||
PackageFolderResolve(#[from] PackageFolderResolveError),
|
||||
#[error(transparent)]
|
||||
ExportsResolve(#[from] PackageExportsResolveError),
|
||||
#[error(transparent)]
|
||||
SubpathResolve(#[from] PackageSubpathResolveError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum NodeResolveError {
|
||||
#[error("Failed joining '{path}' from '{base}'.")]
|
||||
RelativeJoinError {
|
||||
path: String,
|
||||
base: ModuleSpecifier,
|
||||
pub struct NodeResolveRelativeJoinError {
|
||||
pub path: String,
|
||||
pub base: ModuleSpecifier,
|
||||
#[source]
|
||||
source: url::ParseError,
|
||||
},
|
||||
pub source: url::ParseError,
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error("Failed resolving specifier from data url referrer.")]
|
||||
pub struct DataUrlReferrerError {
|
||||
#[source]
|
||||
pub source: url::ParseError,
|
||||
}
|
||||
|
||||
kinded_err!(NodeResolveError, NodeResolveErrorKind);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum NodeResolveErrorKind {
|
||||
#[error(transparent)]
|
||||
RelativeJoin(#[from] NodeResolveRelativeJoinError),
|
||||
#[error(transparent)]
|
||||
PackageImportsResolve(#[from] PackageImportsResolveError),
|
||||
#[error(transparent)]
|
||||
UnsupportedEsmUrlScheme(#[from] UnsupportedEsmUrlSchemeError),
|
||||
#[error("Failed resolving specifier from data url referrer.")]
|
||||
DataUrlReferrerFailed {
|
||||
#[source]
|
||||
source: url::ParseError,
|
||||
},
|
||||
#[error(transparent)]
|
||||
DataUrlReferrer(#[from] DataUrlReferrerError),
|
||||
#[error(transparent)]
|
||||
PackageResolve(#[from] PackageResolveError),
|
||||
#[error(transparent)]
|
||||
PathToDeclarationUrl(#[from] PathToDeclarationUrlError),
|
||||
#[error(transparent)]
|
||||
UrlToNodeResolution(#[from] UrlToNodeResolutionError),
|
||||
TypesNotFound(#[from] TypesNotFoundError),
|
||||
#[error(transparent)]
|
||||
FinalizeResolution(#[from] FinalizeResolutionError),
|
||||
#[error(transparent)]
|
||||
UrlToNodeResolution(#[from] UrlToNodeResolutionError),
|
||||
}
|
||||
|
||||
kinded_err!(FinalizeResolutionError, FinalizeResolutionErrorKind);
|
||||
|
@ -499,6 +549,16 @@ pub enum FinalizeResolutionErrorKind {
|
|||
UnsupportedDirImport(#[from] UnsupportedDirImportError),
|
||||
}
|
||||
|
||||
impl NodeJsErrorCoded for FinalizeResolutionError {
|
||||
fn code(&self) -> NodeJsErrorCode {
|
||||
match self.as_kind() {
|
||||
FinalizeResolutionErrorKind::InvalidModuleSpecifierError(e) => e.code(),
|
||||
FinalizeResolutionErrorKind::ModuleNotFound(e) => e.code(),
|
||||
FinalizeResolutionErrorKind::UnsupportedDirImport(e) => e.code(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error(
|
||||
"[{}] Cannot find {} '{}'{}",
|
||||
|
@ -513,9 +573,9 @@ pub struct ModuleNotFoundError {
|
|||
pub typ: &'static str,
|
||||
}
|
||||
|
||||
impl ModuleNotFoundError {
|
||||
pub fn code(&self) -> &'static str {
|
||||
"ERR_MODULE_NOT_FOUND"
|
||||
impl NodeJsErrorCoded for ModuleNotFoundError {
|
||||
fn code(&self) -> NodeJsErrorCode {
|
||||
NodeJsErrorCode::ERR_MODULE_NOT_FOUND
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,6 @@ pub use path::PathClean;
|
|||
pub use polyfill::is_builtin_node_module;
|
||||
pub use polyfill::SUPPORTED_BUILTIN_NODE_MODULES;
|
||||
pub use polyfill::SUPPORTED_BUILTIN_NODE_MODULES_WITH_PREFIX;
|
||||
pub use resolution::parse_npm_pkg_name;
|
||||
pub use resolution::NodeModuleKind;
|
||||
pub use resolution::NodeResolution;
|
||||
pub use resolution::NodeResolutionMode;
|
||||
|
|
|
@ -18,14 +18,16 @@ use deno_package_json::PackageJsonRc;
|
|||
use crate::errors;
|
||||
use crate::errors::CanonicalizingPkgJsonDirError;
|
||||
use crate::errors::ClosestPkgJsonError;
|
||||
use crate::errors::DataUrlReferrerError;
|
||||
use crate::errors::FinalizeResolutionError;
|
||||
use crate::errors::InvalidModuleSpecifierError;
|
||||
use crate::errors::InvalidPackageTargetError;
|
||||
use crate::errors::LegacyMainResolveError;
|
||||
use crate::errors::LegacyResolveError;
|
||||
use crate::errors::ModuleNotFoundError;
|
||||
use crate::errors::NodeJsErrorCode;
|
||||
use crate::errors::NodeJsErrorCoded;
|
||||
use crate::errors::NodeResolveError;
|
||||
use crate::errors::NodeResolveRelativeJoinError;
|
||||
use crate::errors::PackageExportsResolveError;
|
||||
use crate::errors::PackageImportNotDefinedError;
|
||||
use crate::errors::PackageImportsResolveError;
|
||||
|
@ -38,11 +40,12 @@ use crate::errors::PackageSubpathResolveErrorKind;
|
|||
use crate::errors::PackageTargetNotFoundError;
|
||||
use crate::errors::PackageTargetResolveError;
|
||||
use crate::errors::PackageTargetResolveErrorKind;
|
||||
use crate::errors::PathToDeclarationUrlError;
|
||||
use crate::errors::ResolveBinaryCommandsError;
|
||||
use crate::errors::ResolvePkgJsonBinExportError;
|
||||
use crate::errors::ResolvePkgSubpathFromDenoModuleError;
|
||||
use crate::errors::TypeScriptNotSupportedInNpmError;
|
||||
use crate::errors::TypesNotFoundError;
|
||||
use crate::errors::TypesNotFoundErrorData;
|
||||
use crate::errors::UnsupportedDirImportError;
|
||||
use crate::errors::UnsupportedEsmUrlSchemeError;
|
||||
use crate::errors::UrlToNodeResolutionError;
|
||||
|
@ -55,6 +58,7 @@ use crate::PathClean;
|
|||
|
||||
pub static DEFAULT_CONDITIONS: &[&str] = &["deno", "node", "import"];
|
||||
pub static REQUIRE_CONDITIONS: &[&str] = &["require", "node"];
|
||||
static TYPES_ONLY_CONDITIONS: &[&str] = &["types"];
|
||||
|
||||
pub type NodeModuleKind = deno_package_json::NodeModuleKind;
|
||||
|
||||
|
@ -177,23 +181,23 @@ impl NodeResolver {
|
|||
referrer: &ModuleSpecifier,
|
||||
referrer_kind: NodeModuleKind,
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<Option<NodeResolution>, NodeResolveError> {
|
||||
) -> Result<NodeResolution, NodeResolveError> {
|
||||
// Note: if we are here, then the referrer is an esm module
|
||||
// TODO(bartlomieju): skipped "policy" part as we don't plan to support it
|
||||
|
||||
if crate::is_builtin_node_module(specifier) {
|
||||
return Ok(Some(NodeResolution::BuiltIn(specifier.to_string())));
|
||||
return Ok(NodeResolution::BuiltIn(specifier.to_string()));
|
||||
}
|
||||
|
||||
if let Ok(url) = Url::parse(specifier) {
|
||||
if url.scheme() == "data" {
|
||||
return Ok(Some(NodeResolution::Esm(url)));
|
||||
return Ok(NodeResolution::Esm(url));
|
||||
}
|
||||
|
||||
if let Some(module_name) =
|
||||
get_module_name_from_builtin_node_module_specifier(&url)
|
||||
{
|
||||
return Ok(Some(NodeResolution::BuiltIn(module_name.to_string())));
|
||||
return Ok(NodeResolution::BuiltIn(module_name.to_string()));
|
||||
}
|
||||
|
||||
let protocol = url.scheme();
|
||||
|
@ -209,14 +213,14 @@ impl NodeResolver {
|
|||
|
||||
// todo(dsherret): this seems wrong
|
||||
if referrer.scheme() == "data" {
|
||||
let url = referrer.join(specifier).map_err(|source| {
|
||||
NodeResolveError::DataUrlReferrerFailed { source }
|
||||
})?;
|
||||
return Ok(Some(NodeResolution::Esm(url)));
|
||||
let url = referrer
|
||||
.join(specifier)
|
||||
.map_err(|source| DataUrlReferrerError { source })?;
|
||||
return Ok(NodeResolution::Esm(url));
|
||||
}
|
||||
}
|
||||
|
||||
let maybe_url = self.module_resolve(
|
||||
let url = self.module_resolve(
|
||||
specifier,
|
||||
referrer,
|
||||
referrer_kind,
|
||||
|
@ -226,15 +230,19 @@ impl NodeResolver {
|
|||
},
|
||||
mode,
|
||||
)?;
|
||||
let url = match maybe_url {
|
||||
Some(url) => url,
|
||||
None => return Ok(None),
|
||||
|
||||
let url = if mode.is_types() {
|
||||
let file_path = to_file_path(&url);
|
||||
self.path_to_declaration_url(&file_path, Some(referrer), referrer_kind)?
|
||||
} else {
|
||||
url
|
||||
};
|
||||
|
||||
let url = self.finalize_resolution(url, Some(referrer))?;
|
||||
let resolve_response = self.url_to_node_resolution(url)?;
|
||||
// TODO(bartlomieju): skipped checking errors for commonJS resolution and
|
||||
// "preserveSymlinksMain"/"preserveSymlinks" options.
|
||||
Ok(Some(resolve_response))
|
||||
Ok(resolve_response)
|
||||
}
|
||||
|
||||
fn module_resolve(
|
||||
|
@ -244,12 +252,10 @@ impl NodeResolver {
|
|||
referrer_kind: NodeModuleKind,
|
||||
conditions: &[&str],
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<Option<ModuleSpecifier>, NodeResolveError> {
|
||||
// note: if we're here, the referrer is an esm module
|
||||
let maybe_url = if should_be_treated_as_relative_or_absolute_path(specifier)
|
||||
{
|
||||
Some(referrer.join(specifier).map_err(|err| {
|
||||
NodeResolveError::RelativeJoinError {
|
||||
) -> Result<ModuleSpecifier, NodeResolveError> {
|
||||
if should_be_treated_as_relative_or_absolute_path(specifier) {
|
||||
Ok(referrer.join(specifier).map_err(|err| {
|
||||
NodeResolveRelativeJoinError {
|
||||
path: specifier.to_string(),
|
||||
base: referrer.clone(),
|
||||
source: err,
|
||||
|
@ -260,7 +266,7 @@ impl NodeResolver {
|
|||
.get_closest_package_json(referrer)
|
||||
.map_err(PackageImportsResolveErrorKind::ClosestPkgJson)
|
||||
.map_err(|err| PackageImportsResolveError(Box::new(err)))?;
|
||||
Some(self.package_imports_resolve(
|
||||
Ok(self.package_imports_resolve(
|
||||
specifier,
|
||||
Some(referrer),
|
||||
referrer_kind,
|
||||
|
@ -269,32 +275,16 @@ impl NodeResolver {
|
|||
mode,
|
||||
)?)
|
||||
} else if let Ok(resolved) = Url::parse(specifier) {
|
||||
Some(resolved)
|
||||
Ok(resolved)
|
||||
} else {
|
||||
self.package_resolve(
|
||||
Ok(self.package_resolve(
|
||||
specifier,
|
||||
referrer,
|
||||
referrer_kind,
|
||||
conditions,
|
||||
mode,
|
||||
)?
|
||||
};
|
||||
|
||||
let Some(url) = maybe_url else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let maybe_url = if mode.is_types() {
|
||||
let file_path = to_file_path(&url);
|
||||
self.path_to_declaration_url(&file_path, Some(referrer), referrer_kind)?
|
||||
} else {
|
||||
Some(url)
|
||||
};
|
||||
|
||||
Ok(match maybe_url {
|
||||
Some(url) => Some(self.finalize_resolution(url, Some(referrer))?),
|
||||
None => None,
|
||||
})
|
||||
)?)
|
||||
}
|
||||
}
|
||||
|
||||
fn finalize_resolution(
|
||||
|
@ -369,12 +359,12 @@ impl NodeResolver {
|
|||
package_subpath: Option<&str>,
|
||||
maybe_referrer: Option<&ModuleSpecifier>,
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<Option<NodeResolution>, ResolvePkgSubpathFromDenoModuleError> {
|
||||
) -> Result<NodeResolution, ResolvePkgSubpathFromDenoModuleError> {
|
||||
let node_module_kind = NodeModuleKind::Esm;
|
||||
let package_subpath = package_subpath
|
||||
.map(|s| format!("./{s}"))
|
||||
.unwrap_or_else(|| ".".to_string());
|
||||
let maybe_resolved_url = self.resolve_package_dir_subpath(
|
||||
let resolved_url = self.resolve_package_dir_subpath(
|
||||
package_dir,
|
||||
&package_subpath,
|
||||
maybe_referrer,
|
||||
|
@ -382,14 +372,10 @@ impl NodeResolver {
|
|||
DEFAULT_CONDITIONS,
|
||||
mode,
|
||||
)?;
|
||||
let resolved_url = match maybe_resolved_url {
|
||||
Some(resolved_url) => resolved_url,
|
||||
None => return Ok(None),
|
||||
};
|
||||
let resolve_response = self.url_to_node_resolution(resolved_url)?;
|
||||
// TODO(bartlomieju): skipped checking errors for commonJS resolution and
|
||||
// "preserveSymlinksMain"/"preserveSymlinks" options.
|
||||
Ok(Some(resolve_response))
|
||||
Ok(resolve_response)
|
||||
}
|
||||
|
||||
pub fn resolve_binary_commands(
|
||||
|
@ -475,7 +461,7 @@ impl NodeResolver {
|
|||
path: &Path,
|
||||
maybe_referrer: Option<&ModuleSpecifier>,
|
||||
referrer_kind: NodeModuleKind,
|
||||
) -> Result<Option<ModuleSpecifier>, PathToDeclarationUrlError> {
|
||||
) -> Result<ModuleSpecifier, TypesNotFoundError> {
|
||||
fn probe_extensions(
|
||||
fs: &dyn deno_fs::FileSystem,
|
||||
path: &Path,
|
||||
|
@ -525,15 +511,15 @@ impl NodeResolver {
|
|||
|| lowercase_path.ends_with(".d.cts")
|
||||
|| lowercase_path.ends_with(".d.mts")
|
||||
{
|
||||
return Ok(Some(to_file_specifier(path)));
|
||||
return Ok(to_file_specifier(path));
|
||||
}
|
||||
if let Some(path) =
|
||||
probe_extensions(&*self.fs, path, &lowercase_path, referrer_kind)
|
||||
{
|
||||
return Ok(Some(to_file_specifier(&path)));
|
||||
return Ok(to_file_specifier(&path));
|
||||
}
|
||||
if self.fs.is_dir_sync(path) {
|
||||
let maybe_resolution = self.resolve_package_dir_subpath(
|
||||
let resolution_result = self.resolve_package_dir_subpath(
|
||||
path,
|
||||
/* sub path */ ".",
|
||||
maybe_referrer,
|
||||
|
@ -543,9 +529,9 @@ impl NodeResolver {
|
|||
NodeModuleKind::Cjs => REQUIRE_CONDITIONS,
|
||||
},
|
||||
NodeResolutionMode::Types,
|
||||
)?;
|
||||
if let Some(resolution) = maybe_resolution {
|
||||
return Ok(Some(resolution));
|
||||
);
|
||||
if let Ok(resolution) = resolution_result {
|
||||
return Ok(resolution);
|
||||
}
|
||||
let index_path = path.join("index.js");
|
||||
if let Some(path) = probe_extensions(
|
||||
|
@ -554,14 +540,17 @@ impl NodeResolver {
|
|||
&index_path.to_string_lossy().to_lowercase(),
|
||||
referrer_kind,
|
||||
) {
|
||||
return Ok(Some(to_file_specifier(&path)));
|
||||
return Ok(to_file_specifier(&path));
|
||||
}
|
||||
}
|
||||
// allow resolving .css files for types resolution
|
||||
if lowercase_path.ends_with(".css") {
|
||||
return Ok(Some(to_file_specifier(path)));
|
||||
return Ok(to_file_specifier(path));
|
||||
}
|
||||
Ok(None)
|
||||
Err(TypesNotFoundError(Box::new(TypesNotFoundErrorData {
|
||||
code_specifier: to_file_specifier(path),
|
||||
maybe_referrer: maybe_referrer.cloned(),
|
||||
})))
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
|
@ -719,8 +708,20 @@ impl NodeResolver {
|
|||
conditions,
|
||||
mode,
|
||||
) {
|
||||
Ok(Some(url)) => Ok(url),
|
||||
Ok(None) => Err(
|
||||
Ok(url) => Ok(url),
|
||||
Err(err) => match err.code() {
|
||||
NodeJsErrorCode::ERR_INVALID_MODULE_SPECIFIER
|
||||
| NodeJsErrorCode::ERR_INVALID_PACKAGE_CONFIG
|
||||
| NodeJsErrorCode::ERR_INVALID_PACKAGE_TARGET
|
||||
| NodeJsErrorCode::ERR_PACKAGE_IMPORT_NOT_DEFINED
|
||||
| NodeJsErrorCode::ERR_PACKAGE_PATH_NOT_EXPORTED
|
||||
| NodeJsErrorCode::ERR_UNKNOWN_FILE_EXTENSION
|
||||
| NodeJsErrorCode::ERR_UNSUPPORTED_DIR_IMPORT
|
||||
| NodeJsErrorCode::ERR_UNSUPPORTED_ESM_URL_SCHEME
|
||||
| NodeJsErrorCode::ERR_TYPES_NOT_FOUND => {
|
||||
Err(PackageTargetResolveErrorKind::PackageResolve(err).into())
|
||||
}
|
||||
NodeJsErrorCode::ERR_MODULE_NOT_FOUND => Err(
|
||||
PackageTargetResolveErrorKind::NotFound(
|
||||
PackageTargetNotFoundError {
|
||||
pkg_json_path: package_json_path.to_path_buf(),
|
||||
|
@ -732,9 +733,7 @@ impl NodeResolver {
|
|||
)
|
||||
.into(),
|
||||
),
|
||||
Err(err) => {
|
||||
Err(PackageTargetResolveErrorKind::PackageResolve(err).into())
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
return match result {
|
||||
|
@ -831,6 +830,62 @@ impl NodeResolver {
|
|||
internal: bool,
|
||||
conditions: &[&str],
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<Option<ModuleSpecifier>, PackageTargetResolveError> {
|
||||
let result = self.resolve_package_target_inner(
|
||||
package_json_path,
|
||||
target,
|
||||
subpath,
|
||||
package_subpath,
|
||||
maybe_referrer,
|
||||
referrer_kind,
|
||||
pattern,
|
||||
internal,
|
||||
conditions,
|
||||
mode,
|
||||
);
|
||||
match result {
|
||||
Ok(maybe_resolved) => Ok(maybe_resolved),
|
||||
Err(err) => {
|
||||
if mode.is_types()
|
||||
&& err.code() == NodeJsErrorCode::ERR_TYPES_NOT_FOUND
|
||||
&& conditions != TYPES_ONLY_CONDITIONS
|
||||
{
|
||||
// try resolving with just "types" conditions for when someone misconfigures
|
||||
// and puts the "types" condition in the wrong place
|
||||
if let Ok(Some(resolved)) = self.resolve_package_target_inner(
|
||||
package_json_path,
|
||||
target,
|
||||
subpath,
|
||||
package_subpath,
|
||||
maybe_referrer,
|
||||
referrer_kind,
|
||||
pattern,
|
||||
internal,
|
||||
TYPES_ONLY_CONDITIONS,
|
||||
mode,
|
||||
) {
|
||||
return Ok(Some(resolved));
|
||||
}
|
||||
}
|
||||
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn resolve_package_target_inner(
|
||||
&self,
|
||||
package_json_path: &Path,
|
||||
target: &Value,
|
||||
subpath: &str,
|
||||
package_subpath: &str,
|
||||
maybe_referrer: Option<&ModuleSpecifier>,
|
||||
referrer_kind: NodeModuleKind,
|
||||
pattern: bool,
|
||||
internal: bool,
|
||||
conditions: &[&str],
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<Option<ModuleSpecifier>, PackageTargetResolveError> {
|
||||
if let Some(target) = target.as_str() {
|
||||
let url = self.resolve_package_target_string(
|
||||
|
@ -847,11 +902,11 @@ impl NodeResolver {
|
|||
)?;
|
||||
if mode.is_types() && url.scheme() == "file" {
|
||||
let path = url.to_file_path().unwrap();
|
||||
return Ok(self.path_to_declaration_url(
|
||||
return Ok(Some(self.path_to_declaration_url(
|
||||
&path,
|
||||
maybe_referrer,
|
||||
referrer_kind,
|
||||
)?);
|
||||
)?));
|
||||
} else {
|
||||
return Ok(Some(url));
|
||||
}
|
||||
|
@ -1069,13 +1124,11 @@ impl NodeResolver {
|
|||
referrer_kind: NodeModuleKind,
|
||||
conditions: &[&str],
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<Option<ModuleSpecifier>, PackageResolveError> {
|
||||
) -> Result<ModuleSpecifier, PackageResolveError> {
|
||||
let (package_name, package_subpath, _is_scoped) =
|
||||
parse_npm_pkg_name(specifier, referrer)?;
|
||||
|
||||
let Some(package_config) = self.get_closest_package_json(referrer)? else {
|
||||
return Ok(None);
|
||||
};
|
||||
if let Some(package_config) = self.get_closest_package_json(referrer)? {
|
||||
// ResolveSelf
|
||||
if package_config.name.as_ref() == Some(&package_name) {
|
||||
if let Some(exports) = &package_config.exports {
|
||||
|
@ -1089,13 +1142,12 @@ impl NodeResolver {
|
|||
conditions,
|
||||
mode,
|
||||
)
|
||||
.map(Some)
|
||||
.map_err(|err| err.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self
|
||||
.resolve_package_subpath_for_package(
|
||||
self.resolve_package_subpath_for_package(
|
||||
&package_name,
|
||||
&package_subpath,
|
||||
referrer,
|
||||
|
@ -1103,7 +1155,6 @@ impl NodeResolver {
|
|||
conditions,
|
||||
mode,
|
||||
)
|
||||
.map_err(|err| err.into())
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
|
@ -1115,7 +1166,7 @@ impl NodeResolver {
|
|||
referrer_kind: NodeModuleKind,
|
||||
conditions: &[&str],
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<Option<ModuleSpecifier>, PackageSubpathResolveError> {
|
||||
) -> Result<ModuleSpecifier, PackageResolveError> {
|
||||
let result = self.resolve_package_subpath_for_package_inner(
|
||||
package_name,
|
||||
package_subpath,
|
||||
|
@ -1124,10 +1175,10 @@ impl NodeResolver {
|
|||
conditions,
|
||||
mode,
|
||||
);
|
||||
if mode.is_types() && !matches!(result, Ok(Some(_))) {
|
||||
if mode.is_types() && !matches!(result, Ok(ModuleSpecifier { .. })) {
|
||||
// try to resolve with the @types package
|
||||
let package_name = types_package_name(package_name);
|
||||
if let Ok(Some(result)) = self.resolve_package_subpath_for_package_inner(
|
||||
if let Ok(result) = self.resolve_package_subpath_for_package_inner(
|
||||
&package_name,
|
||||
package_subpath,
|
||||
referrer,
|
||||
|
@ -1135,7 +1186,7 @@ impl NodeResolver {
|
|||
conditions,
|
||||
mode,
|
||||
) {
|
||||
return Ok(Some(result));
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
result
|
||||
|
@ -1150,7 +1201,7 @@ impl NodeResolver {
|
|||
referrer_kind: NodeModuleKind,
|
||||
conditions: &[&str],
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<Option<ModuleSpecifier>, PackageSubpathResolveError> {
|
||||
) -> Result<ModuleSpecifier, PackageResolveError> {
|
||||
let package_dir_path = self
|
||||
.npm_resolver
|
||||
.resolve_package_folder_from_package(package_name, referrer)?;
|
||||
|
@ -1169,7 +1220,8 @@ impl NodeResolver {
|
|||
// ))
|
||||
|
||||
// Package match.
|
||||
self.resolve_package_dir_subpath(
|
||||
self
|
||||
.resolve_package_dir_subpath(
|
||||
&package_dir_path,
|
||||
package_subpath,
|
||||
Some(referrer),
|
||||
|
@ -1177,6 +1229,7 @@ impl NodeResolver {
|
|||
conditions,
|
||||
mode,
|
||||
)
|
||||
.map_err(|err| err.into())
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
|
@ -1188,7 +1241,7 @@ impl NodeResolver {
|
|||
referrer_kind: NodeModuleKind,
|
||||
conditions: &[&str],
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<Option<ModuleSpecifier>, PackageSubpathResolveError> {
|
||||
) -> Result<ModuleSpecifier, PackageSubpathResolveError> {
|
||||
let package_json_path = package_dir_path.join("package.json");
|
||||
match self.load_package_json(&package_json_path)? {
|
||||
Some(pkg_json) => self.resolve_package_subpath(
|
||||
|
@ -1207,7 +1260,9 @@ impl NodeResolver {
|
|||
referrer_kind,
|
||||
mode,
|
||||
)
|
||||
.map_err(|err| PackageSubpathResolveErrorKind::LegacyExact(err).into()),
|
||||
.map_err(|err| {
|
||||
PackageSubpathResolveErrorKind::LegacyResolve(err).into()
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1220,7 +1275,7 @@ impl NodeResolver {
|
|||
referrer_kind: NodeModuleKind,
|
||||
conditions: &[&str],
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<Option<ModuleSpecifier>, PackageSubpathResolveError> {
|
||||
) -> Result<ModuleSpecifier, PackageSubpathResolveError> {
|
||||
if let Some(exports) = &package_json.exports {
|
||||
let result = self.package_exports_resolve(
|
||||
&package_json.path,
|
||||
|
@ -1232,13 +1287,13 @@ impl NodeResolver {
|
|||
mode,
|
||||
);
|
||||
match result {
|
||||
Ok(found) => return Ok(Some(found)),
|
||||
Ok(found) => return Ok(found),
|
||||
Err(exports_err) => {
|
||||
if mode.is_types() && package_subpath == "." {
|
||||
return self
|
||||
.legacy_main_resolve(package_json, referrer, referrer_kind, mode)
|
||||
.map_err(|err| {
|
||||
PackageSubpathResolveErrorKind::LegacyMain(err).into()
|
||||
PackageSubpathResolveErrorKind::LegacyResolve(err).into()
|
||||
});
|
||||
}
|
||||
return Err(
|
||||
|
@ -1251,7 +1306,9 @@ impl NodeResolver {
|
|||
if package_subpath == "." {
|
||||
return self
|
||||
.legacy_main_resolve(package_json, referrer, referrer_kind, mode)
|
||||
.map_err(|err| PackageSubpathResolveErrorKind::LegacyMain(err).into());
|
||||
.map_err(|err| {
|
||||
PackageSubpathResolveErrorKind::LegacyResolve(err).into()
|
||||
});
|
||||
}
|
||||
|
||||
self
|
||||
|
@ -1262,7 +1319,9 @@ impl NodeResolver {
|
|||
referrer_kind,
|
||||
mode,
|
||||
)
|
||||
.map_err(|err| PackageSubpathResolveErrorKind::LegacyExact(err).into())
|
||||
.map_err(|err| {
|
||||
PackageSubpathResolveErrorKind::LegacyResolve(err.into()).into()
|
||||
})
|
||||
}
|
||||
|
||||
fn resolve_subpath_exact(
|
||||
|
@ -1272,13 +1331,13 @@ impl NodeResolver {
|
|||
referrer: Option<&ModuleSpecifier>,
|
||||
referrer_kind: NodeModuleKind,
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<Option<ModuleSpecifier>, PathToDeclarationUrlError> {
|
||||
) -> Result<ModuleSpecifier, TypesNotFoundError> {
|
||||
assert_ne!(package_subpath, ".");
|
||||
let file_path = directory.join(package_subpath);
|
||||
if mode.is_types() {
|
||||
Ok(self.path_to_declaration_url(&file_path, referrer, referrer_kind)?)
|
||||
} else {
|
||||
Ok(Some(to_file_specifier(&file_path)))
|
||||
Ok(to_file_specifier(&file_path))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1286,20 +1345,22 @@ impl NodeResolver {
|
|||
&self,
|
||||
directory: &Path,
|
||||
package_subpath: &str,
|
||||
referrer: Option<&ModuleSpecifier>,
|
||||
maybe_referrer: Option<&ModuleSpecifier>,
|
||||
referrer_kind: NodeModuleKind,
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<Option<ModuleSpecifier>, PathToDeclarationUrlError> {
|
||||
) -> Result<ModuleSpecifier, LegacyResolveError> {
|
||||
if package_subpath == "." {
|
||||
Ok(self.legacy_index_resolve(directory, referrer_kind, mode))
|
||||
self.legacy_index_resolve(directory, maybe_referrer, referrer_kind, mode)
|
||||
} else {
|
||||
self.resolve_subpath_exact(
|
||||
self
|
||||
.resolve_subpath_exact(
|
||||
directory,
|
||||
package_subpath,
|
||||
referrer,
|
||||
maybe_referrer,
|
||||
referrer_kind,
|
||||
mode,
|
||||
)
|
||||
.map_err(|err| err.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1348,7 +1409,7 @@ impl NodeResolver {
|
|||
maybe_referrer: Option<&ModuleSpecifier>,
|
||||
referrer_kind: NodeModuleKind,
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<Option<ModuleSpecifier>, LegacyMainResolveError> {
|
||||
) -> Result<ModuleSpecifier, LegacyResolveError> {
|
||||
let maybe_main = if mode.is_types() {
|
||||
match package_json.types.as_ref() {
|
||||
Some(types) => Some(types.as_str()),
|
||||
|
@ -1357,11 +1418,14 @@ impl NodeResolver {
|
|||
// a corresponding declaration file
|
||||
if let Some(main) = package_json.main(referrer_kind) {
|
||||
let main = package_json.path.parent().unwrap().join(main).clean();
|
||||
let maybe_decl_url = self
|
||||
.path_to_declaration_url(&main, maybe_referrer, referrer_kind)
|
||||
.map_err(LegacyMainResolveError::PathToDeclarationUrl)?;
|
||||
if let Some(path) = maybe_decl_url {
|
||||
return Ok(Some(path));
|
||||
let decl_url_result = self.path_to_declaration_url(
|
||||
&main,
|
||||
maybe_referrer,
|
||||
referrer_kind,
|
||||
);
|
||||
// don't surface errors, fallback to checking the index now
|
||||
if let Ok(url) = decl_url_result {
|
||||
return Ok(url);
|
||||
}
|
||||
}
|
||||
None
|
||||
|
@ -1374,7 +1438,7 @@ impl NodeResolver {
|
|||
if let Some(main) = maybe_main {
|
||||
let guess = package_json.path.parent().unwrap().join(main).clean();
|
||||
if self.fs.is_file_sync(&guess) {
|
||||
return Ok(Some(to_file_specifier(&guess)));
|
||||
return Ok(to_file_specifier(&guess));
|
||||
}
|
||||
|
||||
// todo(dsherret): investigate exactly how node and typescript handles this
|
||||
|
@ -1404,24 +1468,26 @@ impl NodeResolver {
|
|||
.clean();
|
||||
if self.fs.is_file_sync(&guess) {
|
||||
// TODO(bartlomieju): emitLegacyIndexDeprecation()
|
||||
return Ok(Some(to_file_specifier(&guess)));
|
||||
return Ok(to_file_specifier(&guess));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(self.legacy_index_resolve(
|
||||
self.legacy_index_resolve(
|
||||
package_json.path.parent().unwrap(),
|
||||
maybe_referrer,
|
||||
referrer_kind,
|
||||
mode,
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
fn legacy_index_resolve(
|
||||
&self,
|
||||
directory: &Path,
|
||||
maybe_referrer: Option<&ModuleSpecifier>,
|
||||
referrer_kind: NodeModuleKind,
|
||||
mode: NodeResolutionMode,
|
||||
) -> Option<ModuleSpecifier> {
|
||||
) -> Result<ModuleSpecifier, LegacyResolveError> {
|
||||
let index_file_names = if mode.is_types() {
|
||||
// todo(dsherret): investigate exactly how typescript does this
|
||||
match referrer_kind {
|
||||
|
@ -1435,11 +1501,28 @@ impl NodeResolver {
|
|||
let guess = directory.join(index_file_name).clean();
|
||||
if self.fs.is_file_sync(&guess) {
|
||||
// TODO(bartlomieju): emitLegacyIndexDeprecation()
|
||||
return Some(to_file_specifier(&guess));
|
||||
return Ok(to_file_specifier(&guess));
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
if mode.is_types() {
|
||||
Err(
|
||||
TypesNotFoundError(Box::new(TypesNotFoundErrorData {
|
||||
code_specifier: to_file_specifier(&directory.join("index.js")),
|
||||
maybe_referrer: maybe_referrer.cloned(),
|
||||
}))
|
||||
.into(),
|
||||
)
|
||||
} else {
|
||||
Err(
|
||||
ModuleNotFoundError {
|
||||
specifier: to_file_specifier(&directory.join("index.js")),
|
||||
typ: "module",
|
||||
maybe_referrer: maybe_referrer.cloned(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1557,7 +1640,7 @@ fn should_be_treated_as_relative_or_absolute_path(specifier: &str) -> bool {
|
|||
// TODO(ry) We very likely have this utility function elsewhere in Deno.
|
||||
fn is_relative_specifier(specifier: &str) -> bool {
|
||||
let specifier_len = specifier.len();
|
||||
let specifier_chars: Vec<_> = specifier.chars().collect();
|
||||
let specifier_chars: Vec<_> = specifier.chars().take(3).collect();
|
||||
|
||||
if !specifier_chars.is_empty() && specifier_chars[0] == '.' {
|
||||
if specifier_len == 1 || specifier_chars[1] == '/' {
|
||||
|
|
|
@ -15,13 +15,6 @@ use util::TestContextBuilder;
|
|||
|
||||
// NOTE: See how to make test npm packages at ./testdata/npm/README.md
|
||||
|
||||
itest!(esm_import_cjs_default {
|
||||
args: "run --allow-read --allow-env --quiet --check=all npm/esm_import_cjs_default/main.ts",
|
||||
output: "npm/esm_import_cjs_default/main.out",
|
||||
envs: env_vars_for_npm_tests(),
|
||||
http_server: true,
|
||||
});
|
||||
|
||||
itest!(cjs_with_deps {
|
||||
args: "run --allow-read --allow-env npm/cjs_with_deps/main.js",
|
||||
output: "npm/cjs_with_deps/main.out",
|
||||
|
@ -324,14 +317,6 @@ itest!(check_local {
|
|||
exit_code: 1,
|
||||
});
|
||||
|
||||
itest!(types_general {
|
||||
args: "check --quiet npm/types/main.ts",
|
||||
output: "npm/types/main.out",
|
||||
envs: env_vars_for_npm_tests(),
|
||||
http_server: true,
|
||||
exit_code: 1,
|
||||
});
|
||||
|
||||
itest!(types_ambient_module {
|
||||
args: "check --quiet npm/types_ambient_module/main.ts",
|
||||
output: "npm/types_ambient_module/main.out",
|
||||
|
@ -348,22 +333,6 @@ itest!(types_ambient_module_import_map {
|
|||
exit_code: 1,
|
||||
});
|
||||
|
||||
itest!(no_types_cjs {
|
||||
args: "check --quiet npm/no_types_cjs/main.ts",
|
||||
output_str: Some(""),
|
||||
exit_code: 0,
|
||||
envs: env_vars_for_npm_tests(),
|
||||
http_server: true,
|
||||
});
|
||||
|
||||
itest!(no_types_in_conditional_exports {
|
||||
args: "run --check npm/no_types_in_conditional_exports/main.ts",
|
||||
output: "npm/no_types_in_conditional_exports/main.out",
|
||||
exit_code: 0,
|
||||
envs: env_vars_for_npm_tests(),
|
||||
http_server: true,
|
||||
});
|
||||
|
||||
itest!(types_entry_value_not_exists {
|
||||
args: "check --all npm/types_entry_value_not_exists/main.ts",
|
||||
output: "npm/types_entry_value_not_exists/main.out",
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"tests": {
|
||||
"bad_import": {
|
||||
"args": "run bad_import.ts",
|
||||
"output": "bad_import.out",
|
||||
"exitCode": 1
|
||||
},
|
||||
"good_import": {
|
||||
"args": "run good_import.ts",
|
||||
"output": "good_import.out"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
error: [ERR_MODULE_NOT_FOUND] Cannot find module 'file:///[WILDLINE]/node_modules/package/index.js' imported from 'file:///[WILDLINE]/bad_import.ts'
|
||||
at file:///[WILDLINE]/bad_import.ts:1:16
|
|
@ -0,0 +1,3 @@
|
|||
import hi from "package";
|
||||
|
||||
hi();
|
3
tests/specs/node/byonm_phantom_dep_res_failure/deno.json
Normal file
3
tests/specs/node/byonm_phantom_dep_res_failure/deno.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"unstable": ["byonm"]
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
hi
|
|
@ -0,0 +1,3 @@
|
|||
import hi from "package/main.js";
|
||||
|
||||
hi();
|
1
tests/specs/node/byonm_phantom_dep_res_failure/node_modules/package/main.js
generated
vendored
Normal file
1
tests/specs/node/byonm_phantom_dep_res_failure/node_modules/package/main.js
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
module.exports = () => console.log('hi');
|
4
tests/specs/node/byonm_phantom_dep_res_failure/node_modules/package/package.json
generated
vendored
Normal file
4
tests/specs/node/byonm_phantom_dep_res_failure/node_modules/package/package.json
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"name": "package",
|
||||
"version": "1.0.0"
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
{
|
||||
}
|
4
tests/specs/npm/esm_import_cjs_default/__test__.jsonc
Normal file
4
tests/specs/npm/esm_import_cjs_default/__test__.jsonc
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"args": "run --allow-read --allow-env --check=all main.ts",
|
||||
"output": "main.out"
|
||||
}
|
|
@ -1,3 +1,10 @@
|
|||
[UNORDERED_START]
|
||||
Download http://localhost:4260/@denotest/esm-import-cjs-default
|
||||
Download http://localhost:4260/@denotest/cjs-default-export
|
||||
Download http://localhost:4260/@denotest/cjs-default-export/1.0.0.tgz
|
||||
Download http://localhost:4260/@denotest/esm-import-cjs-default/1.0.0.tgz
|
||||
[UNORDERED_END]
|
||||
Check file:///[WILDLINE]/main.ts
|
||||
Node esm importing node cjs
|
||||
===========================
|
||||
{
|
4
tests/specs/npm/no_types_cjs/__test__.jsonc
Normal file
4
tests/specs/npm/no_types_cjs/__test__.jsonc
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"args": "check main.ts",
|
||||
"output": "main.out"
|
||||
}
|
3
tests/specs/npm/no_types_cjs/main.out
Normal file
3
tests/specs/npm/no_types_cjs/main.out
Normal file
|
@ -0,0 +1,3 @@
|
|||
Download http://localhost:4260/@denotest/no-types-cjs
|
||||
Download http://localhost:4260/@denotest/no-types-cjs/1.0.0.tgz
|
||||
Check file:///[WILDLINE]/no_types_cjs/main.ts
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"args": "run --check main.ts",
|
||||
"output": "main.out"
|
||||
}
|
5
tests/specs/npm/types_general/__test__.jsonc
Normal file
5
tests/specs/npm/types_general/__test__.jsonc
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"args": "check main.ts",
|
||||
"output": "main.out",
|
||||
"exitCode": 1
|
||||
}
|
|
@ -1,7 +1,16 @@
|
|||
[UNORDERED_START]
|
||||
Download http://localhost:4260/@denotest/types
|
||||
Download http://localhost:4260/@denotest/types_imported
|
||||
Download http://localhost:4260/@denotest/types-exports-subpaths
|
||||
Download http://localhost:4260/@denotest/types_imported/1.0.0.tgz
|
||||
Download http://localhost:4260/@denotest/types-exports-subpaths/1.0.0.tgz
|
||||
Download http://localhost:4260/@denotest/types/1.0.0.tgz
|
||||
[UNORDERED_END]
|
||||
Check file:///[WILDLINE]/main.ts
|
||||
error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
|
||||
bar: 1,
|
||||
~~~
|
||||
at [WILDCARD]/npm/types/main.ts:[WILDCARD]
|
||||
at [WILDCARD]/main.ts:[WILDCARD]
|
||||
|
||||
The expected type comes from property 'bar' which is declared here on type 'Foobar'
|
||||
bar: string;
|
||||
|
@ -11,7 +20,7 @@ error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
|
|||
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
|
||||
prop: 1,
|
||||
~~~~
|
||||
at [WILDCARD]/npm/types/main.ts:[WILDCARD]
|
||||
at [WILDCARD]/main.ts:[WILDCARD]
|
||||
|
||||
The expected type comes from property 'prop' which is declared here on type 'SomeInterface'
|
||||
prop: string;
|
||||
|
@ -21,7 +30,7 @@ TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
|
|||
TS2322 [ERROR]: Type 'string' is not assignable to type 'number'.
|
||||
prop2: "asdf",
|
||||
~~~~~
|
||||
at [WILDCARD]/npm/types/main.ts:[WILDCARD]
|
||||
at [WILDCARD]/main.ts:[WILDCARD]
|
||||
|
||||
The expected type comes from property 'prop2' which is declared here on type 'SomeInterface'
|
||||
prop2: number;
|
||||
|
@ -31,7 +40,7 @@ TS2322 [ERROR]: Type 'string' is not assignable to type 'number'.
|
|||
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
|
||||
fizz: 1,
|
||||
~~~~
|
||||
at [WILDCARD]/npm/types/main.ts:[WILDCARD]
|
||||
at [WILDCARD]/main.ts:[WILDCARD]
|
||||
|
||||
The expected type comes from property 'fizz' which is declared here on type 'Fizzbuzz'
|
||||
fizz: string;
|
||||
|
@ -41,7 +50,7 @@ TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
|
|||
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
|
||||
buzz: 2,
|
||||
~~~~
|
||||
at [WILDCARD]/npm/types/main.ts:[WILDCARD]
|
||||
at [WILDCARD]/main.ts:[WILDCARD]
|
||||
|
||||
The expected type comes from property 'buzz' which is declared here on type 'Fizzbuzz'
|
||||
buzz: string;
|
||||
|
@ -51,21 +60,21 @@ TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
|
|||
TS2322 [ERROR]: Type '5' is not assignable to type '"test1"'.
|
||||
const valueA: "test1" = getClient();
|
||||
~~~~~~
|
||||
at [WILDCARD]/npm/types/main.ts:[WILDCARD]
|
||||
at [WILDCARD]/main.ts:[WILDCARD]
|
||||
|
||||
TS2322 [ERROR]: Type '"import"' is not assignable to type '"test2"'.
|
||||
const valueB: "test2" = entryImport();
|
||||
~~~~~~
|
||||
at [WILDCARD]/types/main.ts:[WILDCARD]
|
||||
at [WILDCARD]/main.ts:[WILDCARD]
|
||||
|
||||
TS2322 [ERROR]: Type '12' is not assignable to type '"test3"'.
|
||||
const valueC: "test3" = entryA();
|
||||
~~~~~~
|
||||
at [WILDCARD]/types/main.ts:[WILDCARD]
|
||||
at [WILDCARD]/main.ts:[WILDCARD]
|
||||
|
||||
TS2322 [ERROR]: Type '"types"' is not assignable to type '"test4"'.
|
||||
const valueD: "test4" = entryTypes();
|
||||
~~~~~~
|
||||
at file:///[WILDCARD]/types/main.ts:[WILDCARD]
|
||||
at file:///[WILDCARD]/main.ts:[WILDCARD]
|
||||
|
||||
Found 9 errors.
|
|
@ -218,7 +218,7 @@ async function ensureNoNewITests() {
|
|||
"lsp_tests.rs": 0,
|
||||
"node_compat_tests.rs": 4,
|
||||
"node_unit_tests.rs": 2,
|
||||
"npm_tests.rs": 97,
|
||||
"npm_tests.rs": 93,
|
||||
"pm_tests.rs": 0,
|
||||
"publish_tests.rs": 0,
|
||||
"repl_tests.rs": 0,
|
||||
|
|
Loading…
Reference in a new issue