diff --git a/cli/module_loader.rs b/cli/module_loader.rs index 0f0568272e..9798983748 100644 --- a/cli/module_loader.rs +++ b/cli/module_loader.rs @@ -222,7 +222,7 @@ impl ModuleLoadPreparer { } } -struct ModuleCodeSource { +pub struct ModuleCodeSource { pub code: ModuleCode, pub found_url: ModuleSpecifier, pub media_type: MediaType, @@ -238,14 +238,12 @@ pub struct CliModuleLoader { /// "root permissions" for Web Worker. dynamic_permissions: PermissionsContainer, cli_options: Arc, - cjs_resolutions: Arc, emitter: Arc, graph_container: Arc, module_load_preparer: Arc, - node_code_translator: Arc, - node_resolver: Arc, parsed_source_cache: Arc, resolver: Arc, + npm_module_loader: NpmModuleLoader, } impl CliModuleLoader { @@ -259,14 +257,16 @@ impl CliModuleLoader { root_permissions, dynamic_permissions, cli_options: ps.options.clone(), - cjs_resolutions: ps.cjs_resolutions.clone(), emitter: ps.emitter.clone(), graph_container: ps.graph_container.clone(), module_load_preparer: ps.module_load_preparer.clone(), - node_code_translator: ps.node_code_translator.clone(), - node_resolver: ps.node_resolver.clone(), parsed_source_cache: ps.parsed_source_cache.clone(), resolver: ps.resolver.clone(), + npm_module_loader: NpmModuleLoader::new( + ps.cjs_resolutions.clone(), + ps.node_code_translator.clone(), + ps.node_resolver.clone(), + ), }) } @@ -280,14 +280,16 @@ impl CliModuleLoader { root_permissions, dynamic_permissions, cli_options: ps.options.clone(), - cjs_resolutions: ps.cjs_resolutions.clone(), emitter: ps.emitter.clone(), graph_container: ps.graph_container.clone(), module_load_preparer: ps.module_load_preparer.clone(), - node_code_translator: ps.node_code_translator.clone(), - node_resolver: ps.node_resolver.clone(), parsed_source_cache: ps.parsed_source_cache.clone(), resolver: ps.resolver.clone(), + npm_module_loader: NpmModuleLoader::new( + ps.cjs_resolutions.clone(), + ps.node_code_translator.clone(), + ps.node_resolver.clone(), + ), }) } @@ -367,41 +369,16 @@ impl CliModuleLoader { maybe_referrer: Option<&ModuleSpecifier>, is_dynamic: bool, ) -> Result { - 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(); - 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) { - let mut permissions = if is_dynamic { - self.dynamic_permissions.clone() - } else { - self.root_permissions.clone() - }; - // translate cjs to esm if it's cjs and inject node globals - self.node_code_translator.translate_cjs_to_esm( - specifier, - &code, - &mut permissions, - )? - } else { - // only inject node globals for esm - self - .node_code_translator - .esm_code_with_node_globals(specifier, &code)? - }; - ModuleCodeSource { - code: code.into(), - found_url: specifier.clone(), - media_type: MediaType::from_specifier(specifier), - } + let permissions = if is_dynamic { + &self.dynamic_permissions + } else { + &self.root_permissions + }; + let code_source = if let Some(code_source) = self + .npm_module_loader + .load_sync(specifier, maybe_referrer, permissions)? + { + code_source } else { self.load_prepared_module(specifier, maybe_referrer)? }; @@ -424,23 +401,6 @@ impl CliModuleLoader { &code_source.found_url, )) } - - fn handle_node_resolve_result( - &self, - result: Result, AnyError>, - ) -> Result { - 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()); - } else if let NodeResolution::BuiltIn(specifier) = &response { - return deno_node::resolve_builtin_node_module(specifier); - } - Ok(response.into_url()) - } } impl ModuleLoader for CliModuleLoader { @@ -462,18 +422,12 @@ 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.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( - specifier, - referrer, - NodeResolutionMode::Execution, - permissions, - )) - .with_context(|| { - format!("Could not resolve '{specifier}' from '{referrer}'.") - }); + if let Some(result) = self.npm_module_loader.resolve_if_in_npm_package( + specifier, + referrer, + permissions, + ) { + return result; } let graph = self.graph_container.graph(); @@ -490,16 +444,8 @@ impl ModuleLoader for CliModuleLoader { return match graph.get(specifier) { Some(Module::Npm(module)) => self - .handle_node_resolve_result( - self.node_resolver.resolve_npm_reference( - &module.nv_reference, - NodeResolutionMode::Execution, - permissions, - ), - ) - .with_context(|| { - format!("Could not resolve '{}'.", module.nv_reference) - }), + .npm_module_loader + .resolve_npm_module(module, permissions), Some(Module::Node(module)) => { deno_node::resolve_builtin_node_module(&module.module_name) } @@ -552,14 +498,8 @@ impl ModuleLoader for CliModuleLoader { NpmPackageReqReference::from_specifier(&specifier) { return self - .handle_node_resolve_result( - self.node_resolver.resolve_npm_req_reference( - &reference, - NodeResolutionMode::Execution, - permissions, - ), - ) - .with_context(|| format!("Could not resolve '{reference}'.")); + .npm_module_loader + .resolve_for_repl(&reference, permissions); } } } @@ -590,9 +530,8 @@ impl ModuleLoader for CliModuleLoader { _maybe_referrer: Option, is_dynamic: bool, ) -> Pin>>> { - if self.node_resolver.in_npm_package(specifier) { - // nothing to prepare - return Box::pin(deno_core::futures::future::ready(Ok(()))); + if let Some(result) = self.npm_module_loader.maybe_prepare_load(specifier) { + return Box::pin(deno_core::futures::future::ready(result)); } let specifier = specifier.clone(); @@ -658,3 +597,145 @@ impl SourceMapGetter for CliModuleLoader { } } } + +pub struct NpmModuleLoader { + cjs_resolutions: Arc, + node_code_translator: Arc, + node_resolver: Arc, +} + +impl NpmModuleLoader { + pub fn new( + cjs_resolutions: Arc, + node_code_translator: Arc, + node_resolver: Arc, + ) -> Self { + Self { + cjs_resolutions, + node_code_translator, + node_resolver, + } + } + + pub fn resolve_if_in_npm_package( + &self, + specifier: &str, + referrer: &ModuleSpecifier, + permissions: &PermissionsContainer, + ) -> Option> { + if self.node_resolver.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_npm_module( + &self, + module: &deno_graph::NpmModule, + permissions: &PermissionsContainer, + ) -> Result { + self + .handle_node_resolve_result(self.node_resolver.resolve_npm_reference( + &module.nv_reference, + NodeResolutionMode::Execution, + permissions, + )) + .with_context(|| format!("Could not resolve '{}'.", module.nv_reference)) + } + + pub fn resolve_for_repl( + &self, + reference: &NpmPackageReqReference, + permissions: &PermissionsContainer, + ) -> Result { + self + .handle_node_resolve_result(self.node_resolver.resolve_npm_req_reference( + reference, + NodeResolutionMode::Execution, + permissions, + )) + .with_context(|| format!("Could not resolve '{reference}'.")) + } + + pub fn maybe_prepare_load( + &self, + specifier: &ModuleSpecifier, + ) -> Option> { + if self.node_resolver.in_npm_package(specifier) { + // nothing to prepare + Some(Ok(())) + } else { + None + } + } + + pub fn load_sync( + &self, + specifier: &ModuleSpecifier, + maybe_referrer: Option<&ModuleSpecifier>, + permissions: &PermissionsContainer, + ) -> Result, AnyError> { + if !self.node_resolver.in_npm_package(specifier) { + return Ok(None); + } + 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(); + 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, + &code, + permissions, + )? + } else { + // only inject node globals for esm + self + .node_code_translator + .esm_code_with_node_globals(specifier, &code)? + }; + Ok(Some(ModuleCodeSource { + code: code.into(), + found_url: specifier.clone(), + media_type: MediaType::from_specifier(specifier), + })) + } + + fn handle_node_resolve_result( + &self, + result: Result, AnyError>, + ) -> Result { + 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()); + } else if let NodeResolution::BuiltIn(specifier) = &response { + return deno_node::resolve_builtin_node_module(specifier); + } + Ok(response.into_url()) + } +} diff --git a/ext/node/analyze.rs b/ext/node/analyze.rs index f1af2f6110..c7181c4aca 100644 --- a/ext/node/analyze.rs +++ b/ext/node/analyze.rs @@ -113,7 +113,7 @@ impl &self, specifier: &ModuleSpecifier, source: &str, - permissions: &mut dyn NodePermissions, + permissions: &dyn NodePermissions, ) -> Result { let mut temp_var_count = 0; let mut handled_reexports: HashSet = HashSet::default(); @@ -220,7 +220,7 @@ impl referrer: &ModuleSpecifier, conditions: &[&str], mode: NodeResolutionMode, - permissions: &mut dyn NodePermissions, + permissions: &dyn NodePermissions, ) -> Result { if specifier.starts_with('/') { todo!();