summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2023-02-10 12:40:45 +0100
committerGitHub <noreply@github.com>2023-02-10 11:40:45 +0000
commited3a7ce2f719e64e59cfebb3d131a05a1694523b (patch)
treea355c3a0f17ec7dfb8bcdba964deb8dd241b6734
parent9ea899afa76949d2e1a2a6eabbbec14f139a7592 (diff)
refactor: allow to provide polyfills for Node modules from the snapshot (#17706)
This commit does preparatory work to allow snapshotting Node.js compatibility layer, that currently lives in `std/node`. The logic was changed to allow loading some modules from the snapshot and some from the remote URL. Additionally "module_es_shim.js" that provides exports for "node:module" is now snapshotted.
-rw-r--r--cli/module_loader.rs12
-rw-r--r--cli/node/mod.rs21
-rw-r--r--ext/node/lib.rs116
-rw-r--r--ext/node/module_es_shim.js3
4 files changed, 83 insertions, 69 deletions
diff --git a/cli/module_loader.rs b/cli/module_loader.rs
index 112f29170..b61b4304e 100644
--- a/cli/module_loader.rs
+++ b/cli/module_loader.rs
@@ -77,13 +77,11 @@ impl CliModuleLoader {
specifier: &ModuleSpecifier,
maybe_referrer: Option<ModuleSpecifier>,
) -> Result<ModuleCodeSource, AnyError> {
- if specifier.as_str() == "node:module" {
- return Ok(ModuleCodeSource {
- code: deno_runtime::deno_node::MODULE_ES_SHIM.to_string(),
- found_url: specifier.to_owned(),
- media_type: MediaType::JavaScript,
- });
- }
+ // TODO(bartlomieju): uncomment, when all `node:` module have been
+ // snapshotted
+ // if specifier.scheme() == "node" {
+ // unreachable!("Node built-in modules should be handled internally.");
+ // }
let graph = self.ps.graph();
match graph.get(specifier) {
Some(deno_graph::Module {
diff --git a/cli/node/mod.rs b/cli/node/mod.rs
index 9ab593304..dffcb7437 100644
--- a/cli/node/mod.rs
+++ b/cli/node/mod.rs
@@ -26,6 +26,7 @@ use deno_runtime::deno_node::package_resolve;
use deno_runtime::deno_node::path_to_declaration_path;
use deno_runtime::deno_node::NodeModuleKind;
use deno_runtime::deno_node::NodeModulePolyfill;
+use deno_runtime::deno_node::NodeModulePolyfillSpecifier;
use deno_runtime::deno_node::NodePermissions;
use deno_runtime::deno_node::NodeResolutionMode;
use deno_runtime::deno_node::PackageJson;
@@ -133,16 +134,18 @@ fn is_builtin_node_module(specifier: &str) -> bool {
}
pub fn resolve_builtin_node_module(specifier: &str) -> Result<Url, AnyError> {
- // NOTE(bartlomieju): `module` is special, because we don't want to use
- // `deno_std/node/module.ts`, but instead use a special shim that we
- // provide in `ext/node`.
- if specifier == "module" {
- return Ok(Url::parse("node:module").unwrap());
- }
-
if let Some(module) = find_builtin_node_module(specifier) {
- let module_url = NODE_COMPAT_URL.join(module.specifier).unwrap();
- return Ok(module_url);
+ match module.specifier {
+ // We will load the source code from the `std/node` polyfill.
+ NodeModulePolyfillSpecifier::StdNode(specifier) => {
+ let module_url = NODE_COMPAT_URL.join(specifier).unwrap();
+ return Ok(module_url);
+ }
+ // The module has already been snapshotted and is present in the binary.
+ NodeModulePolyfillSpecifier::Embedded(specifier) => {
+ return Ok(ModuleSpecifier::parse(specifier).unwrap());
+ }
+ }
}
Err(generic_error(format!(
diff --git a/ext/node/lib.rs b/ext/node/lib.rs
index d012bf83a..fc506b3b3 100644
--- a/ext/node/lib.rs
+++ b/ext/node/lib.rs
@@ -85,7 +85,11 @@ pub fn init<P: NodePermissions + 'static>(
maybe_npm_resolver: Option<Rc<dyn RequireNpmResolver>>,
) -> Extension {
Extension::builder(env!("CARGO_PKG_NAME"))
- .esm(include_js_files!("01_node.js", "02_require.js",))
+ .esm(include_js_files!(
+ "01_node.js",
+ "02_require.js",
+ "module_es_shim.js",
+ ))
.ops(vec![
op_require_init_paths::decl(),
op_require_node_module_paths::decl::<P>(),
@@ -672,196 +676,204 @@ fn op_require_break_on_next_statement(state: &mut OpState) {
.wait_for_session_and_break_on_next_statement()
}
+pub enum NodeModulePolyfillSpecifier {
+ /// An internal module specifier, like "internal:deno_node/assert.ts". The
+ /// module must be either embedded in the binary or snapshotted.
+ Embedded(&'static str),
+
+ /// Specifier relative to the root of `deno_std` repo, like "node/assert.ts"
+ StdNode(&'static str),
+}
+
pub struct NodeModulePolyfill {
/// Name of the module like "assert" or "timers/promises"
pub name: &'static str,
-
- /// Specifier relative to the root of `deno_std` repo, like "node/assert.ts"
- pub specifier: &'static str,
+ pub specifier: NodeModulePolyfillSpecifier,
}
pub static SUPPORTED_BUILTIN_NODE_MODULES: &[NodeModulePolyfill] = &[
NodeModulePolyfill {
name: "assert",
- specifier: "node/assert.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/assert.ts"),
},
NodeModulePolyfill {
name: "assert/strict",
- specifier: "node/assert/strict.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/assert/strict.ts"),
},
NodeModulePolyfill {
name: "async_hooks",
- specifier: "node/async_hooks.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/async_hooks.ts"),
},
NodeModulePolyfill {
name: "buffer",
- specifier: "node/buffer.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/buffer.ts"),
},
NodeModulePolyfill {
name: "child_process",
- specifier: "node/child_process.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/child_process.ts"),
},
NodeModulePolyfill {
name: "cluster",
- specifier: "node/cluster.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/cluster.ts"),
},
NodeModulePolyfill {
name: "console",
- specifier: "node/console.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/console.ts"),
},
NodeModulePolyfill {
name: "constants",
- specifier: "node/constants.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/constants.ts"),
},
NodeModulePolyfill {
name: "crypto",
- specifier: "node/crypto.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/crypto.ts"),
},
NodeModulePolyfill {
name: "dgram",
- specifier: "node/dgram.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/dgram.ts"),
},
NodeModulePolyfill {
name: "dns",
- specifier: "node/dns.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/dns.ts"),
},
NodeModulePolyfill {
name: "dns/promises",
- specifier: "node/dns/promises.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/dns/promises.ts"),
},
NodeModulePolyfill {
name: "domain",
- specifier: "node/domain.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/domain.ts"),
},
NodeModulePolyfill {
name: "events",
- specifier: "node/events.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/events.ts"),
},
NodeModulePolyfill {
name: "fs",
- specifier: "node/fs.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/fs.ts"),
},
NodeModulePolyfill {
name: "fs/promises",
- specifier: "node/fs/promises.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/fs/promises.ts"),
},
NodeModulePolyfill {
name: "http",
- specifier: "node/http.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/http.ts"),
},
NodeModulePolyfill {
name: "https",
- specifier: "node/https.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/https.ts"),
},
NodeModulePolyfill {
name: "module",
- // NOTE(bartlomieju): `module` is special, because we don't want to use
- // `deno_std/node/module.ts`, but instead use a special shim that we
- // provide in `ext/node`.
- specifier: "[USE `deno_node::MODULE_ES_SHIM` to get this module]",
+ specifier: NodeModulePolyfillSpecifier::Embedded(
+ "internal:deno_node/module_es_shim.js",
+ ),
},
NodeModulePolyfill {
name: "net",
- specifier: "node/net.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/net.ts"),
},
NodeModulePolyfill {
name: "os",
- specifier: "node/os.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/os.ts"),
},
NodeModulePolyfill {
name: "path",
- specifier: "node/path.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/path.ts"),
},
NodeModulePolyfill {
name: "path/posix",
- specifier: "node/path/posix.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/path/posix.ts"),
},
NodeModulePolyfill {
name: "path/win32",
- specifier: "node/path/win32.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/path/win32.ts"),
},
NodeModulePolyfill {
name: "perf_hooks",
- specifier: "node/perf_hooks.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/perf_hooks.ts"),
},
NodeModulePolyfill {
name: "process",
- specifier: "node/process.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/process.ts"),
},
NodeModulePolyfill {
name: "querystring",
- specifier: "node/querystring.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/querystring.ts"),
},
NodeModulePolyfill {
name: "readline",
- specifier: "node/readline.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/readline.ts"),
},
NodeModulePolyfill {
name: "stream",
- specifier: "node/stream.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/stream.ts"),
},
NodeModulePolyfill {
name: "stream/consumers",
- specifier: "node/stream/consumers.mjs",
+ specifier: NodeModulePolyfillSpecifier::StdNode(
+ "node/stream/consumers.mjs",
+ ),
},
NodeModulePolyfill {
name: "stream/promises",
- specifier: "node/stream/promises.mjs",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/stream/promises.mjs"),
},
NodeModulePolyfill {
name: "stream/web",
- specifier: "node/stream/web.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/stream/web.ts"),
},
NodeModulePolyfill {
name: "string_decoder",
- specifier: "node/string_decoder.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/string_decoder.ts"),
},
NodeModulePolyfill {
name: "sys",
- specifier: "node/sys.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/sys.ts"),
},
NodeModulePolyfill {
name: "timers",
- specifier: "node/timers.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/timers.ts"),
},
NodeModulePolyfill {
name: "timers/promises",
- specifier: "node/timers/promises.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/timers/promises.ts"),
},
NodeModulePolyfill {
name: "tls",
- specifier: "node/tls.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/tls.ts"),
},
NodeModulePolyfill {
name: "tty",
- specifier: "node/tty.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/tty.ts"),
},
NodeModulePolyfill {
name: "url",
- specifier: "node/url.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/url.ts"),
},
NodeModulePolyfill {
name: "util",
- specifier: "node/util.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/util.ts"),
},
NodeModulePolyfill {
name: "util/types",
- specifier: "node/util/types.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/util/types.ts"),
},
NodeModulePolyfill {
name: "v8",
- specifier: "node/v8.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/v8.ts"),
},
NodeModulePolyfill {
name: "vm",
- specifier: "node/vm.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/vm.ts"),
},
NodeModulePolyfill {
name: "worker_threads",
- specifier: "node/worker_threads.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/worker_threads.ts"),
},
NodeModulePolyfill {
name: "zlib",
- specifier: "node/zlib.ts",
+ specifier: NodeModulePolyfillSpecifier::StdNode("node/zlib.ts"),
},
];
diff --git a/ext/node/module_es_shim.js b/ext/node/module_es_shim.js
index f32006b4a..2b7c20e26 100644
--- a/ext/node/module_es_shim.js
+++ b/ext/node/module_es_shim.js
@@ -1,6 +1,7 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-const m = Deno[Deno.internal].require.Module;
+const internals = globalThis.__bootstrap.internals;
+const m = internals.require.Module;
export const _cache = m._cache;
export const _extensions = m._extensions;
export const _findPath = m._findPath;