summaryrefslogtreecommitdiff
path: root/cli/node
diff options
context:
space:
mode:
Diffstat (limited to 'cli/node')
-rw-r--r--cli/node/analyze.rs30
-rw-r--r--cli/node/mod.rs83
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,