Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add --compat flag to provide built-in Node modules #12293

Merged
merged 13 commits into from
Oct 4, 2021
32 changes: 32 additions & 0 deletions cli/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ pub struct Flags {
pub log_level: Option<Level>,
pub no_check: bool,
pub no_remote: bool,
/// If true, a list of Node built-in modules will be injected into
/// the import map.
pub node_compat: bool,
pub prompt: bool,
pub reload: bool,
pub repl: bool,
Expand Down Expand Up @@ -1490,6 +1493,7 @@ fn runtime_args<'a, 'b>(
.arg(v8_flags_arg())
.arg(seed_arg())
.arg(enable_testing_features_arg())
.arg(node_compat_arg())
}

fn inspect_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> {
Expand Down Expand Up @@ -1619,6 +1623,12 @@ fn seed_arg<'a, 'b>() -> Arg<'a, 'b> {
})
}

fn node_compat_arg<'a, 'b>() -> Arg<'a, 'b> {
Arg::with_name("node-compat")
.long("node-compat")
.help("Provide shim that allows to use built-in Node modules")
}

fn watch_arg<'a, 'b>() -> Arg<'a, 'b> {
Arg::with_name("watch")
.long("watch")
Expand Down Expand Up @@ -2228,6 +2238,7 @@ fn runtime_args_parse(
location_arg_parse(flags, matches);
v8_flags_arg_parse(flags, matches);
seed_arg_parse(flags, matches);
node_compat_arg_parse(flags, matches);
inspect_arg_parse(flags, matches);
enable_testing_features_arg_parse(flags, matches);
}
Expand Down Expand Up @@ -2313,6 +2324,12 @@ fn seed_arg_parse(flags: &mut Flags, matches: &ArgMatches) {
}
}

fn node_compat_arg_parse(flags: &mut Flags, matches: &ArgMatches) {
if matches.is_present("node-compat") {
flags.node_compat = true;
}
}

fn no_check_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
if matches.is_present("no-check") {
flags.no_check = true;
Expand Down Expand Up @@ -4431,4 +4448,19 @@ mod tests {
.to_string()
.contains("Expected protocol \"http\" or \"https\""));
}

#[test]
fn node_compat() {
let r = flags_from_vec(svec!["deno", "run", "--node-compat", "foo.js"]);
assert_eq!(
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Run(RunFlags {
script: "foo.js".to_string(),
}),
node_compat: true,
..Flags::default()
}
);
}
}
1 change: 1 addition & 0 deletions cli/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ mod logger;
mod lsp;
mod module_graph;
mod module_loader;
mod node_compat;
mod ops;
mod proc_state;
mod source_maps;
Expand Down
41 changes: 41 additions & 0 deletions cli/node_compat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.

use std::collections::HashMap;

// TODO(bartlomieju): this is unversioned, and should be fixed to use latest stable?
static DENO_STD_URL: &'static str = "https://deno.land/std/node/";

static SUPPORTED_MODULES: &[&'static str] = &[
"assert",
"buffer",
"child_process",
"console",
"constants",
"crypto",
"events",
"fs",
"module",
"os",
"path",
"perf_hooks",
"process",
"querystring",
"stream",
"string_decoder",
"sys",
"timers",
"tty",
"url",
"util",
];

pub fn get_mapped_node_builtins() -> HashMap<String, String> {
let mut mappings = HashMap::new();

for module in SUPPORTED_MODULES {
let module_url = format!("{}{}", DENO_STD_URL, module);
mappings.insert(module.to_string(), module_url);
}

mappings
}
kitsonk marked this conversation as resolved.
Show resolved Hide resolved
22 changes: 21 additions & 1 deletion cli/proc_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ impl ProcState {
None
};

let maybe_import_map: Option<ImportMap> =
let mut maybe_import_map: Option<ImportMap> =
match flags.import_map_path.as_ref() {
None => None,
Some(import_map_url) => {
Expand All @@ -204,6 +204,26 @@ impl ProcState {
}
};

if flags.node_compat {
let mut import_map = match maybe_import_map {
Some(import_map) => import_map,
None => {
// INFO: we're creating an empty import map, with its specifier pointing
// to `CWD/node_import_map.json` to make sure the map still works as expected.
let import_map_specifier =
std::env::current_dir()?.join("node_import_map.json");
ImportMap::from_json(import_map_specifier.to_str().unwrap(), "{}")
.unwrap()
}
};
let _node_builtins = crate::node_compat::get_mapped_node_builtins();
// TODO(bartlomieju): should this actually be a hard error if user provided partial
// mapping for Node modules in their own import map, or should we just print out
// that some modules were not shimmed because they were already present in import map?
// import_map.update_in_place(node_builtins)?;
maybe_import_map = Some(import_map);
}

let maybe_inspect_host = flags.inspect.or(flags.inspect_brk);
let maybe_inspector_server = maybe_inspect_host.map(|host| {
Arc::new(InspectorServer::new(host, version::get_user_agent()))
Expand Down
1 change: 1 addition & 0 deletions cli/tools/standalone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ pub fn compile_to_runtime_flags(
lock: None,
log_level: flags.log_level,
no_check: false,
node_compat: flags.node_compat,
unsafely_ignore_certificate_errors: flags
.unsafely_ignore_certificate_errors,
no_remote: false,
Expand Down