diff --git a/cli/state.rs b/cli/state.rs index 808678b210..f10f3b7e0b 100644 --- a/cli/state.rs +++ b/cli/state.rs @@ -10,7 +10,6 @@ use crate::resources::ResourceId; use crate::worker::Worker; use deno::deno_buf; use deno::Buf; -use deno::Dispatch; use deno::Op; use futures::future::Shared; use std; @@ -74,9 +73,9 @@ impl Deref for ThreadSafeState { } } -impl Dispatch for ThreadSafeState { - fn dispatch( - &mut self, +impl ThreadSafeState { + pub fn dispatch( + &self, control: &[u8], zero_copy: deno_buf, ) -> (bool, Box) { diff --git a/cli/worker.rs b/cli/worker.rs index 408bae1c64..8b420cef69 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -9,6 +9,7 @@ use crate::msg; use crate::state::ThreadSafeState; use crate::tokio_util; use deno; +use deno::Config; use deno::JSError; use deno::Loader; use deno::StartupData; @@ -21,7 +22,7 @@ use url::Url; /// Wraps deno::Isolate to provide source maps, ops for the CLI, and /// high-level module loading pub struct Worker { - inner: deno::Isolate, + inner: deno::Isolate, pub modules: deno::Modules, pub state: ThreadSafeState, } @@ -33,8 +34,12 @@ impl Worker { state: ThreadSafeState, ) -> Worker { let state_ = state.clone(); + let mut config = Config::default(); + config.dispatch(move |control_buf, zero_copy_buf| { + state_.dispatch(control_buf, zero_copy_buf) + }); Self { - inner: deno::Isolate::new(startup_data, state_), + inner: deno::Isolate::new(startup_data, config), modules: deno::Modules::new(), state, } @@ -154,7 +159,6 @@ pub fn root_specifier_to_url( } impl Loader for Worker { - type Dispatch = ThreadSafeState; type Error = DenoError; fn resolve(specifier: &str, referrer: &str) -> Result { @@ -187,7 +191,7 @@ impl Loader for Worker { fn isolate_and_modules<'a: 'b + 'c, 'b, 'c>( &'a mut self, - ) -> (&'b mut deno::Isolate, &'c mut deno::Modules) { + ) -> (&'b mut deno::Isolate, &'c mut deno::Modules) { (&mut self.inner, &mut self.modules) } } diff --git a/core/examples/http_bench.rs b/core/examples/http_bench.rs index ea8058019d..3e02cdd46a 100644 --- a/core/examples/http_bench.rs +++ b/core/examples/http_bench.rs @@ -111,62 +111,54 @@ fn test_record_from() { pub type HttpBenchOp = dyn Future + Send; -struct HttpBench(); +fn dispatch(control: &[u8], zero_copy_buf: deno_buf) -> (bool, Box) { + let record = Record::from(control); + let is_sync = record.promise_id == 0; + let http_bench_op = match record.op_id { + OP_LISTEN => { + assert!(is_sync); + op_listen() + } + OP_CLOSE => { + assert!(is_sync); + let rid = record.arg; + op_close(rid) + } + OP_ACCEPT => { + assert!(!is_sync); + let listener_rid = record.arg; + op_accept(listener_rid) + } + OP_READ => { + assert!(!is_sync); + let rid = record.arg; + op_read(rid, zero_copy_buf) + } + OP_WRITE => { + assert!(!is_sync); + let rid = record.arg; + op_write(rid, zero_copy_buf) + } + _ => panic!("bad op {}", record.op_id), + }; + let mut record_a = record.clone(); + let mut record_b = record.clone(); -impl Dispatch for HttpBench { - fn dispatch( - &mut self, - control: &[u8], - zero_copy_buf: deno_buf, - ) -> (bool, Box) { - let record = Record::from(control); - let is_sync = record.promise_id == 0; - let http_bench_op = match record.op_id { - OP_LISTEN => { - assert!(is_sync); - op_listen() - } - OP_CLOSE => { - assert!(is_sync); - let rid = record.arg; - op_close(rid) - } - OP_ACCEPT => { - assert!(!is_sync); - let listener_rid = record.arg; - op_accept(listener_rid) - } - OP_READ => { - assert!(!is_sync); - let rid = record.arg; - op_read(rid, zero_copy_buf) - } - OP_WRITE => { - assert!(!is_sync); - let rid = record.arg; - op_write(rid, zero_copy_buf) - } - _ => panic!("bad op {}", record.op_id), - }; - let mut record_a = record.clone(); - let mut record_b = record.clone(); - - let op = Box::new( - http_bench_op - .and_then(move |result| { - record_a.result = result; - Ok(record_a) - }).or_else(|err| -> Result { - eprintln!("unexpected err {}", err); - record_b.result = -1; - Ok(record_b) - }).then(|result| -> Result { - let record = result.unwrap(); - Ok(record.into()) - }), - ); - (is_sync, op) - } + let op = Box::new( + http_bench_op + .and_then(move |result| { + record_a.result = result; + Ok(record_a) + }).or_else(|err| -> Result { + eprintln!("unexpected err {}", err); + record_b.result = -1; + Ok(record_b) + }).then(|result| -> Result { + let record = result.unwrap(); + Ok(record.into()) + }), + ); + (is_sync, op) } fn main() { @@ -182,7 +174,9 @@ fn main() { filename: "http_bench.js", }); - let isolate = deno::Isolate::new(startup_data, HttpBench()); + let mut config = deno::Config::default(); + config.dispatch(dispatch); + let isolate = deno::Isolate::new(startup_data, config); isolate.then(|r| { js_check(r); diff --git a/core/isolate.rs b/core/isolate.rs index 4975223569..95cf1be17f 100644 --- a/core/isolate.rs +++ b/core/isolate.rs @@ -68,15 +68,21 @@ pub enum StartupData<'a> { None, } -/// Defines the how Deno.core.dispatch() acts. -pub trait Dispatch { +#[derive(Default)] +pub struct Config { + dispatch: Option (bool, Box) + Send + Sync>>, +} + +impl Config { + /// Defines the how Deno.core.dispatch() acts. /// Called whenever Deno.core.dispatch() is called in JavaScript. zero_copy_buf /// corresponds to the second argument of Deno.core.dispatch(). - fn dispatch( - &mut self, - control: &[u8], - zero_copy_buf: deno_buf, - ) -> (bool, Box); + pub fn dispatch(&mut self, f: F) + where + F: Fn(&[u8], deno_buf) -> (bool, Box) + Send + Sync + 'static, + { + self.dispatch = Some(Arc::new(f)); + } } /// A single execution context of JavaScript. Corresponds roughly to the "Web @@ -87,19 +93,19 @@ pub trait Dispatch { /// Ops are created in JavaScript by calling Deno.core.dispatch(), and in Rust /// by implementing deno::Dispatch::dispatch. An Op corresponds exactly to a /// Promise in JavaScript. -pub struct Isolate { +pub struct Isolate { libdeno_isolate: *const libdeno::isolate, shared_libdeno_isolate: Arc>>, - dispatcher: B, + config: Config, needs_init: bool, shared: SharedQueue, pending_ops: FuturesUnordered, have_unpolled_ops: bool, } -unsafe impl Send for Isolate {} +unsafe impl Send for Isolate {} -impl Drop for Isolate { +impl Drop for Isolate { fn drop(&mut self) { // remove shared_libdeno_isolate reference *self.shared_libdeno_isolate.lock().unwrap() = None; @@ -110,10 +116,12 @@ impl Drop for Isolate { static DENO_INIT: Once = ONCE_INIT; -impl Isolate { +impl Isolate { /// startup_data defines the snapshot or script used at startup to initalize /// the isolate. - pub fn new(startup_data: StartupData, dispatcher: B) -> Self { + // TODO(ry) move startup_data into Config. Ideally without introducing a + // generic lifetime into the Isolate struct... + pub fn new(startup_data: StartupData, config: Config) -> Self { DENO_INIT.call_once(|| { unsafe { libdeno::deno_init() }; }); @@ -127,7 +135,7 @@ impl Isolate { StartupData::Script(d) => (None, Some(d)), StartupData::None => (None, None), }; - let config = libdeno::deno_config { + let libdeno_config = libdeno::deno_config { will_snapshot: 0, load_snapshot: match startup_snapshot { Some(s) => Snapshot2::from(s), @@ -136,12 +144,12 @@ impl Isolate { shared: shared.as_deno_buf(), recv_cb: Self::pre_dispatch, }; - let libdeno_isolate = unsafe { libdeno::deno_new(config) }; + let libdeno_isolate = unsafe { libdeno::deno_new(libdeno_config) }; let mut core_isolate = Self { libdeno_isolate, shared_libdeno_isolate: Arc::new(Mutex::new(Some(libdeno_isolate))), - dispatcher, + config, shared, needs_init, pending_ops: FuturesUnordered::new(), @@ -178,19 +186,25 @@ impl Isolate { control_argv0: deno_buf, zero_copy_buf: deno_buf, ) { - let isolate = unsafe { Isolate::::from_raw_ptr(user_data) }; + let isolate = unsafe { Isolate::from_raw_ptr(user_data) }; let zero_copy_id = zero_copy_buf.zero_copy_id; let control_shared = isolate.shared.shift(); let (is_sync, op) = if control_argv0.len() > 0 { // The user called Deno.core.send(control) - isolate - .dispatcher - .dispatch(control_argv0.as_ref(), zero_copy_buf) + if let Some(ref f) = isolate.config.dispatch { + f(control_argv0.as_ref(), zero_copy_buf) + } else { + panic!("isolate.config.dispatch not set") + } } else if let Some(c) = control_shared { // The user called Deno.sharedQueue.push(control) - isolate.dispatcher.dispatch(&c, zero_copy_buf) + if let Some(ref f) = isolate.config.dispatch { + f(&c, zero_copy_buf) + } else { + panic!("isolate.config.dispatch not set") + } } else { // The sharedQueue is empty. The shouldn't happen usually, but it's also // not technically a failure. @@ -362,7 +376,7 @@ impl<'a> ResolveContext<'a> { } } -impl Isolate { +impl Isolate { pub fn mod_instantiate( &mut self, id: deno_mod, @@ -428,7 +442,7 @@ impl Drop for LockerScope { } } -impl Future for Isolate { +impl Future for Isolate { type Item = (); type Error = JSError; @@ -554,7 +568,7 @@ pub mod tests { ) } - pub enum TestDispatchMode { + pub enum Mode { AsyncImmediate, OverflowReqSync, OverflowResSync, @@ -562,84 +576,71 @@ pub mod tests { OverflowResAsync, } - pub struct TestDispatch { - pub dispatch_count: usize, - mode: TestDispatchMode, - } + pub fn setup(mode: Mode) -> (Isolate, Arc) { + let dispatch_count = Arc::new(AtomicUsize::new(0)); + let dispatch_count_ = dispatch_count.clone(); - impl TestDispatch { - pub fn setup(mode: TestDispatchMode) -> Isolate { - let mut isolate = Isolate::new( - StartupData::None, - TestDispatch { - dispatch_count: 0, - mode, - }, - ); - js_check(isolate.execute( - "setup.js", - r#" - function assert(cond) { - if (!cond) { - throw Error("assert"); - } + let mut config = Config::default(); + config.dispatch( + move |control: &[u8], _zero_copy_buf: deno_buf| -> (bool, Box) { + dispatch_count_.fetch_add(1, Ordering::Relaxed); + match mode { + Mode::AsyncImmediate => { + assert_eq!(control.len(), 1); + assert_eq!(control[0], 42); + let buf = vec![43u8].into_boxed_slice(); + (false, Box::new(futures::future::ok(buf))) } - "#, - )); - assert_eq!(isolate.dispatcher.dispatch_count, 0); - isolate - } - } + Mode::OverflowReqSync => { + assert_eq!(control.len(), 100 * 1024 * 1024); + let buf = vec![43u8].into_boxed_slice(); + (true, Box::new(futures::future::ok(buf))) + } + Mode::OverflowResSync => { + assert_eq!(control.len(), 1); + assert_eq!(control[0], 42); + let mut vec = Vec::::new(); + vec.resize(100 * 1024 * 1024, 0); + vec[0] = 99; + let buf = vec.into_boxed_slice(); + (true, Box::new(futures::future::ok(buf))) + } + Mode::OverflowReqAsync => { + assert_eq!(control.len(), 100 * 1024 * 1024); + let buf = vec![43u8].into_boxed_slice(); + (false, Box::new(futures::future::ok(buf))) + } + Mode::OverflowResAsync => { + assert_eq!(control.len(), 1); + assert_eq!(control[0], 42); + let mut vec = Vec::::new(); + vec.resize(100 * 1024 * 1024, 0); + vec[0] = 4; + let buf = vec.into_boxed_slice(); + (false, Box::new(futures::future::ok(buf))) + } + } + }, + ); - impl Dispatch for TestDispatch { - fn dispatch( - &mut self, - control: &[u8], - _zero_copy_buf: deno_buf, - ) -> (bool, Box) { - self.dispatch_count += 1; - match self.mode { - TestDispatchMode::AsyncImmediate => { - assert_eq!(control.len(), 1); - assert_eq!(control[0], 42); - let buf = vec![43u8].into_boxed_slice(); - (false, Box::new(futures::future::ok(buf))) + let mut isolate = Isolate::new(StartupData::None, config); + js_check(isolate.execute( + "setup.js", + r#" + function assert(cond) { + if (!cond) { + throw Error("assert"); + } } - TestDispatchMode::OverflowReqSync => { - assert_eq!(control.len(), 100 * 1024 * 1024); - let buf = vec![43u8].into_boxed_slice(); - (true, Box::new(futures::future::ok(buf))) - } - TestDispatchMode::OverflowResSync => { - assert_eq!(control.len(), 1); - assert_eq!(control[0], 42); - let mut vec = Vec::::new(); - vec.resize(100 * 1024 * 1024, 0); - vec[0] = 99; - let buf = vec.into_boxed_slice(); - (true, Box::new(futures::future::ok(buf))) - } - TestDispatchMode::OverflowReqAsync => { - assert_eq!(control.len(), 100 * 1024 * 1024); - let buf = vec![43u8].into_boxed_slice(); - (false, Box::new(futures::future::ok(buf))) - } - TestDispatchMode::OverflowResAsync => { - assert_eq!(control.len(), 1); - assert_eq!(control[0], 42); - let mut vec = Vec::::new(); - vec.resize(100 * 1024 * 1024, 0); - vec[0] = 4; - let buf = vec.into_boxed_slice(); - (false, Box::new(futures::future::ok(buf))) - } - } - } + "#, + )); + assert_eq!(dispatch_count.load(Ordering::Relaxed), 0); + (isolate, dispatch_count) } #[test] fn test_dispatch() { - let mut isolate = TestDispatch::setup(TestDispatchMode::AsyncImmediate); + let (mut isolate, dispatch_count) = setup(Mode::AsyncImmediate); js_check(isolate.execute( "filename.js", r#" @@ -651,12 +652,12 @@ pub mod tests { main(); "#, )); - assert_eq!(isolate.dispatcher.dispatch_count, 2); + assert_eq!(dispatch_count.load(Ordering::Relaxed), 2); } #[test] fn test_mods() { - let mut isolate = TestDispatch::setup(TestDispatchMode::AsyncImmediate); + let (mut isolate, dispatch_count) = setup(Mode::AsyncImmediate); let mod_a = isolate .mod_new( true, @@ -668,7 +669,7 @@ pub mod tests { Deno.core.send(control); "#, ).unwrap(); - assert_eq!(isolate.dispatcher.dispatch_count, 0); + assert_eq!(dispatch_count.load(Ordering::Relaxed), 0); let imports = isolate.mod_get_imports(mod_a); assert_eq!(imports, vec!["b.js".to_string()]); @@ -689,22 +690,22 @@ pub mod tests { }; js_check(isolate.mod_instantiate(mod_b, &mut resolve)); - assert_eq!(isolate.dispatcher.dispatch_count, 0); + assert_eq!(dispatch_count.load(Ordering::Relaxed), 0); assert_eq!(resolve_count.load(Ordering::SeqCst), 0); js_check(isolate.mod_instantiate(mod_a, &mut resolve)); - assert_eq!(isolate.dispatcher.dispatch_count, 0); + assert_eq!(dispatch_count.load(Ordering::Relaxed), 0); assert_eq!(resolve_count.load(Ordering::SeqCst), 1); js_check(isolate.mod_evaluate(mod_a)); - assert_eq!(isolate.dispatcher.dispatch_count, 1); + assert_eq!(dispatch_count.load(Ordering::Relaxed), 1); assert_eq!(resolve_count.load(Ordering::SeqCst), 1); } #[test] fn test_poll_async_immediate_ops() { run_in_task(|| { - let mut isolate = TestDispatch::setup(TestDispatchMode::AsyncImmediate); + let (mut isolate, dispatch_count) = setup(Mode::AsyncImmediate); js_check(isolate.execute( "setup2.js", @@ -715,7 +716,7 @@ pub mod tests { }); "#, )); - assert_eq!(isolate.dispatcher.dispatch_count, 0); + assert_eq!(dispatch_count.load(Ordering::Relaxed), 0); js_check(isolate.execute( "check1.js", r#" @@ -725,9 +726,9 @@ pub mod tests { assert(nrecv == 0); "#, )); - assert_eq!(isolate.dispatcher.dispatch_count, 1); + assert_eq!(dispatch_count.load(Ordering::Relaxed), 1); assert_eq!(Ok(Async::Ready(())), isolate.poll()); - assert_eq!(isolate.dispatcher.dispatch_count, 1); + assert_eq!(dispatch_count.load(Ordering::Relaxed), 1); js_check(isolate.execute( "check2.js", r#" @@ -736,10 +737,10 @@ pub mod tests { assert(nrecv == 1); "#, )); - assert_eq!(isolate.dispatcher.dispatch_count, 2); + assert_eq!(dispatch_count.load(Ordering::Relaxed), 2); assert_eq!(Ok(Async::Ready(())), isolate.poll()); js_check(isolate.execute("check3.js", "assert(nrecv == 2)")); - assert_eq!(isolate.dispatcher.dispatch_count, 2); + assert_eq!(dispatch_count.load(Ordering::Relaxed), 2); // We are idle, so the next poll should be the last. assert_eq!(Ok(Async::Ready(())), isolate.poll()); }); @@ -748,7 +749,7 @@ pub mod tests { #[test] fn test_shared() { run_in_task(|| { - let mut isolate = TestDispatch::setup(TestDispatchMode::AsyncImmediate); + let (mut isolate, dispatch_count) = setup(Mode::AsyncImmediate); js_check(isolate.execute( "setup2.js", @@ -761,7 +762,7 @@ pub mod tests { }); "#, )); - assert_eq!(isolate.dispatcher.dispatch_count, 0); + assert_eq!(dispatch_count.load(Ordering::Relaxed), 0); js_check(isolate.execute( "send1.js", @@ -776,7 +777,7 @@ pub mod tests { assert(nrecv === 0); "#, )); - assert_eq!(isolate.dispatcher.dispatch_count, 2); + assert_eq!(dispatch_count.load(Ordering::Relaxed), 2); assert_eq!(Ok(Async::Ready(())), isolate.poll()); js_check(isolate.execute("send1.js", "assert(nrecv === 2);")); }); @@ -787,7 +788,7 @@ pub mod tests { let (tx, rx) = std::sync::mpsc::channel::(); let tx_clone = tx.clone(); - let mut isolate = TestDispatch::setup(TestDispatchMode::AsyncImmediate); + let (mut isolate, _dispatch_count) = setup(Mode::AsyncImmediate); let shared = isolate.shared_isolate_handle(); let t1 = std::thread::spawn(move || { @@ -844,7 +845,7 @@ pub mod tests { fn dangling_shared_isolate() { let shared = { // isolate is dropped at the end of this block - let mut isolate = TestDispatch::setup(TestDispatchMode::AsyncImmediate); + let (mut isolate, _dispatch_count) = setup(Mode::AsyncImmediate); isolate.shared_isolate_handle() }; @@ -854,7 +855,7 @@ pub mod tests { #[test] fn overflow_req_sync() { - let mut isolate = TestDispatch::setup(TestDispatchMode::OverflowReqSync); + let (mut isolate, dispatch_count) = setup(Mode::OverflowReqSync); js_check(isolate.execute( "overflow_req_sync.js", r#" @@ -869,14 +870,14 @@ pub mod tests { assert(asyncRecv == 0); "#, )); - assert_eq!(isolate.dispatcher.dispatch_count, 1); + assert_eq!(dispatch_count.load(Ordering::Relaxed), 1); } #[test] fn overflow_res_sync() { // TODO(ry) This test is quite slow due to memcpy-ing 100MB into JS. We // should optimize this. - let mut isolate = TestDispatch::setup(TestDispatchMode::OverflowResSync); + let (mut isolate, dispatch_count) = setup(Mode::OverflowResSync); js_check(isolate.execute( "overflow_res_sync.js", r#" @@ -891,13 +892,13 @@ pub mod tests { assert(asyncRecv == 0); "#, )); - assert_eq!(isolate.dispatcher.dispatch_count, 1); + assert_eq!(dispatch_count.load(Ordering::Relaxed), 1); } #[test] fn overflow_req_async() { run_in_task(|| { - let mut isolate = TestDispatch::setup(TestDispatchMode::OverflowReqAsync); + let (mut isolate, dispatch_count) = setup(Mode::OverflowReqAsync); js_check(isolate.execute( "overflow_req_async.js", r#" @@ -915,7 +916,7 @@ pub mod tests { assert(asyncRecv == 0); "#, )); - assert_eq!(isolate.dispatcher.dispatch_count, 1); + assert_eq!(dispatch_count.load(Ordering::Relaxed), 1); assert_eq!(Ok(Async::Ready(())), isolate.poll()); js_check(isolate.execute("check.js", "assert(asyncRecv == 1);")); }); @@ -926,7 +927,7 @@ pub mod tests { run_in_task(|| { // TODO(ry) This test is quite slow due to memcpy-ing 100MB into JS. We // should optimize this. - let mut isolate = TestDispatch::setup(TestDispatchMode::OverflowResAsync); + let (mut isolate, dispatch_count) = setup(Mode::OverflowResAsync); js_check(isolate.execute( "overflow_res_async.js", r#" @@ -943,7 +944,7 @@ pub mod tests { assert(asyncRecv == 0); "#, )); - assert_eq!(isolate.dispatcher.dispatch_count, 1); + assert_eq!(dispatch_count.load(Ordering::Relaxed), 1); assert_eq!(Ok(()), poll_until_ready(&mut isolate, 3)); js_check(isolate.execute("check.js", "assert(asyncRecv == 1);")); }); @@ -954,7 +955,7 @@ pub mod tests { // TODO(ry) This test is quite slow due to memcpy-ing 100MB into JS. We // should optimize this. run_in_task(|| { - let mut isolate = TestDispatch::setup(TestDispatchMode::OverflowResAsync); + let (mut isolate, dispatch_count) = setup(Mode::OverflowResAsync); js_check(isolate.execute( "overflow_res_multiple_dispatch_async.js", r#" @@ -974,7 +975,7 @@ pub mod tests { Deno.core.dispatch(control); "#, )); - assert_eq!(isolate.dispatcher.dispatch_count, 2); + assert_eq!(dispatch_count.load(Ordering::Relaxed), 2); assert_eq!(Ok(()), poll_until_ready(&mut isolate, 3)); js_check(isolate.execute("check.js", "assert(asyncRecv == 2);")); }); @@ -983,7 +984,7 @@ pub mod tests { #[test] fn test_js() { run_in_task(|| { - let mut isolate = TestDispatch::setup(TestDispatchMode::AsyncImmediate); + let (mut isolate, _dispatch_count) = setup(Mode::AsyncImmediate); js_check( isolate.execute( "shared_queue_test.js", diff --git a/core/modules.rs b/core/modules.rs index 435255856e..1efab663b6 100644 --- a/core/modules.rs +++ b/core/modules.rs @@ -35,7 +35,6 @@ pub type SourceCodeInfoFuture = dyn Future + Send; pub trait Loader { - type Dispatch: crate::isolate::Dispatch; type Error: std::error::Error + 'static; /// Returns an absolute URL. @@ -49,9 +48,9 @@ pub trait Loader { fn isolate_and_modules<'a: 'b + 'c, 'b, 'c>( &'a mut self, - ) -> (&'b mut Isolate, &'c mut Modules); + ) -> (&'b mut Isolate, &'c mut Modules); - fn isolate<'a: 'b, 'b>(&'a mut self) -> &'b mut Isolate { + fn isolate<'a: 'b, 'b>(&'a mut self) -> &'b mut Isolate { let (isolate, _) = self.isolate_and_modules(); isolate } @@ -536,14 +535,14 @@ mod tests { struct MockLoader { pub loads: Vec, - pub isolate: Isolate, + pub isolate: Isolate, pub modules: Modules, } impl MockLoader { fn new() -> Self { let modules = Modules::new(); - let isolate = TestDispatch::setup(TestDispatchMode::AsyncImmediate); + let (isolate, _dispatch_count) = setup(Mode::AsyncImmediate); Self { loads: Vec::new(), isolate, @@ -619,7 +618,6 @@ mod tests { } impl Loader for MockLoader { - type Dispatch = TestDispatch; type Error = MockError; fn resolve(specifier: &str, referrer: &str) -> Result { @@ -659,7 +657,7 @@ mod tests { fn isolate_and_modules<'a: 'b + 'c, 'b, 'c>( &'a mut self, - ) -> (&'b mut Isolate, &'c mut Modules) { + ) -> (&'b mut Isolate, &'c mut Modules) { (&mut self.isolate, &mut self.modules) } }