summaryrefslogtreecommitdiff
path: root/cli/node
diff options
context:
space:
mode:
Diffstat (limited to 'cli/node')
-rw-r--r--cli/node/analyze.rs39
-rw-r--r--cli/node/mod.rs121
2 files changed, 89 insertions, 71 deletions
diff --git a/cli/node/analyze.rs b/cli/node/analyze.rs
index 270615cca..ed2536390 100644
--- a/cli/node/analyze.rs
+++ b/cli/node/analyze.rs
@@ -9,6 +9,7 @@ use deno_ast::ModuleSpecifier;
use deno_ast::ParsedSource;
use deno_ast::SourceRanged;
use deno_core::error::AnyError;
+use deno_runtime::deno_node::NODE_GLOBAL_THIS_NAME;
use std::fmt::Write;
static NODE_GLOBALS: &[&str] = &[
@@ -52,18 +53,7 @@ pub fn esm_code_with_node_globals(
}
let mut result = String::new();
- let has_deno_decl = top_level_decls.contains("Deno");
- let global_this_expr = if has_deno_decl {
- if top_level_decls.contains("window") {
- // Will probably never happen, but if it does then we should consider
- // creating an obscure global name to get this from.
- panic!("The node esm module had a local `Deno` declaration and `window` declaration.");
- }
- // fallback to using `window.Deno`
- "window.Deno[Deno.internal].node.globalThis"
- } else {
- "Deno[Deno.internal].node.globalThis"
- };
+ let global_this_expr = NODE_GLOBAL_THIS_NAME.as_str();
let global_this_expr = if has_global_this {
global_this_expr
} else {
@@ -162,7 +152,10 @@ mod tests {
"export const x = 1;".to_string(),
)
.unwrap();
- assert!(r.contains("var globalThis = Deno[Deno.internal].node.globalThis;"));
+ assert!(r.contains(&format!(
+ "var globalThis = {};",
+ NODE_GLOBAL_THIS_NAME.as_str()
+ )));
assert!(r.contains("var process = globalThis.process;"));
assert!(r.contains("export const x = 1;"));
}
@@ -176,14 +169,18 @@ mod tests {
.unwrap();
assert_eq!(
r,
- concat!(
- "var globalThis = Deno[Deno.internal].node.globalThis;var Buffer = globalThis.Buffer;",
- "var clearImmediate = globalThis.clearImmediate;var clearInterval = globalThis.clearInterval;",
- "var clearTimeout = globalThis.clearTimeout;var global = globalThis.global;",
- "var process = globalThis.process;var setImmediate = globalThis.setImmediate;",
- "var setInterval = globalThis.setInterval;var setTimeout = globalThis.setTimeout;\n",
- "export const x = 1;"
- ),
+ format!(
+ concat!(
+ "var globalThis = {}",
+ ";var Buffer = globalThis.Buffer;",
+ "var clearImmediate = globalThis.clearImmediate;var clearInterval = globalThis.clearInterval;",
+ "var clearTimeout = globalThis.clearTimeout;var global = globalThis.global;",
+ "var process = globalThis.process;var setImmediate = globalThis.setImmediate;",
+ "var setInterval = globalThis.setInterval;var setTimeout = globalThis.setTimeout;\n",
+ "export const x = 1;"
+ ),
+ NODE_GLOBAL_THIS_NAME.as_str(),
+ )
);
}
}
diff --git a/cli/node/mod.rs b/cli/node/mod.rs
index 14cc49473..9bc5b4a96 100644
--- a/cli/node/mod.rs
+++ b/cli/node/mod.rs
@@ -1,10 +1,12 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use std::collections::HashSet;
+use std::collections::VecDeque;
use std::path::Path;
use std::path::PathBuf;
use crate::deno_std::CURRENT_STD_URL;
+use deno_ast::CjsAnalysis;
use deno_ast::MediaType;
use deno_ast::ModuleSpecifier;
use deno_core::anyhow::bail;
@@ -25,6 +27,7 @@ use deno_runtime::deno_node::DenoDirNpmResolver;
use deno_runtime::deno_node::NodeModuleKind;
use deno_runtime::deno_node::PackageJson;
use deno_runtime::deno_node::DEFAULT_CONDITIONS;
+use deno_runtime::deno_node::NODE_GLOBAL_THIS_NAME;
use once_cell::sync::Lazy;
use path_clean::PathClean;
use regex::Regex;
@@ -326,11 +329,12 @@ pub async fn initialize_runtime(
js_runtime: &mut JsRuntime,
) -> Result<(), AnyError> {
let source_code = &format!(
- r#"(async function loadBuiltinNodeModules(moduleAllUrl) {{
+ r#"(async function loadBuiltinNodeModules(moduleAllUrl, nodeGlobalThisName) {{
const moduleAll = await import(moduleAllUrl);
- Deno[Deno.internal].node.initialize(moduleAll.default);
- }})('{}');"#,
+ Deno[Deno.internal].node.initialize(moduleAll.default, nodeGlobalThisName);
+ }})('{}', '{}');"#,
MODULE_ALL_URL.as_str(),
+ NODE_GLOBAL_THIS_NAME.as_str(),
);
let value =
@@ -710,32 +714,60 @@ pub fn translate_cjs_to_esm(
media_type: MediaType,
npm_resolver: &GlobalNpmPackageResolver,
) -> Result<String, AnyError> {
- let parsed_source = deno_ast::parse_script(deno_ast::ParseParams {
- specifier: specifier.to_string(),
- text_info: deno_ast::SourceTextInfo::new(code.into()),
- media_type,
- capture_tokens: true,
- scope_analysis: false,
- maybe_syntax: None,
- })?;
- let analysis = parsed_source.analyze_cjs();
+ fn perform_cjs_analysis(
+ specifier: &str,
+ media_type: MediaType,
+ code: String,
+ ) -> Result<CjsAnalysis, AnyError> {
+ let parsed_source = deno_ast::parse_script(deno_ast::ParseParams {
+ specifier: specifier.to_string(),
+ text_info: deno_ast::SourceTextInfo::new(code.into()),
+ media_type,
+ capture_tokens: true,
+ scope_analysis: false,
+ maybe_syntax: None,
+ })?;
+ Ok(parsed_source.analyze_cjs())
+ }
+
+ let mut temp_var_count = 0;
+ let mut handled_reexports: HashSet<String> = HashSet::default();
+
+ let mut source = vec![
+ r#"var window = undefined;"#.to_string(),
+ r#"const require = Deno[Deno.internal].require.Module.createRequire(import.meta.url);"#.to_string(),
+ ];
+
+ let analysis = perform_cjs_analysis(specifier.as_str(), media_type, code)?;
+
let root_exports = analysis
.exports
.iter()
.map(|s| s.as_str())
.collect::<HashSet<_>>();
- let mut temp_var_count = 0;
+ let mut all_exports = analysis
+ .exports
+ .iter()
+ .map(|s| s.to_string())
+ .collect::<HashSet<_>>();
- let mut source = vec![
- r#"const require = Deno[Deno.internal].require.Module.createRequire(import.meta.url);"#.to_string(),
- ];
+ // (request, referrer)
+ let mut reexports_to_handle = VecDeque::new();
+ for reexport in analysis.reexports {
+ reexports_to_handle.push_back((reexport, specifier.clone()));
+ }
+
+ while let Some((reexport, referrer)) = reexports_to_handle.pop_front() {
+ if handled_reexports.contains(&reexport) {
+ continue;
+ }
+
+ handled_reexports.insert(reexport.to_string());
- // if there are reexports, handle them first
- for (idx, reexport) in analysis.reexports.iter().enumerate() {
- // Firstly, resolve relate reexport specifier
+ // First, resolve relate reexport specifier
let resolved_reexport = resolve(
- reexport,
- specifier,
+ &reexport,
+ &referrer,
// FIXME(bartlomieju): check if these conditions are okay, probably
// should be `deno-require`, because `deno` is already used in `esm_resolver.rs`
&["deno", "require", "default"],
@@ -743,35 +775,26 @@ pub fn translate_cjs_to_esm(
)?;
let reexport_specifier =
ModuleSpecifier::from_file_path(&resolved_reexport).unwrap();
- // Secondly, read the source code from disk
+ // Second, read the source code from disk
let reexport_file = file_fetcher.get_source(&reexport_specifier).unwrap();
- // Now perform analysis again
+
{
- let parsed_source = deno_ast::parse_script(deno_ast::ParseParams {
- specifier: reexport_specifier.to_string(),
- text_info: deno_ast::SourceTextInfo::new(reexport_file.source),
- media_type: reexport_file.media_type,
- capture_tokens: true,
- scope_analysis: false,
- maybe_syntax: None,
- })?;
- let analysis = parsed_source.analyze_cjs();
-
- source.push(format!(
- "const reexport{} = require(\"{}\");",
- idx, reexport
- ));
-
- for export in analysis.exports.iter().filter(|e| {
- e.as_str() != "default" && !root_exports.contains(e.as_str())
- }) {
- add_export(
- &mut source,
- export,
- &format!("Deno[Deno.internal].require.bindExport(reexport{0}[\"{1}\"], reexport{0})", idx, export),
- &mut temp_var_count,
- );
+ let analysis = perform_cjs_analysis(
+ reexport_specifier.as_str(),
+ reexport_file.media_type,
+ reexport_file.source.to_string(),
+ )?;
+
+ for reexport in analysis.reexports {
+ reexports_to_handle.push_back((reexport, reexport_specifier.clone()));
}
+
+ all_exports.extend(
+ analysis
+ .exports
+ .into_iter()
+ .filter(|e| e.as_str() != "default"),
+ );
}
}
@@ -788,7 +811,7 @@ pub fn translate_cjs_to_esm(
));
let mut had_default = false;
- for export in analysis.exports.iter() {
+ for export in &all_exports {
if export.as_str() == "default" {
if root_exports.contains("__esModule") {
source.push(format!(
@@ -880,7 +903,6 @@ fn resolve(
return Ok(module_dir.join("index.js").clean());
}
}
-
Err(not_found(specifier, &referrer_path))
}
@@ -988,7 +1010,6 @@ fn file_extension_probe(
return Ok(p_js);
}
}
-
Err(not_found(&p.to_string_lossy(), referrer))
}