diff options
Diffstat (limited to 'cli')
-rw-r--r-- | cli/factory.rs | 6 | ||||
-rw-r--r-- | cli/module_loader.rs | 238 | ||||
-rw-r--r-- | cli/resolver.rs | 236 | ||||
-rw-r--r-- | cli/standalone/mod.rs | 6 |
4 files changed, 244 insertions, 242 deletions
diff --git a/cli/factory.rs b/cli/factory.rs index 17be83c29..a9fda2b4c 100644 --- a/cli/factory.rs +++ b/cli/factory.rs @@ -23,11 +23,8 @@ use crate::graph_util::FileWatcherReporter; use crate::graph_util::ModuleGraphBuilder; use crate::graph_util::ModuleGraphContainer; use crate::http_util::HttpClient; -use crate::module_loader::CjsResolutionStore; use crate::module_loader::CliModuleLoaderFactory; -use crate::module_loader::CliNodeResolver; use crate::module_loader::ModuleLoadPreparer; -use crate::module_loader::NpmModuleLoader; use crate::node::CliCjsCodeAnalyzer; use crate::node::CliNodeCodeTranslator; use crate::npm::create_cli_npm_resolver; @@ -37,8 +34,11 @@ use crate::npm::CliNpmResolverCreateOptions; use crate::npm::CliNpmResolverManagedCreateOptions; use crate::npm::CliNpmResolverManagedPackageJsonInstallerOption; use crate::npm::CliNpmResolverManagedSnapshotOption; +use crate::resolver::CjsResolutionStore; use crate::resolver::CliGraphResolver; use crate::resolver::CliGraphResolverOptions; +use crate::resolver::CliNodeResolver; +use crate::resolver::NpmModuleLoader; use crate::resolver::SloppyImportsResolver; use crate::standalone::DenoCompileBinaryWriter; use crate::tools::check::TypeChecker; diff --git a/cli/module_loader.rs b/cli/module_loader.rs index e6329a0ec..3d80aeb5c 100644 --- a/cli/module_loader.rs +++ b/cli/module_loader.rs @@ -14,9 +14,10 @@ use crate::graph_util::FileWatcherReporter; use crate::graph_util::ModuleGraphBuilder; use crate::graph_util::ModuleGraphContainer; use crate::node; -use crate::node::CliNodeCodeTranslator; -use crate::npm::CliNpmResolver; use crate::resolver::CliGraphResolver; +use crate::resolver::CliNodeResolver; +use crate::resolver::ModuleCodeStringSource; +use crate::resolver::NpmModuleLoader; use crate::tools::check; use crate::tools::check::TypeChecker; use crate::util::progress_bar::ProgressBar; @@ -53,14 +54,10 @@ use deno_graph::Resolution; use deno_lockfile::Lockfile; use deno_runtime::colors; use deno_runtime::deno_fs; -use deno_runtime::deno_node::NodeResolution; -use deno_runtime::deno_node::NodeResolutionMode; -use deno_runtime::deno_node::NodeResolver; use deno_runtime::permissions::PermissionsContainer; use deno_semver::npm::NpmPackageReqReference; use std::borrow::Cow; use std::collections::HashSet; -use std::path::Path; use std::pin::Pin; use std::rc::Rc; use std::str; @@ -271,12 +268,6 @@ impl ModuleLoadPreparer { } } -pub struct ModuleCodeStringSource { - pub code: ModuleCodeString, - pub found_url: ModuleSpecifier, - pub media_type: MediaType, -} - struct PreparedModuleLoader { emitter: Arc<Emitter>, graph_container: Arc<ModuleGraphContainer>, @@ -741,226 +732,3 @@ impl SourceMapGetter for CliSourceMapGetter { } } } - -pub struct CliNodeResolver { - cjs_resolutions: Arc<CjsResolutionStore>, - node_resolver: Arc<NodeResolver>, - npm_resolver: Arc<dyn CliNpmResolver>, -} - -impl CliNodeResolver { - pub fn new( - cjs_resolutions: Arc<CjsResolutionStore>, - node_resolver: Arc<NodeResolver>, - npm_resolver: Arc<dyn CliNpmResolver>, - ) -> Self { - Self { - cjs_resolutions, - node_resolver, - npm_resolver, - } - } - - pub fn in_npm_package(&self, referrer: &ModuleSpecifier) -> bool { - self.npm_resolver.in_npm_package(referrer) - } - - pub fn resolve_if_in_npm_package( - &self, - specifier: &str, - referrer: &ModuleSpecifier, - permissions: &PermissionsContainer, - ) -> Option<Result<ModuleSpecifier, AnyError>> { - if self.in_npm_package(referrer) { - // we're in an npm package, so use node resolution - Some( - self - .handle_node_resolve_result(self.node_resolver.resolve( - specifier, - referrer, - NodeResolutionMode::Execution, - permissions, - )) - .with_context(|| { - format!("Could not resolve '{specifier}' from '{referrer}'.") - }), - ) - } else { - None - } - } - - pub fn resolve_req_reference( - &self, - req_ref: &NpmPackageReqReference, - permissions: &PermissionsContainer, - referrer: &ModuleSpecifier, - ) -> Result<ModuleSpecifier, AnyError> { - let package_folder = self - .npm_resolver - .resolve_pkg_folder_from_deno_module_req(req_ref.req(), referrer)?; - self - .resolve_package_sub_path( - &package_folder, - req_ref.sub_path(), - referrer, - permissions, - ) - .with_context(|| format!("Could not resolve '{}'.", req_ref)) - } - - pub fn resolve_package_sub_path( - &self, - package_folder: &Path, - sub_path: Option<&str>, - referrer: &ModuleSpecifier, - permissions: &PermissionsContainer, - ) -> Result<ModuleSpecifier, AnyError> { - self.handle_node_resolve_result( - self.node_resolver.resolve_package_subpath_from_deno_module( - package_folder, - sub_path, - referrer, - NodeResolutionMode::Execution, - permissions, - ), - ) - } - - fn handle_node_resolve_result( - &self, - result: Result<Option<NodeResolution>, AnyError>, - ) -> Result<ModuleSpecifier, AnyError> { - let response = match result? { - Some(response) => response, - None => return Err(generic_error("not found")), - }; - if let NodeResolution::CommonJs(specifier) = &response { - // remember that this was a common js resolution - self.cjs_resolutions.insert(specifier.clone()); - } - Ok(response.into_url()) - } -} - -pub struct NpmModuleLoader { - cjs_resolutions: Arc<CjsResolutionStore>, - node_code_translator: Arc<CliNodeCodeTranslator>, - fs: Arc<dyn deno_fs::FileSystem>, - node_resolver: Arc<CliNodeResolver>, -} - -impl NpmModuleLoader { - pub fn new( - cjs_resolutions: Arc<CjsResolutionStore>, - node_code_translator: Arc<CliNodeCodeTranslator>, - fs: Arc<dyn deno_fs::FileSystem>, - node_resolver: Arc<CliNodeResolver>, - ) -> Self { - Self { - cjs_resolutions, - node_code_translator, - fs, - node_resolver, - } - } - - pub fn maybe_prepare_load( - &self, - specifier: &ModuleSpecifier, - ) -> Option<Result<(), AnyError>> { - if self.node_resolver.in_npm_package(specifier) { - // nothing to prepare - Some(Ok(())) - } else { - None - } - } - - pub fn load_sync_if_in_npm_package( - &self, - specifier: &ModuleSpecifier, - maybe_referrer: Option<&ModuleSpecifier>, - permissions: &PermissionsContainer, - ) -> Option<Result<ModuleCodeStringSource, AnyError>> { - if self.node_resolver.in_npm_package(specifier) { - Some(self.load_sync(specifier, maybe_referrer, permissions)) - } else { - None - } - } - - fn load_sync( - &self, - specifier: &ModuleSpecifier, - maybe_referrer: Option<&ModuleSpecifier>, - permissions: &PermissionsContainer, - ) -> Result<ModuleCodeStringSource, AnyError> { - let file_path = specifier.to_file_path().unwrap(); - let code = self - .fs - .read_text_file_sync(&file_path) - .map_err(AnyError::from) - .with_context(|| { - if file_path.is_dir() { - // directory imports are not allowed when importing from an - // ES module, so provide the user with a helpful error message - let dir_path = file_path; - let mut msg = "Directory import ".to_string(); - msg.push_str(&dir_path.to_string_lossy()); - if let Some(referrer) = &maybe_referrer { - msg.push_str(" is not supported resolving import from "); - msg.push_str(referrer.as_str()); - let entrypoint_name = ["index.mjs", "index.js", "index.cjs"] - .iter() - .find(|e| dir_path.join(e).is_file()); - if let Some(entrypoint_name) = entrypoint_name { - msg.push_str("\nDid you mean to import "); - msg.push_str(entrypoint_name); - msg.push_str(" within the directory?"); - } - } - msg - } else { - let mut msg = "Unable to load ".to_string(); - msg.push_str(&file_path.to_string_lossy()); - if let Some(referrer) = &maybe_referrer { - msg.push_str(" imported from "); - msg.push_str(referrer.as_str()); - } - msg - } - })?; - - let code = if self.cjs_resolutions.contains(specifier) { - // translate cjs to esm if it's cjs and inject node globals - self.node_code_translator.translate_cjs_to_esm( - specifier, - Some(code.as_str()), - permissions, - )? - } else { - // esm and json code is untouched - code - }; - Ok(ModuleCodeStringSource { - code: code.into(), - found_url: specifier.clone(), - media_type: MediaType::from_specifier(specifier), - }) - } -} - -/// Keeps track of what module specifiers were resolved as CJS. -#[derive(Debug, Default)] -pub struct CjsResolutionStore(Mutex<HashSet<ModuleSpecifier>>); - -impl CjsResolutionStore { - pub fn contains(&self, specifier: &ModuleSpecifier) -> bool { - self.0.lock().contains(specifier) - } - - pub fn insert(&self, specifier: ModuleSpecifier) { - self.0.lock().insert(specifier); - } -} diff --git a/cli/resolver.rs b/cli/resolver.rs index 2bd947c34..2c04823a7 100644 --- a/cli/resolver.rs +++ b/cli/resolver.rs @@ -2,11 +2,14 @@ use deno_ast::MediaType; use deno_core::anyhow::anyhow; +use deno_core::anyhow::Context; +use deno_core::error::generic_error; use deno_core::error::AnyError; use deno_core::futures::future; use deno_core::futures::future::LocalBoxFuture; use deno_core::futures::FutureExt; use deno_core::parking_lot::Mutex; +use deno_core::ModuleCodeString; use deno_core::ModuleSpecifier; use deno_graph::source::NpmPackageReqResolution; use deno_graph::source::NpmResolver; @@ -15,6 +18,7 @@ use deno_graph::source::ResolveError; use deno_graph::source::Resolver; use deno_graph::source::UnknownBuiltInNodeModuleError; use deno_graph::source::DEFAULT_JSX_IMPORT_SOURCE_MODULE; +use deno_runtime::deno_fs; use deno_runtime::deno_fs::FileSystem; use deno_runtime::deno_node::is_builtin_node_module; use deno_runtime::deno_node::parse_npm_pkg_name; @@ -28,6 +32,7 @@ use deno_semver::package::PackageReq; use import_map::ImportMap; use std::borrow::Cow; use std::collections::HashMap; +use std::collections::HashSet; use std::path::Path; use std::path::PathBuf; use std::sync::Arc; @@ -36,13 +41,242 @@ use crate::args::package_json::PackageJsonDeps; use crate::args::JsxImportSourceConfig; use crate::args::PackageJsonDepsProvider; use crate::graph_util::format_range_with_colors; -use crate::module_loader::CjsResolutionStore; +use crate::node::CliNodeCodeTranslator; use crate::npm::ByonmCliNpmResolver; use crate::npm::CliNpmResolver; use crate::npm::InnerCliNpmResolverRef; use crate::util::path::specifier_to_file_path; use crate::util::sync::AtomicFlag; +pub struct ModuleCodeStringSource { + pub code: ModuleCodeString, + pub found_url: ModuleSpecifier, + pub media_type: MediaType, +} + +pub struct CliNodeResolver { + cjs_resolutions: Arc<CjsResolutionStore>, + node_resolver: Arc<NodeResolver>, + pub(crate) npm_resolver: Arc<dyn CliNpmResolver>, +} + +impl CliNodeResolver { + pub fn new( + cjs_resolutions: Arc<CjsResolutionStore>, + node_resolver: Arc<NodeResolver>, + npm_resolver: Arc<dyn CliNpmResolver>, + ) -> Self { + Self { + cjs_resolutions, + node_resolver, + npm_resolver, + } + } + + pub fn in_npm_package(&self, referrer: &ModuleSpecifier) -> bool { + self.npm_resolver.in_npm_package(referrer) + } + + pub fn resolve_if_in_npm_package( + &self, + specifier: &str, + referrer: &ModuleSpecifier, + permissions: &PermissionsContainer, + ) -> Option<Result<ModuleSpecifier, AnyError>> { + if self.in_npm_package(referrer) { + // we're in an npm package, so use node resolution + Some( + self + .handle_node_resolve_result(self.node_resolver.resolve( + specifier, + referrer, + NodeResolutionMode::Execution, + permissions, + )) + .with_context(|| { + format!("Could not resolve '{specifier}' from '{referrer}'.") + }), + ) + } else { + None + } + } + + pub fn resolve_req_reference( + &self, + req_ref: &NpmPackageReqReference, + permissions: &PermissionsContainer, + referrer: &ModuleSpecifier, + ) -> Result<ModuleSpecifier, AnyError> { + let package_folder = self + .npm_resolver + .resolve_pkg_folder_from_deno_module_req(req_ref.req(), referrer)?; + self + .resolve_package_sub_path( + &package_folder, + req_ref.sub_path(), + referrer, + permissions, + ) + .with_context(|| format!("Could not resolve '{}'.", req_ref)) + } + + pub fn resolve_package_sub_path( + &self, + package_folder: &Path, + sub_path: Option<&str>, + referrer: &ModuleSpecifier, + permissions: &PermissionsContainer, + ) -> Result<ModuleSpecifier, AnyError> { + self.handle_node_resolve_result( + self.node_resolver.resolve_package_subpath_from_deno_module( + package_folder, + sub_path, + referrer, + NodeResolutionMode::Execution, + permissions, + ), + ) + } + + fn handle_node_resolve_result( + &self, + result: Result<Option<NodeResolution>, AnyError>, + ) -> Result<ModuleSpecifier, AnyError> { + let response = match result? { + Some(response) => response, + None => return Err(generic_error("not found")), + }; + if let NodeResolution::CommonJs(specifier) = &response { + // remember that this was a common js resolution + self.cjs_resolutions.insert(specifier.clone()); + } + Ok(response.into_url()) + } +} + +pub struct NpmModuleLoader { + cjs_resolutions: Arc<CjsResolutionStore>, + node_code_translator: Arc<CliNodeCodeTranslator>, + fs: Arc<dyn deno_fs::FileSystem>, + node_resolver: Arc<CliNodeResolver>, +} + +impl NpmModuleLoader { + pub fn new( + cjs_resolutions: Arc<CjsResolutionStore>, + node_code_translator: Arc<CliNodeCodeTranslator>, + fs: Arc<dyn deno_fs::FileSystem>, + node_resolver: Arc<CliNodeResolver>, + ) -> Self { + Self { + cjs_resolutions, + node_code_translator, + fs, + node_resolver, + } + } + + pub fn maybe_prepare_load( + &self, + specifier: &ModuleSpecifier, + ) -> Option<Result<(), AnyError>> { + if self.node_resolver.in_npm_package(specifier) { + // nothing to prepare + Some(Ok(())) + } else { + None + } + } + + pub fn load_sync_if_in_npm_package( + &self, + specifier: &ModuleSpecifier, + maybe_referrer: Option<&ModuleSpecifier>, + permissions: &PermissionsContainer, + ) -> Option<Result<ModuleCodeStringSource, AnyError>> { + if self.node_resolver.in_npm_package(specifier) { + Some(self.load_sync(specifier, maybe_referrer, permissions)) + } else { + None + } + } + + fn load_sync( + &self, + specifier: &ModuleSpecifier, + maybe_referrer: Option<&ModuleSpecifier>, + permissions: &PermissionsContainer, + ) -> Result<ModuleCodeStringSource, AnyError> { + let file_path = specifier.to_file_path().unwrap(); + let code = self + .fs + .read_text_file_sync(&file_path) + .map_err(AnyError::from) + .with_context(|| { + if file_path.is_dir() { + // directory imports are not allowed when importing from an + // ES module, so provide the user with a helpful error message + let dir_path = file_path; + let mut msg = "Directory import ".to_string(); + msg.push_str(&dir_path.to_string_lossy()); + if let Some(referrer) = &maybe_referrer { + msg.push_str(" is not supported resolving import from "); + msg.push_str(referrer.as_str()); + let entrypoint_name = ["index.mjs", "index.js", "index.cjs"] + .iter() + .find(|e| dir_path.join(e).is_file()); + if let Some(entrypoint_name) = entrypoint_name { + msg.push_str("\nDid you mean to import "); + msg.push_str(entrypoint_name); + msg.push_str(" within the directory?"); + } + } + msg + } else { + let mut msg = "Unable to load ".to_string(); + msg.push_str(&file_path.to_string_lossy()); + if let Some(referrer) = &maybe_referrer { + msg.push_str(" imported from "); + msg.push_str(referrer.as_str()); + } + msg + } + })?; + + let code = if self.cjs_resolutions.contains(specifier) { + // translate cjs to esm if it's cjs and inject node globals + self.node_code_translator.translate_cjs_to_esm( + specifier, + Some(code.as_str()), + permissions, + )? + } else { + // esm and json code is untouched + code + }; + Ok(ModuleCodeStringSource { + code: code.into(), + found_url: specifier.clone(), + media_type: MediaType::from_specifier(specifier), + }) + } +} + +/// Keeps track of what module specifiers were resolved as CJS. +#[derive(Debug, Default)] +pub struct CjsResolutionStore(Mutex<HashSet<ModuleSpecifier>>); + +impl CjsResolutionStore { + pub fn contains(&self, specifier: &ModuleSpecifier) -> bool { + self.0.lock().contains(specifier) + } + + pub fn insert(&self, specifier: ModuleSpecifier) { + self.0.lock().insert(specifier); + } +} + /// Result of checking if a specifier is mapped via /// an import map or package.json. pub enum MappedResolution { diff --git a/cli/standalone/mod.rs b/cli/standalone/mod.rs index f3763004c..6859c6a62 100644 --- a/cli/standalone/mod.rs +++ b/cli/standalone/mod.rs @@ -11,9 +11,6 @@ use crate::cache::DenoDirProvider; use crate::cache::NodeAnalysisCache; use crate::file_fetcher::get_source_from_data_url; use crate::http_util::HttpClient; -use crate::module_loader::CjsResolutionStore; -use crate::module_loader::CliNodeResolver; -use crate::module_loader::NpmModuleLoader; use crate::node::CliCjsCodeAnalyzer; use crate::npm::create_cli_npm_resolver; use crate::npm::CliNpmResolverByonmCreateOptions; @@ -22,7 +19,10 @@ use crate::npm::CliNpmResolverManagedCreateOptions; use crate::npm::CliNpmResolverManagedPackageJsonInstallerOption; use crate::npm::CliNpmResolverManagedSnapshotOption; use crate::npm::NpmCacheDir; +use crate::resolver::CjsResolutionStore; +use crate::resolver::CliNodeResolver; use crate::resolver::MappedSpecifierResolver; +use crate::resolver::NpmModuleLoader; use crate::util::progress_bar::ProgressBar; use crate::util::progress_bar::ProgressBarStyle; use crate::util::v8::construct_v8_flags; |