diff options
Diffstat (limited to 'ext/node/analyze.rs')
-rw-r--r-- | ext/node/analyze.rs | 110 |
1 files changed, 59 insertions, 51 deletions
diff --git a/ext/node/analyze.rs b/ext/node/analyze.rs index a206f4425..f1af2f611 100644 --- a/ext/node/analyze.rs +++ b/ext/node/analyze.rs @@ -5,6 +5,7 @@ use std::collections::VecDeque; use std::fmt::Write; use std::path::Path; use std::path::PathBuf; +use std::sync::Arc; use deno_core::anyhow::Context; use deno_core::ModuleSpecifier; @@ -12,11 +13,11 @@ use once_cell::sync::Lazy; use deno_core::error::AnyError; -use crate::package_exports_resolve; use crate::NodeFs; use crate::NodeModuleKind; use crate::NodePermissions; use crate::NodeResolutionMode; +use crate::NodeResolver; use crate::NpmResolver; use crate::PackageJson; use crate::PathClean; @@ -64,23 +65,26 @@ pub trait CjsEsmCodeAnalyzer { ) -> Result<HashSet<String>, AnyError>; } -pub struct NodeCodeTranslator< - TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, - TNpmResolver: NpmResolver, -> { +pub struct NodeCodeTranslator<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer> { cjs_esm_code_analyzer: TCjsEsmCodeAnalyzer, - npm_resolver: TNpmResolver, + fs: Arc<dyn NodeFs>, + node_resolver: Arc<NodeResolver>, + npm_resolver: Arc<dyn NpmResolver>, } -impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver> - NodeCodeTranslator<TCjsEsmCodeAnalyzer, TNpmResolver> +impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer> + NodeCodeTranslator<TCjsEsmCodeAnalyzer> { pub fn new( cjs_esm_code_analyzer: TCjsEsmCodeAnalyzer, - npm_resolver: TNpmResolver, + fs: Arc<dyn NodeFs>, + node_resolver: Arc<NodeResolver>, + npm_resolver: Arc<dyn NpmResolver>, ) -> Self { Self { cjs_esm_code_analyzer, + fs, + node_resolver, npm_resolver, } } @@ -105,7 +109,7 @@ impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver> /// For all discovered reexports the analysis will be performed recursively. /// /// If successful a source code for equivalent ES module is returned. - pub fn translate_cjs_to_esm<Fs: NodeFs>( + pub fn translate_cjs_to_esm( &self, specifier: &ModuleSpecifier, source: &str, @@ -142,7 +146,7 @@ impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver> handled_reexports.insert(reexport.to_string()); // First, resolve relate reexport specifier - let resolved_reexport = self.resolve::<Fs>( + let resolved_reexport = self.resolve( &reexport, &referrer, // FIXME(bartlomieju): check if these conditions are okay, probably @@ -154,7 +158,9 @@ impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver> // Second, read the source code from disk let reexport_specifier = ModuleSpecifier::from_file_path(&resolved_reexport).unwrap(); - let reexport_file_text = Fs::read_to_string(&resolved_reexport) + let reexport_file_text = self + .fs + .read_to_string(&resolved_reexport) .with_context(|| { format!( "Could not find '{}' ({}) referenced from {}", @@ -208,7 +214,7 @@ impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver> Ok(translated_source) } - fn resolve<Fs: NodeFs>( + fn resolve( &self, specifier: &str, referrer: &ModuleSpecifier, @@ -223,10 +229,8 @@ impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver> let referrer_path = referrer.to_file_path().unwrap(); if specifier.starts_with("./") || specifier.starts_with("../") { if let Some(parent) = referrer_path.parent() { - return file_extension_probe::<Fs>( - parent.join(specifier), - &referrer_path, - ); + return self + .file_extension_probe(parent.join(specifier), &referrer_path); } else { todo!(); } @@ -245,15 +249,16 @@ impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver> )?; let package_json_path = module_dir.join("package.json"); - if Fs::exists(&package_json_path) { - let package_json = PackageJson::load::<Fs>( - &self.npm_resolver, + if self.fs.exists(&package_json_path) { + let package_json = PackageJson::load( + &*self.fs, + &*self.npm_resolver, permissions, package_json_path.clone(), )?; if let Some(exports) = &package_json.exports { - return package_exports_resolve::<Fs>( + return self.node_resolver.package_exports_resolve( &package_json_path, package_subpath, exports, @@ -261,7 +266,6 @@ impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver> NodeModuleKind::Esm, conditions, mode, - &self.npm_resolver, permissions, ); } @@ -269,12 +273,13 @@ impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver> // old school if package_subpath != "." { let d = module_dir.join(package_subpath); - if Fs::is_dir(&d) { + if self.fs.is_dir(&d) { // subdir might have a package.json that specifies the entrypoint let package_json_path = d.join("package.json"); - if Fs::exists(&package_json_path) { - let package_json = PackageJson::load::<Fs>( - &self.npm_resolver, + if self.fs.exists(&package_json_path) { + let package_json = PackageJson::load( + &*self.fs, + &*self.npm_resolver, permissions, package_json_path, )?; @@ -285,7 +290,7 @@ impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver> return Ok(d.join("index.js").clean()); } - return file_extension_probe::<Fs>(d, &referrer_path); + return self.file_extension_probe(d, &referrer_path); } else if let Some(main) = package_json.main(NodeModuleKind::Cjs) { return Ok(module_dir.join(main).clean()); } else { @@ -294,6 +299,33 @@ impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver> } Err(not_found(specifier, &referrer_path)) } + + fn file_extension_probe( + &self, + p: PathBuf, + referrer: &Path, + ) -> Result<PathBuf, AnyError> { + let p = p.clean(); + if self.fs.exists(&p) { + let file_name = p.file_name().unwrap(); + let p_js = + p.with_file_name(format!("{}.js", file_name.to_str().unwrap())); + if self.fs.is_file(&p_js) { + return Ok(p_js); + } else if self.fs.is_dir(&p) { + return Ok(p.join("index.js")); + } else { + return Ok(p); + } + } else if let Some(file_name) = p.file_name() { + let p_js = + p.with_file_name(format!("{}.js", file_name.to_str().unwrap())); + if self.fs.is_file(&p_js) { + return Ok(p_js); + } + } + Err(not_found(&p.to_string_lossy(), referrer)) + } } fn esm_code_from_top_level_decls( @@ -455,30 +487,6 @@ fn parse_specifier(specifier: &str) -> Option<(String, String)> { Some((package_name, package_subpath)) } -fn file_extension_probe<Fs: NodeFs>( - p: PathBuf, - referrer: &Path, -) -> Result<PathBuf, AnyError> { - let p = p.clean(); - if Fs::exists(&p) { - let file_name = p.file_name().unwrap(); - let p_js = p.with_file_name(format!("{}.js", file_name.to_str().unwrap())); - if Fs::is_file(&p_js) { - return Ok(p_js); - } else if Fs::is_dir(&p) { - return Ok(p.join("index.js")); - } else { - return Ok(p); - } - } else if let Some(file_name) = p.file_name() { - let p_js = p.with_file_name(format!("{}.js", file_name.to_str().unwrap())); - if Fs::is_file(&p_js) { - return Ok(p_js); - } - } - Err(not_found(&p.to_string_lossy(), referrer)) -} - fn not_found(path: &str, referrer: &Path) -> AnyError { let msg = format!( "[ERR_MODULE_NOT_FOUND] Cannot find module \"{}\" imported from \"{}\"", |