diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/basic_state.rs | 91 | ||||
-rw-r--r-- | core/bindings.rs | 4 | ||||
-rw-r--r-- | core/examples/http_bench_bin_ops.rs | 84 | ||||
-rw-r--r-- | core/examples/http_bench_json_ops.rs | 46 | ||||
-rw-r--r-- | core/gotham_state.rs | 167 | ||||
-rw-r--r-- | core/lib.rs | 8 | ||||
-rw-r--r-- | core/modules.rs | 49 | ||||
-rw-r--r-- | core/ops.rs | 256 | ||||
-rw-r--r-- | core/runtime.rs | 251 |
9 files changed, 532 insertions, 424 deletions
diff --git a/core/basic_state.rs b/core/basic_state.rs deleted file mode 100644 index 54b9ee132..000000000 --- a/core/basic_state.rs +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. - -use crate::BufVec; -use crate::Op; -use crate::OpId; -use crate::OpRegistry; -use crate::OpRouter; -use crate::OpTable; -use crate::ResourceTable; -use std::cell::RefCell; -use std::collections::HashMap; -use std::rc::Rc; - -/// A minimal state struct for use by tests, examples etc. It contains -/// an OpTable and ResourceTable, and implements the relevant traits -/// for working with ops in the most straightforward way possible. -#[derive(Default)] -pub struct BasicState { - pub op_table: RefCell<OpTable<Self>>, - pub resource_table: RefCell<ResourceTable>, -} - -impl BasicState { - pub fn new() -> Rc<Self> { - Default::default() - } -} - -impl OpRegistry for BasicState { - fn get_op_catalog(self: Rc<Self>) -> HashMap<String, OpId> { - self.op_table.borrow().get_op_catalog() - } - - fn register_op<F>(&self, name: &str, op_fn: F) -> OpId - where - F: Fn(Rc<Self>, BufVec) -> Op + 'static, - { - let mut op_table = self.op_table.borrow_mut(); - let (op_id, prev) = op_table.insert_full(name.to_owned(), Rc::new(op_fn)); - assert!(prev.is_none()); - op_id - } -} - -impl OpRouter for BasicState { - fn route_op(self: Rc<Self>, op_id: OpId, bufs: BufVec) -> Op { - let op_fn = self - .op_table - .borrow() - .get_index(op_id) - .map(|(_, op_fn)| op_fn.clone()) - .unwrap(); - (op_fn)(self, bufs) - } -} - -#[test] -fn test_basic_state_ops() { - let state = BasicState::new(); - - let foo_id = state.register_op("foo", |_, _| Op::Sync(b"oof!"[..].into())); - assert_eq!(foo_id, 1); - - let bar_id = state.register_op("bar", |_, _| Op::Sync(b"rab!"[..].into())); - assert_eq!(bar_id, 2); - - let state_ = state.clone(); - let foo_res = state_.route_op(foo_id, Default::default()); - assert!(matches!(foo_res, Op::Sync(buf) if &*buf == b"oof!")); - - let state_ = state.clone(); - let bar_res = state_.route_op(bar_id, Default::default()); - assert!(matches!(bar_res, Op::Sync(buf) if &*buf == b"rab!")); - - let catalog_res = state.route_op(0, Default::default()); - let mut catalog_entries = match catalog_res { - Op::Sync(buf) => serde_json::from_slice::<HashMap<String, OpId>>(&buf) - .map(|map| map.into_iter().collect::<Vec<_>>()) - .unwrap(), - _ => panic!("unexpected `Op` variant"), - }; - catalog_entries.sort_by(|(_, id1), (_, id2)| id1.partial_cmp(id2).unwrap()); - assert_eq!( - catalog_entries, - vec![ - ("ops".to_owned(), 0), - ("foo".to_owned(), 1), - ("bar".to_owned(), 2) - ] - ) -} diff --git a/core/bindings.rs b/core/bindings.rs index d0d916bdc..265906990 100644 --- a/core/bindings.rs +++ b/core/bindings.rs @@ -6,6 +6,7 @@ use crate::JsRuntime; use crate::JsRuntimeState; use crate::Op; use crate::OpId; +use crate::OpTable; use crate::ZeroCopyBuf; use futures::future::FutureExt; use rusty_v8 as v8; @@ -426,8 +427,7 @@ fn send<'s>( } }; - let op_router = state.op_router.clone(); - let op = op_router.route_op(op_id, bufs); + let op = OpTable::route_op(op_id, state.op_state.clone(), bufs); assert_eq!(state.shared.size(), 0); match op { Op::Sync(buf) if !buf.is_empty() => { diff --git a/core/examples/http_bench_bin_ops.rs b/core/examples/http_bench_bin_ops.rs index 00eb95f44..b29af8b9d 100644 --- a/core/examples/http_bench_bin_ops.rs +++ b/core/examples/http_bench_bin_ops.rs @@ -2,11 +2,10 @@ extern crate log; use deno_core::js_check; -use deno_core::BasicState; use deno_core::BufVec; use deno_core::JsRuntime; use deno_core::Op; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::Script; use deno_core::StartupData; use deno_core::ZeroCopyBuf; @@ -14,6 +13,7 @@ use futures::future::poll_fn; use futures::future::FutureExt; use futures::future::TryFuture; use futures::future::TryFutureExt; +use std::cell::RefCell; use std::convert::TryInto; use std::env; use std::fmt::Debug; @@ -78,23 +78,22 @@ impl From<Record> for RecordBuf { } fn create_isolate() -> JsRuntime { - let state = BasicState::new(); - register_op_bin_sync(&state, "listen", op_listen); - register_op_bin_sync(&state, "close", op_close); - register_op_bin_async(&state, "accept", op_accept); - register_op_bin_async(&state, "read", op_read); - register_op_bin_async(&state, "write", op_write); - let startup_data = StartupData::Script(Script { source: include_str!("http_bench_bin_ops.js"), filename: "http_bench_bin_ops.js", }); - JsRuntime::new(state, startup_data, false) + let mut isolate = JsRuntime::new(startup_data, false); + register_op_bin_sync(&mut isolate, "listen", op_listen); + register_op_bin_sync(&mut isolate, "close", op_close); + register_op_bin_async(&mut isolate, "accept", op_accept); + register_op_bin_async(&mut isolate, "read", op_read); + register_op_bin_async(&mut isolate, "write", op_write); + isolate } fn op_listen( - state: &BasicState, + state: &mut OpState, _rid: u32, _bufs: &mut [ZeroCopyBuf], ) -> Result<u32, Error> { @@ -102,36 +101,33 @@ fn op_listen( let addr = "127.0.0.1:4544".parse::<SocketAddr>().unwrap(); let std_listener = std::net::TcpListener::bind(&addr)?; let listener = TcpListener::from_std(std_listener)?; - let rid = state - .resource_table - .borrow_mut() - .add("tcpListener", Box::new(listener)); + let rid = state.resource_table.add("tcpListener", Box::new(listener)); Ok(rid) } fn op_close( - state: &BasicState, + state: &mut OpState, rid: u32, _bufs: &mut [ZeroCopyBuf], ) -> Result<u32, Error> { debug!("close rid={}", rid); state .resource_table - .borrow_mut() .close(rid) .map(|_| 0) .ok_or_else(bad_resource_id) } -fn op_accept( - state: Rc<BasicState>, +async fn op_accept( + state: Rc<RefCell<OpState>>, rid: u32, _bufs: BufVec, -) -> impl TryFuture<Ok = u32, Error = Error> { +) -> Result<u32, Error> { debug!("accept rid={}", rid); poll_fn(move |cx| { - let resource_table = &mut state.resource_table.borrow_mut(); + let resource_table = &mut state.borrow_mut().resource_table; + let listener = resource_table .get_mut::<TcpListener>(rid) .ok_or_else(bad_resource_id)?; @@ -139,10 +135,11 @@ fn op_accept( resource_table.add("tcpStream", Box::new(stream)) }) }) + .await } fn op_read( - state: Rc<BasicState>, + state: Rc<RefCell<OpState>>, rid: u32, bufs: BufVec, ) -> impl TryFuture<Ok = usize, Error = Error> { @@ -152,7 +149,8 @@ fn op_read( debug!("read rid={}", rid); poll_fn(move |cx| { - let resource_table = &mut state.resource_table.borrow_mut(); + let resource_table = &mut state.borrow_mut().resource_table; + let stream = resource_table .get_mut::<TcpStream>(rid) .ok_or_else(bad_resource_id)?; @@ -161,7 +159,7 @@ fn op_read( } fn op_write( - state: Rc<BasicState>, + state: Rc<RefCell<OpState>>, rid: u32, bufs: BufVec, ) -> impl TryFuture<Ok = usize, Error = Error> { @@ -170,7 +168,8 @@ fn op_write( debug!("write rid={}", rid); poll_fn(move |cx| { - let resource_table = &mut state.resource_table.borrow_mut(); + let resource_table = &mut state.borrow_mut().resource_table; + let stream = resource_table .get_mut::<TcpStream>(rid) .ok_or_else(bad_resource_id)?; @@ -178,35 +177,42 @@ fn op_write( }) } -fn register_op_bin_sync<F>(state: &BasicState, name: &'static str, op_fn: F) -where - F: Fn(&BasicState, u32, &mut [ZeroCopyBuf]) -> Result<u32, Error> + 'static, +fn register_op_bin_sync<F>( + isolate: &mut JsRuntime, + name: &'static str, + op_fn: F, +) where + F: Fn(&mut OpState, u32, &mut [ZeroCopyBuf]) -> Result<u32, Error> + 'static, { - let base_op_fn = move |state: Rc<BasicState>, mut bufs: BufVec| -> Op { + let base_op_fn = move |state: Rc<RefCell<OpState>>, mut bufs: BufVec| -> Op { let record = Record::from(bufs[0].as_ref()); let is_sync = record.promise_id == 0; assert!(is_sync); let zero_copy_bufs = &mut bufs[1..]; - let result: i32 = match op_fn(&state, record.rid, zero_copy_bufs) { - Ok(r) => r as i32, - Err(_) => -1, - }; + let result: i32 = + match op_fn(&mut state.borrow_mut(), record.rid, zero_copy_bufs) { + Ok(r) => r as i32, + Err(_) => -1, + }; let buf = RecordBuf::from(Record { result, ..record })[..].into(); Op::Sync(buf) }; - state.register_op(name, base_op_fn); + isolate.register_op(name, base_op_fn); } -fn register_op_bin_async<F, R>(state: &BasicState, name: &'static str, op_fn: F) -where - F: Fn(Rc<BasicState>, u32, BufVec) -> R + Copy + 'static, +fn register_op_bin_async<F, R>( + isolate: &mut JsRuntime, + name: &'static str, + op_fn: F, +) where + F: Fn(Rc<RefCell<OpState>>, u32, BufVec) -> R + Copy + 'static, R: TryFuture, R::Ok: TryInto<i32>, <R::Ok as TryInto<i32>>::Error: Debug, { - let base_op_fn = move |state: Rc<BasicState>, bufs: BufVec| -> Op { + let base_op_fn = move |state: Rc<RefCell<OpState>>, bufs: BufVec| -> Op { let mut bufs_iter = bufs.into_iter(); let record_buf = bufs_iter.next().unwrap(); let zero_copy_bufs = bufs_iter.collect::<BufVec>(); @@ -227,7 +233,7 @@ where Op::Async(fut.boxed_local()) }; - state.register_op(name, base_op_fn); + isolate.register_op(name, base_op_fn); } fn bad_resource_id() -> Error { diff --git a/core/examples/http_bench_json_ops.rs b/core/examples/http_bench_json_ops.rs index de467b8ad..dc0c837e2 100644 --- a/core/examples/http_bench_json_ops.rs +++ b/core/examples/http_bench_json_ops.rs @@ -2,17 +2,17 @@ extern crate log; use deno_core::js_check; -use deno_core::BasicState; use deno_core::BufVec; use deno_core::ErrBox; use deno_core::JsRuntime; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::Script; use deno_core::StartupData; use deno_core::ZeroCopyBuf; use futures::future::poll_fn; use futures::future::Future; use serde_json::Value; +use std::cell::RefCell; use std::convert::TryInto; use std::env; use std::net::SocketAddr; @@ -42,23 +42,21 @@ impl log::Log for Logger { } fn create_isolate() -> JsRuntime { - let state = BasicState::new(); - state.register_op_json_sync("listen", op_listen); - state.register_op_json_sync("close", op_close); - state.register_op_json_async("accept", op_accept); - state.register_op_json_async("read", op_read); - state.register_op_json_async("write", op_write); - let startup_data = StartupData::Script(Script { source: include_str!("http_bench_json_ops.js"), filename: "http_bench_json_ops.js", }); - - JsRuntime::new(state, startup_data, false) + let mut runtime = JsRuntime::new(startup_data, false); + 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("accept", deno_core::json_op_async(op_accept)); + runtime.register_op("read", deno_core::json_op_async(op_read)); + runtime.register_op("write", deno_core::json_op_async(op_write)); + runtime } fn op_listen( - state: &BasicState, + state: &mut OpState, _args: Value, _bufs: &mut [ZeroCopyBuf], ) -> Result<Value, ErrBox> { @@ -66,15 +64,12 @@ fn op_listen( let addr = "127.0.0.1:4544".parse::<SocketAddr>().unwrap(); let std_listener = std::net::TcpListener::bind(&addr)?; let listener = TcpListener::from_std(std_listener)?; - let rid = state - .resource_table - .borrow_mut() - .add("tcpListener", Box::new(listener)); + let rid = state.resource_table.add("tcpListener", Box::new(listener)); Ok(serde_json::json!({ "rid": rid })) } fn op_close( - state: &BasicState, + state: &mut OpState, args: Value, _buf: &mut [ZeroCopyBuf], ) -> Result<Value, ErrBox> { @@ -86,17 +81,15 @@ fn op_close( .try_into() .unwrap(); debug!("close rid={}", rid); - state .resource_table - .borrow_mut() .close(rid) .map(|_| serde_json::json!(())) .ok_or_else(ErrBox::bad_resource_id) } fn op_accept( - state: Rc<BasicState>, + state: Rc<RefCell<OpState>>, args: Value, _bufs: BufVec, ) -> impl Future<Output = Result<Value, ErrBox>> { @@ -110,7 +103,8 @@ fn op_accept( debug!("accept rid={}", rid); poll_fn(move |cx| { - let resource_table = &mut state.resource_table.borrow_mut(); + let resource_table = &mut state.borrow_mut().resource_table; + let listener = resource_table .get_mut::<TcpListener>(rid) .ok_or_else(ErrBox::bad_resource_id)?; @@ -122,7 +116,7 @@ fn op_accept( } fn op_read( - state: Rc<BasicState>, + state: Rc<RefCell<OpState>>, args: Value, mut bufs: BufVec, ) -> impl Future<Output = Result<Value, ErrBox>> { @@ -138,7 +132,8 @@ fn op_read( debug!("read rid={}", rid); poll_fn(move |cx| -> Poll<Result<Value, ErrBox>> { - let resource_table = &mut state.resource_table.borrow_mut(); + let resource_table = &mut state.borrow_mut().resource_table; + let stream = resource_table .get_mut::<TcpStream>(rid) .ok_or_else(ErrBox::bad_resource_id)?; @@ -149,7 +144,7 @@ fn op_read( } fn op_write( - state: Rc<BasicState>, + state: Rc<RefCell<OpState>>, args: Value, bufs: BufVec, ) -> impl Future<Output = Result<Value, ErrBox>> { @@ -165,7 +160,8 @@ fn op_write( debug!("write rid={}", rid); poll_fn(move |cx| { - let resource_table = &mut state.resource_table.borrow_mut(); + let resource_table = &mut state.borrow_mut().resource_table; + let stream = resource_table .get_mut::<TcpStream>(rid) .ok_or_else(ErrBox::bad_resource_id)?; diff --git a/core/gotham_state.rs b/core/gotham_state.rs new file mode 100644 index 000000000..94a2d67d4 --- /dev/null +++ b/core/gotham_state.rs @@ -0,0 +1,167 @@ +// Forked from Gotham: +// https://github.com/gotham-rs/gotham/blob/bcbbf8923789e341b7a0e62c59909428ca4e22e2/gotham/src/state/mod.rs +// Copyright 2017 Gotham Project Developers. MIT license. + +use std::any::Any; +use std::any::TypeId; +use std::collections::HashMap; + +#[derive(Default)] +pub struct GothamState { + data: HashMap<TypeId, Box<dyn Any>>, +} + +impl GothamState { + /// Puts a value into the `GothamState` storage. One value of each type is retained. + /// Successive calls to `put` will overwrite the existing value of the same + /// type. + pub fn put<T: 'static>(&mut self, t: T) { + let type_id = TypeId::of::<T>(); + trace!(" inserting record to state for type_id `{:?}`", type_id); + self.data.insert(type_id, Box::new(t)); + } + + /// Determines if the current value exists in `GothamState` storage. + pub fn has<T: 'static>(&self) -> bool { + let type_id = TypeId::of::<T>(); + self.data.get(&type_id).is_some() + } + + /// Tries to borrow a value from the `GothamState` storage. + pub fn try_borrow<T: 'static>(&self) -> Option<&T> { + let type_id = TypeId::of::<T>(); + trace!(" borrowing state data for type_id `{:?}`", type_id); + self.data.get(&type_id).and_then(|b| b.downcast_ref()) + } + + /// Borrows a value from the `GothamState` storage. + pub fn borrow<T: 'static>(&self) -> &T { + self + .try_borrow() + .expect("required type is not present in GothamState container") + } + + /// Tries to mutably borrow a value from the `GothamState` storage. + pub fn try_borrow_mut<T: 'static>(&mut self) -> Option<&mut T> { + let type_id = TypeId::of::<T>(); + trace!(" mutably borrowing state data for type_id `{:?}`", type_id); + self.data.get_mut(&type_id).and_then(|b| b.downcast_mut()) + } + + /// Mutably borrows a value from the `GothamState` storage. + pub fn borrow_mut<T: 'static>(&mut self) -> &mut T { + self + .try_borrow_mut() + .expect("required type is not present in GothamState container") + } + + /// Tries to move a value out of the `GothamState` storage and return ownership. + pub fn try_take<T: 'static>(&mut self) -> Option<T> { + let type_id = TypeId::of::<T>(); + trace!( + " taking ownership from state data for type_id `{:?}`", + type_id + ); + self + .data + .remove(&type_id) + .and_then(|b| b.downcast().ok()) + .map(|b| *b) + } + + /// Moves a value out of the `GothamState` storage and returns ownership. + /// + /// # Panics + /// + /// If a value of type `T` is not present in `GothamState`. + pub fn take<T: 'static>(&mut self) -> T { + self + .try_take() + .expect("required type is not present in GothamState container") + } +} + +#[cfg(test)] +mod tests { + use super::GothamState; + + struct MyStruct { + value: i32, + } + + struct AnotherStruct { + value: &'static str, + } + + #[test] + fn put_borrow1() { + let mut state = GothamState::default(); + state.put(MyStruct { value: 1 }); + assert_eq!(state.borrow::<MyStruct>().value, 1); + } + + #[test] + fn put_borrow2() { + let mut state = GothamState::default(); + assert!(!state.has::<AnotherStruct>()); + state.put(AnotherStruct { value: "a string" }); + assert!(state.has::<AnotherStruct>()); + assert!(!state.has::<MyStruct>()); + state.put(MyStruct { value: 100 }); + assert!(state.has::<MyStruct>()); + assert_eq!(state.borrow::<MyStruct>().value, 100); + assert_eq!(state.borrow::<AnotherStruct>().value, "a string"); + } + + #[test] + fn try_borrow() { + let mut state = GothamState::default(); + state.put(MyStruct { value: 100 }); + assert!(state.try_borrow::<MyStruct>().is_some()); + assert_eq!(state.try_borrow::<MyStruct>().unwrap().value, 100); + assert!(state.try_borrow::<AnotherStruct>().is_none()); + } + + #[test] + fn try_borrow_mut() { + let mut state = GothamState::default(); + state.put(MyStruct { value: 100 }); + if let Some(a) = state.try_borrow_mut::<MyStruct>() { + a.value += 10; + } + assert_eq!(state.borrow::<MyStruct>().value, 110); + } + + #[test] + fn borrow_mut() { + let mut state = GothamState::default(); + state.put(MyStruct { value: 100 }); + { + let a = state.borrow_mut::<MyStruct>(); + a.value += 10; + } + assert_eq!(state.borrow::<MyStruct>().value, 110); + assert!(state.try_borrow_mut::<AnotherStruct>().is_none()); + } + + #[test] + fn try_take() { + let mut state = GothamState::default(); + state.put(MyStruct { value: 100 }); + assert_eq!(state.try_take::<MyStruct>().unwrap().value, 100); + assert!(state.try_take::<MyStruct>().is_none()); + assert!(state.try_borrow_mut::<MyStruct>().is_none()); + assert!(state.try_borrow::<MyStruct>().is_none()); + assert!(state.try_take::<AnotherStruct>().is_none()); + } + + #[test] + fn take() { + let mut state = GothamState::default(); + state.put(MyStruct { value: 110 }); + assert_eq!(state.take::<MyStruct>().value, 110); + assert!(state.try_take::<MyStruct>().is_none()); + assert!(state.try_borrow_mut::<MyStruct>().is_none()); + assert!(state.try_borrow::<MyStruct>().is_none()); + } +} diff --git a/core/lib.rs b/core/lib.rs index b27419ff5..450b7378a 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -8,10 +8,10 @@ extern crate lazy_static; #[macro_use] extern crate log; -mod basic_state; mod bindings; mod errors; mod flags; +mod gotham_state; mod module_specifier; mod modules; mod normalize_path; @@ -24,7 +24,6 @@ mod zero_copy_buf; pub use rusty_v8 as v8; -pub use crate::basic_state::BasicState; pub use crate::errors::AnyError; pub use crate::errors::ErrBox; pub use crate::errors::JsError; @@ -38,12 +37,13 @@ pub use crate::modules::ModuleSource; pub use crate::modules::ModuleSourceFuture; pub use crate::modules::RecursiveModuleLoad; pub use crate::normalize_path::normalize_path; +pub use crate::ops::json_op_async; +pub use crate::ops::json_op_sync; pub use crate::ops::Op; pub use crate::ops::OpAsyncFuture; pub use crate::ops::OpFn; pub use crate::ops::OpId; -pub use crate::ops::OpRegistry; -pub use crate::ops::OpRouter; +pub use crate::ops::OpState; pub use crate::ops::OpTable; pub use crate::resources::ResourceTable; pub use crate::runtime::js_check; diff --git a/core/modules.rs b/core/modules.rs index 3caeab7b1..57068528d 100644 --- a/core/modules.rs +++ b/core/modules.rs @@ -441,7 +441,6 @@ impl Modules { mod tests { use super::*; use crate::js_check; - use crate::BasicState; use crate::JsRuntime; use crate::StartupData; use futures::future::FutureExt; @@ -620,12 +619,8 @@ mod tests { fn test_recursive_load() { let loader = MockLoader::new(); let loads = loader.loads.clone(); - let mut runtime = JsRuntime::new_with_loader( - loader, - BasicState::new(), - StartupData::None, - false, - ); + let mut runtime = + JsRuntime::new_with_loader(loader, StartupData::None, false); let spec = ModuleSpecifier::resolve_url("file:///a.js").unwrap(); let a_id_fut = runtime.load_module(&spec, None); let a_id = futures::executor::block_on(a_id_fut).expect("Failed to load"); @@ -687,12 +682,8 @@ mod tests { fn test_circular_load() { let loader = MockLoader::new(); let loads = loader.loads.clone(); - let mut runtime = JsRuntime::new_with_loader( - loader, - BasicState::new(), - StartupData::None, - false, - ); + let mut runtime = + JsRuntime::new_with_loader(loader, StartupData::None, false); let fut = async move { let spec = ModuleSpecifier::resolve_url("file:///circular1.js").unwrap(); @@ -765,12 +756,8 @@ mod tests { fn test_redirect_load() { let loader = MockLoader::new(); let loads = loader.loads.clone(); - let mut runtime = JsRuntime::new_with_loader( - loader, - BasicState::new(), - StartupData::None, - false, - ); + let mut runtime = + JsRuntime::new_with_loader(loader, StartupData::None, false); let fut = async move { let spec = ModuleSpecifier::resolve_url("file:///redirect1.js").unwrap(); @@ -834,12 +821,8 @@ mod tests { run_in_task(|mut cx| { let loader = MockLoader::new(); let loads = loader.loads.clone(); - let mut runtime = JsRuntime::new_with_loader( - loader, - BasicState::new(), - StartupData::None, - false, - ); + let mut runtime = + JsRuntime::new_with_loader(loader, StartupData::None, false); let spec = ModuleSpecifier::resolve_url("file:///main.js").unwrap(); let mut recursive_load = runtime.load_module(&spec, None).boxed_local(); @@ -884,12 +867,8 @@ mod tests { fn loader_disappears_after_error() { run_in_task(|mut cx| { let loader = MockLoader::new(); - let mut runtime = JsRuntime::new_with_loader( - loader, - BasicState::new(), - StartupData::None, - false, - ); + let mut runtime = + JsRuntime::new_with_loader(loader, StartupData::None, false); let spec = ModuleSpecifier::resolve_url("file:///bad_import.js").unwrap(); let mut load_fut = runtime.load_module(&spec, None).boxed_local(); let result = load_fut.poll_unpin(&mut cx); @@ -917,12 +896,8 @@ mod tests { fn recursive_load_main_with_code() { let loader = MockLoader::new(); let loads = loader.loads.clone(); - let mut runtime = JsRuntime::new_with_loader( - loader, - BasicState::new(), - StartupData::None, - false, - ); + let mut runtime = + JsRuntime::new_with_loader(loader, StartupData::None, false); // In default resolution code should be empty. // Instead we explicitly pass in our own code. // The behavior should be very similar to /a.js. diff --git a/core/ops.rs b/core/ops.rs index 838596dc0..7af4949a1 100644 --- a/core/ops.rs +++ b/core/ops.rs @@ -1,13 +1,13 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +use crate::gotham_state::GothamState; use crate::BufVec; use crate::ErrBox; use crate::ZeroCopyBuf; use futures::Future; -use futures::FutureExt; use indexmap::IndexMap; -use serde_json::json; use serde_json::Value; +use std::cell::RefCell; use std::collections::HashMap; use std::iter::once; use std::ops::Deref; @@ -16,7 +16,7 @@ use std::pin::Pin; use std::rc::Rc; pub type OpAsyncFuture = Pin<Box<dyn Future<Output = Box<[u8]>>>>; -pub type OpFn<S> = dyn Fn(Rc<S>, BufVec) -> Op + 'static; +pub type OpFn = dyn Fn(Rc<RefCell<OpState>>, BufVec) -> Op + 'static; pub type OpId = usize; pub enum Op { @@ -28,119 +28,191 @@ pub enum Op { NotFound, } -pub trait OpRouter { - fn route_op(self: Rc<Self>, op_id: OpId, bufs: BufVec) -> Op; +pub struct OpState { + pub resource_table: crate::ResourceTable, + pub op_table: OpTable, + pub get_error_class_fn: crate::runtime::GetErrorClassFn, + gotham_state: GothamState, } -pub trait OpRegistry: OpRouter + 'static { - fn get_op_catalog(self: Rc<Self>) -> HashMap<String, OpId>; - - fn register_op<F>(&self, name: &str, op_fn: F) -> OpId - where - F: Fn(Rc<Self>, BufVec) -> Op + 'static; - - fn register_op_json_sync<F>(self: &Rc<Self>, name: &str, op_fn: F) -> OpId - where - F: Fn(&Self, Value, &mut [ZeroCopyBuf]) -> Result<Value, ErrBox> + 'static, - { - let base_op_fn = move |state: Rc<Self>, mut bufs: BufVec| -> Op { - let result = serde_json::from_slice(&bufs[0]) - .map_err(ErrBox::from) - .and_then(|args| op_fn(&state, args, &mut bufs[1..])); - let buf = state.json_serialize_op_result(None, result); - Op::Sync(buf) - }; - - self.register_op(name, base_op_fn) +impl Default for OpState { + // TODO(ry) Only deno_core should be able to construct an OpState. But I don't + // know how to make default private. Maybe rename to + // pub(crate) fn new() -> OpState + fn default() -> OpState { + OpState { + resource_table: crate::ResourceTable::default(), + op_table: OpTable::default(), + get_error_class_fn: &|_| "Error", + gotham_state: GothamState::default(), + } } +} - fn register_op_json_async<F, R>(self: &Rc<Self>, name: &str, op_fn: F) -> OpId - where - F: Fn(Rc<Self>, Value, BufVec) -> R + 'static, - R: Future<Output = Result<Value, ErrBox>> + 'static, - { - let try_dispatch_op = move |state: Rc<Self>, - bufs: BufVec| - -> Result<Op, ErrBox> { - let args: Value = serde_json::from_slice(&bufs[0])?; - let promise_id = args - .get("promiseId") - .and_then(Value::as_u64) - .ok_or_else(|| ErrBox::type_error("missing or invalid `promiseId`"))?; - let bufs = bufs[1..].into(); - let fut = op_fn(state.clone(), args, bufs).map(move |result| { - state.json_serialize_op_result(Some(promise_id), result) - }); - Ok(Op::Async(Box::pin(fut))) - }; - - let base_op_fn = move |state: Rc<Self>, bufs: BufVec| -> Op { - match try_dispatch_op(state.clone(), bufs) { - Ok(op) => op, - Err(err) => Op::Sync(state.json_serialize_op_result(None, Err(err))), - } - }; - - self.register_op(name, base_op_fn) - } +impl Deref for OpState { + type Target = GothamState; - fn json_serialize_op_result( - &self, - promise_id: Option<u64>, - result: Result<Value, ErrBox>, - ) -> Box<[u8]> { - let value = match result { - Ok(v) => json!({ "ok": v, "promiseId": promise_id }), - Err(err) => json!({ - "promiseId": promise_id , - "err": { - "className": self.get_error_class_name(&err), - "message": err.to_string(), - } - }), - }; - serde_json::to_vec(&value).unwrap().into_boxed_slice() + fn deref(&self) -> &Self::Target { + &self.gotham_state } +} - fn get_error_class_name(&self, _err: &ErrBox) -> &'static str { - "Error" +impl DerefMut for OpState { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.gotham_state } } /// Collection for storing registered ops. The special 'get_op_catalog' /// op with OpId `0` is automatically added when the OpTable is created. -pub struct OpTable<S>(IndexMap<String, Rc<OpFn<S>>>); +pub struct OpTable(IndexMap<String, Rc<OpFn>>); -impl<S: OpRegistry> OpTable<S> { - pub fn get_op_catalog(&self) -> HashMap<String, OpId> { - self.keys().cloned().zip(0..).collect() +impl OpTable { + pub fn register_op<F>(&mut self, name: &str, op_fn: F) -> OpId + where + F: Fn(Rc<RefCell<OpState>>, BufVec) -> Op + 'static, + { + let (op_id, prev) = self.0.insert_full(name.to_owned(), Rc::new(op_fn)); + assert!(prev.is_none()); + op_id } - fn op_get_op_catalog(state: Rc<S>, _bufs: BufVec) -> Op { - let ops = state.get_op_catalog(); - let buf = serde_json::to_vec(&ops).map(Into::into).unwrap(); - Op::Sync(buf) + pub fn route_op( + op_id: OpId, + state: Rc<RefCell<OpState>>, + bufs: BufVec, + ) -> Op { + if op_id == 0 { + let ops: HashMap<String, OpId> = + state.borrow().op_table.0.keys().cloned().zip(0..).collect(); + let buf = serde_json::to_vec(&ops).map(Into::into).unwrap(); + Op::Sync(buf) + } else { + let op_fn = state + .borrow() + .op_table + .0 + .get_index(op_id) + .map(|(_, op_fn)| op_fn.clone()); + match op_fn { + Some(f) => (f)(state, bufs), + None => Op::NotFound, + } + } } } -impl<S: OpRegistry> Default for OpTable<S> { +impl Default for OpTable { fn default() -> Self { - Self( - once(("ops".to_owned(), Rc::new(Self::op_get_op_catalog) as _)).collect(), - ) + fn dummy(_state: Rc<RefCell<OpState>>, _bufs: BufVec) -> Op { + unreachable!() + } + Self(once(("ops".to_owned(), Rc::new(dummy) as _)).collect()) } } -impl<S> Deref for OpTable<S> { - type Target = IndexMap<String, Rc<OpFn<S>>>; +#[test] +fn op_table() { + let state = Rc::new(RefCell::new(OpState::default())); - fn deref(&self) -> &Self::Target { - &self.0 + let foo_id; + let bar_id; + { + let op_table = &mut state.borrow_mut().op_table; + foo_id = op_table.register_op("foo", |_, _| Op::Sync(b"oof!"[..].into())); + assert_eq!(foo_id, 1); + bar_id = op_table.register_op("bar", |_, _| Op::Sync(b"rab!"[..].into())); + assert_eq!(bar_id, 2); } + + let foo_res = OpTable::route_op(foo_id, state.clone(), Default::default()); + assert!(matches!(foo_res, Op::Sync(buf) if &*buf == b"oof!")); + let bar_res = OpTable::route_op(bar_id, state.clone(), Default::default()); + assert!(matches!(bar_res, Op::Sync(buf) if &*buf == b"rab!")); + + let catalog_res = OpTable::route_op(0, state, Default::default()); + let mut catalog_entries = match catalog_res { + Op::Sync(buf) => serde_json::from_slice::<HashMap<String, OpId>>(&buf) + .map(|map| map.into_iter().collect::<Vec<_>>()) + .unwrap(), + _ => panic!("unexpected `Op` variant"), + }; + catalog_entries.sort_by(|(_, id1), (_, id2)| id1.partial_cmp(id2).unwrap()); + assert_eq!( + catalog_entries, + vec![ + ("ops".to_owned(), 0), + ("foo".to_owned(), 1), + ("bar".to_owned(), 2) + ] + ) } -impl<S> DerefMut for OpTable<S> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } +pub fn json_op_sync<F>(op_fn: F) -> Box<OpFn> +where + F: Fn(&mut OpState, Value, &mut [ZeroCopyBuf]) -> Result<Value, ErrBox> + + 'static, +{ + Box::new(move |state: Rc<RefCell<OpState>>, mut bufs: BufVec| -> Op { + let result = serde_json::from_slice(&bufs[0]) + .map_err(crate::ErrBox::from) + .and_then(|args| op_fn(&mut state.borrow_mut(), args, &mut bufs[1..])); + let buf = + json_serialize_op_result(None, result, state.borrow().get_error_class_fn); + Op::Sync(buf) + }) +} + +pub fn json_op_async<F, R>(op_fn: F) -> Box<OpFn> +where + F: Fn(Rc<RefCell<OpState>>, Value, BufVec) -> R + 'static, + R: Future<Output = Result<Value, ErrBox>> + 'static, +{ + let try_dispatch_op = + move |state: Rc<RefCell<OpState>>, bufs: BufVec| -> Result<Op, ErrBox> { + let args: Value = serde_json::from_slice(&bufs[0])?; + let promise_id = args + .get("promiseId") + .and_then(Value::as_u64) + .ok_or_else(|| ErrBox::type_error("missing or invalid `promiseId`"))?; + let bufs = bufs[1..].into(); + use crate::futures::FutureExt; + let fut = op_fn(state.clone(), args, bufs).map(move |result| { + json_serialize_op_result( + Some(promise_id), + result, + state.borrow().get_error_class_fn, + ) + }); + Ok(Op::Async(Box::pin(fut))) + }; + + Box::new(move |state: Rc<RefCell<OpState>>, bufs: BufVec| -> Op { + match try_dispatch_op(state.clone(), bufs) { + Ok(op) => op, + Err(err) => Op::Sync(json_serialize_op_result( + None, + Err(err), + state.borrow().get_error_class_fn, + )), + } + }) +} + +fn json_serialize_op_result( + promise_id: Option<u64>, + result: Result<serde_json::Value, crate::ErrBox>, + get_error_class_fn: crate::runtime::GetErrorClassFn, +) -> Box<[u8]> { + let value = match result { + Ok(v) => serde_json::json!({ "ok": v, "promiseId": promise_id }), + Err(err) => serde_json::json!({ + "promiseId": promise_id , + "err": { + "className": (get_error_class_fn)(&err), + "message": err.to_string(), + } + }), + }; + serde_json::to_vec(&value).unwrap().into_boxed_slice() } diff --git a/core/runtime.rs b/core/runtime.rs index 2f574b195..e6fc23084 100644 --- a/core/runtime.rs +++ b/core/runtime.rs @@ -19,9 +19,10 @@ use crate::modules::RecursiveModuleLoad; use crate::ops::*; use crate::shared_queue::SharedQueue; use crate::shared_queue::RECOMMENDED_SIZE; +use crate::BufVec; use crate::ErrBox; use crate::JsError; -use crate::OpRouter; +use crate::OpState; use futures::stream::FuturesUnordered; use futures::stream::StreamExt; use futures::stream::StreamFuture; @@ -94,7 +95,7 @@ impl StartupData<'_> { type JsErrorCreateFn = dyn Fn(JsError) -> ErrBox; -pub type GetErrorClassFn = dyn for<'e> Fn(&'e ErrBox) -> &'static str; +pub type GetErrorClassFn = &'static dyn for<'e> Fn(&'e ErrBox) -> &'static str; /// Objects that need to live as long as the isolate #[derive(Default)] @@ -137,7 +138,8 @@ pub struct JsRuntimeState { pub(crate) pending_ops: FuturesUnordered<PendingOpFuture>, pub(crate) pending_unref_ops: FuturesUnordered<PendingOpFuture>, pub(crate) have_unpolled_ops: Cell<bool>, - pub(crate) op_router: Rc<dyn OpRouter>, + //pub(crate) op_table: OpTable, + pub(crate) op_state: Rc<RefCell<OpState>>, loader: Rc<dyn ModuleLoader>, pub modules: Modules, pub(crate) dyn_import_map: @@ -219,7 +221,6 @@ pub struct HeapLimits { pub(crate) struct IsolateOptions { loader: Rc<dyn ModuleLoader>, - op_router: Rc<dyn OpRouter>, startup_script: Option<OwnedScript>, startup_snapshot: Option<Snapshot>, will_snapshot: bool, @@ -229,15 +230,10 @@ pub(crate) struct IsolateOptions { impl JsRuntime { /// startup_data defines the snapshot or script used at startup to initialize /// the isolate. - pub fn new( - op_router: Rc<dyn OpRouter>, - startup_data: StartupData, - will_snapshot: bool, - ) -> Self { + pub fn new(startup_data: StartupData, will_snapshot: bool) -> Self { let (startup_script, startup_snapshot) = startup_data.into_options(); let options = IsolateOptions { loader: Rc::new(NoopModuleLoader), - op_router, startup_script, startup_snapshot, will_snapshot, @@ -251,14 +247,12 @@ impl JsRuntime { /// Create new isolate that can load and execute ESModules. pub fn new_with_loader( loader: Rc<dyn ModuleLoader>, - op_router: Rc<dyn OpRouter>, startup_data: StartupData, will_snapshot: bool, ) -> Self { let (startup_script, startup_snapshot) = startup_data.into_options(); let options = IsolateOptions { loader, - op_router, startup_script, startup_snapshot, will_snapshot, @@ -275,14 +269,12 @@ impl JsRuntime { /// 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. pub fn with_heap_limits( - op_router: Rc<dyn OpRouter>, startup_data: StartupData, heap_limits: HeapLimits, ) -> Self { let (startup_script, startup_snapshot) = startup_data.into_options(); let options = IsolateOptions { loader: Rc::new(NoopModuleLoader), - op_router, startup_script, startup_snapshot, will_snapshot: false, @@ -347,6 +339,8 @@ impl JsRuntime { (isolate, None) }; + let op_state = OpState::default(); + isolate.set_slot(Rc::new(RefCell::new(JsRuntimeState { global_context: Some(global_context), pending_promise_exceptions: HashMap::new(), @@ -357,8 +351,8 @@ impl JsRuntime { shared: SharedQueue::new(RECOMMENDED_SIZE), pending_ops: FuturesUnordered::new(), pending_unref_ops: FuturesUnordered::new(), + op_state: Rc::new(RefCell::new(op_state)), have_unpolled_ops: Cell::new(false), - op_router: options.op_router, modules: Modules::new(), loader: options.loader, dyn_import_map: HashMap::new(), @@ -406,6 +400,12 @@ impl JsRuntime { } } + pub fn op_state(&mut self) -> Rc<RefCell<OpState>> { + let state_rc = Self::state(self); + let state = state_rc.borrow(); + state.op_state.clone() + } + /// Executes traditional JavaScript code (traditional = not ES modules) /// /// ErrBox can be downcast to a type that exposes additional information about @@ -477,6 +477,18 @@ impl JsRuntime { snapshot } + pub fn register_op<F>(&mut self, name: &str, op_fn: F) -> OpId + where + F: Fn(Rc<RefCell<OpState>>, BufVec) -> Op + 'static, + { + Self::state(self) + .borrow_mut() + .op_state + .borrow_mut() + .op_table + .register_op(name, op_fn) + } + /// Registers a callback on the isolate when the memory limits are approached. /// Use this to prevent V8 from crashing the process when reaching the limit. /// @@ -1283,8 +1295,6 @@ impl JsRuntime { pub mod tests { use super::*; use crate::modules::ModuleSourceFuture; - use crate::ops::*; - use crate::BasicState; use crate::BufVec; use futures::future::lazy; use futures::FutureExt; @@ -1328,89 +1338,89 @@ pub mod tests { OverflowResAsync, } - struct TestOpRouter { + struct TestState { mode: Mode, dispatch_count: Arc<AtomicUsize>, } - impl OpRouter for TestOpRouter { - fn route_op(self: Rc<Self>, op_id: OpId, bufs: BufVec) -> Op { - if op_id != 1 { - return Op::NotFound; + fn dispatch(op_state: Rc<RefCell<OpState>>, bufs: BufVec) -> Op { + let op_state_ = op_state.borrow(); + let test_state = op_state_.borrow::<TestState>(); + test_state.dispatch_count.fetch_add(1, Ordering::Relaxed); + match test_state.mode { + Mode::Async => { + assert_eq!(bufs.len(), 1); + assert_eq!(bufs[0].len(), 1); + assert_eq!(bufs[0][0], 42); + let buf = vec![43u8].into_boxed_slice(); + Op::Async(futures::future::ready(buf).boxed()) } - self.dispatch_count.fetch_add(1, Ordering::Relaxed); - match self.mode { - Mode::Async => { - assert_eq!(bufs.len(), 1); - assert_eq!(bufs[0].len(), 1); - assert_eq!(bufs[0][0], 42); - let buf = vec![43u8].into_boxed_slice(); - Op::Async(futures::future::ready(buf).boxed()) - } - Mode::AsyncUnref => { - assert_eq!(bufs.len(), 1); - assert_eq!(bufs[0].len(), 1); - assert_eq!(bufs[0][0], 42); - let fut = async { - // This future never finish. - futures::future::pending::<()>().await; - vec![43u8].into_boxed_slice() - }; - Op::AsyncUnref(fut.boxed()) - } - Mode::AsyncZeroCopy(count) => { - assert_eq!(bufs.len(), count as usize); - bufs.iter().enumerate().for_each(|(idx, buf)| { - assert_eq!(buf.len(), 1); - assert_eq!(idx, buf[0] as usize); - }); - - let buf = vec![43u8].into_boxed_slice(); - Op::Async(futures::future::ready(buf).boxed()) - } - Mode::OverflowReqSync => { - assert_eq!(bufs.len(), 1); - assert_eq!(bufs[0].len(), 100 * 1024 * 1024); - let buf = vec![43u8].into_boxed_slice(); - Op::Sync(buf) - } - Mode::OverflowResSync => { - assert_eq!(bufs.len(), 1); - assert_eq!(bufs[0].len(), 1); - assert_eq!(bufs[0][0], 42); - let mut vec = Vec::<u8>::new(); - vec.resize(100 * 1024 * 1024, 0); - vec[0] = 99; - let buf = vec.into_boxed_slice(); - Op::Sync(buf) - } - Mode::OverflowReqAsync => { - assert_eq!(bufs.len(), 1); - assert_eq!(bufs[0].len(), 100 * 1024 * 1024); - let buf = vec![43u8].into_boxed_slice(); - Op::Async(futures::future::ready(buf).boxed()) - } - Mode::OverflowResAsync => { - assert_eq!(bufs.len(), 1); - assert_eq!(bufs[0].len(), 1); - assert_eq!(bufs[0][0], 42); - let mut vec = Vec::<u8>::new(); - vec.resize(100 * 1024 * 1024, 0); - vec[0] = 4; - let buf = vec.into_boxed_slice(); - Op::Async(futures::future::ready(buf).boxed()) - } + Mode::AsyncUnref => { + assert_eq!(bufs.len(), 1); + assert_eq!(bufs[0].len(), 1); + assert_eq!(bufs[0][0], 42); + let fut = async { + // This future never finish. + futures::future::pending::<()>().await; + vec![43u8].into_boxed_slice() + }; + Op::AsyncUnref(fut.boxed()) + } + Mode::AsyncZeroCopy(count) => { + assert_eq!(bufs.len(), count as usize); + bufs.iter().enumerate().for_each(|(idx, buf)| { + assert_eq!(buf.len(), 1); + assert_eq!(idx, buf[0] as usize); + }); + + let buf = vec![43u8].into_boxed_slice(); + Op::Async(futures::future::ready(buf).boxed()) + } + Mode::OverflowReqSync => { + assert_eq!(bufs.len(), 1); + assert_eq!(bufs[0].len(), 100 * 1024 * 1024); + let buf = vec![43u8].into_boxed_slice(); + Op::Sync(buf) + } + Mode::OverflowResSync => { + assert_eq!(bufs.len(), 1); + assert_eq!(bufs[0].len(), 1); + assert_eq!(bufs[0][0], 42); + let mut vec = Vec::<u8>::new(); + vec.resize(100 * 1024 * 1024, 0); + vec[0] = 99; + let buf = vec.into_boxed_slice(); + Op::Sync(buf) + } + Mode::OverflowReqAsync => { + assert_eq!(bufs.len(), 1); + assert_eq!(bufs[0].len(), 100 * 1024 * 1024); + let buf = vec![43u8].into_boxed_slice(); + Op::Async(futures::future::ready(buf).boxed()) + } + Mode::OverflowResAsync => { + assert_eq!(bufs.len(), 1); + assert_eq!(bufs[0].len(), 1); + assert_eq!(bufs[0][0], 42); + let mut vec = Vec::<u8>::new(); + vec.resize(100 * 1024 * 1024, 0); + vec[0] = 4; + let buf = vec.into_boxed_slice(); + Op::Async(futures::future::ready(buf).boxed()) } } } fn setup(mode: Mode) -> (JsRuntime, Arc<AtomicUsize>) { let dispatch_count = Arc::new(AtomicUsize::new(0)); - let test_state = Rc::new(TestOpRouter { + let mut runtime = JsRuntime::new(StartupData::None, false); + let op_state = runtime.op_state(); + op_state.borrow_mut().put(TestState { mode, dispatch_count: dispatch_count.clone(), }); - let mut runtime = JsRuntime::new(test_state, StartupData::None, false); + + runtime.register_op("test", dispatch); js_check(runtime.execute( "setup.js", @@ -1774,8 +1784,7 @@ pub mod tests { #[test] fn syntax_error() { - let mut runtime = - JsRuntime::new(BasicState::new(), StartupData::None, false); + let mut runtime = JsRuntime::new(StartupData::None, false); let src = "hocuspocus("; let r = runtime.execute("i.js", src); let e = r.unwrap_err(); @@ -1800,29 +1809,27 @@ pub mod tests { #[test] fn will_snapshot() { let snapshot = { - let mut runtime = - JsRuntime::new(BasicState::new(), StartupData::None, true); + let mut runtime = JsRuntime::new(StartupData::None, true); js_check(runtime.execute("a.js", "a = 1 + 2")); runtime.snapshot() }; let startup_data = StartupData::Snapshot(Snapshot::JustCreated(snapshot)); - let mut runtime2 = JsRuntime::new(BasicState::new(), startup_data, false); + let mut runtime2 = JsRuntime::new(startup_data, false); js_check(runtime2.execute("check.js", "if (a != 3) throw Error('x')")); } #[test] fn test_from_boxed_snapshot() { let snapshot = { - let mut runtime = - JsRuntime::new(BasicState::new(), StartupData::None, true); + let mut runtime = JsRuntime::new(StartupData::None, true); js_check(runtime.execute("a.js", "a = 1 + 2")); let snap: &[u8] = &*runtime.snapshot(); Vec::from(snap).into_boxed_slice() }; let startup_data = StartupData::Snapshot(Snapshot::Boxed(snapshot)); - let mut runtime2 = JsRuntime::new(BasicState::new(), startup_data, false); + let mut runtime2 = JsRuntime::new(startup_data, false); js_check(runtime2.execute("check.js", "if (a != 3) throw Error('x')")); } @@ -1832,11 +1839,8 @@ pub mod tests { initial: 0, max: 20 * 1024, // 20 kB }; - let mut runtime = JsRuntime::with_heap_limits( - BasicState::new(), - StartupData::None, - heap_limits, - ); + let mut runtime = + JsRuntime::with_heap_limits(StartupData::None, heap_limits); let cb_handle = runtime.thread_safe_handle(); let callback_invoke_count = Rc::new(AtomicUsize::default()); @@ -1864,8 +1868,7 @@ pub mod tests { #[test] fn test_heap_limit_cb_remove() { - let mut runtime = - JsRuntime::new(BasicState::new(), StartupData::None, false); + let mut runtime = JsRuntime::new(StartupData::None, false); runtime.add_near_heap_limit_callback(|current_limit, _initial_limit| { current_limit * 2 @@ -1880,11 +1883,8 @@ pub mod tests { initial: 0, max: 20 * 1024, // 20 kB }; - let mut runtime = JsRuntime::with_heap_limits( - BasicState::new(), - StartupData::None, - heap_limits, - ); + let mut runtime = + JsRuntime::with_heap_limits(StartupData::None, heap_limits); let cb_handle = runtime.thread_safe_handle(); let callback_invoke_count_first = Rc::new(AtomicUsize::default()); @@ -1952,13 +1952,12 @@ pub mod tests { } let loader = Rc::new(ModsLoader::default()); - let state = BasicState::new(); let resolve_count = loader.count.clone(); let dispatch_count = Arc::new(AtomicUsize::new(0)); let dispatch_count_ = dispatch_count.clone(); - let dispatcher = move |_state: Rc<BasicState>, bufs: BufVec| -> Op { + let dispatcher = move |_state: Rc<RefCell<OpState>>, bufs: BufVec| -> Op { dispatch_count_.fetch_add(1, Ordering::Relaxed); assert_eq!(bufs.len(), 1); assert_eq!(bufs[0].len(), 1); @@ -1966,10 +1965,10 @@ pub mod tests { let buf = [43u8, 0, 0, 0][..].into(); Op::Async(futures::future::ready(buf).boxed()) }; - state.register_op("test", dispatcher); let mut runtime = - JsRuntime::new_with_loader(loader, state, StartupData::None, false); + JsRuntime::new_with_loader(loader, StartupData::None, false); + runtime.register_op("test", dispatcher); js_check(runtime.execute( "setup.js", @@ -2063,12 +2062,8 @@ pub mod tests { run_in_task(|cx| { let loader = Rc::new(DynImportErrLoader::default()); let count = loader.count.clone(); - let mut runtime = JsRuntime::new_with_loader( - loader, - BasicState::new(), - StartupData::None, - false, - ); + let mut runtime = + JsRuntime::new_with_loader(loader, StartupData::None, false); js_check(runtime.execute( "file:///dyn_import2.js", @@ -2145,12 +2140,8 @@ pub mod tests { let prepare_load_count = loader.prepare_load_count.clone(); let resolve_count = loader.resolve_count.clone(); let load_count = loader.load_count.clone(); - let mut runtime = JsRuntime::new_with_loader( - loader, - BasicState::new(), - StartupData::None, - false, - ); + let mut runtime = + JsRuntime::new_with_loader(loader, StartupData::None, false); // Dynamically import mod_b js_check(runtime.execute( @@ -2190,12 +2181,8 @@ pub mod tests { run_in_task(|cx| { let loader = Rc::new(DynImportOkLoader::default()); let prepare_load_count = loader.prepare_load_count.clone(); - let mut runtime = JsRuntime::new_with_loader( - loader, - BasicState::new(), - StartupData::None, - false, - ); + let mut runtime = + JsRuntime::new_with_loader(loader, StartupData::None, false); js_check(runtime.execute( "file:///dyn_import3.js", r#" @@ -2246,12 +2233,8 @@ pub mod tests { } let loader = std::rc::Rc::new(ModsLoader::default()); - let mut runtime = JsRuntime::new_with_loader( - loader, - BasicState::new(), - StartupData::None, - true, - ); + let mut runtime = + JsRuntime::new_with_loader(loader, StartupData::None, true); let specifier = ModuleSpecifier::resolve_url("file:///main.js").unwrap(); let source_code = "Deno.core.print('hello\\n')".to_string(); |