From ed65bc6abc0a164ea68fae62e9a4e545f729be2d Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Sat, 27 Jan 2024 22:40:36 +0530 Subject: refactor(cli): decouple resolvers from `module_loader.rs` for standalone use (#22147) It makes it easier to write a standalone bin target for `deno compile` without pulling a lot of the tooling and tsc loader logic --- cli/module_loader.rs | 238 +-------------------------------------------------- 1 file changed, 3 insertions(+), 235 deletions(-) (limited to 'cli/module_loader.rs') 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, graph_container: Arc, @@ -741,226 +732,3 @@ impl SourceMapGetter for CliSourceMapGetter { } } } - -pub struct CliNodeResolver { - cjs_resolutions: Arc, - node_resolver: Arc, - npm_resolver: Arc, -} - -impl CliNodeResolver { - pub fn new( - cjs_resolutions: Arc, - node_resolver: Arc, - npm_resolver: Arc, - ) -> 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> { - 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 { - 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 { - 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, 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()); - } - Ok(response.into_url()) - } -} - -pub struct NpmModuleLoader { - cjs_resolutions: Arc, - node_code_translator: Arc, - fs: Arc, - node_resolver: Arc, -} - -impl NpmModuleLoader { - pub fn new( - cjs_resolutions: Arc, - node_code_translator: Arc, - fs: Arc, - node_resolver: Arc, - ) -> Self { - Self { - cjs_resolutions, - node_code_translator, - fs, - node_resolver, - } - } - - 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_if_in_npm_package( - &self, - specifier: &ModuleSpecifier, - maybe_referrer: Option<&ModuleSpecifier>, - permissions: &PermissionsContainer, - ) -> Option> { - 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 { - 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>); - -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); - } -} -- cgit v1.2.3