diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2024-03-21 11:35:51 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-21 11:35:51 -0700 |
commit | 9abc722cc3a998b4f73103c4394b53cccdb5c83b (patch) | |
tree | 228a9eb9665439e52b9588830a80dd6c8ef1499e /cli | |
parent | a90a6f3b291d2a30750c2578fc3763246a182dea (diff) |
feat(node): load ES modules defined as CJS (#22945)
Changes the behaviour in Deno to just always load ES modules in npm
packages even if they're defined as CJS.
Closes #22818
Diffstat (limited to 'cli')
-rw-r--r-- | cli/cache/node.rs | 19 | ||||
-rw-r--r-- | cli/node.rs | 58 | ||||
-rw-r--r-- | cli/resolver.rs | 2 |
3 files changed, 50 insertions, 29 deletions
diff --git a/cli/cache/node.rs b/cli/cache/node.rs index c9286c382..29658bd90 100644 --- a/cli/cache/node.rs +++ b/cli/cache/node.rs @@ -1,10 +1,11 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_ast::CjsAnalysis; use deno_core::error::AnyError; use deno_core::serde_json; use deno_runtime::deno_webstorage::rusqlite::params; +use crate::node::CliCjsAnalysis; + use super::cache_db::CacheDB; use super::cache_db::CacheDBConfiguration; use super::cache_db::CacheFailure; @@ -59,7 +60,7 @@ impl NodeAnalysisCache { &self, specifier: &str, expected_source_hash: &str, - ) -> Option<CjsAnalysis> { + ) -> Option<CliCjsAnalysis> { Self::ensure_ok( self.inner.get_cjs_analysis(specifier, expected_source_hash), ) @@ -69,7 +70,7 @@ impl NodeAnalysisCache { &self, specifier: &str, source_hash: &str, - cjs_analysis: &CjsAnalysis, + cjs_analysis: &CliCjsAnalysis, ) { Self::ensure_ok(self.inner.set_cjs_analysis( specifier, @@ -93,7 +94,7 @@ impl NodeAnalysisCacheInner { &self, specifier: &str, expected_source_hash: &str, - ) -> Result<Option<CjsAnalysis>, AnyError> { + ) -> Result<Option<CliCjsAnalysis>, AnyError> { let query = " SELECT data @@ -118,7 +119,7 @@ impl NodeAnalysisCacheInner { &self, specifier: &str, source_hash: &str, - cjs_analysis: &CjsAnalysis, + cjs_analysis: &CliCjsAnalysis, ) -> Result<(), AnyError> { let sql = " INSERT OR REPLACE INTO @@ -147,7 +148,7 @@ mod test { let cache = NodeAnalysisCacheInner::new(conn); assert!(cache.get_cjs_analysis("file.js", "2").unwrap().is_none()); - let cjs_analysis = CjsAnalysis { + let cjs_analysis = CliCjsAnalysis::Cjs { exports: vec!["export1".to_string()], reexports: vec!["re-export1".to_string()], }; @@ -157,8 +158,7 @@ mod test { assert!(cache.get_cjs_analysis("file.js", "3").unwrap().is_none()); // different hash let actual_cjs_analysis = cache.get_cjs_analysis("file.js", "2").unwrap().unwrap(); - assert_eq!(actual_cjs_analysis.exports, cjs_analysis.exports); - assert_eq!(actual_cjs_analysis.reexports, cjs_analysis.reexports); + assert_eq!(actual_cjs_analysis, cjs_analysis); // adding when already exists should not cause issue cache @@ -170,8 +170,7 @@ mod test { let cache = NodeAnalysisCacheInner::new(conn); let actual_analysis = cache.get_cjs_analysis("file.js", "2").unwrap().unwrap(); - assert_eq!(actual_analysis.exports, cjs_analysis.exports); - assert_eq!(actual_analysis.reexports, cjs_analysis.reexports); + assert_eq!(actual_analysis, cjs_analysis); // now changing the cli version should clear it let conn = cache.conn.recreate_with_version("2.0.0"); diff --git a/cli/node.rs b/cli/node.rs index cbe0aaaf1..5f0ecc653 100644 --- a/cli/node.rs +++ b/cli/node.rs @@ -1,15 +1,15 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use std::borrow::Cow; - -use deno_ast::CjsAnalysis; use deno_ast::MediaType; use deno_ast::ModuleSpecifier; use deno_core::error::AnyError; use deno_runtime::deno_fs; use deno_runtime::deno_node::analyze::CjsAnalysis as ExtNodeCjsAnalysis; +use deno_runtime::deno_node::analyze::CjsAnalysisExports; use deno_runtime::deno_node::analyze::CjsCodeAnalyzer; use deno_runtime::deno_node::analyze::NodeCodeTranslator; +use serde::Deserialize; +use serde::Serialize; use crate::cache::NodeAnalysisCache; use crate::util::fs::canonicalize_path_maybe_not_exists; @@ -35,6 +35,17 @@ pub fn resolve_specifier_into_node_modules( .unwrap_or_else(|| specifier.clone()) } +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum CliCjsAnalysis { + /// The module was found to be an ES module. + Esm, + /// The module was CJS. + Cjs { + exports: Vec<String>, + reexports: Vec<String>, + }, +} + pub struct CliCjsCodeAnalyzer { cache: NodeAnalysisCache, fs: deno_fs::FileSystemRc, @@ -49,7 +60,7 @@ impl CliCjsCodeAnalyzer { &self, specifier: &ModuleSpecifier, source: &str, - ) -> Result<CjsAnalysis, AnyError> { + ) -> Result<CliCjsAnalysis, AnyError> { let source_hash = NodeAnalysisCache::compute_source_hash(source); if let Some(analysis) = self .cache @@ -60,13 +71,13 @@ impl CliCjsCodeAnalyzer { let media_type = MediaType::from_specifier(specifier); if media_type == MediaType::Json { - return Ok(CjsAnalysis { + return Ok(CliCjsAnalysis::Cjs { exports: vec![], reexports: vec![], }); } - let parsed_source = deno_ast::parse_script(deno_ast::ParseParams { + let parsed_source = deno_ast::parse_program(deno_ast::ParseParams { specifier: specifier.clone(), text_info: deno_ast::SourceTextInfo::new(source.into()), media_type, @@ -74,7 +85,15 @@ impl CliCjsCodeAnalyzer { scope_analysis: false, maybe_syntax: None, })?; - let analysis = parsed_source.analyze_cjs(); + let analysis = if parsed_source.is_script() { + let analysis = parsed_source.analyze_cjs(); + CliCjsAnalysis::Cjs { + exports: analysis.exports, + reexports: analysis.reexports, + } + } else { + CliCjsAnalysis::Esm + }; self .cache .set_cjs_analysis(specifier.as_str(), &source_hash, &analysis); @@ -87,20 +106,23 @@ impl CjsCodeAnalyzer for CliCjsCodeAnalyzer { fn analyze_cjs( &self, specifier: &ModuleSpecifier, - source: Option<&str>, + source: Option<String>, ) -> Result<ExtNodeCjsAnalysis, AnyError> { let source = match source { - Some(source) => Cow::Borrowed(source), - None => Cow::Owned( - self - .fs - .read_text_file_sync(&specifier.to_file_path().unwrap())?, - ), + Some(source) => source, + None => self + .fs + .read_text_file_sync(&specifier.to_file_path().unwrap())?, }; let analysis = self.inner_cjs_analysis(specifier, &source)?; - Ok(ExtNodeCjsAnalysis { - exports: analysis.exports, - reexports: analysis.reexports, - }) + match analysis { + CliCjsAnalysis::Esm => Ok(ExtNodeCjsAnalysis::Esm(source)), + CliCjsAnalysis::Cjs { exports, reexports } => { + Ok(ExtNodeCjsAnalysis::Cjs(CjsAnalysisExports { + exports, + reexports, + })) + } + } } } diff --git a/cli/resolver.rs b/cli/resolver.rs index 495b3f9b5..6594bf2d4 100644 --- a/cli/resolver.rs +++ b/cli/resolver.rs @@ -334,7 +334,7 @@ impl NpmModuleLoader { // 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()), + Some(code), permissions, )? } else { |