diff options
Diffstat (limited to 'resolvers/node')
-rw-r--r-- | resolvers/node/analyze.rs | 6 | ||||
-rw-r--r-- | resolvers/node/lib.rs | 5 | ||||
-rw-r--r-- | resolvers/node/npm.rs | 9 | ||||
-rw-r--r-- | resolvers/node/resolution.rs | 51 |
4 files changed, 58 insertions, 13 deletions
diff --git a/resolvers/node/analyze.rs b/resolvers/node/analyze.rs index c7415933d..912689080 100644 --- a/resolvers/node/analyze.rs +++ b/resolvers/node/analyze.rs @@ -23,7 +23,7 @@ use crate::npm::InNpmPackageCheckerRc; use crate::resolution::NodeResolverRc; use crate::NodeModuleKind; use crate::NodeResolutionMode; -use crate::NpmResolverRc; +use crate::NpmPackageFolderResolverRc; use crate::PackageJsonResolverRc; use crate::PathClean; @@ -66,7 +66,7 @@ pub struct NodeCodeTranslator< env: TNodeResolverEnv, in_npm_pkg_checker: InNpmPackageCheckerRc, node_resolver: NodeResolverRc<TNodeResolverEnv>, - npm_resolver: NpmResolverRc, + npm_resolver: NpmPackageFolderResolverRc, pkg_json_resolver: PackageJsonResolverRc<TNodeResolverEnv>, } @@ -78,7 +78,7 @@ impl<TCjsCodeAnalyzer: CjsCodeAnalyzer, TNodeResolverEnv: NodeResolverEnv> env: TNodeResolverEnv, in_npm_pkg_checker: InNpmPackageCheckerRc, node_resolver: NodeResolverRc<TNodeResolverEnv>, - npm_resolver: NpmResolverRc, + npm_resolver: NpmPackageFolderResolverRc, pkg_json_resolver: PackageJsonResolverRc<TNodeResolverEnv>, ) -> Self { Self { diff --git a/resolvers/node/lib.rs b/resolvers/node/lib.rs index 18b0a8536..87bd62994 100644 --- a/resolvers/node/lib.rs +++ b/resolvers/node/lib.rs @@ -15,13 +15,14 @@ mod sync; pub use deno_package_json::PackageJson; pub use npm::InNpmPackageChecker; pub use npm::InNpmPackageCheckerRc; -pub use npm::NpmResolver; -pub use npm::NpmResolverRc; +pub use npm::NpmPackageFolderResolver; +pub use npm::NpmPackageFolderResolverRc; pub use package_json::PackageJsonResolver; pub use package_json::PackageJsonResolverRc; pub use package_json::PackageJsonThreadLocalCache; pub use path::PathClean; pub use resolution::parse_npm_pkg_name; +pub use resolution::resolve_specifier_into_node_modules; pub use resolution::NodeModuleKind; pub use resolution::NodeResolution; pub use resolution::NodeResolutionMode; diff --git a/resolvers/node/npm.rs b/resolvers/node/npm.rs index 2132f0b54..ab3a17942 100644 --- a/resolvers/node/npm.rs +++ b/resolvers/node/npm.rs @@ -13,10 +13,13 @@ use crate::sync::MaybeSend; use crate::sync::MaybeSync; #[allow(clippy::disallowed_types)] -pub type NpmResolverRc = crate::sync::MaybeArc<dyn NpmResolver>; +pub type NpmPackageFolderResolverRc = + crate::sync::MaybeArc<dyn NpmPackageFolderResolver>; -pub trait NpmResolver: std::fmt::Debug + MaybeSend + MaybeSync { - /// Resolves an npm package folder path from an npm package referrer. +pub trait NpmPackageFolderResolver: + std::fmt::Debug + MaybeSend + MaybeSync +{ + /// Resolves an npm package folder path from the specified referrer. fn resolve_package_folder_from_package( &self, specifier: &str, diff --git a/resolvers/node/resolution.rs b/resolvers/node/resolution.rs index fcff29242..673a61abe 100644 --- a/resolvers/node/resolution.rs +++ b/resolvers/node/resolution.rs @@ -41,7 +41,7 @@ use crate::errors::TypesNotFoundErrorData; use crate::errors::UnsupportedDirImportError; use crate::errors::UnsupportedEsmUrlSchemeError; use crate::npm::InNpmPackageCheckerRc; -use crate::NpmResolverRc; +use crate::NpmPackageFolderResolverRc; use crate::PackageJsonResolverRc; use crate::PathClean; use deno_package_json::PackageJson; @@ -101,7 +101,7 @@ pub type NodeResolverRc<TEnv> = crate::sync::MaybeArc<NodeResolver<TEnv>>; pub struct NodeResolver<TEnv: NodeResolverEnv> { env: TEnv, in_npm_pkg_checker: InNpmPackageCheckerRc, - npm_resolver: NpmResolverRc, + npm_pkg_folder_resolver: NpmPackageFolderResolverRc, pkg_json_resolver: PackageJsonResolverRc<TEnv>, } @@ -109,13 +109,13 @@ impl<TEnv: NodeResolverEnv> NodeResolver<TEnv> { pub fn new( env: TEnv, in_npm_pkg_checker: InNpmPackageCheckerRc, - npm_resolver: NpmResolverRc, + npm_pkg_folder_resolver: NpmPackageFolderResolverRc, pkg_json_resolver: PackageJsonResolverRc<TEnv>, ) -> Self { Self { env, in_npm_pkg_checker, - npm_resolver, + npm_pkg_folder_resolver, pkg_json_resolver, } } @@ -1126,7 +1126,7 @@ impl<TEnv: NodeResolverEnv> NodeResolver<TEnv> { mode: NodeResolutionMode, ) -> Result<Url, PackageResolveError> { let package_dir_path = self - .npm_resolver + .npm_pkg_folder_resolver .resolve_package_folder_from_package(package_name, referrer)?; // todo: error with this instead when can't find package @@ -1412,6 +1412,25 @@ impl<TEnv: NodeResolverEnv> NodeResolver<TEnv> { ) } } + + /// Resolves a specifier that is pointing into a node_modules folder by canonicalizing it. + /// + /// Returns `None` when the specifier is not in a node_modules folder. + pub fn handle_if_in_node_modules(&self, specifier: &Url) -> Option<Url> { + // skip canonicalizing if we definitely know it's unnecessary + if specifier.scheme() == "file" + && specifier.path().contains("/node_modules/") + { + // Specifiers in the node_modules directory are canonicalized + // so canoncalize then check if it's in the node_modules directory. + let specifier = resolve_specifier_into_node_modules(specifier, &|path| { + self.env.realpath_sync(path) + }); + return Some(specifier); + } + + None + } } fn resolve_bin_entry_value<'a>( @@ -1660,6 +1679,28 @@ pub fn parse_npm_pkg_name( Ok((package_name, package_subpath, is_scoped)) } +/// Resolves a specifier that is pointing into a node_modules folder. +/// +/// Note: This should be called whenever getting the specifier from +/// a Module::External(module) reference because that module might +/// not be fully resolved at the time deno_graph is analyzing it +/// because the node_modules folder might not exist at that time. +pub fn resolve_specifier_into_node_modules( + specifier: &Url, + canonicalize: &impl Fn(&Path) -> std::io::Result<PathBuf>, +) -> Url { + deno_path_util::url_to_file_path(specifier) + .ok() + // this path might not exist at the time the graph is being created + // because the node_modules folder might not yet exist + .and_then(|path| { + deno_path_util::canonicalize_path_maybe_not_exists(&path, canonicalize) + .ok() + }) + .and_then(|path| deno_path_util::url_from_file_path(&path).ok()) + .unwrap_or_else(|| specifier.clone()) +} + fn pattern_key_compare(a: &str, b: &str) -> i32 { let a_pattern_index = a.find('*'); let b_pattern_index = b.find('*'); |