summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock13
-rw-r--r--cli/Cargo.toml16
-rw-r--r--cli/build.rs574
-rw-r--r--cli/js.rs57
-rw-r--r--cli/js/40_testing.js (renamed from runtime/js/40_testing.js)18
-rw-r--r--cli/lsp/testing/execution.rs4
-rw-r--r--cli/main.rs35
-rw-r--r--cli/standalone.rs2
-rw-r--r--cli/tests/testdata/test/steps/failing_steps.out8
-rw-r--r--cli/tools/bench.rs4
-rw-r--r--cli/tools/test.rs4
-rw-r--r--cli/worker.rs267
-rw-r--r--core/lib.rs1
-rw-r--r--core/snapshot_util.rs95
-rw-r--r--runtime/build.rs96
-rw-r--r--runtime/js.rs40
-rw-r--r--runtime/js/90_deno_ns.js2
-rw-r--r--runtime/js/98_global_scope.js352
-rw-r--r--runtime/js/99_main.js343
-rw-r--r--runtime/lib.rs1
-rw-r--r--runtime/web_worker.rs9
-rw-r--r--runtime/worker.rs198
22 files changed, 1146 insertions, 993 deletions
diff --git a/Cargo.lock b/Cargo.lock
index f0d44b219..c91e2414d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -781,25 +781,13 @@ dependencies = [
"data-url",
"deno_ast 0.21.0",
"deno_bench_util",
- "deno_broadcast_channel",
- "deno_cache",
- "deno_console",
"deno_core",
- "deno_crypto",
"deno_doc",
"deno_emit",
- "deno_fetch",
"deno_graph",
"deno_lint",
- "deno_net",
- "deno_node",
"deno_runtime",
"deno_task_shell",
- "deno_url",
- "deno_web",
- "deno_webgpu",
- "deno_websocket",
- "deno_webstorage",
"dissimilar",
"dotenv",
"dprint-plugin-json",
@@ -822,6 +810,7 @@ dependencies = [
"libc",
"log",
"lsp-types",
+ "lzzzz",
"mitata",
"monch",
"napi_sym",
diff --git a/cli/Cargo.toml b/cli/Cargo.toml
index 83ff3d77e..732d586d2 100644
--- a/cli/Cargo.toml
+++ b/cli/Cargo.toml
@@ -26,25 +26,16 @@ harness = false
path = "./bench/lsp_bench_standalone.rs"
[build-dependencies]
-deno_broadcast_channel = { version = "0.72.0", path = "../ext/broadcast_channel" }
-deno_cache = { version = "0.10.0", path = "../ext/cache" }
-deno_console = { version = "0.78.0", path = "../ext/console" }
+deno_runtime = { version = "0.86.0", path = "../runtime" }
deno_core = { version = "0.160.0", path = "../core" }
-deno_crypto = { version = "0.92.0", path = "../ext/crypto" }
-deno_fetch = { version = "0.101.0", path = "../ext/fetch" }
-deno_net = { version = "0.70.0", path = "../ext/net" }
-deno_node = { version = "0.15.0", path = "../ext/node" }
-deno_url = { version = "0.78.0", path = "../ext/url" }
-deno_web = { version = "0.109.0", path = "../ext/web" }
-deno_webgpu = { version = "0.79.0", path = "../ext/webgpu" }
-deno_websocket = { version = "0.83.0", path = "../ext/websocket" }
-deno_webstorage = { version = "0.73.0", path = "../ext/webstorage" }
regex = "=1.6.0"
serde = { version = "=1.0.144", features = ["derive"] }
serde_json = "1.0.64"
zstd = '=0.11.2'
glibc_version = "0.1.2"
+lzzzz = '1.0'
+
[target.'cfg(windows)'.build-dependencies]
winapi = "=0.3.9"
winres = "=0.1.12"
@@ -86,6 +77,7 @@ jsonc-parser = { version = "=0.21.0", features = ["serde"] }
libc = "=0.2.126"
log = { version = "=0.4.17", features = ["serde"] }
lsp-types = "=0.93.2" # used by tower-lsp and "proposed" feature is unstable in patch releases
+lzzzz = '1.0'
mitata = "=0.0.7"
monch = "=0.4.0"
notify = "=5.0.0"
diff --git a/cli/build.rs b/cli/build.rs
index 73d0208f6..c7d902941 100644
--- a/cli/build.rs
+++ b/cli/build.rs
@@ -1,306 +1,319 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
-use deno_core::error::custom_error;
-use deno_core::error::AnyError;
-use deno_core::op;
-use deno_core::serde::Deserialize;
-use deno_core::serde_json::json;
-use deno_core::serde_json::Value;
use deno_core::Extension;
-use deno_core::JsRuntime;
-use deno_core::OpState;
-use deno_core::RuntimeOptions;
-use regex::Regex;
-use std::collections::HashMap;
use std::env;
use std::path::Path;
use std::path::PathBuf;
-// TODO(bartlomieju): this module contains a lot of duplicated
-// logic with `runtime/build.rs`, factor out to `deno_core`.
-fn create_snapshot(
- mut js_runtime: JsRuntime,
- snapshot_path: &Path,
- files: Vec<PathBuf>,
-) {
- // TODO(nayeemrmn): https://github.com/rust-lang/cargo/issues/3946 to get the
- // workspace root.
- let display_root = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap();
- for file in files {
- println!("cargo:rerun-if-changed={}", file.display());
- let display_path = file.strip_prefix(display_root).unwrap();
- let display_path_str = display_path.display().to_string();
- js_runtime
- .execute_script(
- &("deno:".to_string() + &display_path_str.replace('\\', "/")),
- &std::fs::read_to_string(&file).unwrap(),
- )
- .unwrap();
+use deno_core::snapshot_util::*;
+use deno_runtime::deno_cache::SqliteBackedCache;
+use deno_runtime::permissions::Permissions;
+use deno_runtime::*;
+
+mod ts {
+ use super::*;
+ use crate::deno_webgpu_get_declaration;
+ use deno_core::error::custom_error;
+ use deno_core::error::AnyError;
+ use deno_core::op;
+ use deno_core::OpState;
+ use regex::Regex;
+ use serde::Deserialize;
+ use serde_json::json;
+ use serde_json::Value;
+ use std::collections::HashMap;
+ use std::path::Path;
+ use std::path::PathBuf;
+
+ #[derive(Debug, Deserialize)]
+ struct LoadArgs {
+ /// The fully qualified specifier that should be loaded.
+ specifier: String,
}
- let snapshot = js_runtime.snapshot();
- let snapshot_slice: &[u8] = &snapshot;
- println!("Snapshot size: {}", snapshot_slice.len());
-
- let compressed_snapshot_with_size = {
- let mut vec = vec![];
-
- vec.extend_from_slice(
- &u32::try_from(snapshot.len())
- .expect("snapshot larger than 4gb")
- .to_le_bytes(),
+ pub fn create_compiler_snapshot(
+ snapshot_path: PathBuf,
+ files: Vec<PathBuf>,
+ cwd: &Path,
+ ) {
+ // libs that are being provided by op crates.
+ let mut op_crate_libs = HashMap::new();
+ op_crate_libs.insert("deno.cache", deno_cache::get_declaration());
+ op_crate_libs.insert("deno.console", deno_console::get_declaration());
+ op_crate_libs.insert("deno.url", deno_url::get_declaration());
+ op_crate_libs.insert("deno.web", deno_web::get_declaration());
+ op_crate_libs.insert("deno.fetch", deno_fetch::get_declaration());
+ op_crate_libs.insert("deno.webgpu", deno_webgpu_get_declaration());
+ op_crate_libs.insert("deno.websocket", deno_websocket::get_declaration());
+ op_crate_libs.insert("deno.webstorage", deno_webstorage::get_declaration());
+ op_crate_libs.insert("deno.crypto", deno_crypto::get_declaration());
+ op_crate_libs.insert(
+ "deno.broadcast_channel",
+ deno_broadcast_channel::get_declaration(),
);
+ op_crate_libs.insert("deno.net", deno_net::get_declaration());
- vec.extend_from_slice(
- &zstd::bulk::compress(snapshot_slice, 22)
- .expect("snapshot compression failed"),
- );
-
- vec
- };
-
- println!(
- "Snapshot compressed size: {}",
- compressed_snapshot_with_size.len()
- );
-
- std::fs::write(snapshot_path, compressed_snapshot_with_size).unwrap();
- println!("Snapshot written to: {} ", snapshot_path.display());
-}
-
-#[derive(Debug, Deserialize)]
-struct LoadArgs {
- /// The fully qualified specifier that should be loaded.
- specifier: String,
-}
-
-fn create_compiler_snapshot(
- snapshot_path: &Path,
- files: Vec<PathBuf>,
- cwd: &Path,
-) {
- // libs that are being provided by op crates.
- let mut op_crate_libs = HashMap::new();
- op_crate_libs.insert("deno.cache", deno_cache::get_declaration());
- op_crate_libs.insert("deno.console", deno_console::get_declaration());
- op_crate_libs.insert("deno.url", deno_url::get_declaration());
- op_crate_libs.insert("deno.web", deno_web::get_declaration());
- op_crate_libs.insert("deno.fetch", deno_fetch::get_declaration());
- op_crate_libs.insert("deno.webgpu", deno_webgpu_get_declaration());
- op_crate_libs.insert("deno.websocket", deno_websocket::get_declaration());
- op_crate_libs.insert("deno.webstorage", deno_webstorage::get_declaration());
- op_crate_libs.insert("deno.crypto", deno_crypto::get_declaration());
- op_crate_libs.insert(
- "deno.broadcast_channel",
- deno_broadcast_channel::get_declaration(),
- );
- op_crate_libs.insert("deno.net", deno_net::get_declaration());
-
- // ensure we invalidate the build properly.
- for (_, path) in op_crate_libs.iter() {
- println!("cargo:rerun-if-changed={}", path.display());
- }
-
- // libs that should be loaded into the isolate before snapshotting.
- let libs = vec![
- // Deno custom type libraries
- "deno.window",
- "deno.worker",
- "deno.shared_globals",
- "deno.ns",
- "deno.unstable",
- // Deno built-in type libraries
- "es5",
- "es2015.collection",
- "es2015.core",
- "es2015",
- "es2015.generator",
- "es2015.iterable",
- "es2015.promise",
- "es2015.proxy",
- "es2015.reflect",
- "es2015.symbol",
- "es2015.symbol.wellknown",
- "es2016.array.include",
- "es2016",
- "es2017",
- "es2017.intl",
- "es2017.object",
- "es2017.sharedmemory",
- "es2017.string",
- "es2017.typedarrays",
- "es2018.asyncgenerator",
- "es2018.asynciterable",
- "es2018",
- "es2018.intl",
- "es2018.promise",
- "es2018.regexp",
- "es2019.array",
- "es2019",
- "es2019.object",
- "es2019.string",
- "es2019.symbol",
- "es2020.bigint",
- "es2020",
- "es2020.date",
- "es2020.intl",
- "es2020.number",
- "es2020.promise",
- "es2020.sharedmemory",
- "es2020.string",
- "es2020.symbol.wellknown",
- "es2021",
- "es2021.intl",
- "es2021.promise",
- "es2021.string",
- "es2021.weakref",
- "es2022",
- "es2022.array",
- "es2022.error",
- "es2022.intl",
- "es2022.object",
- "es2022.string",
- "esnext",
- "esnext.array",
- "esnext.intl",
- ];
+ // ensure we invalidate the build properly.
+ for (_, path) in op_crate_libs.iter() {
+ println!("cargo:rerun-if-changed={}", path.display());
+ }
- let path_dts = cwd.join("dts");
- // ensure we invalidate the build properly.
- for name in libs.iter() {
- println!(
- "cargo:rerun-if-changed={}",
- path_dts.join(format!("lib.{}.d.ts", name)).display()
- );
- }
+ // libs that should be loaded into the isolate before snapshotting.
+ let libs = vec![
+ // Deno custom type libraries
+ "deno.window",
+ "deno.worker",
+ "deno.shared_globals",
+ "deno.ns",
+ "deno.unstable",
+ // Deno built-in type libraries
+ "es5",
+ "es2015.collection",
+ "es2015.core",
+ "es2015",
+ "es2015.generator",
+ "es2015.iterable",
+ "es2015.promise",
+ "es2015.proxy",
+ "es2015.reflect",
+ "es2015.symbol",
+ "es2015.symbol.wellknown",
+ "es2016.array.include",
+ "es2016",
+ "es2017",
+ "es2017.intl",
+ "es2017.object",
+ "es2017.sharedmemory",
+ "es2017.string",
+ "es2017.typedarrays",
+ "es2018.asyncgenerator",
+ "es2018.asynciterable",
+ "es2018",
+ "es2018.intl",
+ "es2018.promise",
+ "es2018.regexp",
+ "es2019.array",
+ "es2019",
+ "es2019.object",
+ "es2019.string",
+ "es2019.symbol",
+ "es2020.bigint",
+ "es2020",
+ "es2020.date",
+ "es2020.intl",
+ "es2020.number",
+ "es2020.promise",
+ "es2020.sharedmemory",
+ "es2020.string",
+ "es2020.symbol.wellknown",
+ "es2021",
+ "es2021.intl",
+ "es2021.promise",
+ "es2021.string",
+ "es2021.weakref",
+ "es2022",
+ "es2022.array",
+ "es2022.error",
+ "es2022.intl",
+ "es2022.object",
+ "es2022.string",
+ "esnext",
+ "esnext.array",
+ "esnext.intl",
+ ];
+
+ let path_dts = cwd.join("dts");
+ // ensure we invalidate the build properly.
+ for name in libs.iter() {
+ println!(
+ "cargo:rerun-if-changed={}",
+ path_dts.join(format!("lib.{}.d.ts", name)).display()
+ );
+ }
- // create a copy of the vector that includes any op crate libs to be passed
- // to the JavaScript compiler to build into the snapshot
- let mut build_libs = libs.clone();
- for (op_lib, _) in op_crate_libs.iter() {
- build_libs.push(op_lib.to_owned());
- }
+ // create a copy of the vector that includes any op crate libs to be passed
+ // to the JavaScript compiler to build into the snapshot
+ let mut build_libs = libs.clone();
+ for (op_lib, _) in op_crate_libs.iter() {
+ build_libs.push(op_lib.to_owned());
+ }
- #[op]
- fn op_build_info(state: &mut OpState) -> Value {
- let build_specifier = "asset:///bootstrap.ts";
- let build_libs = state.borrow::<Vec<&str>>();
- json!({
- "buildSpecifier": build_specifier,
- "libs": build_libs,
- })
- }
+ #[op]
+ fn op_build_info(state: &mut OpState) -> Value {
+ let build_specifier = "asset:///bootstrap.ts";
+ let build_libs = state.borrow::<Vec<&str>>();
+ json!({
+ "buildSpecifier": build_specifier,
+ "libs": build_libs,
+ })
+ }
- #[op]
- fn op_cwd() -> String {
- "cache:///".into()
- }
+ #[op]
+ fn op_cwd() -> String {
+ "cache:///".into()
+ }
- #[op]
- fn op_exists() -> bool {
- false
- }
+ #[op]
+ fn op_exists() -> bool {
+ false
+ }
- #[op]
- fn op_is_node_file() -> bool {
- false
- }
+ #[op]
+ fn op_is_node_file() -> bool {
+ false
+ }
- #[op]
- fn op_script_version(
- _state: &mut OpState,
- _args: Value,
- ) -> Result<Option<String>, AnyError> {
- Ok(Some("1".to_string()))
- }
+ #[op]
+ fn op_script_version(
+ _state: &mut OpState,
+ _args: Value,
+ ) -> Result<Option<String>, AnyError> {
+ Ok(Some("1".to_string()))
+ }
- #[op]
- // using the same op that is used in `tsc.rs` for loading modules and reading
- // files, but a slightly different implementation at build time.
- fn op_load(state: &mut OpState, args: LoadArgs) -> Result<Value, AnyError> {
- let op_crate_libs = state.borrow::<HashMap<&str, PathBuf>>();
- let path_dts = state.borrow::<PathBuf>();
- let re_asset =
- Regex::new(r"asset:/{3}lib\.(\S+)\.d\.ts").expect("bad regex");
- let build_specifier = "asset:///bootstrap.ts";
-
- // we need a basic file to send to tsc to warm it up.
- if args.specifier == build_specifier {
- Ok(json!({
- "data": r#"console.log("hello deno!");"#,
- "version": "1",
- // this corresponds to `ts.ScriptKind.TypeScript`
- "scriptKind": 3
- }))
- // specifiers come across as `asset:///lib.{lib_name}.d.ts` and we need to
- // parse out just the name so we can lookup the asset.
- } else if let Some(caps) = re_asset.captures(&args.specifier) {
- if let Some(lib) = caps.get(1).map(|m| m.as_str()) {
- // if it comes from an op crate, we were supplied with the path to the
- // file.
- let path = if let Some(op_crate_lib) = op_crate_libs.get(lib) {
- PathBuf::from(op_crate_lib).canonicalize().unwrap()
- // otherwise we are will generate the path ourself
- } else {
- path_dts.join(format!("lib.{}.d.ts", lib))
- };
- let data = std::fs::read_to_string(path)?;
+ #[op]
+ // using the same op that is used in `tsc.rs` for loading modules and reading
+ // files, but a slightly different implementation at build time.
+ fn op_load(state: &mut OpState, args: LoadArgs) -> Result<Value, AnyError> {
+ let op_crate_libs = state.borrow::<HashMap<&str, PathBuf>>();
+ let path_dts = state.borrow::<PathBuf>();
+ let re_asset =
+ Regex::new(r"asset:/{3}lib\.(\S+)\.d\.ts").expect("bad regex");
+ let build_specifier = "asset:///bootstrap.ts";
+
+ // we need a basic file to send to tsc to warm it up.
+ if args.specifier == build_specifier {
Ok(json!({
- "data": data,
+ "data": r#"console.log("hello deno!");"#,
"version": "1",
// this corresponds to `ts.ScriptKind.TypeScript`
"scriptKind": 3
}))
+ // specifiers come across as `asset:///lib.{lib_name}.d.ts` and we need to
+ // parse out just the name so we can lookup the asset.
+ } else if let Some(caps) = re_asset.captures(&args.specifier) {
+ if let Some(lib) = caps.get(1).map(|m| m.as_str()) {
+ // if it comes from an op crate, we were supplied with the path to the
+ // file.
+ let path = if let Some(op_crate_lib) = op_crate_libs.get(lib) {
+ PathBuf::from(op_crate_lib).canonicalize().unwrap()
+ // otherwise we are will generate the path ourself
+ } else {
+ path_dts.join(format!("lib.{}.d.ts", lib))
+ };
+ let data = std::fs::read_to_string(path)?;
+ Ok(json!({
+ "data": data,
+ "version": "1",
+ // this corresponds to `ts.ScriptKind.TypeScript`
+ "scriptKind": 3
+ }))
+ } else {
+ Err(custom_error(
+ "InvalidSpecifier",
+ format!("An invalid specifier was requested: {}", args.specifier),
+ ))
+ }
} else {
Err(custom_error(
"InvalidSpecifier",
format!("An invalid specifier was requested: {}", args.specifier),
))
}
- } else {
- Err(custom_error(
- "InvalidSpecifier",
- format!("An invalid specifier was requested: {}", args.specifier),
- ))
}
+
+ create_snapshot(CreateSnapshotOptions {
+ cargo_manifest_dir: env!("CARGO_MANIFEST_DIR"),
+ snapshot_path,
+ startup_snapshot: None,
+ extensions: vec![Extension::builder()
+ .ops(vec![
+ op_build_info::decl(),
+ op_cwd::decl(),
+ op_exists::decl(),
+ op_is_node_file::decl(),
+ op_load::decl(),
+ op_script_version::decl(),
+ ])
+ .state(move |state| {
+ state.put(op_crate_libs.clone());
+ state.put(build_libs.clone());
+ state.put(path_dts.clone());
+
+ Ok(())
+ })
+ .build()],
+ additional_files: files,
+ compression_cb: Some(Box::new(|vec, snapshot_slice| {
+ vec.extend_from_slice(
+ &zstd::bulk::compress(snapshot_slice, 22)
+ .expect("snapshot compression failed"),
+ );
+ })),
+ });
}
- let js_runtime = JsRuntime::new(RuntimeOptions {
- will_snapshot: true,
- extensions: vec![Extension::builder()
- .ops(vec![
- op_build_info::decl(),
- op_cwd::decl(),
- op_exists::decl(),
- op_is_node_file::decl(),
- op_load::decl(),
- op_script_version::decl(),
- ])
- .state(move |state| {
- state.put(op_crate_libs.clone());
- state.put(build_libs.clone());
- state.put(path_dts.clone());
-
- Ok(())
- })
- .build()],
- ..Default::default()
- });
- create_snapshot(js_runtime, snapshot_path, files);
+ pub(crate) fn version() -> String {
+ std::fs::read_to_string("tsc/00_typescript.js")
+ .unwrap()
+ .lines()
+ .find(|l| l.contains("ts.version = "))
+ .expect(
+ "Failed to find the pattern `ts.version = ` in typescript source code",
+ )
+ .chars()
+ .skip_while(|c| !char::is_numeric(*c))
+ .take_while(|c| *c != '"')
+ .collect::<String>()
+ }
}
-fn ts_version() -> String {
- std::fs::read_to_string("tsc/00_typescript.js")
- .unwrap()
- .lines()
- .find(|l| l.contains("ts.version = "))
- .expect(
- "Failed to find the pattern `ts.version = ` in typescript source code",
- )
- .chars()
- .skip_while(|c| !char::is_numeric(*c))
- .take_while(|c| *c != '"')
- .collect::<String>()
+fn create_cli_snapshot(snapshot_path: PathBuf, files: Vec<PathBuf>) {
+ let extensions: Vec<Extension> = vec![
+ deno_webidl::init(),
+ deno_console::init(),
+ deno_url::init(),
+ deno_tls::init(),
+ deno_web::init::<Permissions>(
+ deno_web::BlobStore::default(),
+ Default::default(),
+ ),
+ deno_fetch::init::<Permissions>(Default::default()),
+ deno_cache::init::<SqliteBackedCache>(None),
+ deno_websocket::init::<Permissions>("".to_owned(), None, None),
+ deno_webstorage::init(None),
+ deno_crypto::init(None),
+ deno_webgpu::init(false),
+ deno_broadcast_channel::init(
+ deno_broadcast_channel::InMemoryBroadcastChannel::default(),
+ false, // No --unstable.
+ ),
+ deno_node::init::<Permissions>(None), // No --unstable.
+ deno_ffi::init::<Permissions>(false),
+ deno_net::init::<Permissions>(
+ None, false, // No --unstable.
+ None,
+ ),
+ deno_napi::init::<Permissions>(false),
+ deno_http::init(),
+ deno_flash::init::<Permissions>(false), // No --unstable
+ ];
+
+ create_snapshot(CreateSnapshotOptions {
+ cargo_manifest_dir: env!("CARGO_MANIFEST_DIR"),
+ snapshot_path,
+ startup_snapshot: Some(deno_runtime::js::deno_isolate_init()),
+ extensions,
+ additional_files: files,
+ compression_cb: Some(Box::new(|vec, snapshot_slice| {
+ lzzzz::lz4_hc::compress_to_vec(
+ snapshot_slice,
+ vec,
+ lzzzz::lz4_hc::CLEVEL_MAX,
+ )
+ .expect("snapshot compression failed");
+ })),
+ })
}
fn git_commit_hash() -> String {
@@ -386,7 +399,7 @@ fn main() {
println!("cargo:rustc-env=GIT_COMMIT_HASH={}", git_commit_hash());
println!("cargo:rerun-if-env-changed=GIT_COMMIT_HASH");
- println!("cargo:rustc-env=TS_VERSION={}", ts_version());
+ println!("cargo:rustc-env=TS_VERSION={}", ts::version());
println!("cargo:rerun-if-env-changed=TS_VERSION");
println!(
@@ -440,11 +453,14 @@ fn main() {
let c = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
let o = PathBuf::from(env::var_os("OUT_DIR").unwrap());
- // Main snapshot
let compiler_snapshot_path = o.join("COMPILER_SNAPSHOT.bin");
+ let js_files = get_js_files(env!("CARGO_MANIFEST_DIR"), "tsc");
+ ts::create_compiler_snapshot(compiler_snapshot_path, js_files, &c);
- let js_files = get_js_files("tsc");
- create_compiler_snapshot(&compiler_snapshot_path, js_files, &c);
+ let cli_snapshot_path = o.join("CLI_SNAPSHOT.bin");
+ let mut js_files = get_js_files(env!("CARGO_MANIFEST_DIR"), "js");
+ js_files.push(deno_runtime::js::get_99_main());
+ create_cli_snapshot(cli_snapshot_path, js_files);
#[cfg(target_os = "windows")]
{
@@ -462,17 +478,3 @@ fn deno_webgpu_get_declaration() -> PathBuf {
let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
manifest_dir.join("dts").join("lib.deno_webgpu.d.ts")
}
-
-fn get_js_files(d: &str) -> Vec<PathBuf> {
- let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
- let mut js_files = std::fs::read_dir(d)
- .unwrap()
- .map(|dir_entry| {
- let file = dir_entry.unwrap();
- manifest_dir.join(file.path())
- })
- .filter(|path| path.extension().unwrap_or_default() == "js")
- .collect::<Vec<PathBuf>>();
- js_files.sort();
- js_files
-}
diff --git a/cli/js.rs b/cli/js.rs
new file mode 100644
index 000000000..4bf3da627
--- /dev/null
+++ b/cli/js.rs
@@ -0,0 +1,57 @@
+use deno_core::Snapshot;
+use log::debug;
+use once_cell::sync::Lazy;
+
+pub static CLI_SNAPSHOT: Lazy<Box<[u8]>> = Lazy::new(
+ #[allow(clippy::uninit_vec)]
+ #[cold]
+ #[inline(never)]
+ || {
+ static COMPRESSED_CLI_SNAPSHOT: &[u8] =
+ include_bytes!(concat!(env!("OUT_DIR"), "/CLI_SNAPSHOT.bin"));
+
+ let size =
+ u32::from_le_bytes(COMPRESSED_CLI_SNAPSHOT[0..4].try_into().unwrap())
+ as usize;
+ let mut vec = Vec::with_capacity(size);
+
+ // SAFETY: vec is allocated with exact snapshot size (+ alignment)
+ // SAFETY: non zeroed bytes are overwritten with decompressed snapshot
+ unsafe {
+ vec.set_len(size);
+ }
+
+ lzzzz::lz4::decompress(&COMPRESSED_CLI_SNAPSHOT[4..], &mut vec).unwrap();
+
+ vec.into_boxed_slice()
+ },
+);
+
+pub fn deno_isolate_init() -> Snapshot {
+ debug!("Deno isolate init with snapshots.");
+ Snapshot::Static(&CLI_SNAPSHOT)
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn runtime_snapshot() {
+ let mut js_runtime = deno_core::JsRuntime::new(deno_core::RuntimeOptions {
+ startup_snapshot: Some(deno_isolate_init()),
+ ..Default::default()
+ });
+ js_runtime
+ .execute_script(
+ "<anon>",
+ r#"
+ if (!(bootstrap.mainRuntime && bootstrap.workerRuntime)) {
+ throw Error("bad");
+ }
+ console.log("we have console.log!!!");
+ "#,
+ )
+ .unwrap();
+ }
+}
diff --git a/runtime/js/40_testing.js b/cli/js/40_testing.js
index e8590faf1..864d50104 100644
--- a/runtime/js/40_testing.js
+++ b/cli/js/40_testing.js
@@ -1397,12 +1397,16 @@
return testFn;
}
- window.__bootstrap.testing = {
- bench,
- enableBench,
- enableTest,
- runBenchmarks,
- runTests,
- test,
+ window.__bootstrap.internals = {
+ ...window.__bootstrap.internals ?? {},
+ testing: {
+ runTests,
+ runBenchmarks,
+ enableTest,
+ enableBench,
+ },
};
+
+ window.__bootstrap.denoNs.bench = bench;
+ window.__bootstrap.denoNs.test = test;
})(this);
diff --git a/cli/lsp/testing/execution.rs b/cli/lsp/testing/execution.rs
index 950f2a96e..d839cda56 100644
--- a/cli/lsp/testing/execution.rs
+++ b/cli/lsp/testing/execution.rs
@@ -7,7 +7,6 @@ use super::lsp_custom;
use crate::args::flags_from_vec;
use crate::args::DenoSubcommand;
use crate::checksum;
-use crate::create_main_worker;
use crate::lsp::client::Client;
use crate::lsp::client::TestingNotification;
use crate::lsp::config;
@@ -16,6 +15,7 @@ use crate::ops;
use crate::proc_state;
use crate::tools::test;
use crate::tools::test::TestEventSender;
+use crate::worker::create_main_worker_for_test_or_bench;
use deno_core::anyhow::anyhow;
use deno_core::error::AnyError;
@@ -154,7 +154,7 @@ async fn test_specifier(
filter: test::TestFilter,
) -> Result<(), AnyError> {
if !token.is_cancelled() {
- let mut worker = create_main_worker(
+ let mut worker = create_main_worker_for_test_or_bench(
&ps,
specifier.clone(),
permissions,
diff --git a/cli/main.rs b/cli/main.rs
index ed3d459e1..b91540c37 100644
--- a/cli/main.rs
+++ b/cli/main.rs
@@ -18,6 +18,7 @@ mod fs_util;
mod graph_util;
mod http_cache;
mod http_util;
+mod js;
mod lockfile;
mod logger;
mod lsp;
@@ -289,14 +290,8 @@ async fn eval_command(
resolve_url_or_path(&format!("./$deno$eval.{}", eval_flags.ext))?;
let permissions = Permissions::from_options(&flags.permissions_options())?;
let ps = ProcState::build(flags).await?;
- let mut worker = create_main_worker(
- &ps,
- main_module.clone(),
- permissions,
- vec![],
- Default::default(),
- )
- .await?;
+ let mut worker =
+ create_main_worker(&ps, main_module.clone(), permissions).await?;
// Create a dummy source file.
let source_code = if eval_flags.print {
format!("console.log({})", eval_flags.code)
@@ -602,8 +597,6 @@ async fn repl_command(
&ps,
main_module.clone(),
Permissions::from_options(&ps.options.permissions_options())?,
- vec![],
- Default::default(),
)
.await?;
worker.setup_repl().await?;
@@ -623,8 +616,6 @@ async fn run_from_stdin(flags: Flags) -> Result<i32, AnyError> {
&ps.clone(),
main_module.clone(),
Permissions::from_options(&ps.options.permissions_options())?,
- vec![],
- Default::default(),
)
.await?;
@@ -664,14 +655,8 @@ async fn run_with_watch(flags: Flags, script: String) -> Result<i32, AnyError> {
let ps =
ProcState::build_for_file_watcher((*flags).clone(), sender.clone())
.await?;
- let worker = create_main_worker(
- &ps,
- main_module.clone(),
- permissions,
- vec![],
- Default::default(),
- )
- .await?;
+ let worker =
+ create_main_worker(&ps, main_module.clone(), permissions).await?;
worker.run_for_watcher().await?;
Ok(())
@@ -722,14 +707,8 @@ async fn run_command(
};
let permissions =
Permissions::from_options(&ps.options.permissions_options())?;
- let mut worker = create_main_worker(
- &ps,
- main_module.clone(),
- permissions,
- vec![],
- Default::default(),
- )
- .await?;
+ let mut worker =
+ create_main_worker(&ps, main_module.clone(), permissions).await?;
let exit_code = worker.run().await?;
Ok(exit_code)
diff --git a/cli/standalone.rs b/cli/standalone.rs
index 5e66bcb18..2742f9bbd 100644
--- a/cli/standalone.rs
+++ b/cli/standalone.rs
@@ -287,7 +287,7 @@ pub async fn run(
inspect: ps.options.is_inspecting(),
},
extensions: ops::cli_exts(ps.clone()),
- startup_snapshot: None,
+ startup_snapshot: Some(crate::js::deno_isolate_init()),
unsafely_ignore_certificate_errors: metadata
.unsafely_ignore_certificate_errors,
root_cert_store: Some(root_cert_store),
diff --git a/cli/tests/testdata/test/steps/failing_steps.out b/cli/tests/testdata/test/steps/failing_steps.out
index 1e5f2f64d..4df104bd7 100644
--- a/cli/tests/testdata/test/steps/failing_steps.out
+++ b/cli/tests/testdata/test/steps/failing_steps.out
@@ -37,13 +37,13 @@ failing step in failing test ... FAILED ([WILDCARD])
nested failure => ./test/steps/failing_steps.ts:[WILDCARD]
error: Error: 1 test step failed.
- at runTest (deno:runtime/js/40_testing.js:[WILDCARD])
- at async runTests (deno:runtime/js/40_testing.js:[WILDCARD])
+ at runTest (deno:cli/js/40_testing.js:[WILDCARD])
+ at async runTests (deno:cli/js/40_testing.js:[WILDCARD])
multiple test step failures => ./test/steps/failing_steps.ts:[WILDCARD]
error: Error: 2 test steps failed.
- at runTest (deno:runtime/js/40_testing.js:[WILDCARD])
- at async runTests (deno:runtime/js/40_testing.js:[WILDCARD])
+ at runTest (deno:cli/js/40_testing.js:[WILDCARD])
+ at async runTests (deno:cli/js/40_testing.js:[WILDCARD])
failing step in failing test => ./test/steps/failing_steps.ts:[WILDCARD]
error: Error: Fail test.
diff --git a/cli/tools/bench.rs b/cli/tools/bench.rs
index c055d8a9c..a81c0a406 100644
--- a/cli/tools/bench.rs
+++ b/cli/tools/bench.rs
@@ -4,7 +4,6 @@ use crate::args::BenchFlags;
use crate::args::Flags;
use crate::args::TypeCheckMode;
use crate::colors;
-use crate::create_main_worker;
use crate::file_watcher;
use crate::file_watcher::ResolutionResult;
use crate::fs_util::collect_specifiers;
@@ -15,6 +14,7 @@ use crate::ops;
use crate::proc_state::ProcState;
use crate::tools::test::format_test_error;
use crate::tools::test::TestFilter;
+use crate::worker::create_main_worker_for_test_or_bench;
use deno_core::error::generic_error;
use deno_core::error::AnyError;
@@ -352,7 +352,7 @@ async fn bench_specifier(
options: BenchSpecifierOptions,
) -> Result<(), AnyError> {
let filter = TestFilter::from_flag(&options.filter);
- let mut worker = create_main_worker(
+ let mut worker = create_main_worker_for_test_or_bench(
&ps,
specifier.clone(),
permissions,
diff --git a/cli/tools/test.rs b/cli/tools/test.rs
index 09257efff..1bb891a1e 100644
--- a/cli/tools/test.rs
+++ b/cli/tools/test.rs
@@ -5,7 +5,6 @@ use crate::args::TestFlags;
use crate::args::TypeCheckMode;
use crate::checksum;
use crate::colors;
-use crate::create_main_worker;
use crate::display;
use crate::file_fetcher::File;
use crate::file_watcher;
@@ -18,6 +17,7 @@ use crate::graph_util::contains_specifier;
use crate::graph_util::graph_valid;
use crate::ops;
use crate::proc_state::ProcState;
+use crate::worker::create_main_worker_for_test_or_bench;
use deno_ast::swc::common::comments::CommentKind;
use deno_ast::MediaType;
@@ -715,7 +715,7 @@ async fn test_specifier(
sender: &TestEventSender,
options: TestSpecifierOptions,
) -> Result<(), AnyError> {
- let mut worker = create_main_worker(
+ let mut worker = create_main_worker_for_test_or_bench(
&ps,
specifier.clone(),
permissions,
diff --git a/cli/worker.rs b/cli/worker.rs
index 7fe1f3c0b..d06864634 100644
--- a/cli/worker.rs
+++ b/cli/worker.rs
@@ -7,6 +7,9 @@ use deno_core::error::AnyError;
use deno_core::futures::task::LocalFutureObj;
use deno_core::futures::FutureExt;
use deno_core::located_script_name;
+use deno_core::serde_json::json;
+use deno_core::serde_v8;
+use deno_core::v8;
use deno_core::Extension;
use deno_core::ModuleId;
use deno_runtime::colors;
@@ -38,6 +41,11 @@ pub struct CliMainWorker {
is_main_cjs: bool,
worker: MainWorker,
ps: ProcState,
+
+ js_run_tests_callback: Option<v8::Global<v8::Function>>,
+ js_run_benchmarks_callback: Option<v8::Global<v8::Function>>,
+ js_enable_test_callback: Option<v8::Global<v8::Function>>,
+ js_enable_bench_callback: Option<v8::Global<v8::Function>>,
}
impl CliMainWorker {
@@ -168,7 +176,7 @@ impl CliMainWorker {
&mut self,
mode: TestMode,
) -> Result<(), AnyError> {
- self.worker.enable_test();
+ self.enable_test();
// Enable op call tracing in core to enable better debugging of op sanitizer
// failures.
@@ -194,10 +202,7 @@ impl CliMainWorker {
}
self.worker.dispatch_load_event(&located_script_name!())?;
- self
- .worker
- .run_tests(&self.ps.options.shuffle_tests())
- .await?;
+ self.run_tests(&self.ps.options.shuffle_tests()).await?;
loop {
if !self
.worker
@@ -223,7 +228,7 @@ impl CliMainWorker {
&mut self,
mode: TestMode,
) -> Result<(), AnyError> {
- self.worker.enable_test();
+ self.enable_test();
self
.worker
@@ -239,7 +244,7 @@ impl CliMainWorker {
}
self.worker.dispatch_load_event(&located_script_name!())?;
- self.worker.run_tests(&None).await?;
+ self.run_tests(&None).await?;
loop {
if !self
.worker
@@ -254,13 +259,13 @@ impl CliMainWorker {
}
pub async fn run_bench_specifier(&mut self) -> Result<(), AnyError> {
- self.worker.enable_bench();
+ self.enable_bench();
// We execute the module module as a side module so that import.meta.main is not set.
self.execute_side_module_possibly_with_npm().await?;
self.worker.dispatch_load_event(&located_script_name!())?;
- self.worker.run_benchmarks().await?;
+ self.run_benchmarks().await?;
loop {
if !self
.worker
@@ -340,14 +345,104 @@ impl CliMainWorker {
Ok(None)
}
}
+
+ /// Run tests declared with `Deno.test()`. Test events will be dispatched
+ /// by calling ops which are currently only implemented in the CLI crate.
+ pub async fn run_tests(
+ &mut self,
+ shuffle: &Option<u64>,
+ ) -> Result<(), AnyError> {
+ let promise = {
+ let scope = &mut self.worker.js_runtime.handle_scope();
+ let cb = self.js_run_tests_callback.as_ref().unwrap().open(scope);
+ let this = v8::undefined(scope).into();
+ let options =
+ serde_v8::to_v8(scope, json!({ "shuffle": shuffle })).unwrap();
+ let promise = cb.call(scope, this, &[options]).unwrap();
+ v8::Global::new(scope, promise)
+ };
+ self.worker.js_runtime.resolve_value(promise).await?;
+ Ok(())
+ }
+
+ /// Run benches declared with `Deno.bench()`. Bench events will be dispatched
+ /// by calling ops which are currently only implemented in the CLI crate.
+ pub async fn run_benchmarks(&mut self) -> Result<(), AnyError> {
+ let promise = {
+ let scope = &mut self.worker.js_runtime.handle_scope();
+ let cb = self
+ .js_run_benchmarks_callback
+ .as_ref()
+ .unwrap()
+ .open(scope);
+ let this = v8::undefined(scope).into();
+ let promise = cb.call(scope, this, &[]).unwrap();
+ v8::Global::new(scope, promise)
+ };
+ self.worker.js_runtime.resolve_value(promise).await?;
+ Ok(())
+ }
+
+ /// Enable `Deno.test()`. If this isn't called before executing user code,
+ /// `Deno.test()` calls will noop.
+ pub fn enable_test(&mut self) {
+ let scope = &mut self.worker.js_runtime.handle_scope();
+ let cb = self.js_enable_test_callback.as_ref().unwrap().open(scope);
+ let this = v8::undefined(scope).into();
+ cb.call(scope, this, &[]).unwrap();
+ }
+
+ /// Enable `Deno.bench()`. If this isn't called before executing user code,
+ /// `Deno.bench()` calls will noop.
+ pub fn enable_bench(&mut self) {
+ let scope = &mut self.worker.js_runtime.handle_scope();
+ let cb = self.js_enable_bench_callback.as_ref().unwrap().open(scope);
+ let this = v8::undefined(scope).into();
+ cb.call(scope, this, &[]).unwrap();
+ }
}
pub async fn create_main_worker(
ps: &ProcState,
main_module: ModuleSpecifier,
permissions: Permissions,
+) -> Result<CliMainWorker, AnyError> {
+ create_main_worker_internal(
+ ps,
+ main_module,
+ permissions,
+ vec![],
+ Default::default(),
+ false,
+ )
+ .await
+}
+
+pub async fn create_main_worker_for_test_or_bench(
+ ps: &ProcState,
+ main_module: ModuleSpecifier,
+ permissions: Permissions,
+ custom_extensions: Vec<Extension>,
+ stdio: deno_runtime::ops::io::Stdio,
+) -> Result<CliMainWorker, AnyError> {
+ create_main_worker_internal(
+ ps,
+ main_module,
+ permissions,
+ custom_extensions,
+ stdio,
+ true,
+ )
+ .await
+}
+
+async fn create_main_worker_internal(
+ ps: &ProcState,
+ main_module: ModuleSpecifier,
+ permissions: Permissions,
mut custom_extensions: Vec<Extension>,
stdio: deno_runtime::ops::io::Stdio,
+ bench_or_test: bool,
) -> Result<CliMainWorker, AnyError> {
let (main_module, is_main_cjs) = if let Ok(package_ref) =
NpmPackageReference::from_specifier(&main_module)
@@ -426,7 +521,7 @@ pub async fn create_main_worker(
inspect: ps.options.is_inspecting(),
},
extensions,
- startup_snapshot: None,
+ startup_snapshot: Some(crate::js::deno_isolate_init()),
unsafely_ignore_certificate_errors: ps
.options
.unsafely_ignore_certificate_errors()
@@ -452,16 +547,59 @@ pub async fn create_main_worker(
stdio,
};
- let worker = MainWorker::bootstrap_from_options(
+ let mut worker = MainWorker::bootstrap_from_options(
main_module.clone(),
permissions,
options,
);
+
+ let (
+ js_run_tests_callback,
+ js_run_benchmarks_callback,
+ js_enable_test_callback,
+ js_enable_bench_callback,
+ ) = if bench_or_test {
+ let scope = &mut worker.js_runtime.handle_scope();
+ let js_run_tests_callback = deno_core::JsRuntime::eval::<v8::Function>(
+ scope,
+ "Deno[Deno.internal].testing.runTests",
+ )
+ .unwrap();
+ let js_run_benchmarks_callback =
+ deno_core::JsRuntime::eval::<v8::Function>(
+ scope,
+ "Deno[Deno.internal].testing.runBenchmarks",
+ )
+ .unwrap();
+ let js_enable_tests_callback = deno_core::JsRuntime::eval::<v8::Function>(
+ scope,
+ "Deno[Deno.internal].testing.enableTest",
+ )
+ .unwrap();
+ let js_enable_bench_callback = deno_core::JsRuntime::eval::<v8::Function>(
+ scope,
+ "Deno[Deno.internal].testing.enableBench",
+ )
+ .unwrap();
+ (
+ Some(v8::Global::new(scope, js_run_tests_callback)),
+ Some(v8::Global::new(scope, js_run_benchmarks_callback)),
+ Some(v8::Global::new(scope, js_enable_tests_callback)),
+ Some(v8::Global::new(scope, js_enable_bench_callback)),
+ )
+ } else {
+ (None, None, None, None)
+ };
+
Ok(CliMainWorker {
main_module,
is_main_cjs,
worker,
ps: ps.clone(),
+ js_run_tests_callback,
+ js_run_benchmarks_callback,
+ js_enable_test_callback,
+ js_enable_bench_callback,
})
}
@@ -544,6 +682,7 @@ fn create_web_worker_callback(
inspect: ps.options.is_inspecting(),
},
extensions,
+ startup_snapshot: Some(crate::js::deno_isolate_init()),
unsafely_ignore_certificate_errors: ps
.options
.unsafely_ignore_certificate_errors()
@@ -577,3 +716,109 @@ fn create_web_worker_callback(
)
})
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use deno_core::{resolve_url_or_path, FsModuleLoader};
+ use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel;
+ use deno_runtime::deno_web::BlobStore;
+
+ fn create_test_worker() -> MainWorker {
+ let main_module = resolve_url_or_path("./hello.js").unwrap();
+ let permissions = Permissions::default();
+
+ let options = WorkerOptions {
+ bootstrap: BootstrapOptions {
+ args: vec![],
+ cpu_count: 1,
+ debug_flag: false,
+ enable_testing_features: false,
+ locale: deno_core::v8::icu::get_language_tag(),
+ location: None,
+ no_color: true,
+ is_tty: false,
+ runtime_version: "x".to_string(),
+ ts_version: "x".to_string(),
+ unstable: false,
+ user_agent: "x".to_string(),
+ inspect: false,
+ },
+ extensions: vec![],
+ startup_snapshot: Some(crate::js::deno_isolate_init()),
+ unsafely_ignore_certificate_errors: None,
+ root_cert_store: None,
+ seed: None,
+ format_js_error_fn: None,
+ source_map_getter: None,
+ web_worker_preload_module_cb: Arc::new(|_| unreachable!()),
+ web_worker_pre_execute_module_cb: Arc::new(|_| unreachable!()),
+ create_web_worker_cb: Arc::new(|_| unreachable!()),
+ maybe_inspector_server: None,
+ should_break_on_first_statement: false,
+ module_loader: Rc::new(FsModuleLoader),
+ npm_resolver: None,
+ get_error_class_fn: None,
+ cache_storage_dir: None,
+ origin_storage_dir: None,
+ blob_store: BlobStore::default(),
+ broadcast_channel: InMemoryBroadcastChannel::default(),
+ shared_array_buffer_store: None,
+ compiled_wasm_module_store: None,
+ stdio: Default::default(),
+ };
+
+ MainWorker::bootstrap_from_options(main_module, permissions, options)
+ }
+
+ #[tokio::test]
+ async fn execute_mod_esm_imports_a() {
+ let p = test_util::testdata_path().join("runtime/esm_imports_a.js");
+ let module_specifier = resolve_url_or_path(&p.to_string_lossy()).unwrap();
+ let mut worker = create_test_worker();
+ let result = worker.execute_main_module(&module_specifier).await;
+ if let Err(err) = result {
+ eprintln!("execute_mod err {:?}", err);
+ }
+ if let Err(e) = worker.run_event_loop(false).await {
+ panic!("Future got unexpected error: {:?}", e);
+ }
+ }
+
+ #[tokio::test]
+ async fn execute_mod_circular() {
+ let p = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
+ .parent()
+ .unwrap()
+ .join("tests/circular1.js");
+ let module_specifier = resolve_url_or_path(&p.to_string_lossy()).unwrap();
+ let mut worker = create_test_worker();
+ let result = worker.execute_main_module(&module_specifier).await;
+ if let Err(err) = result {
+ eprintln!("execute_mod err {:?}", err);
+ }
+ if let Err(e) = worker.run_event_loop(false).await {
+ panic!("Future got unexpected error: {:?}", e);
+ }
+ }
+
+ #[tokio::test]
+ async fn execute_mod_resolve_error() {
+ // "foo" is not a valid module specifier so this should return an error.
+ let mut worker = create_test_worker();
+ let module_specifier = resolve_url_or_path("does-not-exist").unwrap();
+ let result = worker.execute_main_module(&module_specifier).await;
+ assert!(result.is_err());
+ }
+
+ #[tokio::test]
+ async fn execute_mod_002_hello() {
+ // This assumes cwd is project root (an assumption made throughout the
+ // tests).
+ let mut worker = create_test_worker();
+ let p = test_util::testdata_path().join("run/001_hello.js");
+ let module_specifier = resolve_url_or_path(&p.to_string_lossy()).unwrap();
+ let result = worker.execute_main_module(&module_specifier).await;
+ assert!(result.is_ok());
+ }
+}
diff --git a/core/lib.rs b/core/lib.rs
index 607d90f0b..011fa6c50 100644
--- a/core/lib.rs
+++ b/core/lib.rs
@@ -18,6 +18,7 @@ mod ops_builtin_v8;
mod ops_metrics;
mod resources;
mod runtime;
+pub mod snapshot_util;
mod source_map;
// Re-exports
diff --git a/core/snapshot_util.rs b/core/snapshot_util.rs
new file mode 100644
index 000000000..b408bad56
--- /dev/null
+++ b/core/snapshot_util.rs
@@ -0,0 +1,95 @@
+use crate::Extension;
+use crate::JsRuntime;
+use crate::RuntimeOptions;
+use crate::Snapshot;
+use std::path::Path;
+use std::path::PathBuf;
+
+pub type CompressionCb = dyn Fn(&mut Vec<u8>, &[u8]);
+
+pub struct CreateSnapshotOptions {
+ pub cargo_manifest_dir: &'static str,
+ pub snapshot_path: PathBuf,
+ pub startup_snapshot: Option<Snapshot>,
+ pub extensions: Vec<Extension>,
+ pub additional_files: Vec<PathBuf>,
+ pub compression_cb: Option<Box<CompressionCb>>,
+}
+
+pub fn create_snapshot(create_snapshot_options: CreateSnapshotOptions) {
+ let mut js_runtime = JsRuntime::new(RuntimeOptions {
+ will_snapshot: true,
+ startup_snapshot: create_snapshot_options.startup_snapshot,
+ extensions: create_snapshot_options.extensions,
+ ..Default::default()
+ });
+
+ // TODO(nayeemrmn): https://github.com/rust-lang/cargo/issues/3946 to get the
+ // workspace root.
+ let display_root = Path::new(create_snapshot_options.cargo_manifest_dir)
+ .parent()
+ .unwrap();
+ for file in create_snapshot_options.additional_files {
+ let display_path = file.strip_prefix(display_root).unwrap_or(&file);
+ let display_path_str = display_path.display().to_string();
+ js_runtime
+ .execute_script(
+ &("deno:".to_string() + &display_path_str.replace('\\', "/")),
+ &std::fs::read_to_string(&file).unwrap(),
+ )
+ .unwrap();
+ }
+
+ let snapshot = js_runtime.snapshot();
+ let snapshot_slice: &[u8] = &snapshot;
+ println!("Snapshot size: {}", snapshot_slice.len());
+
+ let maybe_compressed_snapshot: Box<dyn AsRef<[u8]>> =
+ if let Some(compression_cb) = create_snapshot_options.compression_cb {
+ let mut vec = vec![];
+
+ vec.extend_from_slice(
+ &u32::try_from(snapshot.len())
+ .expect("snapshot larger than 4gb")
+ .to_le_bytes(),
+ );
+
+ (compression_cb)(&mut vec, snapshot_slice);
+
+ println!("Snapshot compressed size: {}", vec.len());
+
+ Box::new(vec)
+ } else {
+ Box::new(snapshot_slice)
+ };
+
+ std::fs::write(
+ &create_snapshot_options.snapshot_path,
+ &*maybe_compressed_snapshot,
+ )
+ .unwrap();
+ println!(
+ "Snapshot written to: {} ",
+ create_snapshot_options.snapshot_path.display()
+ );
+}
+
+pub fn get_js_files(
+ cargo_manifest_dir: &'static str,
+ directory: &str,
+) -> Vec<PathBuf> {
+ let manifest_dir = Path::new(cargo_manifest_dir);
+ let mut js_files = std::fs::read_dir(directory)
+ .unwrap()
+ .map(|dir_entry| {
+ let file = dir_entry.unwrap();
+ manifest_dir.join(file.path())
+ })
+ .filter(|path| {
+ path.extension().unwrap_or_default() == "js"
+ && !path.ends_with("99_main.js")
+ })
+ .collect::<Vec<PathBuf>>();
+ js_files.sort();
+ js_files
+}
diff --git a/runtime/build.rs b/runtime/build.rs
index 3feca3e76..bab7745cc 100644
--- a/runtime/build.rs
+++ b/runtime/build.rs
@@ -9,63 +9,8 @@ use std::path::PathBuf;
mod not_docs {
use super::*;
use deno_cache::SqliteBackedCache;
+ use deno_core::snapshot_util::*;
use deno_core::Extension;
- use deno_core::JsRuntime;
- use deno_core::RuntimeOptions;
-
- // TODO(bartlomieju): this module contains a lot of duplicated
- // logic with `cli/build.rs`, factor out to `deno_core`.
- fn create_snapshot(
- mut js_runtime: JsRuntime,
- snapshot_path: &Path,
- files: Vec<PathBuf>,
- ) {
- // TODO(nayeemrmn): https://github.com/rust-lang/cargo/issues/3946 to get the
- // workspace root.
- let display_root = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap();
- for file in files {
- println!("cargo:rerun-if-changed={}", file.display());
- let display_path = file.strip_prefix(display_root).unwrap();
- let display_path_str = display_path.display().to_string();
- js_runtime
- .execute_script(
- &("deno:".to_string() + &display_path_str.replace('\\', "/")),
- &std::fs::read_to_string(&file).unwrap(),
- )
- .unwrap();
- }
-
- let snapshot = js_runtime.snapshot();
- let snapshot_slice: &[u8] = &snapshot;
- println!("Snapshot size: {}", snapshot_slice.len());
-
- let compressed_snapshot_with_size = {
- let mut vec = vec![];
-
- vec.extend_from_slice(
- &u32::try_from(snapshot.len())
- .expect("snapshot larger than 4gb")
- .to_le_bytes(),
- );
-
- lzzzz::lz4_hc::compress_to_vec(
- snapshot_slice,
- &mut vec,
- lzzzz::lz4_hc::CLEVEL_MAX,
- )
- .expect("snapshot compression failed");
-
- vec
- };
-
- println!(
- "Snapshot compressed size: {}",
- compressed_snapshot_with_size.len()
- );
-
- std::fs::write(snapshot_path, compressed_snapshot_with_size).unwrap();
- println!("Snapshot written to: {} ", snapshot_path.display());
- }
struct Permissions;
@@ -174,7 +119,7 @@ mod not_docs {
}
}
- fn create_runtime_snapshot(snapshot_path: &Path, files: Vec<PathBuf>) {
+ fn create_runtime_snapshot(snapshot_path: PathBuf, files: Vec<PathBuf>) {
let extensions: Vec<Extension> = vec![
deno_webidl::init(),
deno_console::init(),
@@ -205,31 +150,26 @@ mod not_docs {
deno_flash::init::<Permissions>(false), // No --unstable
];
- let js_runtime = JsRuntime::new(RuntimeOptions {
- will_snapshot: true,
+ create_snapshot(CreateSnapshotOptions {
+ cargo_manifest_dir: env!("CARGO_MANIFEST_DIR"),
+ snapshot_path,
+ startup_snapshot: None,
extensions,
- ..Default::default()
+ additional_files: files,
+ compression_cb: Some(Box::new(|vec, snapshot_slice| {
+ lzzzz::lz4_hc::compress_to_vec(
+ snapshot_slice,
+ vec,
+ lzzzz::lz4_hc::CLEVEL_MAX,
+ )
+ .expect("snapshot compression failed");
+ })),
});
- create_snapshot(js_runtime, snapshot_path, files);
- }
-
- fn get_js_files(d: &str) -> Vec<PathBuf> {
- let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
- let mut js_files = std::fs::read_dir(d)
- .unwrap()
- .map(|dir_entry| {
- let file = dir_entry.unwrap();
- manifest_dir.join(file.path())
- })
- .filter(|path| path.extension().unwrap_or_default() == "js")
- .collect::<Vec<PathBuf>>();
- js_files.sort();
- js_files
}
pub fn build_snapshot(runtime_snapshot_path: PathBuf) {
- let js_files = get_js_files("js");
- create_runtime_snapshot(&runtime_snapshot_path, js_files);
+ let js_files = get_js_files(env!("CARGO_MANIFEST_DIR"), "js");
+ create_runtime_snapshot(runtime_snapshot_path, js_files);
}
}
@@ -242,7 +182,7 @@ fn main() {
let o = PathBuf::from(env::var_os("OUT_DIR").unwrap());
// Main snapshot
- let runtime_snapshot_path = o.join("CLI_SNAPSHOT.bin");
+ let runtime_snapshot_path = o.join("RUNTIME_SNAPSHOT.bin");
// If we're building on docs.rs we just create
// and empty snapshot file and return, because `rusty_v8`
diff --git a/runtime/js.rs b/runtime/js.rs
index 54a08d9b4..3ad241670 100644
--- a/runtime/js.rs
+++ b/runtime/js.rs
@@ -2,17 +2,18 @@
use deno_core::Snapshot;
use log::debug;
use once_cell::sync::Lazy;
+use std::path::PathBuf;
-pub static CLI_SNAPSHOT: Lazy<Box<[u8]>> = Lazy::new(
+pub static RUNTIME_SNAPSHOT: Lazy<Box<[u8]>> = Lazy::new(
#[allow(clippy::uninit_vec)]
#[cold]
#[inline(never)]
|| {
- static COMPRESSED_CLI_SNAPSHOT: &[u8] =
- include_bytes!(concat!(env!("OUT_DIR"), "/CLI_SNAPSHOT.bin"));
+ static COMPRESSED_RUNTIME_SNAPSHOT: &[u8] =
+ include_bytes!(concat!(env!("OUT_DIR"), "/RUNTIME_SNAPSHOT.bin"));
let size =
- u32::from_le_bytes(COMPRESSED_CLI_SNAPSHOT[0..4].try_into().unwrap())
+ u32::from_le_bytes(COMPRESSED_RUNTIME_SNAPSHOT[0..4].try_into().unwrap())
as usize;
let mut vec = Vec::with_capacity(size);
@@ -22,7 +23,8 @@ pub static CLI_SNAPSHOT: Lazy<Box<[u8]>> = Lazy::new(
vec.set_len(size);
}
- lzzzz::lz4::decompress(&COMPRESSED_CLI_SNAPSHOT[4..], &mut vec).unwrap();
+ lzzzz::lz4::decompress(&COMPRESSED_RUNTIME_SNAPSHOT[4..], &mut vec)
+ .unwrap();
vec.into_boxed_slice()
},
@@ -30,29 +32,11 @@ pub static CLI_SNAPSHOT: Lazy<Box<[u8]>> = Lazy::new(
pub fn deno_isolate_init() -> Snapshot {
debug!("Deno isolate init with snapshots.");
- Snapshot::Static(&CLI_SNAPSHOT)
+ Snapshot::Static(&RUNTIME_SNAPSHOT)
}
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn cli_snapshot() {
- let mut js_runtime = deno_core::JsRuntime::new(deno_core::RuntimeOptions {
- startup_snapshot: Some(deno_isolate_init()),
- ..Default::default()
- });
- js_runtime
- .execute_script(
- "<anon>",
- r#"
- if (!(bootstrap.mainRuntime && bootstrap.workerRuntime)) {
- throw Error("bad");
- }
- console.log("we have console.log!!!");
- "#,
- )
- .unwrap();
- }
+pub fn get_99_main() -> PathBuf {
+ let manifest = env!("CARGO_MANIFEST_DIR");
+ let path = PathBuf::from(manifest);
+ path.join("js").join("99_main.js")
}
diff --git a/runtime/js/90_deno_ns.js b/runtime/js/90_deno_ns.js
index 16dd5c72f..cd6c07464 100644
--- a/runtime/js/90_deno_ns.js
+++ b/runtime/js/90_deno_ns.js
@@ -7,8 +7,6 @@
__bootstrap.denoNs = {
metrics: core.metrics,
- test: __bootstrap.testing.test,
- bench: __bootstrap.testing.bench,
Process: __bootstrap.process.Process,
run: __bootstrap.process.run,
isatty: __bootstrap.tty.isatty,
diff --git a/runtime/js/98_global_scope.js b/runtime/js/98_global_scope.js
new file mode 100644
index 000000000..7afb4472c
--- /dev/null
+++ b/runtime/js/98_global_scope.js
@@ -0,0 +1,352 @@
+// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
+"use strict";
+
+((window) => {
+ const core = Deno.core;
+ const {
+ ObjectDefineProperties,
+ SymbolFor,
+ } = window.__bootstrap.primordials;
+
+ const util = window.__bootstrap.util;
+ const location = window.__bootstrap.location;
+ const event = window.__bootstrap.event;
+ const eventTarget = window.__bootstrap.eventTarget;
+ const timers = window.__bootstrap.timers;
+ const base64 = window.__bootstrap.base64;
+ const encoding = window.__bootstrap.encoding;
+ const Console = window.__bootstrap.console.Console;
+ const caches = window.__bootstrap.caches;
+ const compression = window.__bootstrap.compression;
+ const worker = window.__bootstrap.worker;
+ const performance = window.__bootstrap.performance;
+ const crypto = window.__bootstrap.crypto;
+ const url = window.__bootstrap.url;
+ const urlPattern = window.__bootstrap.urlPattern;
+ const headers = window.__bootstrap.headers;
+ const streams = window.__bootstrap.streams;
+ const fileReader = window.__bootstrap.fileReader;
+ const webgpu = window.__bootstrap.webgpu;
+ const webSocket = window.__bootstrap.webSocket;
+ const broadcastChannel = window.__bootstrap.broadcastChannel;
+ const file = window.__bootstrap.file;
+ const formData = window.__bootstrap.formData;
+ const fetch = window.__bootstrap.fetch;
+ const messagePort = window.__bootstrap.messagePort;
+ const webidl = window.__bootstrap.webidl;
+ const domException = window.__bootstrap.domException;
+ const abortSignal = window.__bootstrap.abortSignal;
+ const globalInterfaces = window.__bootstrap.globalInterfaces;
+ const webStorage = window.__bootstrap.webStorage;
+ const prompt = window.__bootstrap.prompt;
+
+ // https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope
+ const windowOrWorkerGlobalScope = {
+ AbortController: util.nonEnumerable(abortSignal.AbortController),
+ AbortSignal: util.nonEnumerable(abortSignal.AbortSignal),
+ Blob: util.nonEnumerable(file.Blob),
+ ByteLengthQueuingStrategy: util.nonEnumerable(
+ streams.ByteLengthQueuingStrategy,
+ ),
+ CloseEvent: util.nonEnumerable(event.CloseEvent),
+ CompressionStream: util.nonEnumerable(compression.CompressionStream),
+ CountQueuingStrategy: util.nonEnumerable(
+ streams.CountQueuingStrategy,
+ ),
+ CryptoKey: util.nonEnumerable(crypto.CryptoKey),
+ CustomEvent: util.nonEnumerable(event.CustomEvent),
+ DecompressionStream: util.nonEnumerable(compression.DecompressionStream),
+ DOMException: util.nonEnumerable(domException.DOMException),
+ ErrorEvent: util.nonEnumerable(event.ErrorEvent),
+ Event: util.nonEnumerable(event.Event),
+ EventTarget: util.nonEnumerable(eventTarget.EventTarget),
+ File: util.nonEnumerable(file.File),
+ FileReader: util.nonEnumerable(fileReader.FileReader),
+ FormData: util.nonEnumerable(formData.FormData),
+ Headers: util.nonEnumerable(headers.Headers),
+ MessageEvent: util.nonEnumerable(event.MessageEvent),
+ Performance: util.nonEnumerable(performance.Performance),
+ PerformanceEntry: util.nonEnumerable(performance.PerformanceEntry),
+ PerformanceMark: util.nonEnumerable(performance.PerformanceMark),
+ PerformanceMeasure: util.nonEnumerable(performance.PerformanceMeasure),
+ PromiseRejectionEvent: util.nonEnumerable(event.PromiseRejectionEvent),
+ ProgressEvent: util.nonEnumerable(event.ProgressEvent),
+ ReadableStream: util.nonEnumerable(streams.ReadableStream),
+ ReadableStreamDefaultReader: util.nonEnumerable(
+ streams.ReadableStreamDefaultReader,
+ ),
+ Request: util.nonEnumerable(fetch.Request),
+ Response: util.nonEnumerable(fetch.Response),
+ TextDecoder: util.nonEnumerable(encoding.TextDecoder),
+ TextEncoder: util.nonEnumerable(encoding.TextEncoder),
+ TextDecoderStream: util.nonEnumerable(encoding.TextDecoderStream),
+ TextEncoderStream: util.nonEnumerable(encoding.TextEncoderStream),
+ TransformStream: util.nonEnumerable(streams.TransformStream),
+ URL: util.nonEnumerable(url.URL),
+ URLPattern: util.nonEnumerable(urlPattern.URLPattern),
+ URLSearchParams: util.nonEnumerable(url.URLSearchParams),
+ WebSocket: util.nonEnumerable(webSocket.WebSocket),
+ MessageChannel: util.nonEnumerable(messagePort.MessageChannel),
+ MessagePort: util.nonEnumerable(messagePort.MessagePort),
+ Worker: util.nonEnumerable(worker.Worker),
+ WritableStream: util.nonEnumerable(streams.WritableStream),
+ WritableStreamDefaultWriter: util.nonEnumerable(
+ streams.WritableStreamDefaultWriter,
+ ),
+ WritableStreamDefaultController: util.nonEnumerable(
+ streams.WritableStreamDefaultController,
+ ),
+ ReadableByteStreamController: util.nonEnumerable(
+ streams.ReadableByteStreamController,
+ ),
+ ReadableStreamBYOBReader: util.nonEnumerable(
+ streams.ReadableStreamBYOBReader,
+ ),
+ ReadableStreamBYOBRequest: util.nonEnumerable(
+ streams.ReadableStreamBYOBRequest,
+ ),
+ ReadableStreamDefaultController: util.nonEnumerable(
+ streams.ReadableStreamDefaultController,
+ ),
+ TransformStreamDefaultController: util.nonEnumerable(
+ streams.TransformStreamDefaultController,
+ ),
+ atob: util.writable(base64.atob),
+ btoa: util.writable(base64.btoa),
+ clearInterval: util.writable(timers.clearInterval),
+ clearTimeout: util.writable(timers.clearTimeout),
+ caches: {
+ enumerable: true,
+ configurable: true,
+ get: caches.cacheStorage,
+ },
+ CacheStorage: util.nonEnumerable(caches.CacheStorage),
+ Cache: util.nonEnumerable(caches.Cache),
+ console: util.nonEnumerable(
+ new Console((msg, level) => core.print(msg, level > 1)),
+ ),
+ crypto: util.readOnly(crypto.crypto),
+ Crypto: util.nonEnumerable(crypto.Crypto),
+ SubtleCrypto: util.nonEnumerable(crypto.SubtleCrypto),
+ fetch: util.writable(fetch.fetch),
+ performance: util.writable(performance.performance),
+ reportError: util.writable(event.reportError),
+ setInterval: util.writable(timers.setInterval),
+ setTimeout: util.writable(timers.setTimeout),
+ structuredClone: util.writable(messagePort.structuredClone),
+ // Branding as a WebIDL object
+ [webidl.brand]: util.nonEnumerable(webidl.brand),
+ };
+
+ const unstableWindowOrWorkerGlobalScope = {
+ BroadcastChannel: util.nonEnumerable(broadcastChannel.BroadcastChannel),
+ WebSocketStream: util.nonEnumerable(webSocket.WebSocketStream),
+
+ GPU: util.nonEnumerable(webgpu.GPU),
+ GPUAdapter: util.nonEnumerable(webgpu.GPUAdapter),
+ GPUSupportedLimits: util.nonEnumerable(webgpu.GPUSupportedLimits),
+ GPUSupportedFeatures: util.nonEnumerable(webgpu.GPUSupportedFeatures),
+ GPUDevice: util.nonEnumerable(webgpu.GPUDevice),
+ GPUQueue: util.nonEnumerable(webgpu.GPUQueue),
+ GPUBuffer: util.nonEnumerable(webgpu.GPUBuffer),
+ GPUBufferUsage: util.nonEnumerable(webgpu.GPUBufferUsage),
+ GPUMapMode: util.nonEnumerable(webgpu.GPUMapMode),
+ GPUTexture: util.nonEnumerable(webgpu.GPUTexture),
+ GPUTextureUsage: util.nonEnumerable(webgpu.GPUTextureUsage),
+ GPUTextureView: util.nonEnumerable(webgpu.GPUTextureView),
+ GPUSampler: util.nonEnumerable(webgpu.GPUSampler),
+ GPUBindGroupLayout: util.nonEnumerable(webgpu.GPUBindGroupLayout),
+ GPUPipelineLayout: util.nonEnumerable(webgpu.GPUPipelineLayout),
+ GPUBindGroup: util.nonEnumerable(webgpu.GPUBindGroup),
+ GPUShaderModule: util.nonEnumerable(webgpu.GPUShaderModule),
+ GPUShaderStage: util.nonEnumerable(webgpu.GPUShaderStage),
+ GPUComputePipeline: util.nonEnumerable(webgpu.GPUComputePipeline),
+ GPURenderPipeline: util.nonEnumerable(webgpu.GPURenderPipeline),
+ GPUColorWrite: util.nonEnumerable(webgpu.GPUColorWrite),
+ GPUCommandEncoder: util.nonEnumerable(webgpu.GPUCommandEncoder),
+ GPURenderPassEncoder: util.nonEnumerable(webgpu.GPURenderPassEncoder),
+ GPUComputePassEncoder: util.nonEnumerable(webgpu.GPUComputePassEncoder),
+ GPUCommandBuffer: util.nonEnumerable(webgpu.GPUCommandBuffer),
+ GPURenderBundleEncoder: util.nonEnumerable(webgpu.GPURenderBundleEncoder),
+ GPURenderBundle: util.nonEnumerable(webgpu.GPURenderBundle),
+ GPUQuerySet: util.nonEnumerable(webgpu.GPUQuerySet),
+ GPUOutOfMemoryError: util.nonEnumerable(webgpu.GPUOutOfMemoryError),
+ GPUValidationError: util.nonEnumerable(webgpu.GPUValidationError),
+ };
+
+ class Navigator {
+ constructor() {
+ webidl.illegalConstructor();
+ }
+
+ [SymbolFor("Deno.privateCustomInspect")](inspect) {
+ return `${this.constructor.name} ${inspect({})}`;
+ }
+ }
+
+ const navigator = webidl.createBranded(Navigator);
+
+ let numCpus, userAgent, language;
+
+ function setNumCpus(val) {
+ numCpus = val;
+ }
+
+ function setUserAgent(val) {
+ userAgent = val;
+ }
+
+ function setLanguage(val) {
+ language = val;
+ }
+
+ ObjectDefineProperties(Navigator.prototype, {
+ gpu: {
+ configurable: true,
+ enumerable: true,
+ get() {
+ webidl.assertBranded(this, NavigatorPrototype);
+ return webgpu.gpu;
+ },
+ },
+ hardwareConcurrency: {
+ configurable: true,
+ enumerable: true,
+ get() {
+ webidl.assertBranded(this, NavigatorPrototype);
+ return numCpus;
+ },
+ },
+ userAgent: {
+ configurable: true,
+ enumerable: true,
+ get() {
+ webidl.assertBranded(this, NavigatorPrototype);
+ return userAgent;
+ },
+ },
+ language: {
+ configurable: true,
+ enumerable: true,
+ get() {
+ webidl.assertBranded(this, NavigatorPrototype);
+ return language;
+ },
+ },
+ languages: {
+ configurable: true,
+ enumerable: true,
+ get() {
+ webidl.assertBranded(this, NavigatorPrototype);
+ return [language];
+ },
+ },
+ });
+ const NavigatorPrototype = Navigator.prototype;
+
+ class WorkerNavigator {
+ constructor() {
+ webidl.illegalConstructor();
+ }
+
+ [SymbolFor("Deno.privateCustomInspect")](inspect) {
+ return `${this.constructor.name} ${inspect({})}`;
+ }
+ }
+
+ const workerNavigator = webidl.createBranded(WorkerNavigator);
+
+ ObjectDefineProperties(WorkerNavigator.prototype, {
+ gpu: {
+ configurable: true,
+ enumerable: true,
+ get() {
+ webidl.assertBranded(this, WorkerNavigatorPrototype);
+ return webgpu.gpu;
+ },
+ },
+ hardwareConcurrency: {
+ configurable: true,
+ enumerable: true,
+ get() {
+ webidl.assertBranded(this, WorkerNavigatorPrototype);
+ return numCpus;
+ },
+ language: {
+ configurable: true,
+ enumerable: true,
+ get() {
+ webidl.assertBranded(this, WorkerNavigatorPrototype);
+ return language;
+ },
+ },
+ languages: {
+ configurable: true,
+ enumerable: true,
+ get() {
+ webidl.assertBranded(this, WorkerNavigatorPrototype);
+ return [language];
+ },
+ },
+ },
+ });
+ const WorkerNavigatorPrototype = WorkerNavigator.prototype;
+
+ const mainRuntimeGlobalProperties = {
+ Location: location.locationConstructorDescriptor,
+ location: location.locationDescriptor,
+ Window: globalInterfaces.windowConstructorDescriptor,
+ window: util.readOnly(globalThis),
+ self: util.writable(globalThis),
+ Navigator: util.nonEnumerable(Navigator),
+ navigator: {
+ configurable: true,
+ enumerable: true,
+ get: () => navigator,
+ },
+ alert: util.writable(prompt.alert),
+ confirm: util.writable(prompt.confirm),
+ prompt: util.writable(prompt.prompt),
+ localStorage: {
+ configurable: true,
+ enumerable: true,
+ get: webStorage.localStorage,
+ // Makes this reassignable to make astro work
+ set: () => {},
+ },
+ sessionStorage: {
+ configurable: true,
+ enumerable: true,
+ get: webStorage.sessionStorage,
+ // Makes this reassignable to make astro work
+ set: () => {},
+ },
+ Storage: util.nonEnumerable(webStorage.Storage),
+ };
+
+ const workerRuntimeGlobalProperties = {
+ WorkerLocation: location.workerLocationConstructorDescriptor,
+ location: location.workerLocationDescriptor,
+ WorkerGlobalScope: globalInterfaces.workerGlobalScopeConstructorDescriptor,
+ DedicatedWorkerGlobalScope:
+ globalInterfaces.dedicatedWorkerGlobalScopeConstructorDescriptor,
+ WorkerNavigator: util.nonEnumerable(WorkerNavigator),
+ navigator: {
+ configurable: true,
+ enumerable: true,
+ get: () => workerNavigator,
+ },
+ self: util.readOnly(globalThis),
+ };
+
+ window.__bootstrap.globalScope = {
+ windowOrWorkerGlobalScope,
+ unstableWindowOrWorkerGlobalScope,
+ mainRuntimeGlobalProperties,
+ workerRuntimeGlobalProperties,
+
+ setNumCpus,
+ setUserAgent,
+ setLanguage,
+ };
+})(this);
diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js
index c7faefcdd..2ea3504e2 100644
--- a/runtime/js/99_main.js
+++ b/runtime/js/99_main.js
@@ -41,48 +41,37 @@ delete Intl.v8BreakIterator;
const util = window.__bootstrap.util;
const event = window.__bootstrap.event;
const eventTarget = window.__bootstrap.eventTarget;
- const globalInterfaces = window.__bootstrap.globalInterfaces;
const location = window.__bootstrap.location;
const build = window.__bootstrap.build;
const version = window.__bootstrap.version;
const os = window.__bootstrap.os;
const timers = window.__bootstrap.timers;
- const base64 = window.__bootstrap.base64;
- const encoding = window.__bootstrap.encoding;
const colors = window.__bootstrap.colors;
- const Console = window.__bootstrap.console.Console;
- const caches = window.__bootstrap.caches;
const inspectArgs = window.__bootstrap.console.inspectArgs;
const quoteString = window.__bootstrap.console.quoteString;
- const compression = window.__bootstrap.compression;
- const worker = window.__bootstrap.worker;
const internals = window.__bootstrap.internals;
const performance = window.__bootstrap.performance;
const net = window.__bootstrap.net;
- const crypto = window.__bootstrap.crypto;
const url = window.__bootstrap.url;
- const urlPattern = window.__bootstrap.urlPattern;
- const headers = window.__bootstrap.headers;
- const streams = window.__bootstrap.streams;
- const fileReader = window.__bootstrap.fileReader;
- const webgpu = window.__bootstrap.webgpu;
- const webSocket = window.__bootstrap.webSocket;
- const webStorage = window.__bootstrap.webStorage;
- const broadcastChannel = window.__bootstrap.broadcastChannel;
- const file = window.__bootstrap.file;
- const formData = window.__bootstrap.formData;
const fetch = window.__bootstrap.fetch;
- const prompt = window.__bootstrap.prompt;
const messagePort = window.__bootstrap.messagePort;
const denoNs = window.__bootstrap.denoNs;
const denoNsUnstable = window.__bootstrap.denoNsUnstable;
const errors = window.__bootstrap.errors.errors;
const webidl = window.__bootstrap.webidl;
const domException = window.__bootstrap.domException;
- const abortSignal = window.__bootstrap.abortSignal;
const { defineEventHandler, reportException } = window.__bootstrap.event;
const { deserializeJsMessageData, serializeJsMessageData } =
window.__bootstrap.messagePort;
+ const {
+ windowOrWorkerGlobalScope,
+ unstableWindowOrWorkerGlobalScope,
+ workerRuntimeGlobalProperties,
+ mainRuntimeGlobalProperties,
+ setNumCpus,
+ setUserAgent,
+ setLanguage,
+ } = window.__bootstrap.globalScope;
let windowIsClosing = false;
@@ -326,298 +315,6 @@ delete Intl.v8BreakIterator;
);
}
- class Navigator {
- constructor() {
- webidl.illegalConstructor();
- }
-
- [SymbolFor("Deno.privateCustomInspect")](inspect) {
- return `${this.constructor.name} ${inspect({})}`;
- }
- }
-
- const navigator = webidl.createBranded(Navigator);
-
- let numCpus, userAgent, language;
-
- ObjectDefineProperties(Navigator.prototype, {
- gpu: {
- configurable: true,
- enumerable: true,
- get() {
- webidl.assertBranded(this, NavigatorPrototype);
- return webgpu.gpu;
- },
- },
- hardwareConcurrency: {
- configurable: true,
- enumerable: true,
- get() {
- webidl.assertBranded(this, NavigatorPrototype);
- return numCpus;
- },
- },
- userAgent: {
- configurable: true,
- enumerable: true,
- get() {
- webidl.assertBranded(this, NavigatorPrototype);
- return userAgent;
- },
- },
- language: {
- configurable: true,
- enumerable: true,
- get() {
- webidl.assertBranded(this, NavigatorPrototype);
- return language;
- },
- },
- languages: {
- configurable: true,
- enumerable: true,
- get() {
- webidl.assertBranded(this, NavigatorPrototype);
- return [language];
- },
- },
- });
- const NavigatorPrototype = Navigator.prototype;
-
- class WorkerNavigator {
- constructor() {
- webidl.illegalConstructor();
- }
-
- [SymbolFor("Deno.privateCustomInspect")](inspect) {
- return `${this.constructor.name} ${inspect({})}`;
- }
- }
-
- const workerNavigator = webidl.createBranded(WorkerNavigator);
-
- ObjectDefineProperties(WorkerNavigator.prototype, {
- gpu: {
- configurable: true,
- enumerable: true,
- get() {
- webidl.assertBranded(this, WorkerNavigatorPrototype);
- return webgpu.gpu;
- },
- },
- hardwareConcurrency: {
- configurable: true,
- enumerable: true,
- get() {
- webidl.assertBranded(this, WorkerNavigatorPrototype);
- return numCpus;
- },
- language: {
- configurable: true,
- enumerable: true,
- get() {
- webidl.assertBranded(this, WorkerNavigatorPrototype);
- return language;
- },
- },
- languages: {
- configurable: true,
- enumerable: true,
- get() {
- webidl.assertBranded(this, WorkerNavigatorPrototype);
- return [language];
- },
- },
- },
- });
- const WorkerNavigatorPrototype = WorkerNavigator.prototype;
-
- // https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope
- const windowOrWorkerGlobalScope = {
- AbortController: util.nonEnumerable(abortSignal.AbortController),
- AbortSignal: util.nonEnumerable(abortSignal.AbortSignal),
- Blob: util.nonEnumerable(file.Blob),
- ByteLengthQueuingStrategy: util.nonEnumerable(
- streams.ByteLengthQueuingStrategy,
- ),
- CloseEvent: util.nonEnumerable(event.CloseEvent),
- CompressionStream: util.nonEnumerable(compression.CompressionStream),
- CountQueuingStrategy: util.nonEnumerable(
- streams.CountQueuingStrategy,
- ),
- CryptoKey: util.nonEnumerable(crypto.CryptoKey),
- CustomEvent: util.nonEnumerable(event.CustomEvent),
- DecompressionStream: util.nonEnumerable(compression.DecompressionStream),
- DOMException: util.nonEnumerable(domException.DOMException),
- ErrorEvent: util.nonEnumerable(event.ErrorEvent),
- Event: util.nonEnumerable(event.Event),
- EventTarget: util.nonEnumerable(eventTarget.EventTarget),
- File: util.nonEnumerable(file.File),
- FileReader: util.nonEnumerable(fileReader.FileReader),
- FormData: util.nonEnumerable(formData.FormData),
- Headers: util.nonEnumerable(headers.Headers),
- MessageEvent: util.nonEnumerable(event.MessageEvent),
- Performance: util.nonEnumerable(performance.Performance),
- PerformanceEntry: util.nonEnumerable(performance.PerformanceEntry),
- PerformanceMark: util.nonEnumerable(performance.PerformanceMark),
- PerformanceMeasure: util.nonEnumerable(performance.PerformanceMeasure),
- PromiseRejectionEvent: util.nonEnumerable(event.PromiseRejectionEvent),
- ProgressEvent: util.nonEnumerable(event.ProgressEvent),
- ReadableStream: util.nonEnumerable(streams.ReadableStream),
- ReadableStreamDefaultReader: util.nonEnumerable(
- streams.ReadableStreamDefaultReader,
- ),
- Request: util.nonEnumerable(fetch.Request),
- Response: util.nonEnumerable(fetch.Response),
- TextDecoder: util.nonEnumerable(encoding.TextDecoder),
- TextEncoder: util.nonEnumerable(encoding.TextEncoder),
- TextDecoderStream: util.nonEnumerable(encoding.TextDecoderStream),
- TextEncoderStream: util.nonEnumerable(encoding.TextEncoderStream),
- TransformStream: util.nonEnumerable(streams.TransformStream),
- URL: util.nonEnumerable(url.URL),
- URLPattern: util.nonEnumerable(urlPattern.URLPattern),
- URLSearchParams: util.nonEnumerable(url.URLSearchParams),
- WebSocket: util.nonEnumerable(webSocket.WebSocket),
- MessageChannel: util.nonEnumerable(messagePort.MessageChannel),
- MessagePort: util.nonEnumerable(messagePort.MessagePort),
- Worker: util.nonEnumerable(worker.Worker),
- WritableStream: util.nonEnumerable(streams.WritableStream),
- WritableStreamDefaultWriter: util.nonEnumerable(
- streams.WritableStreamDefaultWriter,
- ),
- WritableStreamDefaultController: util.nonEnumerable(
- streams.WritableStreamDefaultController,
- ),
- ReadableByteStreamController: util.nonEnumerable(
- streams.ReadableByteStreamController,
- ),
- ReadableStreamBYOBReader: util.nonEnumerable(
- streams.ReadableStreamBYOBReader,
- ),
- ReadableStreamBYOBRequest: util.nonEnumerable(
- streams.ReadableStreamBYOBRequest,
- ),
- ReadableStreamDefaultController: util.nonEnumerable(
- streams.ReadableStreamDefaultController,
- ),
- TransformStreamDefaultController: util.nonEnumerable(
- streams.TransformStreamDefaultController,
- ),
- atob: util.writable(base64.atob),
- btoa: util.writable(base64.btoa),
- clearInterval: util.writable(timers.clearInterval),
- clearTimeout: util.writable(timers.clearTimeout),
- caches: {
- enumerable: true,
- configurable: true,
- get: caches.cacheStorage,
- },
- CacheStorage: util.nonEnumerable(caches.CacheStorage),
- Cache: util.nonEnumerable(caches.Cache),
- console: util.nonEnumerable(
- new Console((msg, level) => core.print(msg, level > 1)),
- ),
- crypto: util.readOnly(crypto.crypto),
- Crypto: util.nonEnumerable(crypto.Crypto),
- SubtleCrypto: util.nonEnumerable(crypto.SubtleCrypto),
- fetch: util.writable(fetch.fetch),
- performance: util.writable(performance.performance),
- reportError: util.writable(event.reportError),
- setInterval: util.writable(timers.setInterval),
- setTimeout: util.writable(timers.setTimeout),
- structuredClone: util.writable(messagePort.structuredClone),
- // Branding as a WebIDL object
- [webidl.brand]: util.nonEnumerable(webidl.brand),
- };
-
- const unstableWindowOrWorkerGlobalScope = {
- BroadcastChannel: util.nonEnumerable(broadcastChannel.BroadcastChannel),
- WebSocketStream: util.nonEnumerable(webSocket.WebSocketStream),
-
- GPU: util.nonEnumerable(webgpu.GPU),
- GPUAdapter: util.nonEnumerable(webgpu.GPUAdapter),
- GPUSupportedLimits: util.nonEnumerable(webgpu.GPUSupportedLimits),
- GPUSupportedFeatures: util.nonEnumerable(webgpu.GPUSupportedFeatures),
- GPUDevice: util.nonEnumerable(webgpu.GPUDevice),
- GPUQueue: util.nonEnumerable(webgpu.GPUQueue),
- GPUBuffer: util.nonEnumerable(webgpu.GPUBuffer),
- GPUBufferUsage: util.nonEnumerable(webgpu.GPUBufferUsage),
- GPUMapMode: util.nonEnumerable(webgpu.GPUMapMode),
- GPUTexture: util.nonEnumerable(webgpu.GPUTexture),
- GPUTextureUsage: util.nonEnumerable(webgpu.GPUTextureUsage),
- GPUTextureView: util.nonEnumerable(webgpu.GPUTextureView),
- GPUSampler: util.nonEnumerable(webgpu.GPUSampler),
- GPUBindGroupLayout: util.nonEnumerable(webgpu.GPUBindGroupLayout),
- GPUPipelineLayout: util.nonEnumerable(webgpu.GPUPipelineLayout),
- GPUBindGroup: util.nonEnumerable(webgpu.GPUBindGroup),
- GPUShaderModule: util.nonEnumerable(webgpu.GPUShaderModule),
- GPUShaderStage: util.nonEnumerable(webgpu.GPUShaderStage),
- GPUComputePipeline: util.nonEnumerable(webgpu.GPUComputePipeline),
- GPURenderPipeline: util.nonEnumerable(webgpu.GPURenderPipeline),
- GPUColorWrite: util.nonEnumerable(webgpu.GPUColorWrite),
- GPUCommandEncoder: util.nonEnumerable(webgpu.GPUCommandEncoder),
- GPURenderPassEncoder: util.nonEnumerable(webgpu.GPURenderPassEncoder),
- GPUComputePassEncoder: util.nonEnumerable(webgpu.GPUComputePassEncoder),
- GPUCommandBuffer: util.nonEnumerable(webgpu.GPUCommandBuffer),
- GPURenderBundleEncoder: util.nonEnumerable(webgpu.GPURenderBundleEncoder),
- GPURenderBundle: util.nonEnumerable(webgpu.GPURenderBundle),
- GPUQuerySet: util.nonEnumerable(webgpu.GPUQuerySet),
- GPUOutOfMemoryError: util.nonEnumerable(webgpu.GPUOutOfMemoryError),
- GPUValidationError: util.nonEnumerable(webgpu.GPUValidationError),
- };
-
- const mainRuntimeGlobalProperties = {
- Location: location.locationConstructorDescriptor,
- location: location.locationDescriptor,
- Window: globalInterfaces.windowConstructorDescriptor,
- window: util.readOnly(globalThis),
- self: util.writable(globalThis),
- Navigator: util.nonEnumerable(Navigator),
- navigator: {
- configurable: true,
- enumerable: true,
- get: () => navigator,
- },
- close: util.writable(windowClose),
- closed: util.getterOnly(() => windowIsClosing),
- alert: util.writable(prompt.alert),
- confirm: util.writable(prompt.confirm),
- prompt: util.writable(prompt.prompt),
- localStorage: {
- configurable: true,
- enumerable: true,
- get: webStorage.localStorage,
- // Makes this reassignable to make astro work
- set: () => {},
- },
- sessionStorage: {
- configurable: true,
- enumerable: true,
- get: webStorage.sessionStorage,
- // Makes this reassignable to make astro work
- set: () => {},
- },
- Storage: util.nonEnumerable(webStorage.Storage),
- };
-
- const workerRuntimeGlobalProperties = {
- WorkerLocation: location.workerLocationConstructorDescriptor,
- location: location.workerLocationDescriptor,
- WorkerGlobalScope: globalInterfaces.workerGlobalScopeConstructorDescriptor,
- DedicatedWorkerGlobalScope:
- globalInterfaces.dedicatedWorkerGlobalScopeConstructorDescriptor,
- WorkerNavigator: util.nonEnumerable(WorkerNavigator),
- navigator: {
- configurable: true,
- enumerable: true,
- get: () => workerNavigator,
- },
- self: util.readOnly(globalThis),
- // TODO(bartlomieju): should be readonly?
- close: util.nonEnumerable(workerClose),
- postMessage: util.writable(postMessage),
- };
-
const pendingRejections = [];
const pendingRejectionsReasons = new SafeWeakMap();
@@ -726,6 +423,10 @@ delete Intl.v8BreakIterator;
ObjectDefineProperties(globalThis, unstableWindowOrWorkerGlobalScope);
}
ObjectDefineProperties(globalThis, mainRuntimeGlobalProperties);
+ ObjectDefineProperties(globalThis, {
+ close: util.writable(windowClose),
+ closed: util.getterOnly(() => windowIsClosing),
+ });
ObjectSetPrototypeOf(globalThis, Window.prototype);
if (runtimeOptions.inspectFlag) {
@@ -754,9 +455,9 @@ delete Intl.v8BreakIterator;
runtimeStart(runtimeOptions);
- numCpus = runtimeOptions.cpuCount;
- userAgent = runtimeOptions.userAgent;
- language = runtimeOptions.locale;
+ setNumCpus(runtimeOptions.cpuCount);
+ setUserAgent(runtimeOptions.userAgent);
+ setLanguage(runtimeOptions.locale);
const internalSymbol = Symbol("Deno.internal");
@@ -849,7 +550,12 @@ delete Intl.v8BreakIterator;
ObjectDefineProperties(globalThis, unstableWindowOrWorkerGlobalScope);
}
ObjectDefineProperties(globalThis, workerRuntimeGlobalProperties);
- ObjectDefineProperties(globalThis, { name: util.writable(name) });
+ ObjectDefineProperties(globalThis, {
+ name: util.writable(name),
+ // TODO(bartlomieju): should be readonly?
+ close: util.nonEnumerable(workerClose),
+ postMessage: util.writable(postMessage),
+ });
if (runtimeOptions.enableTestingFeaturesFlag) {
ObjectDefineProperty(
globalThis,
@@ -882,8 +588,9 @@ delete Intl.v8BreakIterator;
);
location.setLocationHref(runtimeOptions.location);
- numCpus = runtimeOptions.cpuCount;
- language = runtimeOptions.locale;
+
+ setNumCpus(runtimeOptions.cpuCount);
+ setLanguage(runtimeOptions.locale);
globalThis.pollForMessages = pollForMessages;
diff --git a/runtime/lib.rs b/runtime/lib.rs
index d0d27b71c..de104f2ca 100644
--- a/runtime/lib.rs
+++ b/runtime/lib.rs
@@ -7,6 +7,7 @@ pub use deno_core;
pub use deno_crypto;
pub use deno_fetch;
pub use deno_ffi;
+pub use deno_flash;
pub use deno_http;
pub use deno_napi;
pub use deno_net;
diff --git a/runtime/web_worker.rs b/runtime/web_worker.rs
index 10d7e440e..a8e0842f2 100644
--- a/runtime/web_worker.rs
+++ b/runtime/web_worker.rs
@@ -17,7 +17,6 @@ use deno_core::futures::channel::mpsc;
use deno_core::futures::future::poll_fn;
use deno_core::futures::stream::StreamExt;
use deno_core::futures::task::AtomicWaker;
-use deno_core::located_script_name;
use deno_core::serde::Deserialize;
use deno_core::serde::Serialize;
use deno_core::serde_json::json;
@@ -33,6 +32,7 @@ use deno_core::ModuleSpecifier;
use deno_core::RuntimeOptions;
use deno_core::SharedArrayBufferStore;
use deno_core::SourceMapGetter;
+use deno_core::{located_script_name, Snapshot};
use deno_node::RequireNpmResolver;
use deno_tls::rustls::RootCertStore;
use deno_web::create_entangled_message_port;
@@ -322,6 +322,7 @@ pub struct WebWorker {
pub struct WebWorkerOptions {
pub bootstrap: BootstrapOptions,
pub extensions: Vec<Extension>,
+ pub startup_snapshot: Option<Snapshot>,
pub unsafely_ignore_certificate_errors: Option<Vec<String>>,
pub root_cert_store: Option<RootCertStore>,
pub seed: Option<u64>,
@@ -451,7 +452,11 @@ impl WebWorker {
let mut js_runtime = JsRuntime::new(RuntimeOptions {
module_loader: Some(options.module_loader.clone()),
- startup_snapshot: Some(js::deno_isolate_init()),
+ startup_snapshot: Some(
+ options
+ .startup_snapshot
+ .unwrap_or_else(js::deno_isolate_init),
+ ),
source_map_getter: options.source_map_getter,
get_error_class_fn: options.get_error_class_fn,
shared_array_buffer_store: options.shared_array_buffer_store.clone(),
diff --git a/runtime/worker.rs b/runtime/worker.rs
index c7226b76b..0c439c703 100644
--- a/runtime/worker.rs
+++ b/runtime/worker.rs
@@ -13,9 +13,6 @@ use deno_core::error::AnyError;
use deno_core::error::JsError;
use deno_core::futures::Future;
use deno_core::located_script_name;
-use deno_core::serde_json::json;
-use deno_core::serde_v8;
-use deno_core::v8;
use deno_core::CompiledWasmModuleStore;
use deno_core::Extension;
use deno_core::FsModuleLoader;
@@ -66,10 +63,6 @@ pub struct MainWorker {
pub js_runtime: JsRuntime,
should_break_on_first_statement: bool,
exit_code: ExitCode,
- js_run_tests_callback: v8::Global<v8::Function>,
- js_run_benchmarks_callback: v8::Global<v8::Function>,
- js_enable_test_callback: v8::Global<v8::Function>,
- js_enable_bench_callback: v8::Global<v8::Function>,
}
pub struct WorkerOptions {
@@ -99,15 +92,6 @@ pub struct WorkerOptions {
pub stdio: Stdio,
}
-fn grab_cb(
- scope: &mut v8::HandleScope,
- path: &str,
-) -> v8::Global<v8::Function> {
- let cb = JsRuntime::eval::<v8::Function>(scope, path)
- .unwrap_or_else(|| panic!("{} must be defined", path));
- v8::Global::new(scope, cb)
-}
-
impl Default for WorkerOptions {
fn default() -> Self {
Self {
@@ -267,29 +251,10 @@ impl MainWorker {
);
}
- let (
- js_run_tests_callback,
- js_run_benchmarks_callback,
- js_enable_test_callback,
- js_enable_bench_callback,
- ) = {
- let scope = &mut js_runtime.handle_scope();
- (
- grab_cb(scope, "__bootstrap.testing.runTests"),
- grab_cb(scope, "__bootstrap.testing.runBenchmarks"),
- grab_cb(scope, "__bootstrap.testing.enableTest"),
- grab_cb(scope, "__bootstrap.testing.enableBench"),
- )
- };
-
Self {
js_runtime,
should_break_on_first_statement: options.should_break_on_first_statement,
exit_code,
- js_run_tests_callback,
- js_run_benchmarks_callback,
- js_enable_test_callback,
- js_enable_bench_callback,
}
}
@@ -377,65 +342,6 @@ impl MainWorker {
self.evaluate_module(id).await
}
- /// Run tests declared with `Deno.test()`. Test events will be dispatched
- /// by calling ops which are currently only implemented in the CLI crate.
- // TODO(nayeemrmn): Move testing ops to deno_runtime and redesign/unhide.
- #[doc(hidden)]
- pub async fn run_tests(
- &mut self,
- shuffle: &Option<u64>,
- ) -> Result<(), AnyError> {
- let promise = {
- let scope = &mut self.js_runtime.handle_scope();
- let cb = self.js_run_tests_callback.open(scope);
- let this = v8::undefined(scope).into();
- let options =
- serde_v8::to_v8(scope, json!({ "shuffle": shuffle })).unwrap();
- let promise = cb.call(scope, this, &[options]).unwrap();
- v8::Global::new(scope, promise)
- };
- self.js_runtime.resolve_value(promise).await?;
- Ok(())
- }
-
- /// Run benches declared with `Deno.bench()`. Bench events will be dispatched
- /// by calling ops which are currently only implemented in the CLI crate.
- // TODO(nayeemrmn): Move benchmark ops to deno_runtime and redesign/unhide.
- #[doc(hidden)]
- pub async fn run_benchmarks(&mut self) -> Result<(), AnyError> {
- let promise = {
- let scope = &mut self.js_runtime.handle_scope();
- let cb = self.js_run_benchmarks_callback.open(scope);
- let this = v8::undefined(scope).into();
- let promise = cb.call(scope, this, &[]).unwrap();
- v8::Global::new(scope, promise)
- };
- self.js_runtime.resolve_value(promise).await?;
- Ok(())
- }
-
- /// Enable `Deno.test()`. If this isn't called before executing user code,
- /// `Deno.test()` calls will noop.
- // TODO(nayeemrmn): Move testing ops to deno_runtime and redesign/unhide.
- #[doc(hidden)]
- pub fn enable_test(&mut self) {
- let scope = &mut self.js_runtime.handle_scope();
- let cb = self.js_enable_test_callback.open(scope);
- let this = v8::undefined(scope).into();
- cb.call(scope, this, &[]).unwrap();
- }
-
- /// Enable `Deno.bench()`. If this isn't called before executing user code,
- /// `Deno.bench()` calls will noop.
- // TODO(nayeemrmn): Move benchmark ops to deno_runtime and redesign/unhide.
- #[doc(hidden)]
- pub fn enable_bench(&mut self) {
- let scope = &mut self.js_runtime.handle_scope();
- let cb = self.js_enable_bench_callback.open(scope);
- let this = v8::undefined(scope).into();
- cb.call(scope, this, &[]).unwrap();
- }
-
fn wait_for_inspector_session(&mut self) {
if self.should_break_on_first_statement {
self
@@ -542,107 +448,3 @@ impl MainWorker {
Ok(local_value.is_false())
}
}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use deno_core::resolve_url_or_path;
-
- fn create_test_worker() -> MainWorker {
- let main_module = resolve_url_or_path("./hello.js").unwrap();
- let permissions = Permissions::default();
-
- let options = WorkerOptions {
- bootstrap: BootstrapOptions {
- args: vec![],
- cpu_count: 1,
- debug_flag: false,
- enable_testing_features: false,
- locale: deno_core::v8::icu::get_language_tag(),
- location: None,
- no_color: true,
- is_tty: false,
- runtime_version: "x".to_string(),
- ts_version: "x".to_string(),
- unstable: false,
- user_agent: "x".to_string(),
- inspect: false,
- },
- extensions: vec![],
- startup_snapshot: None,
- unsafely_ignore_certificate_errors: None,
- root_cert_store: None,
- seed: None,
- format_js_error_fn: None,
- source_map_getter: None,
- web_worker_preload_module_cb: Arc::new(|_| unreachable!()),
- web_worker_pre_execute_module_cb: Arc::new(|_| unreachable!()),
- create_web_worker_cb: Arc::new(|_| unreachable!()),
- maybe_inspector_server: None,
- should_break_on_first_statement: false,
- module_loader: Rc::new(FsModuleLoader),
- npm_resolver: None,
- get_error_class_fn: None,
- cache_storage_dir: None,
- origin_storage_dir: None,
- blob_store: BlobStore::default(),
- broadcast_channel: InMemoryBroadcastChannel::default(),
- shared_array_buffer_store: None,
- compiled_wasm_module_store: None,
- stdio: Default::default(),
- };
-
- MainWorker::bootstrap_from_options(main_module, permissions, options)
- }
-
- #[tokio::test]
- async fn execute_mod_esm_imports_a() {
- let p = test_util::testdata_path().join("runtime/esm_imports_a.js");
- let module_specifier = resolve_url_or_path(&p.to_string_lossy()).unwrap();
- let mut worker = create_test_worker();
- let result = worker.execute_main_module(&module_specifier).await;
- if let Err(err) = result {
- eprintln!("execute_mod err {:?}", err);
- }
- if let Err(e) = worker.run_event_loop(false).await {
- panic!("Future got unexpected error: {:?}", e);
- }
- }
-
- #[tokio::test]
- async fn execute_mod_circular() {
- let p = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
- .parent()
- .unwrap()
- .join("tests/circular1.js");
- let module_specifier = resolve_url_or_path(&p.to_string_lossy()).unwrap();
- let mut worker = create_test_worker();
- let result = worker.execute_main_module(&module_specifier).await;
- if let Err(err) = result {
- eprintln!("execute_mod err {:?}", err);
- }
- if let Err(e) = worker.run_event_loop(false).await {
- panic!("Future got unexpected error: {:?}", e);
- }
- }
-
- #[tokio::test]
- async fn execute_mod_resolve_error() {
- // "foo" is not a valid module specifier so this should return an error.
- let mut worker = create_test_worker();
- let module_specifier = resolve_url_or_path("does-not-exist").unwrap();
- let result = worker.execute_main_module(&module_specifier).await;
- assert!(result.is_err());
- }
-
- #[tokio::test]
- async fn execute_mod_002_hello() {
- // This assumes cwd is project root (an assumption made throughout the
- // tests).
- let mut worker = create_test_worker();
- let p = test_util::testdata_path().join("run/001_hello.js");
- let module_specifier = resolve_url_or_path(&p.to_string_lossy()).unwrap();
- let result = worker.execute_main_module(&module_specifier).await;
- assert!(result.is_ok());
- }
-}