1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-22 07:14:47 -05:00

refactor(core): JsRuntime initialization (#7415)

Removes:
- "deno_core::StartupData"
- "deno_core::Script"
- "deno_core::OwnedScript"

Changes to "JsRuntime":
- remove "new_with_loader()"
- remove "with_heap_limits()"
- rename "IsolateOptions" to "RuntimeOptions" and make public
- "JsRuntime::new()" takes "RuntimeOptions" as a single param
This commit is contained in:
Bartek Iwańczuk 2020-09-11 15:18:49 +02:00 committed by GitHub
parent 7c2e7c6608
commit 0d1f626edd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 191 additions and 240 deletions

View file

@ -4,7 +4,7 @@ mod op_fetch_asset;
use deno_core::js_check; use deno_core::js_check;
use deno_core::JsRuntime; use deno_core::JsRuntime;
use deno_core::StartupData; use deno_core::RuntimeOptions;
use std::collections::HashMap; use std::collections::HashMap;
use std::env; use std::env;
use std::path::Path; use std::path::Path;
@ -37,7 +37,10 @@ fn create_snapshot(
} }
fn create_runtime_snapshot(snapshot_path: &Path, files: Vec<PathBuf>) { fn create_runtime_snapshot(snapshot_path: &Path, files: Vec<PathBuf>) {
let isolate = JsRuntime::new(StartupData::None, true); let isolate = JsRuntime::new(RuntimeOptions {
will_snapshot: true,
..Default::default()
});
create_snapshot(isolate, snapshot_path, files); create_snapshot(isolate, snapshot_path, files);
} }
@ -70,7 +73,10 @@ fn create_compiler_snapshot(
cwd.join("dts/lib.deno.unstable.d.ts"), cwd.join("dts/lib.deno.unstable.d.ts"),
); );
let mut isolate = JsRuntime::new(StartupData::None, true); let mut isolate = JsRuntime::new(RuntimeOptions {
will_snapshot: true,
..Default::default()
});
isolate.register_op( isolate.register_op(
"op_fetch_asset", "op_fetch_asset",
op_fetch_asset::op_fetch_asset(custom_libs), op_fetch_asset::op_fetch_asset(custom_libs),

View file

@ -1,3 +1,7 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use deno_core::Snapshot;
pub const TS_VERSION: &str = env!("TS_VERSION"); pub const TS_VERSION: &str = env!("TS_VERSION");
pub static CLI_SNAPSHOT: &[u8] = pub static CLI_SNAPSHOT: &[u8] =
@ -11,12 +15,24 @@ pub static SHARED_GLOBALS_LIB: &str =
pub static WINDOW_LIB: &str = include_str!("dts/lib.deno.window.d.ts"); pub static WINDOW_LIB: &str = include_str!("dts/lib.deno.window.d.ts");
pub static UNSTABLE_NS_LIB: &str = include_str!("dts/lib.deno.unstable.d.ts"); pub static UNSTABLE_NS_LIB: &str = include_str!("dts/lib.deno.unstable.d.ts");
pub fn deno_isolate_init() -> Snapshot {
debug!("Deno isolate init with snapshots.");
let data = CLI_SNAPSHOT;
Snapshot::Static(data)
}
pub fn compiler_isolate_init() -> Snapshot {
debug!("Deno compiler isolate init with snapshots.");
let data = COMPILER_SNAPSHOT;
Snapshot::Static(data)
}
#[test] #[test]
fn cli_snapshot() { fn cli_snapshot() {
let mut isolate = deno_core::JsRuntime::new( let mut isolate = deno_core::JsRuntime::new(deno_core::RuntimeOptions {
deno_core::StartupData::Snapshot(deno_core::Snapshot::Static(CLI_SNAPSHOT)), startup_snapshot: Some(deno_isolate_init()),
false, ..Default::default()
); });
deno_core::js_check(isolate.execute( deno_core::js_check(isolate.execute(
"<anon>", "<anon>",
r#" r#"
@ -30,12 +46,10 @@ fn cli_snapshot() {
#[test] #[test]
fn compiler_snapshot() { fn compiler_snapshot() {
let mut isolate = deno_core::JsRuntime::new( let mut isolate = deno_core::JsRuntime::new(deno_core::RuntimeOptions {
deno_core::StartupData::Snapshot(deno_core::Snapshot::Static( startup_snapshot: Some(compiler_isolate_init()),
COMPILER_SNAPSHOT, ..Default::default()
)), });
false,
);
deno_core::js_check(isolate.execute( deno_core::js_check(isolate.execute(
"<anon>", "<anon>",
r#" r#"

View file

@ -56,7 +56,6 @@ mod repl;
pub mod resolve_addr; pub mod resolve_addr;
pub mod signal; pub mod signal;
pub mod source_maps; pub mod source_maps;
mod startup_data;
pub mod state; pub mod state;
mod swc_util; mod swc_util;
mod test_runner; mod test_runner;

View file

@ -4,7 +4,6 @@ use crate::fmt_errors::JsError;
use crate::global_state::GlobalState; use crate::global_state::GlobalState;
use crate::ops::io::get_stdio; use crate::ops::io::get_stdio;
use crate::permissions::Permissions; use crate::permissions::Permissions;
use crate::startup_data;
use crate::tokio_util::create_basic_runtime; use crate::tokio_util::create_basic_runtime;
use crate::web_worker::WebWorker; use crate::web_worker::WebWorker;
use crate::web_worker::WebWorkerHandle; use crate::web_worker::WebWorkerHandle;
@ -48,12 +47,7 @@ fn create_web_worker(
specifier, specifier,
)?; )?;
let mut worker = WebWorker::new( let mut worker = WebWorker::new(name.clone(), &cli_state, has_deno_namespace);
name.clone(),
startup_data::deno_isolate_init(),
&cli_state,
has_deno_namespace,
);
if has_deno_namespace { if has_deno_namespace {
let state = worker.isolate.op_state(); let state = worker.isolate.op_state();

View file

@ -1,18 +0,0 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::js::CLI_SNAPSHOT;
use crate::js::COMPILER_SNAPSHOT;
use deno_core::Snapshot;
use deno_core::StartupData;
pub fn deno_isolate_init() -> StartupData<'static> {
debug!("Deno isolate init with snapshots.");
let data = CLI_SNAPSHOT;
StartupData::Snapshot(Snapshot::Static(data))
}
pub fn compiler_isolate_init() -> StartupData<'static> {
debug!("Deno isolate init with snapshots.");
let data = COMPILER_SNAPSHOT;
StartupData::Snapshot(Snapshot::Static(data))
}

View file

@ -9,6 +9,7 @@ use crate::file_fetcher::SourceFileFetcher;
use crate::flags::Flags; use crate::flags::Flags;
use crate::fmt_errors::JsError; use crate::fmt_errors::JsError;
use crate::global_state::GlobalState; use crate::global_state::GlobalState;
use crate::js;
use crate::module_graph::ModuleGraph; use crate::module_graph::ModuleGraph;
use crate::module_graph::ModuleGraphLoader; use crate::module_graph::ModuleGraphLoader;
use crate::msg; use crate::msg;
@ -16,7 +17,6 @@ use crate::msg::MediaType;
use crate::ops; use crate::ops;
use crate::permissions::Permissions; use crate::permissions::Permissions;
use crate::source_maps::SourceMapGetter; use crate::source_maps::SourceMapGetter;
use crate::startup_data;
use crate::state::State; use crate::state::State;
use crate::swc_util; use crate::swc_util;
use crate::swc_util::AstParser; use crate::swc_util::AstParser;
@ -28,7 +28,6 @@ use crate::worker::Worker;
use core::task::Context; use core::task::Context;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ModuleSpecifier; use deno_core::ModuleSpecifier;
use deno_core::StartupData;
use futures::future::Future; use futures::future::Future;
use futures::future::FutureExt; use futures::future::FutureExt;
use log::debug; use log::debug;
@ -134,12 +133,9 @@ pub struct CompilerWorker {
} }
impl CompilerWorker { impl CompilerWorker {
pub fn new( pub fn new(name: String, state: &Rc<State>) -> Self {
name: String, let mut worker =
startup_data: StartupData, Worker::new(name, Some(js::compiler_isolate_init()), state);
state: &Rc<State>,
) -> Self {
let mut worker = Worker::new(name, startup_data, state);
let response = Arc::new(Mutex::new(None)); let response = Arc::new(Mutex::new(None));
ops::runtime::init(&mut worker); ops::runtime::init(&mut worker);
ops::errors::init(&mut worker); ops::errors::init(&mut worker);
@ -232,11 +228,7 @@ fn create_compiler_worker(
// Count how many times we start the compiler worker. // Count how many times we start the compiler worker.
global_state.compiler_starts.fetch_add(1, Ordering::SeqCst); global_state.compiler_starts.fetch_add(1, Ordering::SeqCst);
let mut worker = CompilerWorker::new( let mut worker = CompilerWorker::new("TS".to_string(), &worker_state);
"TS".to_string(),
startup_data::compiler_isolate_init(),
&worker_state,
);
worker worker
.execute("globalThis.bootstrapCompilerRuntime()") .execute("globalThis.bootstrapCompilerRuntime()")
.unwrap(); .unwrap();

View file

@ -1,5 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::js;
use crate::ops; use crate::ops;
use crate::state::State; use crate::state::State;
use crate::worker::Worker; use crate::worker::Worker;
@ -7,7 +8,6 @@ use crate::worker::WorkerEvent;
use crate::worker::WorkerHandle; use crate::worker::WorkerHandle;
use deno_core::v8; use deno_core::v8;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::StartupData;
use futures::channel::mpsc; use futures::channel::mpsc;
use futures::future::FutureExt; use futures::future::FutureExt;
use futures::stream::StreamExt; use futures::stream::StreamExt;
@ -85,11 +85,10 @@ pub struct WebWorker {
impl WebWorker { impl WebWorker {
pub fn new( pub fn new(
name: String, name: String,
startup_data: StartupData,
state: &Rc<State>, state: &Rc<State>,
has_deno_namespace: bool, has_deno_namespace: bool,
) -> Self { ) -> Self {
let mut worker = Worker::new(name, startup_data, &state); let mut worker = Worker::new(name, Some(js::deno_isolate_init()), &state);
let terminated = Arc::new(AtomicBool::new(false)); let terminated = Arc::new(AtomicBool::new(false));
let isolate_handle = worker.isolate.thread_safe_handle(); let isolate_handle = worker.isolate.thread_safe_handle();
@ -240,19 +239,13 @@ impl Future for WebWorker {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::startup_data;
use crate::state::State; use crate::state::State;
use crate::tokio_util; use crate::tokio_util;
use crate::worker::WorkerEvent; use crate::worker::WorkerEvent;
fn create_test_worker() -> WebWorker { fn create_test_worker() -> WebWorker {
let state = State::mock("./hello.js"); let state = State::mock("./hello.js");
let mut worker = WebWorker::new( let mut worker = WebWorker::new("TEST".to_string(), &state, false);
"TEST".to_string(),
startup_data::deno_isolate_init(),
&state,
false,
);
worker worker
.execute("bootstrap.workerRuntime(\"TEST\", false)") .execute("bootstrap.workerRuntime(\"TEST\", false)")
.unwrap(); .unwrap();

View file

@ -3,15 +3,16 @@
use crate::fmt_errors::JsError; use crate::fmt_errors::JsError;
use crate::global_state::GlobalState; use crate::global_state::GlobalState;
use crate::inspector::DenoInspector; use crate::inspector::DenoInspector;
use crate::js;
use crate::ops; use crate::ops;
use crate::ops::io::get_stdio; use crate::ops::io::get_stdio;
use crate::startup_data;
use crate::state::State; use crate::state::State;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::JsRuntime; use deno_core::JsRuntime;
use deno_core::ModuleId; use deno_core::ModuleId;
use deno_core::ModuleSpecifier; use deno_core::ModuleSpecifier;
use deno_core::StartupData; use deno_core::RuntimeOptions;
use deno_core::Snapshot;
use futures::channel::mpsc; use futures::channel::mpsc;
use futures::future::FutureExt; use futures::future::FutureExt;
use futures::stream::StreamExt; use futures::stream::StreamExt;
@ -102,11 +103,14 @@ pub struct Worker {
impl Worker { impl Worker {
pub fn new( pub fn new(
name: String, name: String,
startup_data: StartupData, startup_snapshot: Option<Snapshot>,
state: &Rc<State>, state: &Rc<State>,
) -> Self { ) -> Self {
let mut isolate = let mut isolate = JsRuntime::new(RuntimeOptions {
JsRuntime::new_with_loader(state.clone(), startup_data, false); module_loader: Some(state.clone()),
startup_snapshot,
..Default::default()
});
{ {
let global_state = state.global_state.clone(); let global_state = state.global_state.clone();
let js_runtime_state = JsRuntime::state(&isolate); let js_runtime_state = JsRuntime::state(&isolate);
@ -257,8 +261,12 @@ pub struct MainWorker(Worker);
impl MainWorker { impl MainWorker {
// TODO(ry) combine MainWorker::new and MainWorker::create. // TODO(ry) combine MainWorker::new and MainWorker::create.
fn new(name: String, startup_data: StartupData, state: &Rc<State>) -> Self { fn new(
let mut worker = Worker::new(name, startup_data, state); name: String,
startup_snapshot: Option<Snapshot>,
state: &Rc<State>,
) -> Self {
let mut worker = Worker::new(name, startup_snapshot, state);
{ {
ops::runtime::init(&mut worker); ops::runtime::init(&mut worker);
ops::runtime_compiler::init(&mut worker); ops::runtime_compiler::init(&mut worker);
@ -299,7 +307,7 @@ impl MainWorker {
)?; )?;
let mut worker = MainWorker::new( let mut worker = MainWorker::new(
"main".to_string(), "main".to_string(),
startup_data::deno_isolate_init(), Some(js::deno_isolate_init()),
&state, &state,
); );
{ {
@ -340,7 +348,7 @@ mod tests {
use super::*; use super::*;
use crate::flags; use crate::flags;
use crate::global_state::GlobalState; use crate::global_state::GlobalState;
use crate::startup_data; use crate::js;
use crate::tokio_util; use crate::tokio_util;
use std::sync::atomic::Ordering; use std::sync::atomic::Ordering;
@ -357,8 +365,7 @@ mod tests {
State::new(&global_state, None, module_specifier.clone(), None, false) State::new(&global_state, None, module_specifier.clone(), None, false)
.unwrap(); .unwrap();
tokio_util::run_basic(async { tokio_util::run_basic(async {
let mut worker = let mut worker = MainWorker::new("TEST".to_string(), None, &state);
MainWorker::new("TEST".to_string(), StartupData::None, &state);
let result = worker.execute_module(&module_specifier).await; let result = worker.execute_module(&module_specifier).await;
if let Err(err) = result { if let Err(err) = result {
eprintln!("execute_mod err {:?}", err); eprintln!("execute_mod err {:?}", err);
@ -385,8 +392,7 @@ mod tests {
State::new(&global_state, None, module_specifier.clone(), None, false) State::new(&global_state, None, module_specifier.clone(), None, false)
.unwrap(); .unwrap();
tokio_util::run_basic(async { tokio_util::run_basic(async {
let mut worker = let mut worker = MainWorker::new("TEST".to_string(), None, &state);
MainWorker::new("TEST".to_string(), StartupData::None, &state);
let result = worker.execute_module(&module_specifier).await; let result = worker.execute_module(&module_specifier).await;
if let Err(err) = result { if let Err(err) = result {
eprintln!("execute_mod err {:?}", err); eprintln!("execute_mod err {:?}", err);
@ -422,7 +428,7 @@ mod tests {
.unwrap(); .unwrap();
let mut worker = MainWorker::new( let mut worker = MainWorker::new(
"TEST".to_string(), "TEST".to_string(),
startup_data::deno_isolate_init(), Some(js::deno_isolate_init()),
&state, &state,
); );
worker.execute("bootstrap.mainRuntime()").unwrap(); worker.execute("bootstrap.mainRuntime()").unwrap();
@ -442,7 +448,7 @@ mod tests {
let state = State::mock("./hello.js"); let state = State::mock("./hello.js");
let mut worker = MainWorker::new( let mut worker = MainWorker::new(
"TEST".to_string(), "TEST".to_string(),
startup_data::deno_isolate_init(), Some(js::deno_isolate_init()),
&state, &state,
); );
worker.execute("bootstrap.mainRuntime()").unwrap(); worker.execute("bootstrap.mainRuntime()").unwrap();

View file

@ -6,8 +6,6 @@ use deno_core::BufVec;
use deno_core::JsRuntime; use deno_core::JsRuntime;
use deno_core::Op; use deno_core::Op;
use deno_core::OpState; use deno_core::OpState;
use deno_core::Script;
use deno_core::StartupData;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use futures::future::poll_fn; use futures::future::poll_fn;
use futures::future::FutureExt; use futures::future::FutureExt;
@ -78,12 +76,7 @@ impl From<Record> for RecordBuf {
} }
fn create_isolate() -> JsRuntime { fn create_isolate() -> JsRuntime {
let startup_data = StartupData::Script(Script { let mut isolate = JsRuntime::new(Default::default());
source: include_str!("http_bench_bin_ops.js"),
filename: "http_bench_bin_ops.js",
});
let mut isolate = JsRuntime::new(startup_data, false);
register_op_bin_sync(&mut isolate, "listen", op_listen); register_op_bin_sync(&mut isolate, "listen", op_listen);
register_op_bin_sync(&mut isolate, "close", op_close); register_op_bin_sync(&mut isolate, "close", op_close);
register_op_bin_async(&mut isolate, "accept", op_accept); register_op_bin_async(&mut isolate, "accept", op_accept);
@ -252,13 +245,23 @@ fn main() {
// NOTE: `--help` arg will display V8 help and exit // NOTE: `--help` arg will display V8 help and exit
deno_core::v8_set_flags(env::args().collect()); deno_core::v8_set_flags(env::args().collect());
let isolate = create_isolate(); let mut isolate = create_isolate();
let mut runtime = runtime::Builder::new() let mut runtime = runtime::Builder::new()
.basic_scheduler() .basic_scheduler()
.enable_all() .enable_all()
.build() .build()
.unwrap(); .unwrap();
js_check(runtime.block_on(isolate));
let future = async move {
isolate
.execute(
"http_bench_bin_ops.js",
include_str!("http_bench_bin_ops.js"),
)
.unwrap();
isolate.await
};
js_check(runtime.block_on(future));
} }
#[test] #[test]

View file

@ -6,8 +6,6 @@ use deno_core::BufVec;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::JsRuntime; use deno_core::JsRuntime;
use deno_core::OpState; use deno_core::OpState;
use deno_core::Script;
use deno_core::StartupData;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use futures::future::poll_fn; use futures::future::poll_fn;
use futures::future::Future; use futures::future::Future;
@ -42,11 +40,7 @@ impl log::Log for Logger {
} }
fn create_isolate() -> JsRuntime { fn create_isolate() -> JsRuntime {
let startup_data = StartupData::Script(Script { let mut runtime = JsRuntime::new(Default::default());
source: include_str!("http_bench_json_ops.js"),
filename: "http_bench_json_ops.js",
});
let mut runtime = JsRuntime::new(startup_data, false);
runtime.register_op("listen", deno_core::json_op_sync(op_listen)); runtime.register_op("listen", deno_core::json_op_sync(op_listen));
runtime.register_op("close", deno_core::json_op_sync(op_close)); runtime.register_op("close", deno_core::json_op_sync(op_close));
runtime.register_op("accept", deno_core::json_op_async(op_accept)); runtime.register_op("accept", deno_core::json_op_async(op_accept));
@ -183,11 +177,21 @@ fn main() {
// NOTE: `--help` arg will display V8 help and exit // NOTE: `--help` arg will display V8 help and exit
deno_core::v8_set_flags(env::args().collect()); deno_core::v8_set_flags(env::args().collect());
let isolate = create_isolate(); let mut isolate = create_isolate();
let mut runtime = runtime::Builder::new() let mut runtime = runtime::Builder::new()
.basic_scheduler() .basic_scheduler()
.enable_all() .enable_all()
.build() .build()
.unwrap(); .unwrap();
js_check(runtime.block_on(isolate));
let future = async move {
isolate
.execute(
"http_bench_json_ops.js",
include_str!("http_bench_json_ops.js"),
)
.unwrap();
isolate.await
};
js_check(runtime.block_on(future));
} }

View file

@ -51,9 +51,8 @@ pub use crate::runtime::GetErrorClassFn;
pub use crate::runtime::HeapLimits; pub use crate::runtime::HeapLimits;
pub use crate::runtime::JsRuntime; pub use crate::runtime::JsRuntime;
pub use crate::runtime::JsRuntimeState; pub use crate::runtime::JsRuntimeState;
pub use crate::runtime::Script; pub use crate::runtime::RuntimeOptions;
pub use crate::runtime::Snapshot; pub use crate::runtime::Snapshot;
pub use crate::runtime::StartupData;
pub use crate::zero_copy_buf::BufVec; pub use crate::zero_copy_buf::BufVec;
pub use crate::zero_copy_buf::ZeroCopyBuf; pub use crate::zero_copy_buf::ZeroCopyBuf;
pub use serde_json; pub use serde_json;

View file

@ -442,7 +442,7 @@ mod tests {
use super::*; use super::*;
use crate::js_check; use crate::js_check;
use crate::JsRuntime; use crate::JsRuntime;
use crate::StartupData; use crate::RuntimeOptions;
use futures::future::FutureExt; use futures::future::FutureExt;
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
@ -619,8 +619,10 @@ mod tests {
fn test_recursive_load() { fn test_recursive_load() {
let loader = MockLoader::new(); let loader = MockLoader::new();
let loads = loader.loads.clone(); let loads = loader.loads.clone();
let mut runtime = let mut runtime = JsRuntime::new(RuntimeOptions {
JsRuntime::new_with_loader(loader, StartupData::None, false); module_loader: Some(loader),
..Default::default()
});
let spec = ModuleSpecifier::resolve_url("file:///a.js").unwrap(); let spec = ModuleSpecifier::resolve_url("file:///a.js").unwrap();
let a_id_fut = runtime.load_module(&spec, None); let a_id_fut = runtime.load_module(&spec, None);
let a_id = futures::executor::block_on(a_id_fut).expect("Failed to load"); let a_id = futures::executor::block_on(a_id_fut).expect("Failed to load");
@ -682,8 +684,10 @@ mod tests {
fn test_circular_load() { fn test_circular_load() {
let loader = MockLoader::new(); let loader = MockLoader::new();
let loads = loader.loads.clone(); let loads = loader.loads.clone();
let mut runtime = let mut runtime = JsRuntime::new(RuntimeOptions {
JsRuntime::new_with_loader(loader, StartupData::None, false); module_loader: Some(loader),
..Default::default()
});
let fut = async move { let fut = async move {
let spec = ModuleSpecifier::resolve_url("file:///circular1.js").unwrap(); let spec = ModuleSpecifier::resolve_url("file:///circular1.js").unwrap();
@ -756,8 +760,10 @@ mod tests {
fn test_redirect_load() { fn test_redirect_load() {
let loader = MockLoader::new(); let loader = MockLoader::new();
let loads = loader.loads.clone(); let loads = loader.loads.clone();
let mut runtime = let mut runtime = JsRuntime::new(RuntimeOptions {
JsRuntime::new_with_loader(loader, StartupData::None, false); module_loader: Some(loader),
..Default::default()
});
let fut = async move { let fut = async move {
let spec = ModuleSpecifier::resolve_url("file:///redirect1.js").unwrap(); let spec = ModuleSpecifier::resolve_url("file:///redirect1.js").unwrap();
@ -821,8 +827,10 @@ mod tests {
run_in_task(|mut cx| { run_in_task(|mut cx| {
let loader = MockLoader::new(); let loader = MockLoader::new();
let loads = loader.loads.clone(); let loads = loader.loads.clone();
let mut runtime = let mut runtime = JsRuntime::new(RuntimeOptions {
JsRuntime::new_with_loader(loader, StartupData::None, false); module_loader: Some(loader),
..Default::default()
});
let spec = ModuleSpecifier::resolve_url("file:///main.js").unwrap(); let spec = ModuleSpecifier::resolve_url("file:///main.js").unwrap();
let mut recursive_load = runtime.load_module(&spec, None).boxed_local(); let mut recursive_load = runtime.load_module(&spec, None).boxed_local();
@ -867,8 +875,10 @@ mod tests {
fn loader_disappears_after_error() { fn loader_disappears_after_error() {
run_in_task(|mut cx| { run_in_task(|mut cx| {
let loader = MockLoader::new(); let loader = MockLoader::new();
let mut runtime = let mut runtime = JsRuntime::new(RuntimeOptions {
JsRuntime::new_with_loader(loader, StartupData::None, false); module_loader: Some(loader),
..Default::default()
});
let spec = ModuleSpecifier::resolve_url("file:///bad_import.js").unwrap(); let spec = ModuleSpecifier::resolve_url("file:///bad_import.js").unwrap();
let mut load_fut = runtime.load_module(&spec, None).boxed_local(); let mut load_fut = runtime.load_module(&spec, None).boxed_local();
let result = load_fut.poll_unpin(&mut cx); let result = load_fut.poll_unpin(&mut cx);
@ -896,8 +906,10 @@ mod tests {
fn recursive_load_main_with_code() { fn recursive_load_main_with_code() {
let loader = MockLoader::new(); let loader = MockLoader::new();
let loads = loader.loads.clone(); let loads = loader.loads.clone();
let mut runtime = let mut runtime = JsRuntime::new(RuntimeOptions {
JsRuntime::new_with_loader(loader, StartupData::None, false); module_loader: Some(loader),
..Default::default()
});
// In default resolution code should be empty. // In default resolution code should be empty.
// Instead we explicitly pass in our own code. // Instead we explicitly pass in our own code.
// The behavior should be very similar to /a.js. // The behavior should be very similar to /a.js.

View file

@ -32,7 +32,6 @@ use std::any::Any;
use std::cell::Cell; use std::cell::Cell;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::From;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::ffi::c_void; use std::ffi::c_void;
use std::mem::forget; use std::mem::forget;
@ -47,52 +46,12 @@ use std::task::Poll;
type PendingOpFuture = Pin<Box<dyn Future<Output = (OpId, Box<[u8]>)>>>; type PendingOpFuture = Pin<Box<dyn Future<Output = (OpId, Box<[u8]>)>>>;
/// Stores a script used to initialize a Isolate
pub struct Script<'a> {
pub source: &'a str,
pub filename: &'a str,
}
// TODO(ry) It's ugly that we have both Script and OwnedScript. Ideally we
// wouldn't expose such twiddly complexity.
struct OwnedScript {
pub source: String,
pub filename: String,
}
impl From<Script<'_>> for OwnedScript {
fn from(s: Script) -> OwnedScript {
OwnedScript {
source: s.source.to_string(),
filename: s.filename.to_string(),
}
}
}
pub enum Snapshot { pub enum Snapshot {
Static(&'static [u8]), Static(&'static [u8]),
JustCreated(v8::StartupData), JustCreated(v8::StartupData),
Boxed(Box<[u8]>), Boxed(Box<[u8]>),
} }
/// Represents data used to initialize an isolate at startup, either
/// in the form of a binary snapshot or a JavaScript source file.
pub enum StartupData<'a> {
Script(Script<'a>),
Snapshot(Snapshot),
None,
}
impl StartupData<'_> {
fn into_options(self) -> (Option<OwnedScript>, Option<Snapshot>) {
match self {
Self::Script(script) => (Some(script.into()), None),
Self::Snapshot(snapshot) => (None, Some(snapshot)),
Self::None => (None, None),
}
}
}
type JsErrorCreateFn = dyn Fn(JsError) -> ErrBox; type JsErrorCreateFn = dyn Fn(JsError) -> ErrBox;
pub type GetErrorClassFn = &'static dyn for<'e> Fn(&'e ErrBox) -> &'static str; pub type GetErrorClassFn = &'static dyn for<'e> Fn(&'e ErrBox) -> &'static str;
@ -121,7 +80,6 @@ pub struct JsRuntime {
snapshot_creator: Option<v8::SnapshotCreator>, snapshot_creator: Option<v8::SnapshotCreator>,
has_snapshotted: bool, has_snapshotted: bool,
needs_init: bool, needs_init: bool,
startup_script: Option<OwnedScript>,
allocations: IsolateAllocations, allocations: IsolateAllocations,
} }
@ -219,48 +177,24 @@ pub struct HeapLimits {
pub max: usize, pub max: usize,
} }
pub(crate) struct IsolateOptions { #[derive(Default)]
loader: Rc<dyn ModuleLoader>, pub struct RuntimeOptions {
startup_script: Option<OwnedScript>, /// Implementation of `ModuleLoader` which will be
startup_snapshot: Option<Snapshot>, /// called when V8 requests to load ES modules.
will_snapshot: bool, ///
heap_limits: Option<HeapLimits>, /// If not provided runtime will error if code being
} /// executed tries to load modules.
pub module_loader: Option<Rc<dyn ModuleLoader>>,
impl JsRuntime { /// V8 snapshot that should be loaded on startup.
/// startup_data defines the snapshot or script used at startup to initialize ///
/// the isolate. /// Currently can't be used with `will_snapshot`.
pub fn new(startup_data: StartupData, will_snapshot: bool) -> Self { pub startup_snapshot: Option<Snapshot>,
let (startup_script, startup_snapshot) = startup_data.into_options();
let options = IsolateOptions {
loader: Rc::new(NoopModuleLoader),
startup_script,
startup_snapshot,
will_snapshot,
heap_limits: None,
};
Self::from_options(options) /// Prepare runtime to take snapshot of loaded code.
} ///
/// Currently can't be used with `startup_snapshot`.
// TODO(bartlomieju): add `new_with_loader_and_heap_limits` function? pub will_snapshot: bool,
/// Create new isolate that can load and execute ESModules.
pub fn new_with_loader(
loader: Rc<dyn ModuleLoader>,
startup_data: StartupData,
will_snapshot: bool,
) -> Self {
let (startup_script, startup_snapshot) = startup_data.into_options();
let options = IsolateOptions {
loader,
startup_script,
startup_snapshot,
will_snapshot,
heap_limits: None,
};
Self::from_options(options)
}
/// This is useful for controlling memory usage of scripts. /// This is useful for controlling memory usage of scripts.
/// ///
@ -268,23 +202,11 @@ impl JsRuntime {
/// ///
/// Make sure to use [`add_near_heap_limit_callback`](#method.add_near_heap_limit_callback) /// Make sure to use [`add_near_heap_limit_callback`](#method.add_near_heap_limit_callback)
/// to prevent v8 from crashing when reaching the upper limit. /// to prevent v8 from crashing when reaching the upper limit.
pub fn with_heap_limits( pub heap_limits: Option<HeapLimits>,
startup_data: StartupData, }
heap_limits: HeapLimits,
) -> Self {
let (startup_script, startup_snapshot) = startup_data.into_options();
let options = IsolateOptions {
loader: Rc::new(NoopModuleLoader),
startup_script,
startup_snapshot,
will_snapshot: false,
heap_limits: Some(heap_limits),
};
Self::from_options(options) impl JsRuntime {
} pub fn new(options: RuntimeOptions) -> Self {
fn from_options(options: IsolateOptions) -> Self {
static DENO_INIT: Once = Once::new(); static DENO_INIT: Once = Once::new();
DENO_INIT.call_once(|| { DENO_INIT.call_once(|| {
unsafe { v8_init() }; unsafe { v8_init() };
@ -339,6 +261,10 @@ impl JsRuntime {
(isolate, None) (isolate, None)
}; };
let loader = options
.module_loader
.unwrap_or_else(|| Rc::new(NoopModuleLoader));
let op_state = OpState::default(); let op_state = OpState::default();
isolate.set_slot(Rc::new(RefCell::new(JsRuntimeState { isolate.set_slot(Rc::new(RefCell::new(JsRuntimeState {
@ -354,7 +280,7 @@ impl JsRuntime {
op_state: Rc::new(RefCell::new(op_state)), op_state: Rc::new(RefCell::new(op_state)),
have_unpolled_ops: Cell::new(false), have_unpolled_ops: Cell::new(false),
modules: Modules::new(), modules: Modules::new(),
loader: options.loader, loader,
dyn_import_map: HashMap::new(), dyn_import_map: HashMap::new(),
preparing_dyn_imports: FuturesUnordered::new(), preparing_dyn_imports: FuturesUnordered::new(),
pending_dyn_imports: FuturesUnordered::new(), pending_dyn_imports: FuturesUnordered::new(),
@ -366,7 +292,6 @@ impl JsRuntime {
snapshot_creator: maybe_snapshot_creator, snapshot_creator: maybe_snapshot_creator,
has_snapshotted: false, has_snapshotted: false,
needs_init: true, needs_init: true,
startup_script: options.startup_script,
allocations: IsolateAllocations::default(), allocations: IsolateAllocations::default(),
} }
} }
@ -393,10 +318,6 @@ impl JsRuntime {
if self.needs_init { if self.needs_init {
self.needs_init = false; self.needs_init = false;
js_check(self.execute("core.js", include_str!("core.js"))); js_check(self.execute("core.js", include_str!("core.js")));
// Maybe execute the startup script.
if let Some(s) = self.startup_script.take() {
self.execute(&s.filename, &s.source).unwrap()
}
} }
} }
@ -1413,7 +1334,7 @@ pub mod tests {
fn setup(mode: Mode) -> (JsRuntime, Arc<AtomicUsize>) { fn setup(mode: Mode) -> (JsRuntime, Arc<AtomicUsize>) {
let dispatch_count = Arc::new(AtomicUsize::new(0)); let dispatch_count = Arc::new(AtomicUsize::new(0));
let mut runtime = JsRuntime::new(StartupData::None, false); let mut runtime = JsRuntime::new(Default::default());
let op_state = runtime.op_state(); let op_state = runtime.op_state();
op_state.borrow_mut().put(TestState { op_state.borrow_mut().put(TestState {
mode, mode,
@ -1784,7 +1705,7 @@ pub mod tests {
#[test] #[test]
fn syntax_error() { fn syntax_error() {
let mut runtime = JsRuntime::new(StartupData::None, false); let mut runtime = JsRuntime::new(Default::default());
let src = "hocuspocus("; let src = "hocuspocus(";
let r = runtime.execute("i.js", src); let r = runtime.execute("i.js", src);
let e = r.unwrap_err(); let e = r.unwrap_err();
@ -1809,27 +1730,39 @@ pub mod tests {
#[test] #[test]
fn will_snapshot() { fn will_snapshot() {
let snapshot = { let snapshot = {
let mut runtime = JsRuntime::new(StartupData::None, true); let mut runtime = JsRuntime::new(RuntimeOptions {
will_snapshot: true,
..Default::default()
});
js_check(runtime.execute("a.js", "a = 1 + 2")); js_check(runtime.execute("a.js", "a = 1 + 2"));
runtime.snapshot() runtime.snapshot()
}; };
let startup_data = StartupData::Snapshot(Snapshot::JustCreated(snapshot)); let snapshot = Snapshot::JustCreated(snapshot);
let mut runtime2 = JsRuntime::new(startup_data, false); let mut runtime2 = JsRuntime::new(RuntimeOptions {
startup_snapshot: Some(snapshot),
..Default::default()
});
js_check(runtime2.execute("check.js", "if (a != 3) throw Error('x')")); js_check(runtime2.execute("check.js", "if (a != 3) throw Error('x')"));
} }
#[test] #[test]
fn test_from_boxed_snapshot() { fn test_from_boxed_snapshot() {
let snapshot = { let snapshot = {
let mut runtime = JsRuntime::new(StartupData::None, true); let mut runtime = JsRuntime::new(RuntimeOptions {
will_snapshot: true,
..Default::default()
});
js_check(runtime.execute("a.js", "a = 1 + 2")); js_check(runtime.execute("a.js", "a = 1 + 2"));
let snap: &[u8] = &*runtime.snapshot(); let snap: &[u8] = &*runtime.snapshot();
Vec::from(snap).into_boxed_slice() Vec::from(snap).into_boxed_slice()
}; };
let startup_data = StartupData::Snapshot(Snapshot::Boxed(snapshot)); let snapshot = Snapshot::Boxed(snapshot);
let mut runtime2 = JsRuntime::new(startup_data, false); let mut runtime2 = JsRuntime::new(RuntimeOptions {
startup_snapshot: Some(snapshot),
..Default::default()
});
js_check(runtime2.execute("check.js", "if (a != 3) throw Error('x')")); js_check(runtime2.execute("check.js", "if (a != 3) throw Error('x')"));
} }
@ -1839,8 +1772,10 @@ pub mod tests {
initial: 0, initial: 0,
max: 20 * 1024, // 20 kB max: 20 * 1024, // 20 kB
}; };
let mut runtime = let mut runtime = JsRuntime::new(RuntimeOptions {
JsRuntime::with_heap_limits(StartupData::None, heap_limits); heap_limits: Some(heap_limits),
..Default::default()
});
let cb_handle = runtime.thread_safe_handle(); let cb_handle = runtime.thread_safe_handle();
let callback_invoke_count = Rc::new(AtomicUsize::default()); let callback_invoke_count = Rc::new(AtomicUsize::default());
@ -1868,7 +1803,7 @@ pub mod tests {
#[test] #[test]
fn test_heap_limit_cb_remove() { fn test_heap_limit_cb_remove() {
let mut runtime = JsRuntime::new(StartupData::None, false); let mut runtime = JsRuntime::new(Default::default());
runtime.add_near_heap_limit_callback(|current_limit, _initial_limit| { runtime.add_near_heap_limit_callback(|current_limit, _initial_limit| {
current_limit * 2 current_limit * 2
@ -1883,8 +1818,10 @@ pub mod tests {
initial: 0, initial: 0,
max: 20 * 1024, // 20 kB max: 20 * 1024, // 20 kB
}; };
let mut runtime = let mut runtime = JsRuntime::new(RuntimeOptions {
JsRuntime::with_heap_limits(StartupData::None, heap_limits); heap_limits: Some(heap_limits),
..Default::default()
});
let cb_handle = runtime.thread_safe_handle(); let cb_handle = runtime.thread_safe_handle();
let callback_invoke_count_first = Rc::new(AtomicUsize::default()); let callback_invoke_count_first = Rc::new(AtomicUsize::default());
@ -1966,8 +1903,10 @@ pub mod tests {
Op::Async(futures::future::ready(buf).boxed()) Op::Async(futures::future::ready(buf).boxed())
}; };
let mut runtime = let mut runtime = JsRuntime::new(RuntimeOptions {
JsRuntime::new_with_loader(loader, StartupData::None, false); module_loader: Some(loader),
..Default::default()
});
runtime.register_op("test", dispatcher); runtime.register_op("test", dispatcher);
js_check(runtime.execute( js_check(runtime.execute(
@ -2062,8 +2001,10 @@ pub mod tests {
run_in_task(|cx| { run_in_task(|cx| {
let loader = Rc::new(DynImportErrLoader::default()); let loader = Rc::new(DynImportErrLoader::default());
let count = loader.count.clone(); let count = loader.count.clone();
let mut runtime = let mut runtime = JsRuntime::new(RuntimeOptions {
JsRuntime::new_with_loader(loader, StartupData::None, false); module_loader: Some(loader),
..Default::default()
});
js_check(runtime.execute( js_check(runtime.execute(
"file:///dyn_import2.js", "file:///dyn_import2.js",
@ -2140,8 +2081,10 @@ pub mod tests {
let prepare_load_count = loader.prepare_load_count.clone(); let prepare_load_count = loader.prepare_load_count.clone();
let resolve_count = loader.resolve_count.clone(); let resolve_count = loader.resolve_count.clone();
let load_count = loader.load_count.clone(); let load_count = loader.load_count.clone();
let mut runtime = let mut runtime = JsRuntime::new(RuntimeOptions {
JsRuntime::new_with_loader(loader, StartupData::None, false); module_loader: Some(loader),
..Default::default()
});
// Dynamically import mod_b // Dynamically import mod_b
js_check(runtime.execute( js_check(runtime.execute(
@ -2181,8 +2124,10 @@ pub mod tests {
run_in_task(|cx| { run_in_task(|cx| {
let loader = Rc::new(DynImportOkLoader::default()); let loader = Rc::new(DynImportOkLoader::default());
let prepare_load_count = loader.prepare_load_count.clone(); let prepare_load_count = loader.prepare_load_count.clone();
let mut runtime = let mut runtime = JsRuntime::new(RuntimeOptions {
JsRuntime::new_with_loader(loader, StartupData::None, false); module_loader: Some(loader),
..Default::default()
});
js_check(runtime.execute( js_check(runtime.execute(
"file:///dyn_import3.js", "file:///dyn_import3.js",
r#" r#"
@ -2233,8 +2178,11 @@ pub mod tests {
} }
let loader = std::rc::Rc::new(ModsLoader::default()); let loader = std::rc::Rc::new(ModsLoader::default());
let mut runtime = let mut runtime = JsRuntime::new(RuntimeOptions {
JsRuntime::new_with_loader(loader, StartupData::None, true); module_loader: Some(loader),
will_snapshot: true,
..Default::default()
});
let specifier = ModuleSpecifier::resolve_url("file:///main.js").unwrap(); let specifier = ModuleSpecifier::resolve_url("file:///main.js").unwrap();
let source_code = "Deno.core.print('hello\\n')".to_string(); let source_code = "Deno.core.print('hello\\n')".to_string();

View file

@ -34,7 +34,6 @@ pub fn get_declaration() -> PathBuf {
mod tests { mod tests {
use deno_core::js_check; use deno_core::js_check;
use deno_core::JsRuntime; use deno_core::JsRuntime;
use deno_core::StartupData;
use futures::future::lazy; use futures::future::lazy;
use futures::future::FutureExt; use futures::future::FutureExt;
use futures::task::Context; use futures::task::Context;
@ -48,7 +47,7 @@ mod tests {
} }
fn setup() -> JsRuntime { fn setup() -> JsRuntime {
let mut isolate = JsRuntime::new(StartupData::None, false); let mut isolate = JsRuntime::new(Default::default());
crate::init(&mut isolate); crate::init(&mut isolate);
isolate isolate
} }