diff options
Diffstat (limited to 'cli')
-rw-r--r-- | cli/Cargo.toml | 4 | ||||
-rw-r--r-- | cli/graph_util.rs | 9 | ||||
-rw-r--r-- | cli/lsp/diagnostics.rs | 8 | ||||
-rw-r--r-- | cli/lsp/documents.rs | 10 | ||||
-rw-r--r-- | cli/lsp/language_server.rs | 22 | ||||
-rw-r--r-- | cli/module_loader.rs | 26 | ||||
-rw-r--r-- | cli/node.rs (renamed from cli/node/analyze.rs) | 28 | ||||
-rw-r--r-- | cli/node/mod.rs | 735 | ||||
-rw-r--r-- | cli/npm/mod.rs | 3 | ||||
-rw-r--r-- | cli/npm/resolution.rs | 2 | ||||
-rw-r--r-- | cli/npm/resolvers/mod.rs | 91 | ||||
-rw-r--r-- | cli/ops/mod.rs | 8 | ||||
-rw-r--r-- | cli/proc_state.rs | 17 | ||||
-rw-r--r-- | cli/tools/check.rs | 6 | ||||
-rw-r--r-- | cli/tools/info.rs | 10 | ||||
-rw-r--r-- | cli/tools/task.rs | 8 | ||||
-rw-r--r-- | cli/tsc/mod.rs | 16 | ||||
-rw-r--r-- | cli/worker.rs | 23 |
18 files changed, 154 insertions, 872 deletions
diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 64ce5fce7..96fe458ae 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -47,9 +47,9 @@ deno_emit = "0.20.0" deno_graph = "=0.48.0" deno_lint = { version = "0.44.0", features = ["docs"] } deno_lockfile.workspace = true -deno_npm = "0.3.0" +deno_npm.workspace = true deno_runtime = { workspace = true, features = ["dont_create_runtime_snapshot", "include_js_files_for_snapshotting"] } -deno_semver = "0.2.1" +deno_semver.workspace = true deno_task_shell = "0.11.0" napi_sym.workspace = true diff --git a/cli/graph_util.rs b/cli/graph_util.rs index dacd3be17..d5bc6ac0d 100644 --- a/cli/graph_util.rs +++ b/cli/graph_util.rs @@ -9,7 +9,7 @@ use crate::cache::ParsedSourceCache; use crate::colors; use crate::errors::get_error_class_name; use crate::file_fetcher::FileFetcher; -use crate::npm::NpmPackageResolver; +use crate::npm::CliNpmResolver; use crate::resolver::CliGraphResolver; use crate::tools::check; use crate::tools::check::TypeChecker; @@ -29,6 +29,7 @@ use deno_graph::ModuleGraph; use deno_graph::ModuleGraphError; use deno_graph::ResolutionError; use deno_graph::SpecifierError; +use deno_runtime::deno_node; use deno_runtime::permissions::PermissionsContainer; use import_map::ImportMapError; use std::collections::HashMap; @@ -165,7 +166,7 @@ pub fn graph_lock_or_exit(graph: &ModuleGraph, lockfile: &mut Lockfile) { pub struct ModuleGraphBuilder { options: Arc<CliOptions>, resolver: Arc<CliGraphResolver>, - npm_resolver: Arc<NpmPackageResolver>, + npm_resolver: Arc<CliNpmResolver>, parsed_source_cache: Arc<ParsedSourceCache>, lockfile: Option<Arc<Mutex<Lockfile>>>, emit_cache: cache::EmitCache, @@ -178,7 +179,7 @@ impl ModuleGraphBuilder { pub fn new( options: Arc<CliOptions>, resolver: Arc<CliGraphResolver>, - npm_resolver: Arc<NpmPackageResolver>, + npm_resolver: Arc<CliNpmResolver>, parsed_source_cache: Arc<ParsedSourceCache>, lockfile: Option<Arc<Mutex<Lockfile>>>, emit_cache: cache::EmitCache, @@ -377,7 +378,7 @@ pub fn get_resolution_error_bare_node_specifier( error: &ResolutionError, ) -> Option<&str> { get_resolution_error_bare_specifier(error).filter(|specifier| { - crate::node::resolve_builtin_node_module(specifier).is_ok() + deno_node::resolve_builtin_node_module(specifier).is_ok() }) } diff --git a/cli/lsp/diagnostics.rs b/cli/lsp/diagnostics.rs index 8c2126561..965075a2d 100644 --- a/cli/lsp/diagnostics.rs +++ b/cli/lsp/diagnostics.rs @@ -16,7 +16,6 @@ use super::tsc::TsServer; use crate::args::LintOptions; use crate::graph_util; use crate::graph_util::enhanced_resolution_error_message; -use crate::node; use crate::tools::lint::get_configured_rules; use deno_ast::MediaType; @@ -31,6 +30,7 @@ use deno_graph::Resolution; use deno_graph::ResolutionError; use deno_graph::SpecifierError; use deno_lint::rules::LintRule; +use deno_runtime::deno_node; use deno_runtime::tokio_util::create_basic_runtime; use deno_semver::npm::NpmPackageReqReference; use log::error; @@ -469,8 +469,8 @@ async fn generate_lint_diagnostics( } // ignore any npm package files - if let Some(npm_resolver) = &snapshot.maybe_npm_resolver { - if npm_resolver.in_npm_package(document.specifier()) { + if let Some(node_resolver) = &snapshot.maybe_node_resolver { + if node_resolver.in_npm_package(document.specifier()) { continue; } } @@ -926,7 +926,7 @@ fn diagnose_resolution( } } else if let Some(module_name) = specifier.as_str().strip_prefix("node:") { - if node::resolve_builtin_node_module(module_name).is_err() { + if deno_node::resolve_builtin_node_module(module_name).is_err() { diagnostics.push( DenoDiagnostic::InvalidNodeSpecifier(specifier.clone()) .to_lsp_diagnostic(&range), diff --git a/cli/lsp/documents.rs b/cli/lsp/documents.rs index 7b206406c..fd40bb95f 100644 --- a/cli/lsp/documents.rs +++ b/cli/lsp/documents.rs @@ -18,7 +18,6 @@ use crate::file_fetcher::map_content_type; use crate::file_fetcher::SUPPORTED_SCHEMES; use crate::lsp::logging::lsp_warn; use crate::node::CliNodeResolver; -use crate::node::NodeResolution; use crate::npm::CliNpmRegistryApi; use crate::npm::NpmResolution; use crate::npm::PackageJsonDepsInstaller; @@ -37,8 +36,11 @@ use deno_core::url; use deno_core::ModuleSpecifier; use deno_graph::GraphImport; use deno_graph::Resolution; +use deno_runtime::deno_node; +use deno_runtime::deno_node::NodeResolution; use deno_runtime::deno_node::NodeResolutionMode; use deno_runtime::deno_node::PackageJson; +use deno_runtime::deno_node::RealFs; use deno_runtime::permissions::PermissionsContainer; use deno_semver::npm::NpmPackageReq; use deno_semver::npm::NpmPackageReqReference; @@ -1069,7 +1071,7 @@ impl Documents { // we're in an npm package, so use node resolution results.push(Some(NodeResolution::into_specifier_and_media_type( node_resolver - .resolve( + .resolve::<RealFs>( &specifier, referrer, NodeResolutionMode::Types, @@ -1082,7 +1084,7 @@ impl Documents { } } if let Some(module_name) = specifier.strip_prefix("node:") { - if crate::node::resolve_builtin_node_module(module_name).is_ok() { + if deno_node::resolve_builtin_node_module(module_name).is_ok() { // return itself for node: specifiers because during type checking // we resolve to the ambient modules in the @types/node package // rather than deno_std/node @@ -1457,7 +1459,7 @@ fn node_resolve_npm_req_ref( maybe_node_resolver.map(|node_resolver| { NodeResolution::into_specifier_and_media_type( node_resolver - .resolve_npm_req_reference( + .resolve_npm_req_reference::<RealFs>( &npm_req_ref, NodeResolutionMode::Types, &mut PermissionsContainer::allow_all(), diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index 239ff8a6e..f1b9cb434 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -9,6 +9,7 @@ use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::serde_json::Value; use deno_core::ModuleSpecifier; +use deno_runtime::deno_node::NodeResolver; use deno_runtime::deno_node::PackageJson; use deno_runtime::deno_web::BlobStore; use import_map::ImportMap; @@ -81,8 +82,8 @@ use crate::lsp::urls::LspUrlKind; use crate::node::CliNodeResolver; use crate::npm::create_npm_fs_resolver; use crate::npm::CliNpmRegistryApi; +use crate::npm::CliNpmResolver; use crate::npm::NpmCache; -use crate::npm::NpmPackageResolver; use crate::npm::NpmResolution; use crate::proc_state::ProcState; use crate::tools::fmt::format_file; @@ -103,7 +104,7 @@ pub struct StateSnapshot { pub documents: Documents, pub maybe_import_map: Option<Arc<ImportMap>>, pub maybe_node_resolver: Option<Arc<CliNodeResolver>>, - pub maybe_npm_resolver: Option<Arc<NpmPackageResolver>>, + pub maybe_npm_resolver: Option<Arc<CliNpmResolver>>, } #[derive(Debug)] @@ -153,7 +154,7 @@ pub struct Inner { /// Npm resolution that is stored in memory. npm_resolution: Arc<NpmResolution>, /// Resolver for npm packages. - npm_resolver: Arc<NpmPackageResolver>, + npm_resolver: Arc<CliNpmResolver>, /// A collection of measurements which instrument that performance of the LSP. performance: Arc<Performance>, /// A memoized version of fixable diagnostic codes retrieved from TypeScript. @@ -424,7 +425,7 @@ fn create_lsp_structs( ) -> ( Arc<CliNpmRegistryApi>, Arc<NpmCache>, - Arc<NpmPackageResolver>, + Arc<CliNpmResolver>, Arc<NpmResolution>, ) { let registry_url = CliNpmRegistryApi::default_url(); @@ -457,11 +458,7 @@ fn create_lsp_structs( ( api, npm_cache, - Arc::new(NpmPackageResolver::new( - resolution.clone(), - fs_resolver, - None, - )), + Arc::new(CliNpmResolver::new(resolution.clone(), fs_resolver, None)), resolution, ) } @@ -703,19 +700,18 @@ impl Inner { self.npm_resolution.snapshot(), None, )); - let npm_resolver = Arc::new(NpmPackageResolver::new( + let npm_resolver = Arc::new(CliNpmResolver::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(), + npm_resolution, None, ), None, )); - let node_resolver = - Arc::new(CliNodeResolver::new(npm_resolution, npm_resolver.clone())); + let node_resolver = Arc::new(NodeResolver::new(npm_resolver.clone())); Arc::new(StateSnapshot { assets: self.assets.snapshot(), cache_metadata: self.cache_metadata.clone(), diff --git a/cli/module_loader.rs b/cli/module_loader.rs index 07fad6ffc..c4ef0ed7e 100644 --- a/cli/module_loader.rs +++ b/cli/module_loader.rs @@ -11,10 +11,8 @@ 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::CliCjsEsmCodeAnalyzer; +use crate::node::CliNodeCodeTranslator; use crate::node::CliNodeResolver; -use crate::node::NodeResolution; -use crate::npm::CliRequireNpmResolver; use crate::proc_state::CjsResolutionStore; use crate::proc_state::FileWatcherReporter; use crate::proc_state::ProcState; @@ -50,7 +48,8 @@ use deno_graph::JsonModule; use deno_graph::Module; use deno_graph::Resolution; use deno_lockfile::Lockfile; -use deno_runtime::deno_node::analyze::NodeCodeTranslator; +use deno_runtime::deno_node; +use deno_runtime::deno_node::NodeResolution; use deno_runtime::deno_node::NodeResolutionMode; use deno_runtime::deno_node::RealFs; use deno_runtime::permissions::PermissionsContainer; @@ -244,8 +243,7 @@ pub struct CliModuleLoader { emitter: Arc<Emitter>, graph_container: Arc<ModuleGraphContainer>, module_load_preparer: Arc<ModuleLoadPreparer>, - node_code_translator: - Arc<NodeCodeTranslator<CliCjsEsmCodeAnalyzer, CliRequireNpmResolver>>, + node_code_translator: Arc<CliNodeCodeTranslator>, node_resolver: Arc<CliNodeResolver>, parsed_source_cache: Arc<ParsedSourceCache>, resolver: Arc<CliGraphResolver>, @@ -430,7 +428,7 @@ impl CliModuleLoader { fn handle_node_resolve_result( &self, - result: Result<Option<node::NodeResolution>, AnyError>, + result: Result<Option<NodeResolution>, AnyError>, ) -> Result<ModuleSpecifier, AnyError> { let response = match result? { Some(response) => response, @@ -440,7 +438,7 @@ impl CliModuleLoader { // remember that this was a common js resolution self.cjs_resolutions.insert(specifier.clone()); } else if let NodeResolution::BuiltIn(specifier) = &response { - return node::resolve_builtin_node_module(specifier); + return deno_node::resolve_builtin_node_module(specifier); } Ok(response.into_url()) } @@ -468,7 +466,7 @@ impl ModuleLoader for CliModuleLoader { if self.node_resolver.in_npm_package(referrer) { // we're in an npm package, so use node resolution return self - .handle_node_resolve_result(self.node_resolver.resolve( + .handle_node_resolve_result(self.node_resolver.resolve::<RealFs>( specifier, referrer, NodeResolutionMode::Execution, @@ -494,7 +492,7 @@ impl ModuleLoader for CliModuleLoader { return match graph.get(specifier) { Some(Module::Npm(module)) => self .handle_node_resolve_result( - self.node_resolver.resolve_npm_reference( + self.node_resolver.resolve_npm_reference::<RealFs>( &module.nv_reference, NodeResolutionMode::Execution, &mut permissions, @@ -504,7 +502,7 @@ impl ModuleLoader for CliModuleLoader { format!("Could not resolve '{}'.", module.nv_reference) }), Some(Module::Node(module)) => { - node::resolve_builtin_node_module(&module.module_name) + deno_node::resolve_builtin_node_module(&module.module_name) } Some(Module::Esm(module)) => Ok(module.specifier.clone()), Some(Module::Json(module)) => Ok(module.specifier.clone()), @@ -526,7 +524,7 @@ impl ModuleLoader for CliModuleLoader { // Built-in Node modules if let Some(module_name) = specifier.strip_prefix("node:") { - return node::resolve_builtin_node_module(module_name); + return deno_node::resolve_builtin_node_module(module_name); } // FIXME(bartlomieju): this is a hacky way to provide compatibility with REPL @@ -556,9 +554,9 @@ impl ModuleLoader for CliModuleLoader { { return self .handle_node_resolve_result( - self.node_resolver.resolve_npm_req_reference( + self.node_resolver.resolve_npm_req_reference::<RealFs>( &reference, - deno_runtime::deno_node::NodeResolutionMode::Execution, + NodeResolutionMode::Execution, &mut permissions, ), ) diff --git a/cli/node/analyze.rs b/cli/node.rs index 27818639e..3ec9500e8 100644 --- a/cli/node/analyze.rs +++ b/cli/node.rs @@ -1,6 +1,7 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. use std::collections::HashSet; +use std::sync::Arc; use deno_ast::swc::common::SyntaxContext; use deno_ast::view::Node; @@ -13,8 +14,35 @@ use deno_ast::SourceRanged; use deno_core::error::AnyError; use deno_runtime::deno_node::analyze::CjsAnalysis as ExtNodeCjsAnalysis; use deno_runtime::deno_node::analyze::CjsEsmCodeAnalyzer; +use deno_runtime::deno_node::analyze::NodeCodeTranslator; +use deno_runtime::deno_node::NodeResolver; use crate::cache::NodeAnalysisCache; +use crate::npm::CliNpmResolver; +use crate::util::fs::canonicalize_path_maybe_not_exists; + +pub type CliNodeCodeTranslator = + NodeCodeTranslator<CliCjsEsmCodeAnalyzer, Arc<CliNpmResolver>>; +pub type CliNodeResolver = NodeResolver<Arc<CliNpmResolver>>; + +/// 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: &ModuleSpecifier, +) -> ModuleSpecifier { + specifier + .to_file_path() + .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| canonicalize_path_maybe_not_exists(&path).ok()) + .and_then(|path| ModuleSpecifier::from_file_path(path).ok()) + .unwrap_or_else(|| specifier.clone()) +} pub struct CliCjsEsmCodeAnalyzer { cache: NodeAnalysisCache, diff --git a/cli/node/mod.rs b/cli/node/mod.rs deleted file mode 100644 index eb584879e..000000000 --- a/cli/node/mod.rs +++ /dev/null @@ -1,735 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. - -use std::path::Path; -use std::path::PathBuf; -use std::sync::Arc; - -use deno_ast::MediaType; -use deno_ast::ModuleSpecifier; -use deno_core::anyhow::bail; -use deno_core::anyhow::Context; -use deno_core::error::generic_error; -use deno_core::error::AnyError; -use deno_core::serde_json::Value; -use deno_core::url::Url; -use deno_runtime::deno_node; -use deno_runtime::deno_node::errors; -use deno_runtime::deno_node::find_builtin_node_module; -use deno_runtime::deno_node::get_closest_package_json; -use deno_runtime::deno_node::legacy_main_resolve; -use deno_runtime::deno_node::package_exports_resolve; -use deno_runtime::deno_node::package_imports_resolve; -use deno_runtime::deno_node::package_resolve; -use deno_runtime::deno_node::path_to_declaration_path; -use deno_runtime::deno_node::NodeModuleKind; -use deno_runtime::deno_node::NodePermissions; -use deno_runtime::deno_node::NodeResolutionMode; -use deno_runtime::deno_node::PackageJson; -use deno_runtime::deno_node::RealFs; -use deno_runtime::deno_node::RequireNpmResolver; -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::CliRequireNpmResolver; -use crate::npm::NpmPackageResolver; -use crate::npm::NpmResolution; -use crate::util::fs::canonicalize_path_maybe_not_exists; - -mod analyze; - -pub use analyze::CliCjsEsmCodeAnalyzer; - -#[derive(Debug)] -pub enum NodeResolution { - Esm(ModuleSpecifier), - CommonJs(ModuleSpecifier), - BuiltIn(String), -} - -impl NodeResolution { - pub fn into_url(self) -> ModuleSpecifier { - match self { - Self::Esm(u) => u, - Self::CommonJs(u) => u, - Self::BuiltIn(specifier) => { - if specifier.starts_with("node:") { - ModuleSpecifier::parse(&specifier).unwrap() - } else { - ModuleSpecifier::parse(&format!("node:{specifier}")).unwrap() - } - } - } - } - - pub fn into_specifier_and_media_type( - resolution: Option<Self>, - ) -> (ModuleSpecifier, MediaType) { - match resolution { - Some(NodeResolution::CommonJs(specifier)) => { - let media_type = MediaType::from_specifier(&specifier); - ( - specifier, - match media_type { - MediaType::JavaScript | MediaType::Jsx => MediaType::Cjs, - MediaType::TypeScript | MediaType::Tsx => MediaType::Cts, - MediaType::Dts => MediaType::Dcts, - _ => media_type, - }, - ) - } - Some(NodeResolution::Esm(specifier)) => { - let media_type = MediaType::from_specifier(&specifier); - ( - specifier, - match media_type { - MediaType::JavaScript | MediaType::Jsx => MediaType::Mjs, - MediaType::TypeScript | MediaType::Tsx => MediaType::Mts, - MediaType::Dts => MediaType::Dmts, - _ => media_type, - }, - ) - } - Some(resolution) => (resolution.into_url(), MediaType::Dts), - None => ( - ModuleSpecifier::parse("internal:///missing_dependency.d.ts").unwrap(), - MediaType::Dts, - ), - } - } -} - -// TODO(bartlomieju): seems super wasteful to parse specified each time -pub fn resolve_builtin_node_module(module_name: &str) -> Result<Url, AnyError> { - if let Some(module) = find_builtin_node_module(module_name) { - return Ok(ModuleSpecifier::parse(module.specifier).unwrap()); - } - - Err(generic_error(format!( - "Unknown built-in \"node:\" module: {module_name}" - ))) -} - -#[derive(Debug)] -pub struct CliNodeResolver { - npm_resolution: Arc<NpmResolution>, - npm_resolver: Arc<NpmPackageResolver>, - require_npm_resolver: CliRequireNpmResolver, -} - -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, - } - } - - pub fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool { - self.npm_resolver.in_npm_package(specifier) - } - - /// 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()))); - } - - 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 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)); - } - - // 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)) - } - - 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), - } - } - }; - 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)) - } - - 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, - )?; - - 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)) - } - } -} - -/// 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: &ModuleSpecifier, -) -> ModuleSpecifier { - specifier - .to_file_path() - .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| canonicalize_path_maybe_not_exists(&path).ok()) - .and_then(|path| ModuleSpecifier::from_file_path(path).ok()) - .unwrap_or_else(|| specifier.clone()) -} - -fn resolve_bin_entry_value<'a>( - pkg_nv: &NpmPackageNv, - bin_name: Option<&str>, - bin: &'a Value, -) -> Result<&'a str, AnyError> { - let bin_entry = match bin { - Value::String(_) => { - if bin_name.is_some() && bin_name.unwrap() != pkg_nv.name { - None - } else { - Some(bin) - } - } - Value::Object(o) => { - if let Some(bin_name) = bin_name { - o.get(bin_name) - } else if o.len() == 1 || o.len() > 1 && o.values().all(|v| v == o.values().next().unwrap()) { - o.values().next() - } else { - o.get(&pkg_nv.name) - } - }, - _ => bail!("package '{}' did not have a bin property with a string or object value in its package.json", pkg_nv), - }; - let bin_entry = match bin_entry { - Some(e) => e, - None => { - let keys = bin - .as_object() - .map(|o| { - o.keys() - .map(|k| format!(" * npm:{pkg_nv}/{k}")) - .collect::<Vec<_>>() - }) - .unwrap_or_default(); - bail!( - "package '{}' did not have a bin entry for '{}' in its package.json{}", - pkg_nv, - bin_name.unwrap_or(&pkg_nv.name), - if keys.is_empty() { - "".to_string() - } else { - format!("\n\nPossibilities:\n{}", keys.join("\n")) - } - ) - } - }; - match bin_entry { - Value::String(s) => Ok(s), - _ => bail!( - "package '{}' had a non-string sub property of bin in its package.json", - pkg_nv, - ), - } -} - -fn package_config_resolve( - package_subpath: &str, - package_dir: &Path, - referrer_kind: NodeModuleKind, - conditions: &[&str], - mode: NodeResolutionMode, - npm_resolver: &dyn RequireNpmResolver, - permissions: &mut dyn NodePermissions, -) -> Result<Option<PathBuf>, AnyError> { - let package_json_path = package_dir.join("package.json"); - let referrer = ModuleSpecifier::from_directory_path(package_dir).unwrap(); - let package_config = PackageJson::load::<RealFs>( - npm_resolver, - permissions, - package_json_path.clone(), - )?; - if let Some(exports) = &package_config.exports { - let result = package_exports_resolve::<RealFs>( - &package_json_path, - package_subpath.to_string(), - exports, - &referrer, - referrer_kind, - conditions, - mode, - npm_resolver, - permissions, - ); - match result { - Ok(found) => return Ok(Some(found)), - Err(exports_err) => { - if mode.is_types() && package_subpath == "." { - if let Ok(Some(path)) = - legacy_main_resolve::<RealFs>(&package_config, referrer_kind, mode) - { - return Ok(Some(path)); - } else { - return Ok(None); - } - } - return Err(exports_err); - } - } - } - if package_subpath == "." { - return legacy_main_resolve::<RealFs>(&package_config, referrer_kind, mode); - } - - Ok(Some(package_dir.join(package_subpath))) -} - -fn finalize_resolution( - resolved: ModuleSpecifier, - base: &ModuleSpecifier, -) -> Result<ModuleSpecifier, AnyError> { - let encoded_sep_re = lazy_regex::regex!(r"%2F|%2C"); - - if encoded_sep_re.is_match(resolved.path()) { - return Err(errors::err_invalid_module_specifier( - resolved.path(), - "must not include encoded \"/\" or \"\\\\\" characters", - Some(to_file_path_string(base)), - )); - } - - let path = to_file_path(&resolved); - - // TODO(bartlomieju): currently not supported - // if (getOptionValue('--experimental-specifier-resolution') === 'node') { - // ... - // } - - let p_str = path.to_str().unwrap(); - let p = if p_str.ends_with('/') { - p_str[p_str.len() - 1..].to_string() - } else { - p_str.to_string() - }; - - let (is_dir, is_file) = if let Ok(stats) = std::fs::metadata(p) { - (stats.is_dir(), stats.is_file()) - } else { - (false, false) - }; - if is_dir { - return Err(errors::err_unsupported_dir_import( - resolved.as_str(), - base.as_str(), - )); - } else if !is_file { - return Err(errors::err_module_not_found( - resolved.as_str(), - base.as_str(), - "module", - )); - } - - Ok(resolved) -} - -fn to_file_path(url: &ModuleSpecifier) -> PathBuf { - url - .to_file_path() - .unwrap_or_else(|_| panic!("Provided URL was not file:// URL: {url}")) -} - -fn to_file_path_string(url: &ModuleSpecifier) -> String { - to_file_path(url).display().to_string() -} - -fn should_be_treated_as_relative_or_absolute_path(specifier: &str) -> bool { - if specifier.is_empty() { - return false; - } - - if specifier.starts_with('/') { - return true; - } - - is_relative_specifier(specifier) -} - -// 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(); - - if !specifier_chars.is_empty() && specifier_chars[0] == '.' { - if specifier_len == 1 || specifier_chars[1] == '/' { - return true; - } - if specifier_chars[1] == '.' - && (specifier_len == 2 || specifier_chars[2] == '/') - { - return true; - } - } - false -} - -#[cfg(test)] -mod tests { - use deno_core::serde_json::json; - - use super::*; - - #[test] - fn test_resolve_bin_entry_value() { - // should resolve the specified value - let value = json!({ - "bin1": "./value1", - "bin2": "./value2", - "test": "./value3", - }); - assert_eq!( - resolve_bin_entry_value( - &NpmPackageNv::from_str("test@1.1.1").unwrap(), - Some("bin1"), - &value - ) - .unwrap(), - "./value1" - ); - - // should resolve the value with the same name when not specified - assert_eq!( - resolve_bin_entry_value( - &NpmPackageNv::from_str("test@1.1.1").unwrap(), - None, - &value - ) - .unwrap(), - "./value3" - ); - - // should not resolve when specified value does not exist - assert_eq!( - resolve_bin_entry_value( - &NpmPackageNv::from_str("test@1.1.1").unwrap(), - Some("other"), - &value - ) - .err() - .unwrap() - .to_string(), - concat!( - "package 'test@1.1.1' did not have a bin entry for 'other' in its package.json\n", - "\n", - "Possibilities:\n", - " * npm:test@1.1.1/bin1\n", - " * npm:test@1.1.1/bin2\n", - " * npm:test@1.1.1/test" - ) - ); - - // should not resolve when default value can't be determined - assert_eq!( - resolve_bin_entry_value( - &NpmPackageNv::from_str("asdf@1.2.3").unwrap(), - None, - &value - ) - .err() - .unwrap() - .to_string(), - concat!( - "package 'asdf@1.2.3' did not have a bin entry for 'asdf' in its package.json\n", - "\n", - "Possibilities:\n", - " * npm:asdf@1.2.3/bin1\n", - " * npm:asdf@1.2.3/bin2\n", - " * npm:asdf@1.2.3/test" - ) - ); - - // should resolve since all the values are the same - let value = json!({ - "bin1": "./value", - "bin2": "./value", - }); - assert_eq!( - resolve_bin_entry_value( - &NpmPackageNv::from_str("test@1.2.3").unwrap(), - None, - &value - ) - .unwrap(), - "./value" - ); - - // should not resolve when specified and is a string - let value = json!("./value"); - assert_eq!( - resolve_bin_entry_value( - &NpmPackageNv::from_str("test@1.2.3").unwrap(), - Some("path"), - &value - ) - .err() - .unwrap() - .to_string(), - "package 'test@1.2.3' did not have a bin entry for 'path' in its package.json" - ); - } -} diff --git a/cli/npm/mod.rs b/cli/npm/mod.rs index 8f6ac77bc..488f8eae6 100644 --- a/cli/npm/mod.rs +++ b/cli/npm/mod.rs @@ -13,6 +13,5 @@ pub use installer::PackageJsonDepsInstaller; pub use registry::CliNpmRegistryApi; pub use resolution::NpmResolution; pub use resolvers::create_npm_fs_resolver; -pub use resolvers::CliRequireNpmResolver; -pub use resolvers::NpmPackageResolver; +pub use resolvers::CliNpmResolver; pub use resolvers::NpmProcessState; diff --git a/cli/npm/resolution.rs b/cli/npm/resolution.rs index 26fc356ff..1b191b245 100644 --- a/cli/npm/resolution.rs +++ b/cli/npm/resolution.rs @@ -154,7 +154,7 @@ impl NpmResolution { Ok(()) } - pub fn pkg_req_ref_to_nv_ref( + pub fn resolve_nv_ref_from_pkg_req_ref( &self, req_ref: &NpmPackageReqReference, ) -> Result<NpmPackageNvReference, PackageReqNotFoundError> { diff --git a/cli/npm/resolvers/mod.rs b/cli/npm/resolvers/mod.rs index f693d3d23..8b871beaf 100644 --- a/cli/npm/resolvers/mod.rs +++ b/cli/npm/resolvers/mod.rs @@ -20,10 +20,12 @@ use deno_npm::resolution::SerializedNpmResolutionSnapshot; use deno_npm::NpmPackageId; use deno_runtime::deno_node::NodePermissions; use deno_runtime::deno_node::NodeResolutionMode; +use deno_runtime::deno_node::NpmResolver; 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; @@ -45,13 +47,13 @@ pub struct NpmProcessState { } /// Brings together the npm resolution with the file system. -pub struct NpmPackageResolver { +pub struct CliNpmResolver { fs_resolver: Arc<dyn NpmPackageFsResolver>, resolution: Arc<NpmResolution>, maybe_lockfile: Option<Arc<Mutex<Lockfile>>>, } -impl std::fmt::Debug for NpmPackageResolver { +impl std::fmt::Debug for CliNpmResolver { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("NpmPackageResolver") .field("fs_resolver", &"<omitted>") @@ -61,7 +63,7 @@ impl std::fmt::Debug for NpmPackageResolver { } } -impl NpmPackageResolver { +impl CliNpmResolver { pub fn new( resolution: Arc<NpmResolution>, fs_resolver: Arc<dyn NpmPackageFsResolver>, @@ -85,15 +87,6 @@ impl NpmPackageResolver { self.resolution.resolve_pkg_id_from_pkg_req(req) } - /// Resolves an npm package folder path from a Deno module. - pub fn resolve_package_folder_from_deno_module( - &self, - pkg_nv: &NpmPackageNv, - ) -> Result<PathBuf, AnyError> { - let pkg_id = self.resolution.resolve_pkg_id_from_deno_module(pkg_nv)?; - self.resolve_pkg_folder_from_deno_module_at_pkg_id(&pkg_id) - } - fn resolve_pkg_folder_from_deno_module_at_pkg_id( &self, pkg_id: &NpmPackageId, @@ -108,20 +101,6 @@ impl NpmPackageResolver { Ok(path) } - /// Resolves an npm package folder path from an npm package referrer. - pub fn resolve_package_folder_from_package( - &self, - name: &str, - referrer: &ModuleSpecifier, - mode: NodeResolutionMode, - ) -> Result<PathBuf, AnyError> { - let path = self - .fs_resolver - .resolve_package_folder_from_package(name, referrer, mode)?; - log::debug!("Resolved {} from {} to {}", name, referrer, path.display()); - Ok(path) - } - /// Resolve the root folder of the package the provided specifier is in. /// /// This will error when the provided specifier is not in an npm package. @@ -228,26 +207,20 @@ impl NpmPackageResolver { self.fs_resolver.cache_packages().await?; Ok(()) } - - pub fn as_require_npm_resolver(self: &Arc<Self>) -> CliRequireNpmResolver { - CliRequireNpmResolver(self.clone()) - } } -#[derive(Debug)] -pub struct CliRequireNpmResolver(Arc<NpmPackageResolver>); - -impl RequireNpmResolver for CliRequireNpmResolver { +impl NpmResolver for CliNpmResolver { fn resolve_package_folder_from_package( &self, - specifier: &str, - referrer: &std::path::Path, + name: &str, + referrer: &ModuleSpecifier, mode: NodeResolutionMode, ) -> Result<PathBuf, AnyError> { - let referrer = path_to_specifier(referrer)?; - self - .0 - .resolve_package_folder_from_package(specifier, &referrer, mode) + let path = self + .fs_resolver + .resolve_package_folder_from_package(name, referrer, mode)?; + log::debug!("Resolved {} from {} to {}", name, referrer, path.display()); + Ok(path) } fn resolve_package_folder_from_path( @@ -255,18 +228,34 @@ impl RequireNpmResolver for CliRequireNpmResolver { path: &Path, ) -> Result<PathBuf, AnyError> { let specifier = path_to_specifier(path)?; - self.0.resolve_package_folder_from_specifier(&specifier) + self.resolve_package_folder_from_specifier(&specifier) + } + + fn resolve_package_folder_from_deno_module( + &self, + pkg_nv: &NpmPackageNv, + ) -> Result<PathBuf, AnyError> { + let pkg_id = self.resolution.resolve_pkg_id_from_deno_module(pkg_nv)?; + self.resolve_pkg_folder_from_deno_module_at_pkg_id(&pkg_id) + } + + fn resolve_pkg_id_from_pkg_req( + &self, + req: &NpmPackageReq, + ) -> Result<NpmPackageId, PackageReqNotFoundError> { + self.resolution.resolve_pkg_id_from_pkg_req(req) + } + + fn resolve_nv_ref_from_pkg_req_ref( + &self, + req_ref: &NpmPackageReqReference, + ) -> Result<NpmPackageNvReference, PackageReqNotFoundError> { + self.resolution.resolve_nv_ref_from_pkg_req_ref(req_ref) } - fn in_npm_package(&self, path: &Path) -> bool { - let specifier = - match ModuleSpecifier::from_file_path(path.to_path_buf().clean()) { - Ok(p) => p, - Err(_) => return false, - }; + fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool { self - .0 - .resolve_package_folder_from_specifier(&specifier) + .resolve_package_folder_from_specifier(specifier) .is_ok() } @@ -275,7 +264,7 @@ impl RequireNpmResolver for CliRequireNpmResolver { permissions: &mut dyn NodePermissions, path: &Path, ) -> Result<(), AnyError> { - self.0.fs_resolver.ensure_read_permission(permissions, path) + self.fs_resolver.ensure_read_permission(permissions, path) } } diff --git a/cli/ops/mod.rs b/cli/ops/mod.rs index 9adc944ce..d39f19270 100644 --- a/cli/ops/mod.rs +++ b/cli/ops/mod.rs @@ -2,7 +2,7 @@ use std::sync::Arc; -use crate::npm::NpmPackageResolver; +use crate::npm::CliNpmResolver; use deno_core::error::AnyError; use deno_core::op; use deno_core::Extension; @@ -11,14 +11,14 @@ use deno_core::OpState; pub mod bench; pub mod testing; -pub fn cli_exts(npm_resolver: Arc<NpmPackageResolver>) -> Vec<Extension> { +pub fn cli_exts(npm_resolver: Arc<CliNpmResolver>) -> Vec<Extension> { vec![deno_cli::init_ops(npm_resolver)] } deno_core::extension!(deno_cli, ops = [op_npm_process_state], options = { - npm_resolver: Arc<NpmPackageResolver>, + npm_resolver: Arc<CliNpmResolver>, }, state = |state, options| { state.put(options.npm_resolver); @@ -30,6 +30,6 @@ deno_core::extension!(deno_cli, #[op] fn op_npm_process_state(state: &mut OpState) -> Result<String, AnyError> { - let npm_resolver = state.borrow_mut::<Arc<NpmPackageResolver>>(); + let npm_resolver = state.borrow_mut::<Arc<CliNpmResolver>>(); Ok(npm_resolver.get_npm_process_state()) } diff --git a/cli/proc_state.rs b/cli/proc_state.rs index bfe45bc86..6b7e9b1f2 100644 --- a/cli/proc_state.rs +++ b/cli/proc_state.rs @@ -18,12 +18,12 @@ use crate::graph_util::ModuleGraphContainer; use crate::http_util::HttpClient; use crate::module_loader::ModuleLoadPreparer; use crate::node::CliCjsEsmCodeAnalyzer; +use crate::node::CliNodeCodeTranslator; use crate::node::CliNodeResolver; use crate::npm::create_npm_fs_resolver; use crate::npm::CliNpmRegistryApi; -use crate::npm::CliRequireNpmResolver; +use crate::npm::CliNpmResolver; use crate::npm::NpmCache; -use crate::npm::NpmPackageResolver; use crate::npm::NpmResolution; use crate::npm::PackageJsonDepsInstaller; use crate::resolver::CliGraphResolver; @@ -39,6 +39,7 @@ use deno_core::SharedArrayBufferStore; use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel; use deno_runtime::deno_node::analyze::NodeCodeTranslator; +use deno_runtime::deno_node::NodeResolver; use deno_runtime::deno_tls::rustls::RootCertStore; use deno_runtime::deno_web::BlobStore; use deno_runtime::inspector_server::InspectorServer; @@ -77,12 +78,11 @@ pub struct Inner { maybe_file_watcher_reporter: Option<FileWatcherReporter>, pub module_graph_builder: Arc<ModuleGraphBuilder>, pub module_load_preparer: Arc<ModuleLoadPreparer>, - pub node_code_translator: - Arc<NodeCodeTranslator<CliCjsEsmCodeAnalyzer, CliRequireNpmResolver>>, + pub node_code_translator: Arc<CliNodeCodeTranslator>, pub node_resolver: Arc<CliNodeResolver>, pub npm_api: Arc<CliNpmRegistryApi>, pub npm_cache: Arc<NpmCache>, - pub npm_resolver: Arc<NpmPackageResolver>, + pub npm_resolver: Arc<CliNpmResolver>, pub npm_resolution: Arc<NpmResolution>, pub package_json_deps_installer: Arc<PackageJsonDepsInstaller>, pub cjs_resolutions: Arc<CjsResolutionStore>, @@ -252,7 +252,7 @@ impl ProcState { npm_resolution.clone(), cli_options.node_modules_dir_path(), ); - let npm_resolver = Arc::new(NpmPackageResolver::new( + let npm_resolver = Arc::new(CliNpmResolver::new( npm_resolution.clone(), npm_fs_resolver, lockfile.as_ref().cloned(), @@ -310,12 +310,9 @@ impl ProcState { let cjs_esm_analyzer = CliCjsEsmCodeAnalyzer::new(node_analysis_cache); let node_code_translator = Arc::new(NodeCodeTranslator::new( cjs_esm_analyzer, - npm_resolver.as_require_npm_resolver(), - )); - let node_resolver = Arc::new(CliNodeResolver::new( - npm_resolution.clone(), npm_resolver.clone(), )); + let node_resolver = Arc::new(NodeResolver::new(npm_resolver.clone())); let type_checker = Arc::new(TypeChecker::new( dir.clone(), caches.clone(), diff --git a/cli/tools/check.rs b/cli/tools/check.rs index c7f404223..36bc25d6a 100644 --- a/cli/tools/check.rs +++ b/cli/tools/check.rs @@ -22,7 +22,7 @@ use crate::cache::DenoDir; use crate::cache::FastInsecureHasher; use crate::cache::TypeCheckCache; use crate::node::CliNodeResolver; -use crate::npm::NpmPackageResolver; +use crate::npm::CliNpmResolver; use crate::tsc; use crate::version; @@ -43,7 +43,7 @@ pub struct TypeChecker { caches: Arc<Caches>, cli_options: Arc<CliOptions>, node_resolver: Arc<CliNodeResolver>, - npm_resolver: Arc<NpmPackageResolver>, + npm_resolver: Arc<CliNpmResolver>, } impl TypeChecker { @@ -52,7 +52,7 @@ impl TypeChecker { caches: Arc<Caches>, cli_options: Arc<CliOptions>, node_resolver: Arc<CliNodeResolver>, - npm_resolver: Arc<NpmPackageResolver>, + npm_resolver: Arc<CliNpmResolver>, ) -> Self { Self { deno_dir, diff --git a/cli/tools/info.rs b/cli/tools/info.rs index 69faa10fb..a59f8a4c8 100644 --- a/cli/tools/info.rs +++ b/cli/tools/info.rs @@ -28,7 +28,7 @@ use crate::args::Flags; use crate::args::InfoFlags; use crate::display; use crate::graph_util::graph_lock_or_exit; -use crate::npm::NpmPackageResolver; +use crate::npm::CliNpmResolver; use crate::proc_state::ProcState; use crate::util::checksum; @@ -141,7 +141,7 @@ fn print_cache_info( fn add_npm_packages_to_json( json: &mut serde_json::Value, - npm_resolver: &NpmPackageResolver, + npm_resolver: &CliNpmResolver, ) { // ideally deno_graph could handle this, but for now we just modify the json here let snapshot = npm_resolver.snapshot(); @@ -318,7 +318,7 @@ struct NpmInfo { impl NpmInfo { pub fn build<'a>( graph: &'a ModuleGraph, - npm_resolver: &'a NpmPackageResolver, + npm_resolver: &'a CliNpmResolver, npm_snapshot: &'a NpmResolutionSnapshot, ) -> Self { let mut info = NpmInfo::default(); @@ -344,7 +344,7 @@ impl NpmInfo { fn fill_package_info<'a>( &mut self, package: &NpmResolutionPackage, - npm_resolver: &'a NpmPackageResolver, + npm_resolver: &'a CliNpmResolver, npm_snapshot: &'a NpmResolutionSnapshot, ) { self @@ -380,7 +380,7 @@ struct GraphDisplayContext<'a> { impl<'a> GraphDisplayContext<'a> { pub fn write<TWrite: Write>( graph: &'a ModuleGraph, - npm_resolver: &'a NpmPackageResolver, + npm_resolver: &'a CliNpmResolver, writer: &mut TWrite, ) -> fmt::Result { let npm_snapshot = npm_resolver.snapshot(); diff --git a/cli/tools/task.rs b/cli/tools/task.rs index c64e2a77c..898cdd8d9 100644 --- a/cli/tools/task.rs +++ b/cli/tools/task.rs @@ -5,7 +5,7 @@ use crate::args::Flags; use crate::args::TaskFlags; use crate::colors; use crate::node::CliNodeResolver; -use crate::npm::NpmPackageResolver; +use crate::npm::CliNpmResolver; use crate::proc_state::ProcState; use crate::util::fs::canonicalize_path; use deno_core::anyhow::bail; @@ -13,6 +13,7 @@ use deno_core::anyhow::Context; use deno_core::error::AnyError; use deno_core::futures; use deno_core::futures::future::LocalBoxFuture; +use deno_runtime::deno_node::RealFs; use deno_semver::npm::NpmPackageNv; use deno_task_shell::ExecuteResult; use deno_task_shell::ShellCommand; @@ -234,13 +235,14 @@ impl ShellCommand for NpmPackageBinCommand { } fn resolve_npm_commands( - npm_resolver: &NpmPackageResolver, + npm_resolver: &CliNpmResolver, node_resolver: &CliNodeResolver, ) -> Result<HashMap<String, Rc<dyn ShellCommand>>, AnyError> { let mut result = HashMap::new(); let snapshot = npm_resolver.snapshot(); for id in snapshot.top_level_packages() { - let bin_commands = node_resolver.resolve_binary_commands(&id.nv)?; + let bin_commands = + node_resolver.resolve_binary_commands::<RealFs>(&id.nv)?; for bin_command in bin_commands { result.insert( bin_command.to_string(), diff --git a/cli/tsc/mod.rs b/cli/tsc/mod.rs index 57a4a1be8..0d956b661 100644 --- a/cli/tsc/mod.rs +++ b/cli/tsc/mod.rs @@ -5,7 +5,6 @@ use crate::args::TypeCheckMode; use crate::cache::FastInsecureHasher; use crate::node; use crate::node::CliNodeResolver; -use crate::node::NodeResolution; use crate::util::checksum; use crate::util::path::mapped_specifier_for_tsc; @@ -33,7 +32,10 @@ use deno_core::Snapshot; use deno_graph::Module; use deno_graph::ModuleGraph; use deno_graph::ResolutionResolved; +use deno_runtime::deno_node; +use deno_runtime::deno_node::NodeResolution; use deno_runtime::deno_node::NodeResolutionMode; +use deno_runtime::deno_node::RealFs; use deno_runtime::permissions::PermissionsContainer; use deno_semver::npm::NpmPackageReqReference; use lsp_types::Url; @@ -537,7 +539,7 @@ fn op_resolve( }; for specifier in args.specifiers { if let Some(module_name) = specifier.strip_prefix("node:") { - if crate::node::resolve_builtin_node_module(module_name).is_ok() { + if deno_node::resolve_builtin_node_module(module_name).is_ok() { // return itself for node: specifiers because during type checking // we resolve to the ambient modules in the @types/node package // rather than deno_std/node @@ -635,7 +637,7 @@ fn resolve_graph_specifier_types( } Some(Module::Npm(module)) => { if let Some(node_resolver) = &state.maybe_node_resolver { - let maybe_resolution = node_resolver.resolve_npm_reference( + let maybe_resolution = node_resolver.resolve_npm_reference::<RealFs>( &module.nv_reference, NodeResolutionMode::Types, &mut PermissionsContainer::allow_all(), @@ -653,7 +655,9 @@ fn resolve_graph_specifier_types( let specifier = node::resolve_specifier_into_node_modules(&module.specifier); NodeResolution::into_specifier_and_media_type( - node_resolver.url_to_node_resolution(specifier).ok(), + node_resolver + .url_to_node_resolution::<RealFs>(specifier) + .ok(), ) })) } @@ -674,7 +678,7 @@ fn resolve_non_graph_specifier_types( // we're in an npm package, so use node resolution Ok(Some(NodeResolution::into_specifier_and_media_type( node_resolver - .resolve( + .resolve::<RealFs>( specifier, referrer, NodeResolutionMode::Types, @@ -688,7 +692,7 @@ fn resolve_non_graph_specifier_types( // 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 maybe_resolution = node_resolver.resolve_npm_req_reference( + let maybe_resolution = node_resolver.resolve_npm_req_reference::<RealFs>( &npm_ref, NodeResolutionMode::Types, &mut PermissionsContainer::allow_all(), diff --git a/cli/worker.rs b/cli/worker.rs index 7ee8fc802..c73e4edbe 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -13,6 +13,8 @@ use deno_core::Extension; use deno_core::ModuleId; use deno_runtime::colors; use deno_runtime::deno_node; +use deno_runtime::deno_node::NodeResolution; +use deno_runtime::deno_node::RealFs; use deno_runtime::fmt_errors::format_js_error; use deno_runtime::ops::worker_host::CreateWebWorkerCb; use deno_runtime::ops::worker_host::WorkerEventCb; @@ -27,7 +29,6 @@ use deno_semver::npm::NpmPackageReqReference; use crate::args::DenoSubcommand; use crate::errors; use crate::module_loader::CliModuleLoader; -use crate::node; use crate::ops; use crate::proc_state::ProcState; use crate::tools; @@ -258,16 +259,16 @@ pub async fn create_custom_worker( ps.npm_resolver .add_package_reqs(vec![package_ref.req.clone()]) .await?; - let node_resolution = - ps.node_resolver.resolve_binary_export(&package_ref)?; - let is_main_cjs = - matches!(node_resolution, node::NodeResolution::CommonJs(_)); + let node_resolution = ps + .node_resolver + .resolve_binary_export::<RealFs>(&package_ref)?; + let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_)); (node_resolution.into_url(), is_main_cjs) } else if ps.options.is_npm_main() { - let node_resolution = - ps.node_resolver.url_to_node_resolution(main_module)?; - let is_main_cjs = - matches!(node_resolution, node::NodeResolution::CommonJs(_)); + let node_resolution = ps + .node_resolver + .url_to_node_resolution::<RealFs>(main_module)?; + let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_)); (node_resolution.into_url(), is_main_cjs) } else { (main_module, false) @@ -344,7 +345,7 @@ pub async fn create_custom_worker( should_break_on_first_statement: ps.options.inspect_brk().is_some(), should_wait_for_inspector_session: ps.options.inspect_wait().is_some(), module_loader, - npm_resolver: Some(Rc::new(ps.npm_resolver.as_require_npm_resolver())), + npm_resolver: Some(Rc::new(ps.npm_resolver.clone())), get_error_class_fn: Some(&errors::get_error_class_name), cache_storage_dir, origin_storage_dir, @@ -467,7 +468,7 @@ fn create_web_worker_callback( format_js_error_fn: Some(Arc::new(format_js_error)), source_map_getter: Some(Box::new(module_loader.clone())), module_loader, - npm_resolver: Some(Rc::new(ps.npm_resolver.as_require_npm_resolver())), + npm_resolver: Some(Rc::new(ps.npm_resolver.clone())), worker_type: args.worker_type, maybe_inspector_server, get_error_class_fn: Some(&errors::get_error_class_name), |