diff options
Diffstat (limited to 'cli/node')
-rw-r--r-- | cli/node/analyze.rs | 30 | ||||
-rw-r--r-- | cli/node/mod.rs | 83 |
2 files changed, 112 insertions, 1 deletions
diff --git a/cli/node/analyze.rs b/cli/node/analyze.rs index 9da2cbf4b..270615cca 100644 --- a/cli/node/analyze.rs +++ b/cli/node/analyze.rs @@ -74,7 +74,15 @@ pub fn esm_code_with_node_globals( write!(result, "var {0} = {1}.{0};", global, global_this_expr).unwrap(); } - result.push_str(parsed_source.text_info().text_str()); + let file_text = parsed_source.text_info().text_str(); + // strip the shebang + let file_text = if file_text.starts_with("#!/") { + let start_index = file_text.find('\n').unwrap_or(file_text.len()); + &file_text[start_index..] + } else { + file_text + }; + result.push_str(file_text); Ok(result) } @@ -158,4 +166,24 @@ mod tests { assert!(r.contains("var process = globalThis.process;")); assert!(r.contains("export const x = 1;")); } + + #[test] + fn test_esm_code_with_node_globals_with_shebang() { + let r = esm_code_with_node_globals( + &ModuleSpecifier::parse("https://example.com/foo/bar.js").unwrap(), + "#!/usr/bin/env node\nexport const x = 1;".to_string(), + ) + .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;" + ), + ); + } } diff --git a/cli/node/mod.rs b/cli/node/mod.rs index 2af4f2308..385c6cfa2 100644 --- a/cli/node/mod.rs +++ b/cli/node/mod.rs @@ -6,6 +6,7 @@ use std::path::PathBuf; use deno_ast::MediaType; use deno_ast::ModuleSpecifier; +use deno_core::anyhow::bail; use deno_core::anyhow::Context; use deno_core::error::generic_error; use deno_core::error::AnyError; @@ -31,6 +32,7 @@ use crate::compat; use crate::file_fetcher::FileFetcher; use crate::npm::GlobalNpmPackageResolver; use crate::npm::NpmPackageReference; +use crate::npm::NpmPackageReq; use crate::npm::NpmPackageResolver; mod analyze; @@ -185,6 +187,87 @@ pub fn node_resolve_npm_reference( Ok(Some(resolve_response)) } +pub fn node_resolve_binary_export( + pkg_req: &NpmPackageReq, + bin_name: Option<&str>, + npm_resolver: &GlobalNpmPackageResolver, +) -> Result<ResolveResponse, AnyError> { + let pkg = npm_resolver.resolve_package_from_deno_module(pkg_req)?; + let package_folder = pkg.folder_path; + let package_json_path = package_folder.join("package.json"); + let package_json = PackageJson::load(npm_resolver, package_json_path)?; + let bin = match &package_json.bin { + Some(bin) => bin, + None => bail!( + "package {} did not have a 'bin' property in its package.json", + pkg.id + ), + }; + let bin_entry = match bin { + Value::String(_) => { + if bin_name.is_some() && bin_name.unwrap() != pkg_req.name { + None + } else { + Some(bin) + } + } + Value::Object(o) => { + if let Some(bin_name) = bin_name { + o.get(bin_name) + } else if o.len() == 1 { + o.values().next() + } else { + o.get(&pkg_req.name) + } + }, + _ => bail!("package {} did not have a 'bin' property with a string or object value in its package.json", pkg.id), + }; + let bin_entry = match bin_entry { + Some(e) => e, + None => bail!( + "package {} did not have a 'bin' entry for {} in its package.json", + pkg.id, + bin_name.unwrap_or(&pkg_req.name), + ), + }; + let bin_entry = match bin_entry { + Value::String(s) => s, + _ => bail!( + "package {} had a non-string sub property of 'bin' in its package.json", + pkg.id + ), + }; + + let url = + ModuleSpecifier::from_file_path(package_folder.join(bin_entry)).unwrap(); + + let resolve_response = url_to_resolve_response(url, npm_resolver)?; + // TODO(bartlomieju): skipped checking errors for commonJS resolution and + // "preserveSymlinksMain"/"preserveSymlinks" options. + Ok(resolve_response) +} + +pub fn load_cjs_module_from_ext_node( + js_runtime: &mut JsRuntime, + module: &str, + main: bool, +) -> Result<(), AnyError> { + fn escape_for_single_quote_string(text: &str) -> String { + text.replace('\\', r"\\").replace('\'', r"\'") + } + + let source_code = &format!( + r#"(function loadCjsModule(module) {{ + Deno[Deno.internal].require.Module._load(module, null, {main}); + }})('{module}');"#, + main = main, + module = escape_for_single_quote_string(module), + ); + + js_runtime.execute_script(&located_script_name!(), source_code)?; + Ok(()) +} + fn package_config_resolve( package_subpath: &str, package_dir: &Path, |