mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -05:00
feat(core): Ability to create snapshots from existing snapshots (#16597)
Co-authored-by: crowlkats <crowlkats@toaxl.com>
This commit is contained in:
parent
fedeea6dde
commit
d232746928
22 changed files with 1144 additions and 991 deletions
13
Cargo.lock
generated
13
Cargo.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
|
|
176
cli/build.rs
176
cli/build.rs
|
@ -1,72 +1,29 @@
|
|||
// 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::*;
|
||||
|
||||
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(),
|
||||
);
|
||||
|
||||
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());
|
||||
}
|
||||
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 {
|
||||
|
@ -74,8 +31,8 @@ struct LoadArgs {
|
|||
specifier: String,
|
||||
}
|
||||
|
||||
fn create_compiler_snapshot(
|
||||
snapshot_path: &Path,
|
||||
pub fn create_compiler_snapshot(
|
||||
snapshot_path: PathBuf,
|
||||
files: Vec<PathBuf>,
|
||||
cwd: &Path,
|
||||
) {
|
||||
|
@ -264,8 +221,11 @@ fn create_compiler_snapshot(
|
|||
))
|
||||
}
|
||||
}
|
||||
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: vec![Extension::builder()
|
||||
.ops(vec![
|
||||
op_build_info::decl(),
|
||||
|
@ -283,13 +243,17 @@ fn create_compiler_snapshot(
|
|||
Ok(())
|
||||
})
|
||||
.build()],
|
||||
..Default::default()
|
||||
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"),
|
||||
);
|
||||
})),
|
||||
});
|
||||
|
||||
create_snapshot(js_runtime, snapshot_path, files);
|
||||
}
|
||||
|
||||
fn ts_version() -> String {
|
||||
pub(crate) fn version() -> String {
|
||||
std::fs::read_to_string("tsc/00_typescript.js")
|
||||
.unwrap()
|
||||
.lines()
|
||||
|
@ -302,6 +266,55 @@ fn ts_version() -> String {
|
|||
.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 {
|
||||
if let Ok(output) = std::process::Command::new("git")
|
||||
|
@ -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
|
||||
}
|
||||
|
|
57
cli/js.rs
Normal file
57
cli/js.rs
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -1397,12 +1397,16 @@
|
|||
return testFn;
|
||||
}
|
||||
|
||||
window.__bootstrap.testing = {
|
||||
bench,
|
||||
enableBench,
|
||||
enableTest,
|
||||
runBenchmarks,
|
||||
window.__bootstrap.internals = {
|
||||
...window.__bootstrap.internals ?? {},
|
||||
testing: {
|
||||
runTests,
|
||||
test,
|
||||
runBenchmarks,
|
||||
enableTest,
|
||||
enableBench,
|
||||
},
|
||||
};
|
||||
|
||||
window.__bootstrap.denoNs.bench = bench;
|
||||
window.__bootstrap.denoNs.test = test;
|
||||
})(this);
|
|
@ -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,
|
||||
|
|
35
cli/main.rs
35
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)
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
267
cli/worker.rs
267
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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ mod ops_builtin_v8;
|
|||
mod ops_metrics;
|
||||
mod resources;
|
||||
mod runtime;
|
||||
pub mod snapshot_util;
|
||||
mod source_map;
|
||||
|
||||
// Re-exports
|
||||
|
|
95
core/snapshot_util.rs
Normal file
95
core/snapshot_util.rs
Normal file
|
@ -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
|
||||
}
|
|
@ -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`
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
352
runtime/js/98_global_scope.js
Normal file
352
runtime/js/98_global_scope.js
Normal file
|
@ -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);
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue