diff options
Diffstat (limited to 'cli')
-rw-r--r-- | cli/lsp/documents.rs | 66 | ||||
-rw-r--r-- | cli/lsp/language_server.rs | 42 | ||||
-rw-r--r-- | cli/lsp/tsc.rs | 2 | ||||
-rw-r--r-- | cli/module_loader.rs | 49 | ||||
-rw-r--r-- | cli/node/mod.rs | 523 | ||||
-rw-r--r-- | cli/npm/mod.rs | 1 | ||||
-rw-r--r-- | cli/npm/resolution.rs | 4 | ||||
-rw-r--r-- | cli/npm/resolvers/mod.rs | 10 | ||||
-rw-r--r-- | cli/ops/mod.rs | 16 | ||||
-rw-r--r-- | cli/proc_state.rs | 9 | ||||
-rw-r--r-- | cli/standalone.rs | 4 | ||||
-rw-r--r-- | cli/tools/check.rs | 8 | ||||
-rw-r--r-- | cli/tools/task.rs | 23 | ||||
-rw-r--r-- | cli/tools/vendor/mod.rs | 15 | ||||
-rw-r--r-- | cli/tsc/mod.rs | 93 | ||||
-rw-r--r-- | cli/worker.rs | 21 |
16 files changed, 459 insertions, 427 deletions
diff --git a/cli/lsp/documents.rs b/cli/lsp/documents.rs index c003a61c7..7b206406c 100644 --- a/cli/lsp/documents.rs +++ b/cli/lsp/documents.rs @@ -17,11 +17,9 @@ use crate::file_fetcher::get_source_from_bytes; use crate::file_fetcher::map_content_type; use crate::file_fetcher::SUPPORTED_SCHEMES; use crate::lsp::logging::lsp_warn; -use crate::node; -use crate::node::node_resolve_npm_reference; +use crate::node::CliNodeResolver; use crate::node::NodeResolution; use crate::npm::CliNpmRegistryApi; -use crate::npm::NpmPackageResolver; use crate::npm::NpmResolution; use crate::npm::PackageJsonDepsInstaller; use crate::resolver::CliGraphResolver; @@ -1057,7 +1055,7 @@ impl Documents { &self, specifiers: Vec<String>, referrer_doc: &AssetOrDocument, - maybe_npm_resolver: Option<&Arc<NpmPackageResolver>>, + maybe_node_resolver: Option<&Arc<CliNodeResolver>>, ) -> Vec<Option<(ModuleSpecifier, MediaType)>> { let referrer = referrer_doc.specifier(); let dependencies = match referrer_doc { @@ -1066,19 +1064,19 @@ impl Documents { }; let mut results = Vec::new(); for specifier in specifiers { - if let Some(npm_resolver) = maybe_npm_resolver { - if npm_resolver.in_npm_package(referrer) { + if let Some(node_resolver) = maybe_node_resolver { + if node_resolver.in_npm_package(referrer) { // we're in an npm package, so use node resolution results.push(Some(NodeResolution::into_specifier_and_media_type( - node::node_resolve( - &specifier, - referrer, - NodeResolutionMode::Types, - &npm_resolver.as_require_npm_resolver(), - &mut PermissionsContainer::allow_all(), - ) - .ok() - .flatten(), + node_resolver + .resolve( + &specifier, + referrer, + NodeResolutionMode::Types, + &mut PermissionsContainer::allow_all(), + ) + .ok() + .flatten(), ))); continue; } @@ -1106,9 +1104,9 @@ impl Documents { dependencies.as_ref().and_then(|d| d.deps.get(&specifier)) { if let Some(specifier) = dep.maybe_type.maybe_specifier() { - results.push(self.resolve_dependency(specifier, maybe_npm_resolver)); + results.push(self.resolve_dependency(specifier, maybe_node_resolver)); } else if let Some(specifier) = dep.maybe_code.maybe_specifier() { - results.push(self.resolve_dependency(specifier, maybe_npm_resolver)); + results.push(self.resolve_dependency(specifier, maybe_node_resolver)); } else { results.push(None); } @@ -1116,11 +1114,12 @@ impl Documents { .resolve_imports_dependency(&specifier) .and_then(|r| r.maybe_specifier()) { - results.push(self.resolve_dependency(specifier, maybe_npm_resolver)); + results.push(self.resolve_dependency(specifier, maybe_node_resolver)); } else if let Ok(npm_req_ref) = NpmPackageReqReference::from_str(&specifier) { - results.push(node_resolve_npm_req_ref(npm_req_ref, maybe_npm_resolver)); + results + .push(node_resolve_npm_req_ref(npm_req_ref, maybe_node_resolver)); } else { results.push(None); } @@ -1418,10 +1417,10 @@ impl Documents { fn resolve_dependency( &self, specifier: &ModuleSpecifier, - maybe_npm_resolver: Option<&Arc<NpmPackageResolver>>, + maybe_node_resolver: Option<&Arc<CliNodeResolver>>, ) -> Option<(ModuleSpecifier, MediaType)> { if let Ok(npm_ref) = NpmPackageReqReference::from_specifier(specifier) { - return node_resolve_npm_req_ref(npm_ref, maybe_npm_resolver); + return node_resolve_npm_req_ref(npm_ref, maybe_node_resolver); } let doc = self.get(specifier)?; let maybe_module = doc.maybe_esm_module().and_then(|r| r.as_ref().ok()); @@ -1430,7 +1429,7 @@ impl Documents { if let Some(specifier) = maybe_types_dependency.and_then(|d| d.maybe_specifier()) { - self.resolve_dependency(specifier, maybe_npm_resolver) + self.resolve_dependency(specifier, maybe_node_resolver) } else { let media_type = doc.media_type(); Some((specifier.clone(), media_type)) @@ -1453,23 +1452,18 @@ impl Documents { fn node_resolve_npm_req_ref( npm_req_ref: NpmPackageReqReference, - maybe_npm_resolver: Option<&Arc<NpmPackageResolver>>, + maybe_node_resolver: Option<&Arc<CliNodeResolver>>, ) -> Option<(ModuleSpecifier, MediaType)> { - maybe_npm_resolver.map(|npm_resolver| { + maybe_node_resolver.map(|node_resolver| { NodeResolution::into_specifier_and_media_type( - npm_resolver - .pkg_req_ref_to_nv_ref(npm_req_ref) + node_resolver + .resolve_npm_req_reference( + &npm_req_ref, + NodeResolutionMode::Types, + &mut PermissionsContainer::allow_all(), + ) .ok() - .and_then(|pkg_id_ref| { - node_resolve_npm_reference( - &pkg_id_ref, - NodeResolutionMode::Types, - npm_resolver, - &mut PermissionsContainer::allow_all(), - ) - .ok() - .flatten() - }), + .flatten(), ) }) } diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index 3f395f410..239ff8a6e 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -78,6 +78,7 @@ use crate::file_fetcher::FileFetcher; use crate::graph_util; use crate::http_util::HttpClient; use crate::lsp::urls::LspUrlKind; +use crate::node::CliNodeResolver; use crate::npm::create_npm_fs_resolver; use crate::npm::CliNpmRegistryApi; use crate::npm::NpmCache; @@ -101,6 +102,7 @@ pub struct StateSnapshot { pub cache_metadata: cache::CacheMetadata, pub documents: Documents, pub maybe_import_map: Option<Arc<ImportMap>>, + pub maybe_node_resolver: Option<Arc<CliNodeResolver>>, pub maybe_npm_resolver: Option<Arc<NpmPackageResolver>>, } @@ -695,30 +697,32 @@ impl Inner { } pub fn snapshot(&self) -> Arc<StateSnapshot> { + // create a new snapshotted npm resolution and resolver + let npm_resolution = Arc::new(NpmResolution::new( + self.npm_api.clone(), + self.npm_resolution.snapshot(), + None, + )); + let npm_resolver = Arc::new(NpmPackageResolver::new( + npm_resolution.clone(), + create_npm_fs_resolver( + self.npm_cache.clone(), + &ProgressBar::new(ProgressBarStyle::TextOnly), + self.npm_api.base_url().clone(), + npm_resolution.clone(), + None, + ), + None, + )); + let node_resolver = + Arc::new(CliNodeResolver::new(npm_resolution, npm_resolver.clone())); Arc::new(StateSnapshot { assets: self.assets.snapshot(), cache_metadata: self.cache_metadata.clone(), documents: self.documents.clone(), maybe_import_map: self.maybe_import_map.clone(), - maybe_npm_resolver: Some({ - // create a new snapshotted npm resolution and resolver - let resolution = Arc::new(NpmResolution::new( - self.npm_api.clone(), - self.npm_resolution.snapshot(), - None, - )); - Arc::new(NpmPackageResolver::new( - resolution.clone(), - create_npm_fs_resolver( - self.npm_cache.clone(), - &ProgressBar::new(ProgressBarStyle::TextOnly), - self.npm_api.base_url().clone(), - resolution, - None, - ), - None, - )) - }), + maybe_node_resolver: Some(node_resolver), + maybe_npm_resolver: Some(npm_resolver), }) } diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs index eba3c5b3e..c6035192c 100644 --- a/cli/lsp/tsc.rs +++ b/cli/lsp/tsc.rs @@ -2763,7 +2763,7 @@ fn op_resolve( let resolved = state.state_snapshot.documents.resolve( args.specifiers, &referrer_doc, - state.state_snapshot.maybe_npm_resolver.as_ref(), + state.state_snapshot.maybe_node_resolver.as_ref(), ); Ok( resolved diff --git a/cli/module_loader.rs b/cli/module_loader.rs index e681821cd..06755bbf5 100644 --- a/cli/module_loader.rs +++ b/cli/module_loader.rs @@ -11,10 +11,9 @@ use crate::graph_util::graph_valid_with_cli_options; use crate::graph_util::ModuleGraphBuilder; use crate::graph_util::ModuleGraphContainer; use crate::node; +use crate::node::CliNodeResolver; use crate::node::NodeCodeTranslator; use crate::node::NodeResolution; -use crate::npm::NpmPackageResolver; -use crate::npm::NpmResolution; use crate::proc_state::CjsResolutionStore; use crate::proc_state::FileWatcherReporter; use crate::proc_state::ProcState; @@ -243,8 +242,7 @@ pub struct CliModuleLoader { graph_container: Arc<ModuleGraphContainer>, module_load_preparer: Arc<ModuleLoadPreparer>, node_code_translator: Arc<NodeCodeTranslator>, - npm_resolution: Arc<NpmResolution>, - npm_resolver: Arc<NpmPackageResolver>, + node_resolver: Arc<CliNodeResolver>, parsed_source_cache: Arc<ParsedSourceCache>, resolver: Arc<CliGraphResolver>, } @@ -265,8 +263,7 @@ impl CliModuleLoader { graph_container: ps.graph_container.clone(), module_load_preparer: ps.module_load_preparer.clone(), node_code_translator: ps.node_code_translator.clone(), - npm_resolution: ps.npm_resolution.clone(), - npm_resolver: ps.npm_resolver.clone(), + node_resolver: ps.node_resolver.clone(), parsed_source_cache: ps.parsed_source_cache.clone(), resolver: ps.resolver.clone(), }) @@ -287,8 +284,7 @@ impl CliModuleLoader { graph_container: ps.graph_container.clone(), module_load_preparer: ps.module_load_preparer.clone(), node_code_translator: ps.node_code_translator.clone(), - npm_resolution: ps.npm_resolution.clone(), - npm_resolver: ps.npm_resolver.clone(), + node_resolver: ps.node_resolver.clone(), parsed_source_cache: ps.parsed_source_cache.clone(), resolver: ps.resolver.clone(), }) @@ -370,7 +366,7 @@ impl CliModuleLoader { maybe_referrer: Option<&ModuleSpecifier>, is_dynamic: bool, ) -> Result<ModuleSource, AnyError> { - let code_source = if self.npm_resolver.in_npm_package(specifier) { + let code_source = if self.node_resolver.in_npm_package(specifier) { let file_path = specifier.to_file_path().unwrap(); let code = std::fs::read_to_string(&file_path).with_context(|| { let mut msg = "Unable to load ".to_string(); @@ -466,14 +462,13 @@ impl ModuleLoader for CliModuleLoader { let referrer_result = deno_core::resolve_url_or_path(referrer, &cwd); if let Ok(referrer) = referrer_result.as_ref() { - if self.npm_resolver.in_npm_package(referrer) { + if self.node_resolver.in_npm_package(referrer) { // we're in an npm package, so use node resolution return self - .handle_node_resolve_result(node::node_resolve( + .handle_node_resolve_result(self.node_resolver.resolve( specifier, referrer, NodeResolutionMode::Execution, - &self.npm_resolver.as_require_npm_resolver(), &mut permissions, )) .with_context(|| { @@ -495,12 +490,13 @@ impl ModuleLoader for CliModuleLoader { return match graph.get(specifier) { Some(Module::Npm(module)) => self - .handle_node_resolve_result(node::node_resolve_npm_reference( - &module.nv_reference, - NodeResolutionMode::Execution, - &self.npm_resolver, - &mut permissions, - )) + .handle_node_resolve_result( + self.node_resolver.resolve_npm_reference( + &module.nv_reference, + NodeResolutionMode::Execution, + &mut permissions, + ), + ) .with_context(|| { format!("Could not resolve '{}'.", module.nv_reference) }), @@ -555,15 +551,14 @@ impl ModuleLoader for CliModuleLoader { if let Ok(reference) = NpmPackageReqReference::from_specifier(&specifier) { - let reference = - self.npm_resolution.pkg_req_ref_to_nv_ref(reference)?; return self - .handle_node_resolve_result(node::node_resolve_npm_reference( - &reference, - deno_runtime::deno_node::NodeResolutionMode::Execution, - &self.npm_resolver, - &mut permissions, - )) + .handle_node_resolve_result( + self.node_resolver.resolve_npm_req_reference( + &reference, + deno_runtime::deno_node::NodeResolutionMode::Execution, + &mut permissions, + ), + ) .with_context(|| format!("Could not resolve '{reference}'.")); } } @@ -595,7 +590,7 @@ impl ModuleLoader for CliModuleLoader { _maybe_referrer: Option<String>, is_dynamic: bool, ) -> Pin<Box<dyn Future<Output = Result<(), AnyError>>>> { - if self.npm_resolver.in_npm_package(specifier) { + if self.node_resolver.in_npm_package(specifier) { // nothing to prepare return Box::pin(deno_core::futures::future::ready(Ok(()))); } diff --git a/cli/node/mod.rs b/cli/node/mod.rs index 99df672fc..01216f50c 100644 --- a/cli/node/mod.rs +++ b/cli/node/mod.rs @@ -31,8 +31,11 @@ use deno_runtime::deno_node::DEFAULT_CONDITIONS; use deno_runtime::permissions::PermissionsContainer; use deno_semver::npm::NpmPackageNv; use deno_semver::npm::NpmPackageNvReference; +use deno_semver::npm::NpmPackageReqReference; use crate::npm::NpmPackageResolver; +use crate::npm::NpmResolution; +use crate::npm::RequireNpmPackageResolver; use crate::util::fs::canonicalize_path_maybe_not_exists; mod analyze; @@ -109,127 +112,305 @@ pub fn resolve_builtin_node_module(module_name: &str) -> Result<Url, AnyError> { ))) } -/// This function is an implementation of `defaultResolve` in -/// `lib/internal/modules/esm/resolve.js` from Node. -pub fn node_resolve( - specifier: &str, - referrer: &ModuleSpecifier, - mode: NodeResolutionMode, - npm_resolver: &dyn RequireNpmResolver, - permissions: &mut dyn NodePermissions, -) -> Result<Option<NodeResolution>, AnyError> { - // 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 +#[derive(Debug)] +pub struct CliNodeResolver { + npm_resolution: Arc<NpmResolution>, + npm_resolver: Arc<NpmPackageResolver>, + require_npm_resolver: RequireNpmPackageResolver, +} + +impl CliNodeResolver { + pub fn new( + npm_resolution: Arc<NpmResolution>, + npm_package_resolver: Arc<NpmPackageResolver>, + ) -> Self { + Self { + npm_resolution, + require_npm_resolver: npm_package_resolver.as_require_npm_resolver(), + npm_resolver: npm_package_resolver, + } + } - if deno_node::is_builtin_node_module(specifier) { - return Ok(Some(NodeResolution::BuiltIn(specifier.to_string()))); + pub fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool { + self.npm_resolver.in_npm_package(specifier) } - if let Ok(url) = Url::parse(specifier) { - if url.scheme() == "data" { - return Ok(Some(NodeResolution::Esm(url))); + /// This function is an implementation of `defaultResolve` in + /// `lib/internal/modules/esm/resolve.js` from Node. + pub fn resolve( + &self, + specifier: &str, + referrer: &ModuleSpecifier, + mode: NodeResolutionMode, + permissions: &mut dyn NodePermissions, + ) -> Result<Option<NodeResolution>, AnyError> { + // 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 deno_node::is_builtin_node_module(specifier) { + return Ok(Some(NodeResolution::BuiltIn(specifier.to_string()))); } - let protocol = url.scheme(); + if let Ok(url) = Url::parse(specifier) { + if url.scheme() == "data" { + return Ok(Some(NodeResolution::Esm(url))); + } + + let protocol = url.scheme(); - if protocol == "node" { - let split_specifier = url.as_str().split(':'); - let specifier = split_specifier.skip(1).collect::<String>(); + if protocol == "node" { + let split_specifier = url.as_str().split(':'); + let specifier = split_specifier.skip(1).collect::<String>(); - if deno_node::is_builtin_node_module(&specifier) { - return Ok(Some(NodeResolution::BuiltIn(specifier))); + if deno_node::is_builtin_node_module(&specifier) { + return Ok(Some(NodeResolution::BuiltIn(specifier))); + } } - } - if protocol != "file" && protocol != "data" { - return Err(errors::err_unsupported_esm_url_scheme(&url)); - } + if protocol != "file" && protocol != "data" { + return Err(errors::err_unsupported_esm_url_scheme(&url)); + } - // todo(dsherret): this seems wrong - if referrer.scheme() == "data" { - let url = referrer.join(specifier).map_err(AnyError::from)?; - return Ok(Some(NodeResolution::Esm(url))); + // todo(dsherret): this seems wrong + if referrer.scheme() == "data" { + let url = referrer.join(specifier).map_err(AnyError::from)?; + return Ok(Some(NodeResolution::Esm(url))); + } } + + let url = self.module_resolve( + specifier, + referrer, + DEFAULT_CONDITIONS, + mode, + permissions, + )?; + let url = match url { + Some(url) => url, + None => return Ok(None), + }; + let url = match mode { + NodeResolutionMode::Execution => url, + NodeResolutionMode::Types => { + let path = url.to_file_path().unwrap(); + // todo(16370): the module kind is not correct here. I think we need + // typescript to tell us if the referrer is esm or cjs + let path = + match path_to_declaration_path::<RealFs>(path, NodeModuleKind::Esm) { + Some(path) => path, + None => return Ok(None), + }; + ModuleSpecifier::from_file_path(path).unwrap() + } + }; + + 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)) } - let url = module_resolve( - specifier, - referrer, - DEFAULT_CONDITIONS, - mode, - npm_resolver, - permissions, - )?; - let url = match url { - Some(url) => url, - None => return Ok(None), - }; - let url = match mode { - NodeResolutionMode::Execution => url, - NodeResolutionMode::Types => { - let path = url.to_file_path().unwrap(); - // todo(16370): the module kind is not correct here. I think we need - // typescript to tell us if the referrer is esm or cjs - let path = - match path_to_declaration_path::<RealFs>(path, NodeModuleKind::Esm) { + fn module_resolve( + &self, + specifier: &str, + referrer: &ModuleSpecifier, + conditions: &[&str], + mode: NodeResolutionMode, + permissions: &mut dyn NodePermissions, + ) -> Result<Option<ModuleSpecifier>, AnyError> { + // note: if we're here, the referrer is an esm module + let url = if should_be_treated_as_relative_or_absolute_path(specifier) { + let resolved_specifier = referrer.join(specifier)?; + if mode.is_types() { + let file_path = to_file_path(&resolved_specifier); + // todo(dsherret): the node module kind is not correct and we + // should use the value provided by typescript instead + let declaration_path = + path_to_declaration_path::<RealFs>(file_path, NodeModuleKind::Esm); + declaration_path.map(|declaration_path| { + ModuleSpecifier::from_file_path(declaration_path).unwrap() + }) + } else { + Some(resolved_specifier) + } + } else if specifier.starts_with('#') { + Some( + package_imports_resolve::<RealFs>( + specifier, + referrer, + NodeModuleKind::Esm, + conditions, + mode, + &self.require_npm_resolver, + permissions, + ) + .map(|p| ModuleSpecifier::from_file_path(p).unwrap())?, + ) + } else if let Ok(resolved) = Url::parse(specifier) { + Some(resolved) + } else { + package_resolve::<RealFs>( + specifier, + referrer, + NodeModuleKind::Esm, + conditions, + mode, + &self.require_npm_resolver, + permissions, + )? + .map(|p| ModuleSpecifier::from_file_path(p).unwrap()) + }; + Ok(match url { + Some(url) => Some(finalize_resolution(url, referrer)?), + None => None, + }) + } + + pub fn resolve_npm_req_reference( + &self, + reference: &NpmPackageReqReference, + mode: NodeResolutionMode, + permissions: &mut dyn NodePermissions, + ) -> Result<Option<NodeResolution>, AnyError> { + let reference = self.npm_resolution.pkg_req_ref_to_nv_ref(reference)?; + self.resolve_npm_reference(&reference, mode, permissions) + } + + pub fn resolve_npm_reference( + &self, + reference: &NpmPackageNvReference, + mode: NodeResolutionMode, + permissions: &mut dyn NodePermissions, + ) -> Result<Option<NodeResolution>, AnyError> { + let package_folder = self + .npm_resolver + .resolve_package_folder_from_deno_module(&reference.nv)?; + let node_module_kind = NodeModuleKind::Esm; + let maybe_resolved_path = package_config_resolve( + &reference + .sub_path + .as_ref() + .map(|s| format!("./{s}")) + .unwrap_or_else(|| ".".to_string()), + &package_folder, + node_module_kind, + DEFAULT_CONDITIONS, + mode, + &self.require_npm_resolver, + permissions, + ) + .with_context(|| { + format!("Error resolving package config for '{reference}'") + })?; + let resolved_path = match maybe_resolved_path { + Some(resolved_path) => resolved_path, + None => return Ok(None), + }; + let resolved_path = match mode { + NodeResolutionMode::Execution => resolved_path, + NodeResolutionMode::Types => { + match path_to_declaration_path::<RealFs>( + resolved_path, + node_module_kind, + ) { Some(path) => path, None => return Ok(None), - }; - ModuleSpecifier::from_file_path(path).unwrap() - } - }; + } + } + }; + let url = ModuleSpecifier::from_file_path(resolved_path).unwrap(); + 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)) + } - let resolve_response = url_to_node_resolution(url, npm_resolver)?; - // TODO(bartlomieju): skipped checking errors for commonJS resolution and - // "preserveSymlinksMain"/"preserveSymlinks" options. - Ok(Some(resolve_response)) -} + pub fn resolve_binary_commands( + &self, + pkg_nv: &NpmPackageNv, + ) -> Result<Vec<String>, AnyError> { + let package_folder = self + .npm_resolver + .resolve_package_folder_from_deno_module(pkg_nv)?; + let package_json_path = package_folder.join("package.json"); + let package_json = PackageJson::load::<RealFs>( + &self.require_npm_resolver, + &mut PermissionsContainer::allow_all(), + package_json_path, + )?; -pub fn node_resolve_npm_reference( - reference: &NpmPackageNvReference, - mode: NodeResolutionMode, - npm_resolver: &Arc<NpmPackageResolver>, - permissions: &mut dyn NodePermissions, -) -> Result<Option<NodeResolution>, AnyError> { - let package_folder = - npm_resolver.resolve_package_folder_from_deno_module(&reference.nv)?; - let node_module_kind = NodeModuleKind::Esm; - let maybe_resolved_path = package_config_resolve( - &reference - .sub_path - .as_ref() - .map(|s| format!("./{s}")) - .unwrap_or_else(|| ".".to_string()), - &package_folder, - node_module_kind, - DEFAULT_CONDITIONS, - mode, - &npm_resolver.as_require_npm_resolver(), - permissions, - ) - .with_context(|| { - format!("Error resolving package config for '{reference}'") - })?; - let resolved_path = match maybe_resolved_path { - Some(resolved_path) => resolved_path, - None => return Ok(None), - }; - let resolved_path = match mode { - NodeResolutionMode::Execution => resolved_path, - NodeResolutionMode::Types => { - match path_to_declaration_path::<RealFs>(resolved_path, node_module_kind) - { - Some(path) => path, - None => return Ok(None), + Ok(match package_json.bin { + Some(Value::String(_)) => vec![pkg_nv.name.to_string()], + Some(Value::Object(o)) => { + o.into_iter().map(|(key, _)| key).collect::<Vec<_>>() } + _ => Vec::new(), + }) + } + + pub fn resolve_binary_export( + &self, + pkg_ref: &NpmPackageReqReference, + ) -> Result<NodeResolution, AnyError> { + let pkg_nv = self + .npm_resolution + .resolve_pkg_id_from_pkg_req(&pkg_ref.req)? + .nv; + let bin_name = pkg_ref.sub_path.as_deref(); + let package_folder = self + .npm_resolver + .resolve_package_folder_from_deno_module(&pkg_nv)?; + let package_json_path = package_folder.join("package.json"); + let package_json = PackageJson::load::<RealFs>( + &self.require_npm_resolver, + &mut PermissionsContainer::allow_all(), + package_json_path, + )?; + let bin = match &package_json.bin { + Some(bin) => bin, + None => bail!( + "package '{}' did not have a bin property in its package.json", + &pkg_nv.name, + ), + }; + let bin_entry = resolve_bin_entry_value(&pkg_nv, bin_name, bin)?; + let url = + ModuleSpecifier::from_file_path(package_folder.join(bin_entry)).unwrap(); + + let resolve_response = self.url_to_node_resolution(url)?; + // TODO(bartlomieju): skipped checking errors for commonJS resolution and + // "preserveSymlinksMain"/"preserveSymlinks" options. + Ok(resolve_response) + } + + pub fn url_to_node_resolution( + &self, + url: ModuleSpecifier, + ) -> Result<NodeResolution, AnyError> { + let url_str = url.as_str().to_lowercase(); + if url_str.starts_with("http") { + Ok(NodeResolution::Esm(url)) + } else if url_str.ends_with(".js") || url_str.ends_with(".d.ts") { + let package_config = get_closest_package_json::<RealFs>( + &url, + &self.require_npm_resolver, + &mut PermissionsContainer::allow_all(), + )?; + if package_config.typ == "module" { + Ok(NodeResolution::Esm(url)) + } else { + Ok(NodeResolution::CommonJs(url)) + } + } else if url_str.ends_with(".mjs") || url_str.ends_with(".d.mts") { + Ok(NodeResolution::Esm(url)) + } else if url_str.ends_with(".ts") { + Err(generic_error(format!( + "TypeScript files are not supported in npm packages: {url}" + ))) + } else { + Ok(NodeResolution::CommonJs(url)) } - }; - let url = ModuleSpecifier::from_file_path(resolved_path).unwrap(); - let resolve_response = - url_to_node_resolution(url, &npm_resolver.as_require_npm_resolver())?; - // TODO(bartlomieju): skipped checking errors for commonJS resolution and - // "preserveSymlinksMain"/"preserveSymlinks" options. - Ok(Some(resolve_response)) + } } /// Resolves a specifier that is pointing into a node_modules folder. @@ -251,59 +432,6 @@ pub fn resolve_specifier_into_node_modules( .unwrap_or_else(|| specifier.clone()) } -pub fn node_resolve_binary_commands( - pkg_nv: &NpmPackageNv, - npm_resolver: &Arc<NpmPackageResolver>, -) -> Result<Vec<String>, AnyError> { - let package_folder = - npm_resolver.resolve_package_folder_from_deno_module(pkg_nv)?; - let package_json_path = package_folder.join("package.json"); - let package_json = PackageJson::load::<RealFs>( - &npm_resolver.as_require_npm_resolver(), - &mut PermissionsContainer::allow_all(), - package_json_path, - )?; - - Ok(match package_json.bin { - Some(Value::String(_)) => vec![pkg_nv.name.to_string()], - Some(Value::Object(o)) => { - o.into_iter().map(|(key, _)| key).collect::<Vec<_>>() - } - _ => Vec::new(), - }) -} - -pub fn node_resolve_binary_export( - pkg_nv: &NpmPackageNv, - bin_name: Option<&str>, - npm_resolver: &Arc<NpmPackageResolver>, -) -> Result<NodeResolution, AnyError> { - let package_folder = - npm_resolver.resolve_package_folder_from_deno_module(pkg_nv)?; - let package_json_path = package_folder.join("package.json"); - let package_json = PackageJson::load::<RealFs>( - &npm_resolver.as_require_npm_resolver(), - &mut PermissionsContainer::allow_all(), - package_json_path, - )?; - let bin = match &package_json.bin { - Some(bin) => bin, - None => bail!( - "package '{}' did not have a bin property in its package.json", - &pkg_nv.name, - ), - }; - let bin_entry = resolve_bin_entry_value(pkg_nv, bin_name, bin)?; - let url = - ModuleSpecifier::from_file_path(package_folder.join(bin_entry)).unwrap(); - - let resolve_response = - url_to_node_resolution(url, &npm_resolver.as_require_npm_resolver())?; - // TODO(bartlomieju): skipped checking errors for commonJS resolution and - // "preserveSymlinksMain"/"preserveSymlinks" options. - Ok(resolve_response) -} - fn resolve_bin_entry_value<'a>( pkg_nv: &NpmPackageNv, bin_name: Option<&str>, @@ -411,35 +539,6 @@ fn package_config_resolve( Ok(Some(package_dir.join(package_subpath))) } -pub fn url_to_node_resolution( - url: ModuleSpecifier, - npm_resolver: &dyn RequireNpmResolver, -) -> Result<NodeResolution, AnyError> { - let url_str = url.as_str().to_lowercase(); - if url_str.starts_with("http") { - Ok(NodeResolution::Esm(url)) - } else if url_str.ends_with(".js") || url_str.ends_with(".d.ts") { - let package_config = get_closest_package_json::<RealFs>( - &url, - npm_resolver, - &mut PermissionsContainer::allow_all(), - )?; - if package_config.typ == "module" { - Ok(NodeResolution::Esm(url)) - } else { - Ok(NodeResolution::CommonJs(url)) - } - } else if url_str.ends_with(".mjs") || url_str.ends_with(".d.mts") { - Ok(NodeResolution::Esm(url)) - } else if url_str.ends_with(".ts") { - Err(generic_error(format!( - "TypeScript files are not supported in npm packages: {url}" - ))) - } else { - Ok(NodeResolution::CommonJs(url)) - } -} - fn finalize_resolution( resolved: ModuleSpecifier, base: &ModuleSpecifier, @@ -489,62 +588,6 @@ fn finalize_resolution( Ok(resolved) } -fn module_resolve( - specifier: &str, - referrer: &ModuleSpecifier, - conditions: &[&str], - mode: NodeResolutionMode, - npm_resolver: &dyn RequireNpmResolver, - permissions: &mut dyn NodePermissions, -) -> Result<Option<ModuleSpecifier>, AnyError> { - // note: if we're here, the referrer is an esm module - let url = if should_be_treated_as_relative_or_absolute_path(specifier) { - let resolved_specifier = referrer.join(specifier)?; - if mode.is_types() { - let file_path = to_file_path(&resolved_specifier); - // todo(dsherret): the node module kind is not correct and we - // should use the value provided by typescript instead - let declaration_path = - path_to_declaration_path::<RealFs>(file_path, NodeModuleKind::Esm); - declaration_path.map(|declaration_path| { - ModuleSpecifier::from_file_path(declaration_path).unwrap() - }) - } else { - Some(resolved_specifier) - } - } else if specifier.starts_with('#') { - Some( - package_imports_resolve::<RealFs>( - specifier, - referrer, - NodeModuleKind::Esm, - conditions, - mode, - npm_resolver, - permissions, - ) - .map(|p| ModuleSpecifier::from_file_path(p).unwrap())?, - ) - } else if let Ok(resolved) = Url::parse(specifier) { - Some(resolved) - } else { - package_resolve::<RealFs>( - specifier, - referrer, - NodeModuleKind::Esm, - conditions, - mode, - npm_resolver, - permissions, - )? - .map(|p| ModuleSpecifier::from_file_path(p).unwrap()) - }; - Ok(match url { - Some(url) => Some(finalize_resolution(url, referrer)?), - None => None, - }) -} - fn to_file_path(url: &ModuleSpecifier) -> PathBuf { url .to_file_path() diff --git a/cli/npm/mod.rs b/cli/npm/mod.rs index 8433a8f0c..8a38ee079 100644 --- a/cli/npm/mod.rs +++ b/cli/npm/mod.rs @@ -15,3 +15,4 @@ pub use resolution::NpmResolution; pub use resolvers::create_npm_fs_resolver; pub use resolvers::NpmPackageResolver; pub use resolvers::NpmProcessState; +pub use resolvers::RequireNpmPackageResolver; diff --git a/cli/npm/resolution.rs b/cli/npm/resolution.rs index 375191b2d..26fc356ff 100644 --- a/cli/npm/resolution.rs +++ b/cli/npm/resolution.rs @@ -156,12 +156,12 @@ impl NpmResolution { pub fn pkg_req_ref_to_nv_ref( &self, - req_ref: NpmPackageReqReference, + req_ref: &NpmPackageReqReference, ) -> Result<NpmPackageNvReference, PackageReqNotFoundError> { let node_id = self.resolve_pkg_id_from_pkg_req(&req_ref.req)?; Ok(NpmPackageNvReference { nv: node_id.nv, - sub_path: req_ref.sub_path, + sub_path: req_ref.sub_path.clone(), }) } diff --git a/cli/npm/resolvers/mod.rs b/cli/npm/resolvers/mod.rs index c8b841b54..5d3eb52b0 100644 --- a/cli/npm/resolvers/mod.rs +++ b/cli/npm/resolvers/mod.rs @@ -23,9 +23,7 @@ use deno_runtime::deno_node::NodeResolutionMode; use deno_runtime::deno_node::PathClean; use deno_runtime::deno_node::RequireNpmResolver; use deno_semver::npm::NpmPackageNv; -use deno_semver::npm::NpmPackageNvReference; use deno_semver::npm::NpmPackageReq; -use deno_semver::npm::NpmPackageReqReference; use global::GlobalNpmPackageResolver; use serde::Deserialize; use serde::Serialize; @@ -87,13 +85,6 @@ impl NpmPackageResolver { self.resolution.resolve_pkg_id_from_pkg_req(req) } - pub fn pkg_req_ref_to_nv_ref( - &self, - req_ref: NpmPackageReqReference, - ) -> Result<NpmPackageNvReference, PackageReqNotFoundError> { - self.resolution.pkg_req_ref_to_nv_ref(req_ref) - } - /// Resolves an npm package folder path from a Deno module. pub fn resolve_package_folder_from_deno_module( &self, @@ -245,6 +236,7 @@ impl NpmPackageResolver { } } +#[derive(Debug)] pub struct RequireNpmPackageResolver(Arc<NpmPackageResolver>); impl RequireNpmResolver for RequireNpmPackageResolver { diff --git a/cli/ops/mod.rs b/cli/ops/mod.rs index 4d5595e09..9adc944ce 100644 --- a/cli/ops/mod.rs +++ b/cli/ops/mod.rs @@ -1,6 +1,8 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. -use crate::proc_state::ProcState; +use std::sync::Arc; + +use crate::npm::NpmPackageResolver; use deno_core::error::AnyError; use deno_core::op; use deno_core::Extension; @@ -9,17 +11,17 @@ use deno_core::OpState; pub mod bench; pub mod testing; -pub fn cli_exts(ps: ProcState) -> Vec<Extension> { - vec![deno_cli::init_ops(ps)] +pub fn cli_exts(npm_resolver: Arc<NpmPackageResolver>) -> Vec<Extension> { + vec![deno_cli::init_ops(npm_resolver)] } deno_core::extension!(deno_cli, ops = [op_npm_process_state], options = { - ps: ProcState, + npm_resolver: Arc<NpmPackageResolver>, }, state = |state, options| { - state.put(options.ps); + state.put(options.npm_resolver); }, customizer = |ext: &mut deno_core::ExtensionBuilder| { ext.force_op_registration(); @@ -28,6 +30,6 @@ deno_core::extension!(deno_cli, #[op] fn op_npm_process_state(state: &mut OpState) -> Result<String, AnyError> { - let proc_state = state.borrow_mut::<ProcState>(); - Ok(proc_state.npm_resolver.get_npm_process_state()) + let npm_resolver = state.borrow_mut::<Arc<NpmPackageResolver>>(); + Ok(npm_resolver.get_npm_process_state()) } diff --git a/cli/proc_state.rs b/cli/proc_state.rs index 728363bc2..75466e5fe 100644 --- a/cli/proc_state.rs +++ b/cli/proc_state.rs @@ -17,6 +17,7 @@ use crate::graph_util::ModuleGraphBuilder; use crate::graph_util::ModuleGraphContainer; use crate::http_util::HttpClient; use crate::module_loader::ModuleLoadPreparer; +use crate::node::CliNodeResolver; use crate::node::NodeCodeTranslator; use crate::npm::create_npm_fs_resolver; use crate::npm::CliNpmRegistryApi; @@ -75,6 +76,7 @@ pub struct Inner { pub module_graph_builder: Arc<ModuleGraphBuilder>, pub module_load_preparer: Arc<ModuleLoadPreparer>, pub node_code_translator: Arc<NodeCodeTranslator>, + pub node_resolver: Arc<CliNodeResolver>, pub npm_api: Arc<CliNpmRegistryApi>, pub npm_cache: Arc<NpmCache>, pub npm_resolver: Arc<NpmPackageResolver>, @@ -145,6 +147,7 @@ impl ProcState { module_graph_builder: self.module_graph_builder.clone(), module_load_preparer: self.module_load_preparer.clone(), node_code_translator: self.node_code_translator.clone(), + node_resolver: self.node_resolver.clone(), npm_api: self.npm_api.clone(), npm_cache: self.npm_cache.clone(), npm_resolver: self.npm_resolver.clone(), @@ -306,10 +309,15 @@ impl ProcState { file_fetcher.clone(), npm_resolver.clone(), )); + let node_resolver = Arc::new(CliNodeResolver::new( + npm_resolution.clone(), + npm_resolver.clone(), + )); let type_checker = Arc::new(TypeChecker::new( dir.clone(), caches.clone(), cli_options.clone(), + node_resolver.clone(), npm_resolver.clone(), )); let module_graph_builder = Arc::new(ModuleGraphBuilder::new( @@ -357,6 +365,7 @@ impl ProcState { maybe_file_watcher_reporter, module_graph_builder, node_code_translator, + node_resolver, npm_api, npm_cache, npm_resolver, diff --git a/cli/standalone.rs b/cli/standalone.rs index 3ef0ad132..48d71a045 100644 --- a/cli/standalone.rs +++ b/cli/standalone.rs @@ -265,7 +265,7 @@ fn create_web_worker_callback( user_agent: version::get_user_agent().to_string(), inspect: ps.options.is_inspecting(), }, - extensions: ops::cli_exts(ps.clone()), + extensions: ops::cli_exts(ps.npm_resolver.clone()), startup_snapshot: Some(crate::js::deno_isolate_init()), unsafely_ignore_certificate_errors: ps .options @@ -354,7 +354,7 @@ pub async fn run( user_agent: version::get_user_agent().to_string(), inspect: ps.options.is_inspecting(), }, - extensions: ops::cli_exts(ps.clone()), + extensions: ops::cli_exts(ps.npm_resolver.clone()), startup_snapshot: Some(crate::js::deno_isolate_init()), unsafely_ignore_certificate_errors: metadata .unsafely_ignore_certificate_errors, diff --git a/cli/tools/check.rs b/cli/tools/check.rs index eee82adcf..c7f404223 100644 --- a/cli/tools/check.rs +++ b/cli/tools/check.rs @@ -21,6 +21,7 @@ use crate::cache::Caches; use crate::cache::DenoDir; use crate::cache::FastInsecureHasher; use crate::cache::TypeCheckCache; +use crate::node::CliNodeResolver; use crate::npm::NpmPackageResolver; use crate::tsc; use crate::version; @@ -41,6 +42,7 @@ pub struct TypeChecker { deno_dir: DenoDir, caches: Arc<Caches>, cli_options: Arc<CliOptions>, + node_resolver: Arc<CliNodeResolver>, npm_resolver: Arc<NpmPackageResolver>, } @@ -49,12 +51,14 @@ impl TypeChecker { deno_dir: DenoDir, caches: Arc<Caches>, cli_options: Arc<CliOptions>, + node_resolver: Arc<CliNodeResolver>, npm_resolver: Arc<NpmPackageResolver>, ) -> Self { Self { deno_dir, caches, cli_options, + node_resolver, npm_resolver, } } @@ -133,7 +137,7 @@ impl TypeChecker { debug, graph: graph.clone(), hash_data, - maybe_npm_resolver: Some(self.npm_resolver.clone()), + maybe_node_resolver: Some(self.node_resolver.clone()), maybe_tsbuildinfo, root_names, check_mode: type_check_mode, @@ -144,7 +148,7 @@ impl TypeChecker { if let Some(file_name) = &d.file_name { if !file_name.starts_with("http") { if ModuleSpecifier::parse(file_name) - .map(|specifier| !self.npm_resolver.in_npm_package(&specifier)) + .map(|specifier| !self.node_resolver.in_npm_package(&specifier)) .unwrap_or(true) { Some(d.clone()) diff --git a/cli/tools/task.rs b/cli/tools/task.rs index 9e82f14d9..c64e2a77c 100644 --- a/cli/tools/task.rs +++ b/cli/tools/task.rs @@ -1,8 +1,11 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +use crate::args::CliOptions; use crate::args::Flags; use crate::args::TaskFlags; use crate::colors; +use crate::node::CliNodeResolver; +use crate::npm::NpmPackageResolver; use crate::proc_state::ProcState; use crate::util::fs::canonicalize_path; use deno_core::anyhow::bail; @@ -50,7 +53,7 @@ pub async fn execute_script( Some(path) => canonicalize_path(&PathBuf::from(path))?, None => config_file_path.parent().unwrap().to_owned(), }; - let script = get_script_with_args(script, &ps); + let script = get_script_with_args(script, &ps.options); output_task(task_name, &script); let seq_list = deno_task_shell::parser::parse(&script) .with_context(|| format!("Error parsing script '{task_name}'."))?; @@ -92,11 +95,12 @@ pub async fn execute_script( .unwrap() .to_owned(), }; - let script = get_script_with_args(script, &ps); + let script = get_script_with_args(script, &ps.options); output_task(task_name, &script); let seq_list = deno_task_shell::parser::parse(&script) .with_context(|| format!("Error parsing script '{task_name}'."))?; - let npx_commands = resolve_npm_commands(&ps)?; + let npx_commands = + resolve_npm_commands(&ps.npm_resolver, &ps.node_resolver)?; let env_vars = collect_env_vars(); let exit_code = deno_task_shell::execute(seq_list, env_vars, &cwd, npx_commands).await; @@ -108,9 +112,8 @@ pub async fn execute_script( } } -fn get_script_with_args(script: &str, ps: &ProcState) -> String { - let additional_args = ps - .options +fn get_script_with_args(script: &str, options: &CliOptions) -> String { + let additional_args = options .argv() .iter() // surround all the additional arguments in double quotes @@ -231,13 +234,13 @@ impl ShellCommand for NpmPackageBinCommand { } fn resolve_npm_commands( - ps: &ProcState, + npm_resolver: &NpmPackageResolver, + node_resolver: &CliNodeResolver, ) -> Result<HashMap<String, Rc<dyn ShellCommand>>, AnyError> { let mut result = HashMap::new(); - let snapshot = ps.npm_resolver.snapshot(); + let snapshot = npm_resolver.snapshot(); for id in snapshot.top_level_packages() { - let bin_commands = - crate::node::node_resolve_binary_commands(&id.nv, &ps.npm_resolver)?; + let bin_commands = node_resolver.resolve_binary_commands(&id.nv)?; for bin_command in bin_commands { result.insert( bin_command.to_string(), diff --git a/cli/tools/vendor/mod.rs b/cli/tools/vendor/mod.rs index e75b19e2c..225c3e6a8 100644 --- a/cli/tools/vendor/mod.rs +++ b/cli/tools/vendor/mod.rs @@ -15,6 +15,7 @@ use crate::args::CliOptions; use crate::args::Flags; use crate::args::FmtOptionsConfig; use crate::args::VendorFlags; +use crate::graph_util::ModuleGraphBuilder; use crate::proc_state::ProcState; use crate::tools::fmt::format_json; use crate::util::fs::canonicalize_path; @@ -43,7 +44,12 @@ pub async fn vendor( validate_output_dir(&output_dir, &vendor_flags)?; validate_options(&mut cli_options, &output_dir)?; let ps = ProcState::from_cli_options(Arc::new(cli_options)).await?; - let graph = create_graph(&ps, &vendor_flags).await?; + let graph = create_graph( + &ps.module_graph_builder, + &vendor_flags, + ps.options.initial_cwd(), + ) + .await?; let vendored_count = build::build( graph, &ps.parsed_source_cache, @@ -261,16 +267,17 @@ fn is_dir_empty(dir_path: &Path) -> Result<bool, AnyError> { } async fn create_graph( - ps: &ProcState, + module_graph_builder: &ModuleGraphBuilder, flags: &VendorFlags, + initial_cwd: &Path, ) -> Result<deno_graph::ModuleGraph, AnyError> { let entry_points = flags .specifiers .iter() - .map(|p| resolve_url_or_path(p, ps.options.initial_cwd())) + .map(|p| resolve_url_or_path(p, initial_cwd)) .collect::<Result<Vec<_>, _>>()?; - ps.module_graph_builder.create_graph(entry_points).await + module_graph_builder.create_graph(entry_points).await } #[cfg(test)] diff --git a/cli/tsc/mod.rs b/cli/tsc/mod.rs index eaa7aba36..57a4a1be8 100644 --- a/cli/tsc/mod.rs +++ b/cli/tsc/mod.rs @@ -4,9 +4,8 @@ use crate::args::TsConfig; use crate::args::TypeCheckMode; use crate::cache::FastInsecureHasher; use crate::node; -use crate::node::node_resolve_npm_reference; +use crate::node::CliNodeResolver; use crate::node::NodeResolution; -use crate::npm::NpmPackageResolver; use crate::util::checksum; use crate::util::path::mapped_specifier_for_tsc; @@ -36,7 +35,6 @@ use deno_graph::ModuleGraph; use deno_graph::ResolutionResolved; use deno_runtime::deno_node::NodeResolutionMode; use deno_runtime::permissions::PermissionsContainer; -use deno_semver::npm::NpmPackageNvReference; use deno_semver::npm::NpmPackageReqReference; use lsp_types::Url; use once_cell::sync::Lazy; @@ -307,7 +305,7 @@ pub struct Request { pub debug: bool, pub graph: Arc<ModuleGraph>, pub hash_data: u64, - pub maybe_npm_resolver: Option<Arc<NpmPackageResolver>>, + pub maybe_node_resolver: Option<Arc<CliNodeResolver>>, pub maybe_tsbuildinfo: Option<String>, /// A vector of strings that represent the root/entry point modules for the /// program. @@ -331,7 +329,7 @@ struct State { graph: Arc<ModuleGraph>, maybe_tsbuildinfo: Option<String>, maybe_response: Option<RespondArgs>, - maybe_npm_resolver: Option<Arc<NpmPackageResolver>>, + maybe_node_resolver: Option<Arc<CliNodeResolver>>, remapped_specifiers: HashMap<String, ModuleSpecifier>, root_map: HashMap<String, ModuleSpecifier>, current_dir: PathBuf, @@ -341,7 +339,7 @@ impl State { pub fn new( graph: Arc<ModuleGraph>, hash_data: u64, - maybe_npm_resolver: Option<Arc<NpmPackageResolver>>, + maybe_node_resolver: Option<Arc<CliNodeResolver>>, maybe_tsbuildinfo: Option<String>, root_map: HashMap<String, ModuleSpecifier>, remapped_specifiers: HashMap<String, ModuleSpecifier>, @@ -350,7 +348,7 @@ impl State { State { hash_data, graph, - maybe_npm_resolver, + maybe_node_resolver, maybe_tsbuildinfo, maybe_response: None, remapped_specifiers, @@ -483,7 +481,7 @@ fn op_load(state: &mut OpState, args: Value) -> Result<Value, AnyError> { } } } else if state - .maybe_npm_resolver + .maybe_node_resolver .as_ref() .map(|resolver| resolver.in_npm_package(specifier)) .unwrap_or(false) @@ -636,24 +634,26 @@ fn resolve_graph_specifier_types( Ok(Some((module.specifier.clone(), module.media_type))) } Some(Module::Npm(module)) => { - if let Some(npm_resolver) = &state.maybe_npm_resolver { - resolve_npm_package_reference_types(&module.nv_reference, npm_resolver) - .map(Some) + if let Some(node_resolver) = &state.maybe_node_resolver { + let maybe_resolution = node_resolver.resolve_npm_reference( + &module.nv_reference, + NodeResolutionMode::Types, + &mut PermissionsContainer::allow_all(), + )?; + Ok(Some(NodeResolution::into_specifier_and_media_type( + maybe_resolution, + ))) } else { Ok(None) } } Some(Module::External(module)) => { // we currently only use "External" for when the module is in an npm package - Ok(state.maybe_npm_resolver.as_ref().map(|npm_resolver| { + Ok(state.maybe_node_resolver.as_ref().map(|node_resolver| { let specifier = node::resolve_specifier_into_node_modules(&module.specifier); NodeResolution::into_specifier_and_media_type( - node::url_to_node_resolution( - specifier, - &npm_resolver.as_require_npm_resolver(), - ) - .ok(), + node_resolver.url_to_node_resolution(specifier).ok(), ) })) } @@ -666,60 +666,47 @@ fn resolve_non_graph_specifier_types( referrer: &ModuleSpecifier, state: &State, ) -> Result<Option<(ModuleSpecifier, MediaType)>, AnyError> { - let npm_resolver = match state.maybe_npm_resolver.as_ref() { - Some(npm_resolver) => npm_resolver, + let node_resolver = match state.maybe_node_resolver.as_ref() { + Some(node_resolver) => node_resolver, None => return Ok(None), // we only support non-graph types for npm packages }; - if npm_resolver.in_npm_package(referrer) { + if node_resolver.in_npm_package(referrer) { // we're in an npm package, so use node resolution Ok(Some(NodeResolution::into_specifier_and_media_type( - node::node_resolve( - specifier, - referrer, - NodeResolutionMode::Types, - &npm_resolver.as_require_npm_resolver(), - &mut PermissionsContainer::allow_all(), - ) - .ok() - .flatten(), + node_resolver + .resolve( + specifier, + referrer, + NodeResolutionMode::Types, + &mut PermissionsContainer::allow_all(), + ) + .ok() + .flatten(), ))) } else if let Ok(npm_ref) = NpmPackageReqReference::from_str(specifier) { // todo(dsherret): add support for injecting this in the graph so // we don't need this special code here. // This could occur when resolving npm:@types/node when it is // injected and not part of the graph - let node_id = npm_resolver.resolve_pkg_id_from_pkg_req(&npm_ref.req)?; - let npm_id_ref = NpmPackageNvReference { - nv: node_id.nv, - sub_path: npm_ref.sub_path, - }; - resolve_npm_package_reference_types(&npm_id_ref, npm_resolver).map(Some) + let maybe_resolution = node_resolver.resolve_npm_req_reference( + &npm_ref, + NodeResolutionMode::Types, + &mut PermissionsContainer::allow_all(), + )?; + Ok(Some(NodeResolution::into_specifier_and_media_type( + maybe_resolution, + ))) } else { Ok(None) } } -pub fn resolve_npm_package_reference_types( - npm_ref: &NpmPackageNvReference, - npm_resolver: &Arc<NpmPackageResolver>, -) -> Result<(ModuleSpecifier, MediaType), AnyError> { - let maybe_resolution = node_resolve_npm_reference( - npm_ref, - NodeResolutionMode::Types, - npm_resolver, - &mut PermissionsContainer::allow_all(), - )?; - Ok(NodeResolution::into_specifier_and_media_type( - maybe_resolution, - )) -} - #[op] fn op_is_node_file(state: &mut OpState, path: &str) -> bool { let state = state.borrow::<State>(); match ModuleSpecifier::parse(path) { Ok(specifier) => state - .maybe_npm_resolver + .maybe_node_resolver .as_ref() .map(|r| r.in_npm_package(&specifier)) .unwrap_or(false), @@ -783,7 +770,7 @@ pub fn exec(request: Request) -> Result<Response, AnyError> { state.put(State::new( options.request.graph, options.request.hash_data, - options.request.maybe_npm_resolver, + options.request.maybe_node_resolver, options.request.maybe_tsbuildinfo, options.root_map, options.remapped_specifiers, @@ -955,7 +942,7 @@ mod tests { debug: false, graph: Arc::new(graph), hash_data, - maybe_npm_resolver: None, + maybe_node_resolver: None, maybe_tsbuildinfo: None, root_names: vec![(specifier.clone(), MediaType::TypeScript)], check_mode: TypeCheckMode::All, diff --git a/cli/worker.rs b/cli/worker.rs index 30092cff4..7ee8fc802 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -258,23 +258,14 @@ pub async fn create_custom_worker( ps.npm_resolver .add_package_reqs(vec![package_ref.req.clone()]) .await?; - let pkg_nv = ps - .npm_resolution - .resolve_pkg_id_from_pkg_req(&package_ref.req)? - .nv; - let node_resolution = node::node_resolve_binary_export( - &pkg_nv, - package_ref.sub_path.as_deref(), - &ps.npm_resolver, - )?; + let node_resolution = + ps.node_resolver.resolve_binary_export(&package_ref)?; let is_main_cjs = matches!(node_resolution, node::NodeResolution::CommonJs(_)); (node_resolution.into_url(), is_main_cjs) } else if ps.options.is_npm_main() { - let node_resolution = node::url_to_node_resolution( - main_module, - &ps.npm_resolver.as_require_npm_resolver(), - )?; + let node_resolution = + ps.node_resolver.url_to_node_resolution(main_module)?; let is_main_cjs = matches!(node_resolution, node::NodeResolution::CommonJs(_)); (node_resolution.into_url(), is_main_cjs) @@ -311,7 +302,7 @@ pub async fn create_custom_worker( .join(checksum::gen(&[key.as_bytes()])) }); - let mut extensions = ops::cli_exts(ps.clone()); + let mut extensions = ops::cli_exts(ps.npm_resolver.clone()); extensions.append(&mut custom_extensions); let options = WorkerOptions { @@ -429,7 +420,7 @@ fn create_web_worker_callback( let pre_execute_module_cb = create_web_worker_pre_execute_module_callback(ps.clone()); - let extensions = ops::cli_exts(ps.clone()); + let extensions = ops::cli_exts(ps.npm_resolver.clone()); let maybe_storage_key = ps.options.resolve_storage_key(&args.main_module); let cache_storage_dir = maybe_storage_key.map(|key| { |