summaryrefslogtreecommitdiff
path: root/cli/compat/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/compat/mod.rs')
-rw-r--r--cli/compat/mod.rs132
1 files changed, 132 insertions, 0 deletions
diff --git a/cli/compat/mod.rs b/cli/compat/mod.rs
new file mode 100644
index 000000000..b95b65ddb
--- /dev/null
+++ b/cli/compat/mod.rs
@@ -0,0 +1,132 @@
+// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
+
+mod errors;
+mod esm_resolver;
+
+use deno_core::error::AnyError;
+use deno_core::located_script_name;
+use deno_core::url::Url;
+use deno_core::JsRuntime;
+
+pub use esm_resolver::NodeEsmResolver;
+
+// TODO(bartlomieju): this needs to be bumped manually for
+// each release, a better mechanism is preferable, but it's a quick and dirty
+// solution to avoid printing `X-Deno-Warning` headers when the compat layer is
+// downloaded
+static STD_URL_STR: &str = "https://deno.land/std@0.112.0/";
+
+static SUPPORTED_MODULES: &[&str] = &[
+ "assert",
+ "assert/strict",
+ "async_hooks",
+ "buffer",
+ "child_process",
+ "cluster",
+ "console",
+ "constants",
+ "crypto",
+ "dgram",
+ "dns",
+ "domain",
+ "events",
+ "fs",
+ "fs/promises",
+ "http",
+ "https",
+ "module",
+ "net",
+ "os",
+ "path",
+ "path/posix",
+ "path/win32",
+ "perf_hooks",
+ "process",
+ "querystring",
+ "readline",
+ "stream",
+ "stream/promises",
+ "stream/web",
+ "string_decoder",
+ "sys",
+ "timers",
+ "timers/promises",
+ "tls",
+ "tty",
+ "url",
+ "util",
+ "util/types",
+ "v8",
+ "vm",
+ "zlib",
+];
+
+lazy_static::lazy_static! {
+ static ref GLOBAL_URL_STR: String = format!("{}node/global.ts", STD_URL_STR);
+ pub(crate) static ref GLOBAL_URL: Url = Url::parse(&GLOBAL_URL_STR).unwrap();
+ static ref MODULE_URL_STR: String = format!("{}node/module.ts", STD_URL_STR);
+ pub(crate) static ref MODULE_URL: Url = Url::parse(&MODULE_URL_STR).unwrap();
+ static ref COMPAT_IMPORT_URL: Url = Url::parse("flags:compat").unwrap();
+}
+
+/// Provide imports into a module graph when the compat flag is true.
+pub(crate) fn get_node_imports() -> Vec<(Url, Vec<String>)> {
+ vec![(COMPAT_IMPORT_URL.clone(), vec![GLOBAL_URL_STR.clone()])]
+}
+
+fn try_resolve_builtin_module(specifier: &str) -> Option<Url> {
+ if SUPPORTED_MODULES.contains(&specifier) {
+ let module_url = format!("{}node/{}.ts", STD_URL_STR, specifier);
+ Some(Url::parse(&module_url).unwrap())
+ } else {
+ None
+ }
+}
+
+pub async fn check_if_should_use_esm_loader(
+ js_runtime: &mut JsRuntime,
+ main_module: &str,
+) -> Result<bool, AnyError> {
+ // Decide if we're running with Node ESM loader or CJS loader.
+ let source_code = &format!(
+ r#"(async function checkIfEsm(main) {{
+ const {{ resolveMainPath, shouldUseESMLoader }} = await import("{}");
+ const resolvedMain = resolveMainPath(main);
+ const useESMLoader = shouldUseESMLoader(resolvedMain);
+ return useESMLoader;
+ }})('{}');"#,
+ MODULE_URL_STR.as_str(),
+ escape_for_single_quote_string(main_module),
+ );
+ let result =
+ js_runtime.execute_script(&located_script_name!(), source_code)?;
+ let use_esm_loader_global = js_runtime.resolve_value(result).await?;
+ let use_esm_loader = {
+ let scope = &mut js_runtime.handle_scope();
+ let use_esm_loader_local = use_esm_loader_global.get(scope);
+ use_esm_loader_local.boolean_value(scope)
+ };
+
+ Ok(use_esm_loader)
+}
+
+pub fn load_cjs_module(
+ js_runtime: &mut JsRuntime,
+ main_module: &str,
+) -> Result<(), AnyError> {
+ let source_code = &format!(
+ r#"(async function loadCjsModule(main) {{
+ const Module = await import("{}");
+ Module.default._load(main, null, true);
+ }})('{}');"#,
+ MODULE_URL_STR.as_str(),
+ escape_for_single_quote_string(main_module),
+ );
+
+ js_runtime.execute_script(&located_script_name!(), source_code)?;
+ Ok(())
+}
+
+fn escape_for_single_quote_string(text: &str) -> String {
+ text.replace(r"\", r"\\").replace("'", r"\'")
+}