From 9abc722cc3a998b4f73103c4394b53cccdb5c83b Mon Sep 17 00:00:00 2001 From: David Sherret Date: Thu, 21 Mar 2024 11:35:51 -0700 Subject: 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 --- ext/node/analyze.rs | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) (limited to 'ext/node/analyze.rs') diff --git a/ext/node/analyze.rs b/ext/node/analyze.rs index 2a0324ccf..0a0226625 100644 --- a/ext/node/analyze.rs +++ b/ext/node/analyze.rs @@ -5,6 +5,7 @@ use std::collections::VecDeque; use std::path::Path; use std::path::PathBuf; +use deno_core::anyhow; use deno_core::anyhow::Context; use deno_core::ModuleSpecifier; use once_cell::sync::Lazy; @@ -21,7 +22,15 @@ use crate::PackageJson; use crate::PathClean; #[derive(Debug, Clone)] -pub struct CjsAnalysis { +pub enum CjsAnalysis { + /// File was found to be an ES module and the translator should + /// load the code as ESM. + Esm(String), + Cjs(CjsAnalysisExports), +} + +#[derive(Debug, Clone)] +pub struct CjsAnalysisExports { pub exports: Vec, pub reexports: Vec, } @@ -38,7 +47,7 @@ pub trait CjsCodeAnalyzer { fn analyze_cjs( &self, specifier: &ModuleSpecifier, - maybe_source: Option<&str>, + maybe_source: Option, ) -> Result; } @@ -73,7 +82,7 @@ impl NodeCodeTranslator { pub fn translate_cjs_to_esm( &self, specifier: &ModuleSpecifier, - source: Option<&str>, + source: Option, permissions: &dyn NodePermissions, ) -> Result { let mut temp_var_count = 0; @@ -81,6 +90,11 @@ impl NodeCodeTranslator { let analysis = self.cjs_code_analyzer.analyze_cjs(specifier, source)?; + let analysis = match analysis { + CjsAnalysis::Esm(source) => return Ok(source), + CjsAnalysis::Cjs(analysis) => analysis, + }; + let mut source = vec![ r#"import {createRequire as __internalCreateRequire} from "node:module"; const require = __internalCreateRequire(import.meta.url);"# @@ -127,6 +141,17 @@ impl NodeCodeTranslator { reexport, reexport_specifier, referrer ) })?; + let analysis = match analysis { + CjsAnalysis::Esm(_) => { + // todo(dsherret): support this once supporting requiring ES modules + return Err(anyhow::anyhow!( + "Cannot require ES module '{}' from '{}'", + reexport_specifier, + specifier + )); + } + CjsAnalysis::Cjs(analysis) => analysis, + }; for reexport in analysis.reexports { reexports_to_handle.push_back((reexport, reexport_specifier.clone())); -- cgit v1.2.3