diff --git a/cli/inspector.rs b/cli/inspector.rs index b67bb89f5a..94114addb4 100644 --- a/cli/inspector.rs +++ b/cli/inspector.rs @@ -375,14 +375,10 @@ impl DenoInspector { isolate: &mut deno_core::CoreIsolate, host: SocketAddr, ) -> Box { - let deno_core::CoreIsolate { - v8_isolate, - global_context, - .. - } = isolate; + let core_state_rc = deno_core::CoreIsolate::state(isolate); + let core_state = core_state_rc.borrow(); - let v8_isolate = v8_isolate.as_mut().unwrap(); - let mut hs = v8::HandleScope::new(v8_isolate); + let mut hs = v8::HandleScope::new(isolate); let scope = hs.enter(); let (new_websocket_tx, new_websocket_rx) = @@ -420,7 +416,7 @@ impl DenoInspector { }); // Tell the inspector about the global context. - let context = global_context.get(scope).unwrap(); + let context = core_state.global_context.get(scope).unwrap(); let context_name = v8::inspector::StringView::from(&b"global context"[..]); self_.context_created(context, Self::CONTEXT_GROUP_ID, context_name); diff --git a/cli/main.rs b/cli/main.rs index 1e90729d17..d947088d26 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -80,7 +80,9 @@ use crate::state::State; use crate::tsc::TargetLib; use crate::worker::MainWorker; use deno_core::v8_set_flags; +use deno_core::CoreIsolate; use deno_core::ErrBox; +use deno_core::EsIsolate; use deno_core::ModuleSpecifier; use flags::DenoSubcommand; use flags::Flags; @@ -170,7 +172,9 @@ fn create_main_worker( { let (stdin, stdout, stderr) = get_stdio(); - let mut t = worker.resource_table.borrow_mut(); + let state_rc = CoreIsolate::state(&worker.isolate); + let state = state_rc.borrow(); + let mut t = state.resource_table.borrow_mut(); t.add("stdin", Box::new(stdin)); t.add("stdout", Box::new(stdout)); t.add("stderr", Box::new(stderr)); @@ -268,7 +272,10 @@ async fn print_file_info( ); } - if let Some(deps) = worker.isolate.modules.deps(&module_specifier) { + let es_state_rc = EsIsolate::state(&worker.isolate); + let es_state = es_state_rc.borrow(); + + if let Some(deps) = es_state.modules.deps(&module_specifier) { println!("{}{}", colors::bold("deps:\n".to_string()), deps.name); if let Some(ref depsdeps) = deps.deps { for d in depsdeps { diff --git a/cli/ops/dispatch_json.rs b/cli/ops/dispatch_json.rs index 6125ea39bb..c2c103f69c 100644 --- a/cli/ops/dispatch_json.rs +++ b/cli/ops/dispatch_json.rs @@ -1,7 +1,7 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. use crate::op_error::OpError; use deno_core::Buf; -use deno_core::CoreIsolate; +use deno_core::CoreIsolateState; use deno_core::Op; use deno_core::ZeroCopyBuf; use futures::future::FutureExt; @@ -46,12 +46,15 @@ struct AsyncArgs { pub fn json_op( d: D, -) -> impl Fn(&mut CoreIsolate, &[u8], Option) -> Op +) -> impl Fn(&mut CoreIsolateState, &[u8], Option) -> Op where - D: - Fn(&mut CoreIsolate, Value, Option) -> Result, + D: Fn( + &mut CoreIsolateState, + Value, + Option, + ) -> Result, { - move |isolate: &mut CoreIsolate, + move |isolate_state: &mut CoreIsolateState, control: &[u8], zero_copy: Option| { let async_args: AsyncArgs = match serde_json::from_slice(control) { @@ -66,7 +69,7 @@ where let result = serde_json::from_slice(control) .map_err(OpError::from) - .and_then(|args| d(isolate, args, zero_copy)); + .and_then(|args| d(isolate_state, args, zero_copy)); // Convert to Op match result { diff --git a/cli/ops/dispatch_minimal.rs b/cli/ops/dispatch_minimal.rs index ac98ea5896..3da8305a13 100644 --- a/cli/ops/dispatch_minimal.rs +++ b/cli/ops/dispatch_minimal.rs @@ -7,7 +7,7 @@ use crate::op_error::OpError; use byteorder::{LittleEndian, WriteBytesExt}; use deno_core::Buf; -use deno_core::CoreIsolate; +use deno_core::CoreIsolateState; use deno_core::Op; use deno_core::ZeroCopyBuf; use futures::future::FutureExt; @@ -116,11 +116,11 @@ fn test_parse_min_record() { pub fn minimal_op( d: D, -) -> impl Fn(&mut CoreIsolate, &[u8], Option) -> Op +) -> impl Fn(&mut CoreIsolateState, &[u8], Option) -> Op where - D: Fn(&mut CoreIsolate, bool, i32, Option) -> MinimalOp, + D: Fn(&mut CoreIsolateState, bool, i32, Option) -> MinimalOp, { - move |isolate: &mut CoreIsolate, + move |isolate_state: &mut CoreIsolateState, control: &[u8], zero_copy: Option| { let mut record = match parse_min_record(control) { @@ -138,7 +138,7 @@ where }; let is_sync = record.promise_id == 0; let rid = record.arg; - let min_op = d(isolate, is_sync, rid, zero_copy); + let min_op = d(isolate_state, is_sync, rid, zero_copy); match min_op { MinimalOp::Sync(sync_result) => Op::Sync(match sync_result { diff --git a/cli/ops/fetch.rs b/cli/ops/fetch.rs index 596c9a2fd2..927bc5f64c 100644 --- a/cli/ops/fetch.rs +++ b/cli/ops/fetch.rs @@ -5,6 +5,7 @@ use crate::http_util::{create_http_client, HttpBody}; use crate::op_error::OpError; use crate::state::State; use deno_core::CoreIsolate; +use deno_core::CoreIsolateState; use deno_core::ZeroCopyBuf; use futures::future::FutureExt; use http::header::HeaderName; @@ -24,7 +25,7 @@ struct FetchArgs { } pub fn op_fetch( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, state: &State, args: Value, data: Option, @@ -67,7 +68,7 @@ pub fn op_fetch( } debug!("Before fetch {}", url); - let resource_table = isolate.resource_table.clone(); + let resource_table = isolate_state.resource_table.clone(); let future = async move { let res = request.send().await?; debug!("Fetch response {}", url); diff --git a/cli/ops/fs.rs b/cli/ops/fs.rs index ce7045e21a..204549d00e 100644 --- a/cli/ops/fs.rs +++ b/cli/ops/fs.rs @@ -7,6 +7,7 @@ use crate::op_error::OpError; use crate::ops::dispatch_json::JsonResult; use crate::state::State; use deno_core::CoreIsolate; +use deno_core::CoreIsolateState; use deno_core::ZeroCopyBuf; use futures::future::FutureExt; use std::convert::From; @@ -68,14 +69,14 @@ struct OpenOptions { } fn op_open( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, state: &State, args: Value, _zero_copy: Option, ) -> Result { let args: OpenArgs = serde_json::from_value(args)?; let path = Path::new(&args.path).to_path_buf(); - let resource_table = isolate.resource_table.clone(); + let resource_table = isolate_state.resource_table.clone(); let mut open_options = std::fs::OpenOptions::new(); @@ -151,7 +152,7 @@ struct SeekArgs { } fn op_seek( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, _state: &State, args: Value, _zero_copy: Option, @@ -174,7 +175,7 @@ fn op_seek( } }; - let resource_table = isolate.resource_table.clone(); + let resource_table = isolate_state.resource_table.clone(); let is_sync = args.promise_id.is_none(); if is_sync { diff --git a/cli/ops/fs_events.rs b/cli/ops/fs_events.rs index 56ed556f4f..8e1831aa2e 100644 --- a/cli/ops/fs_events.rs +++ b/cli/ops/fs_events.rs @@ -3,6 +3,7 @@ use super::dispatch_json::{Deserialize, JsonOp, Value}; use crate::op_error::OpError; use crate::state::State; use deno_core::CoreIsolate; +use deno_core::CoreIsolateState; use deno_core::ErrBox; use deno_core::ZeroCopyBuf; use futures::future::poll_fn; @@ -62,7 +63,7 @@ impl From for FsEvent { } pub fn op_fs_events_open( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, state: &State, args: Value, _zero_copy: Option, @@ -94,13 +95,13 @@ pub fn op_fs_events_open( watcher.watch(path, recursive_mode).map_err(ErrBox::from)?; } let resource = FsEventsResource { watcher, receiver }; - let mut resource_table = isolate.resource_table.borrow_mut(); + let mut resource_table = isolate_state.resource_table.borrow_mut(); let rid = resource_table.add("fsEvents", Box::new(resource)); Ok(JsonOp::Sync(json!(rid))) } pub fn op_fs_events_poll( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, _state: &State, args: Value, _zero_copy: Option, @@ -110,7 +111,7 @@ pub fn op_fs_events_poll( rid: u32, } let PollArgs { rid } = serde_json::from_value(args)?; - let resource_table = isolate.resource_table.clone(); + let resource_table = isolate_state.resource_table.clone(); let f = poll_fn(move |cx| { let mut resource_table = resource_table.borrow_mut(); let watcher = resource_table diff --git a/cli/ops/io.rs b/cli/ops/io.rs index 705083e15c..5769d74ed2 100644 --- a/cli/ops/io.rs +++ b/cli/ops/io.rs @@ -3,6 +3,7 @@ use crate::http_util::HttpBody; use crate::op_error::OpError; use crate::state::State; use deno_core::CoreIsolate; +use deno_core::CoreIsolateState; use deno_core::ResourceTable; use deno_core::ZeroCopyBuf; use futures::future::poll_fn; @@ -206,7 +207,7 @@ impl DenoAsyncRead for StreamResource { } pub fn op_read( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, _state: &State, is_sync: bool, rid: i32, @@ -216,7 +217,7 @@ pub fn op_read( if zero_copy.is_none() { return MinimalOp::Sync(Err(no_buffer_specified())); } - let resource_table = isolate.resource_table.clone(); + let resource_table = isolate_state.resource_table.clone(); let mut buf = zero_copy.unwrap(); @@ -330,7 +331,7 @@ impl DenoAsyncWrite for StreamResource { } pub fn op_write( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, _state: &State, is_sync: bool, rid: i32, @@ -346,7 +347,7 @@ pub fn op_write( if is_sync { MinimalOp::Sync({ // First we look up the rid in the resource table. - let mut resource_table = isolate.resource_table.borrow_mut(); + let mut resource_table = isolate_state.resource_table.borrow_mut(); std_file_resource(&mut resource_table, rid as u32, move |r| match r { Ok(std_file) => { use std::io::Write; @@ -361,7 +362,7 @@ pub fn op_write( }) }) } else { - let resource_table = isolate.resource_table.clone(); + let resource_table = isolate_state.resource_table.clone(); MinimalOp::Async( async move { let nwritten = poll_fn(|cx| { diff --git a/cli/ops/net.rs b/cli/ops/net.rs index ae5bcb9bba..3d524d3f19 100644 --- a/cli/ops/net.rs +++ b/cli/ops/net.rs @@ -5,6 +5,7 @@ use crate::op_error::OpError; use crate::resolve_addr::resolve_addr; use crate::state::State; use deno_core::CoreIsolate; +use deno_core::CoreIsolateState; use deno_core::ResourceTable; use deno_core::ZeroCopyBuf; use futures::future::poll_fn; @@ -37,12 +38,12 @@ struct AcceptArgs { } fn accept_tcp( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, args: AcceptArgs, _zero_copy: Option, ) -> Result { let rid = args.rid as u32; - let resource_table = isolate.resource_table.clone(); + let resource_table = isolate_state.resource_table.clone(); let op = async move { let accept_fut = poll_fn(|cx| { @@ -97,16 +98,16 @@ fn accept_tcp( } fn op_accept( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, _state: &State, args: Value, zero_copy: Option, ) -> Result { let args: AcceptArgs = serde_json::from_value(args)?; match args.transport.as_str() { - "tcp" => accept_tcp(isolate, args, zero_copy), + "tcp" => accept_tcp(isolate_state, args, zero_copy), #[cfg(unix)] - "unix" => net_unix::accept_unix(isolate, args.rid as u32, zero_copy), + "unix" => net_unix::accept_unix(isolate_state, args.rid as u32, zero_copy), _ => Err(OpError::other(format!( "Unsupported transport protocol {}", args.transport @@ -121,7 +122,7 @@ struct ReceiveArgs { } fn receive_udp( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, _state: &State, args: ReceiveArgs, zero_copy: Option, @@ -130,7 +131,7 @@ fn receive_udp( let rid = args.rid as u32; - let resource_table = isolate.resource_table.clone(); + let resource_table = isolate_state.resource_table.clone(); let op = async move { let receive_fut = poll_fn(|cx| { @@ -158,7 +159,7 @@ fn receive_udp( } fn op_receive( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, state: &State, args: Value, zero_copy: Option, @@ -166,10 +167,10 @@ fn op_receive( assert!(zero_copy.is_some()); let args: ReceiveArgs = serde_json::from_value(args)?; match args.transport.as_str() { - "udp" => receive_udp(isolate, state, args, zero_copy), + "udp" => receive_udp(isolate_state, state, args, zero_copy), #[cfg(unix)] "unixpacket" => { - net_unix::receive_unix_packet(isolate, args.rid as u32, zero_copy) + net_unix::receive_unix_packet(isolate_state, args.rid as u32, zero_copy) } _ => Err(OpError::other(format!( "Unsupported transport protocol {}", @@ -187,14 +188,14 @@ struct SendArgs { } fn op_send( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, state: &State, args: Value, zero_copy: Option, ) -> Result { assert!(zero_copy.is_some()); let buf = zero_copy.unwrap(); - let resource_table = isolate.resource_table.clone(); + let resource_table = isolate_state.resource_table.clone(); match serde_json::from_value(args)? { SendArgs { rid, @@ -256,12 +257,12 @@ struct ConnectArgs { } fn op_connect( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, state: &State, args: Value, _zero_copy: Option, ) -> Result { - let resource_table = isolate.resource_table.clone(); + let resource_table = isolate_state.resource_table.clone(); match serde_json::from_value(args)? { ConnectArgs { transport, @@ -342,7 +343,7 @@ struct ShutdownArgs { } fn op_shutdown( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, state: &State, args: Value, _zero_copy: Option, @@ -360,7 +361,7 @@ fn op_shutdown( _ => unimplemented!(), }; - let mut resource_table = isolate.resource_table.borrow_mut(); + let mut resource_table = isolate_state.resource_table.borrow_mut(); let resource_holder = resource_table .get_mut::(rid) .ok_or_else(OpError::bad_resource_id)?; @@ -484,12 +485,12 @@ fn listen_udp( } fn op_listen( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, state: &State, args: Value, _zero_copy: Option, ) -> Result { - let mut resource_table = isolate.resource_table.borrow_mut(); + let mut resource_table = isolate_state.resource_table.borrow_mut(); match serde_json::from_value(args)? { ListenArgs { transport, diff --git a/cli/ops/net_unix.rs b/cli/ops/net_unix.rs index 4b09c2fdb2..a207eaba89 100644 --- a/cli/ops/net_unix.rs +++ b/cli/ops/net_unix.rs @@ -1,7 +1,7 @@ use super::dispatch_json::{Deserialize, JsonOp}; use super::io::{StreamResource, StreamResourceHolder}; use crate::op_error::OpError; -use deno_core::CoreIsolate; +use deno_core::CoreIsolateState; use deno_core::ResourceTable; use deno_core::ZeroCopyBuf; use futures::future::FutureExt; @@ -27,11 +27,11 @@ pub struct UnixListenArgs { } pub fn accept_unix( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, rid: u32, _zero_copy: Option, ) -> Result { - let resource_table = isolate.resource_table.clone(); + let resource_table = isolate_state.resource_table.clone(); { let _ = resource_table .borrow() @@ -78,12 +78,12 @@ pub fn accept_unix( } pub fn receive_unix_packet( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, rid: u32, zero_copy: Option, ) -> Result { let mut buf = zero_copy.unwrap(); - let resource_table = isolate.resource_table.clone(); + let resource_table = isolate_state.resource_table.clone(); let op = async move { let mut resource_table_ = resource_table.borrow_mut(); diff --git a/cli/ops/plugin.rs b/cli/ops/plugin.rs index f55c91df84..fde34ea58b 100644 --- a/cli/ops/plugin.rs +++ b/cli/ops/plugin.rs @@ -7,6 +7,7 @@ use crate::ops::json_op; use crate::state::State; use deno_core::plugin_api; use deno_core::CoreIsolate; +use deno_core::CoreIsolateState; use deno_core::Op; use deno_core::OpAsyncFuture; use deno_core::OpId; @@ -33,7 +34,7 @@ struct OpenPluginArgs { } pub fn op_open_plugin( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, state: &State, args: Value, _zero_copy: Option, @@ -50,7 +51,7 @@ pub fn op_open_plugin( .map_err(OpError::from)?; let plugin_resource = PluginResource::new(&plugin_lib); - let mut resource_table = isolate.resource_table.borrow_mut(); + let mut resource_table = isolate_state.resource_table.borrow_mut(); let rid = resource_table.add("plugin", Box::new(plugin_resource)); let plugin_resource = resource_table.get::(rid).unwrap(); @@ -62,7 +63,7 @@ pub fn op_open_plugin( .unwrap(); drop(resource_table); - let mut interface = PluginInterface::new(isolate, &plugin_lib); + let mut interface = PluginInterface::new(isolate_state, &plugin_lib); deno_plugin_init(&mut interface); Ok(JsonOp::Sync(json!(rid))) @@ -79,14 +80,17 @@ impl PluginResource { } struct PluginInterface<'a> { - isolate: &'a mut CoreIsolate, + isolate_state: &'a mut CoreIsolateState, plugin_lib: &'a Rc, } impl<'a> PluginInterface<'a> { - fn new(isolate: &'a mut CoreIsolate, plugin_lib: &'a Rc) -> Self { + fn new( + isolate_state: &'a mut CoreIsolateState, + plugin_lib: &'a Rc, + ) -> Self { Self { - isolate, + isolate_state, plugin_lib, } } @@ -104,10 +108,10 @@ impl<'a> plugin_api::Interface for PluginInterface<'a> { dispatch_op_fn: plugin_api::DispatchOpFn, ) -> OpId { let plugin_lib = self.plugin_lib.clone(); - self.isolate.op_registry.register( + self.isolate_state.op_registry.register( name, - move |isolate, control, zero_copy| { - let mut interface = PluginInterface::new(isolate, &plugin_lib); + move |isolate_state, control, zero_copy| { + let mut interface = PluginInterface::new(isolate_state, &plugin_lib); let op = dispatch_op_fn(&mut interface, control, zero_copy); match op { sync_op @ Op::Sync(..) => sync_op, diff --git a/cli/ops/process.rs b/cli/ops/process.rs index 125aa136b4..eefabd49fd 100644 --- a/cli/ops/process.rs +++ b/cli/ops/process.rs @@ -5,6 +5,7 @@ use crate::op_error::OpError; use crate::signal::kill; use crate::state::State; use deno_core::CoreIsolate; +use deno_core::CoreIsolateState; use deno_core::ResourceTable; use deno_core::ZeroCopyBuf; use futures::future::poll_fn; @@ -60,7 +61,7 @@ struct ChildResource { } fn op_run( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, state: &State, args: Value, _zero_copy: Option, @@ -68,7 +69,7 @@ fn op_run( let run_args: RunArgs = serde_json::from_value(args)?; state.check_run()?; - let mut resource_table = isolate.resource_table.borrow_mut(); + let mut resource_table = isolate_state.resource_table.borrow_mut(); let args = run_args.cmd; let env = run_args.env; @@ -174,7 +175,7 @@ struct RunStatusArgs { } fn op_run_status( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, state: &State, args: Value, _zero_copy: Option, @@ -183,7 +184,7 @@ fn op_run_status( let rid = args.rid as u32; state.check_run()?; - let resource_table = isolate.resource_table.clone(); + let resource_table = isolate_state.resource_table.clone(); let future = async move { let run_status = poll_fn(|cx| { diff --git a/cli/ops/repl.rs b/cli/ops/repl.rs index 7dc0d0263d..40bc9653ee 100644 --- a/cli/ops/repl.rs +++ b/cli/ops/repl.rs @@ -5,6 +5,7 @@ use crate::repl; use crate::repl::Repl; use crate::state::State; use deno_core::CoreIsolate; +use deno_core::CoreIsolateState; use deno_core::ZeroCopyBuf; use std::sync::Arc; use std::sync::Mutex; @@ -23,7 +24,7 @@ struct ReplStartArgs { } fn op_repl_start( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, state: &State, args: Value, _zero_copy: Option, @@ -34,7 +35,7 @@ fn op_repl_start( repl::history_path(&state.borrow().global_state.dir, &args.history_file); let repl = repl::Repl::new(history_path); let resource = ReplResource(Arc::new(Mutex::new(repl))); - let mut resource_table = isolate.resource_table.borrow_mut(); + let mut resource_table = isolate_state.resource_table.borrow_mut(); let rid = resource_table.add("repl", Box::new(resource)); Ok(JsonOp::Sync(json!(rid))) } @@ -46,7 +47,7 @@ struct ReplReadlineArgs { } fn op_repl_readline( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, _state: &State, args: Value, _zero_copy: Option, @@ -55,7 +56,7 @@ fn op_repl_readline( let rid = args.rid as u32; let prompt = args.prompt; debug!("op_repl_readline {} {}", rid, prompt); - let resource_table = isolate.resource_table.borrow(); + let resource_table = isolate_state.resource_table.borrow(); let resource = resource_table .get::(rid) .ok_or_else(OpError::bad_resource_id)?; diff --git a/cli/ops/resources.rs b/cli/ops/resources.rs index 1aa8dd4dc2..be09598a9f 100644 --- a/cli/ops/resources.rs +++ b/cli/ops/resources.rs @@ -3,6 +3,7 @@ use super::dispatch_json::{Deserialize, JsonOp, Value}; use crate::op_error::OpError; use crate::state::State; use deno_core::CoreIsolate; +use deno_core::CoreIsolateState; use deno_core::ZeroCopyBuf; pub fn init(i: &mut CoreIsolate, s: &State) { @@ -11,18 +12,18 @@ pub fn init(i: &mut CoreIsolate, s: &State) { } fn op_resources( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, _state: &State, _args: Value, _zero_copy: Option, ) -> Result { - let serialized_resources = isolate.resource_table.borrow().entries(); + let serialized_resources = isolate_state.resource_table.borrow().entries(); Ok(JsonOp::Sync(json!(serialized_resources))) } /// op_close removes a resource from the resource table. fn op_close( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, _state: &State, args: Value, _zero_copy: Option, @@ -32,7 +33,7 @@ fn op_close( rid: i32, } let args: CloseArgs = serde_json::from_value(args)?; - let mut resource_table = isolate.resource_table.borrow_mut(); + let mut resource_table = isolate_state.resource_table.borrow_mut(); resource_table .close(args.rid as u32) .ok_or_else(OpError::bad_resource_id)?; diff --git a/cli/ops/signal.rs b/cli/ops/signal.rs index ef652bc671..7a0c29ab01 100644 --- a/cli/ops/signal.rs +++ b/cli/ops/signal.rs @@ -3,6 +3,7 @@ use super::dispatch_json::{JsonOp, Value}; use crate::op_error::OpError; use crate::state::State; use deno_core::CoreIsolate; +use deno_core::CoreIsolateState; use deno_core::ZeroCopyBuf; #[cfg(unix)] @@ -39,14 +40,14 @@ struct SignalArgs { #[cfg(unix)] fn op_signal_bind( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, state: &State, args: Value, _zero_copy: Option, ) -> Result { state.check_unstable("Deno.signal"); let args: BindSignalArgs = serde_json::from_value(args)?; - let mut resource_table = isolate.resource_table.borrow_mut(); + let mut resource_table = isolate_state.resource_table.borrow_mut(); let rid = resource_table.add( "signal", Box::new(SignalStreamResource( @@ -61,7 +62,7 @@ fn op_signal_bind( #[cfg(unix)] fn op_signal_poll( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, state: &State, args: Value, _zero_copy: Option, @@ -69,7 +70,7 @@ fn op_signal_poll( state.check_unstable("Deno.signal"); let args: SignalArgs = serde_json::from_value(args)?; let rid = args.rid as u32; - let resource_table = isolate.resource_table.clone(); + let resource_table = isolate_state.resource_table.clone(); let future = poll_fn(move |cx| { let mut resource_table = resource_table.borrow_mut(); @@ -88,7 +89,7 @@ fn op_signal_poll( #[cfg(unix)] pub fn op_signal_unbind( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, state: &State, args: Value, _zero_copy: Option, @@ -96,7 +97,7 @@ pub fn op_signal_unbind( state.check_unstable("Deno.signal"); let args: SignalArgs = serde_json::from_value(args)?; let rid = args.rid as u32; - let mut resource_table = isolate.resource_table.borrow_mut(); + let mut resource_table = isolate_state.resource_table.borrow_mut(); let resource = resource_table.get::(rid); if let Some(signal) = resource { if let Some(waker) = &signal.1 { @@ -113,7 +114,7 @@ pub fn op_signal_unbind( #[cfg(not(unix))] pub fn op_signal_bind( - _isolate: &mut CoreIsolate, + _isolate_state: &mut CoreIsolateState, _state: &State, _args: Value, _zero_copy: Option, @@ -123,7 +124,7 @@ pub fn op_signal_bind( #[cfg(not(unix))] fn op_signal_unbind( - _isolate: &mut CoreIsolate, + _isolate_state: &mut CoreIsolateState, _state: &State, _args: Value, _zero_copy: Option, @@ -133,7 +134,7 @@ fn op_signal_unbind( #[cfg(not(unix))] fn op_signal_poll( - _isolate: &mut CoreIsolate, + _isolate_state: &mut CoreIsolateState, _state: &State, _args: Value, _zero_copy: Option, diff --git a/cli/ops/tls.rs b/cli/ops/tls.rs index 5cbdff3007..d4252d9ca1 100644 --- a/cli/ops/tls.rs +++ b/cli/ops/tls.rs @@ -5,6 +5,7 @@ use crate::op_error::OpError; use crate::resolve_addr::resolve_addr; use crate::state::State; use deno_core::CoreIsolate; +use deno_core::CoreIsolateState; use deno_core::ZeroCopyBuf; use futures::future::poll_fn; use futures::future::FutureExt; @@ -53,7 +54,7 @@ struct StartTLSArgs { } pub fn op_start_tls( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, state: &State, args: Value, _zero_copy: Option, @@ -62,7 +63,7 @@ pub fn op_start_tls( let args: StartTLSArgs = serde_json::from_value(args)?; let rid = args.rid as u32; let cert_file = args.cert_file.clone(); - let resource_table = isolate.resource_table.clone(); + let resource_table = isolate_state.resource_table.clone(); let mut domain = args.hostname; if domain.is_empty() { @@ -132,14 +133,14 @@ pub fn op_start_tls( } pub fn op_connect_tls( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, state: &State, args: Value, _zero_copy: Option, ) -> Result { let args: ConnectTLSArgs = serde_json::from_value(args)?; let cert_file = args.cert_file.clone(); - let resource_table = isolate.resource_table.clone(); + let resource_table = isolate_state.resource_table.clone(); state.check_net(&args.hostname, args.port)?; if let Some(path) = cert_file.clone() { state.check_read(Path::new(&path))?; @@ -306,7 +307,7 @@ struct ListenTlsArgs { } fn op_listen_tls( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, state: &State, args: Value, _zero_copy: Option, @@ -337,7 +338,7 @@ fn op_listen_tls( local_addr, }; - let mut resource_table = isolate.resource_table.borrow_mut(); + let mut resource_table = isolate_state.resource_table.borrow_mut(); let rid = resource_table.add("tlsListener", Box::new(tls_listener_resource)); Ok(JsonOp::Sync(json!({ @@ -356,14 +357,14 @@ struct AcceptTlsArgs { } fn op_accept_tls( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, _state: &State, args: Value, _zero_copy: Option, ) -> Result { let args: AcceptTlsArgs = serde_json::from_value(args)?; let rid = args.rid as u32; - let resource_table = isolate.resource_table.clone(); + let resource_table = isolate_state.resource_table.clone(); let op = async move { let accept_fut = poll_fn(|cx| { let mut resource_table = resource_table.borrow_mut(); diff --git a/cli/ops/tty.rs b/cli/ops/tty.rs index cf7f62ed88..00a5870e95 100644 --- a/cli/ops/tty.rs +++ b/cli/ops/tty.rs @@ -4,6 +4,7 @@ use super::io::{StreamResource, StreamResourceHolder}; use crate::op_error::OpError; use crate::state::State; use deno_core::CoreIsolate; +use deno_core::CoreIsolateState; use deno_core::ZeroCopyBuf; #[cfg(unix)] use nix::sys::termios; @@ -46,7 +47,7 @@ struct SetRawArgs { } pub fn op_set_raw( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, state: &State, args: Value, _zero_copy: Option, @@ -67,7 +68,7 @@ pub fn op_set_raw( use winapi::shared::minwindef::FALSE; use winapi::um::{consoleapi, handleapi}; - let mut resource_table = isolate.resource_table.borrow_mut(); + let mut resource_table = isolate_state.resource_table.borrow_mut(); let resource_holder = resource_table.get_mut::(rid); if resource_holder.is_none() { return Err(OpError::bad_resource_id()); @@ -133,7 +134,7 @@ pub fn op_set_raw( { use std::os::unix::io::AsRawFd; - let mut resource_table = isolate.resource_table.borrow_mut(); + let mut resource_table = isolate_state.resource_table.borrow_mut(); let resource_holder = resource_table.get_mut::(rid); if resource_holder.is_none() { return Err(OpError::bad_resource_id()); @@ -215,7 +216,7 @@ struct IsattyArgs { } pub fn op_isatty( - isolate: &mut CoreIsolate, + isolate_state: &mut CoreIsolateState, _state: &State, args: Value, _zero_copy: Option, @@ -223,7 +224,7 @@ pub fn op_isatty( let args: IsattyArgs = serde_json::from_value(args)?; let rid = args.rid; - let mut resource_table = isolate.resource_table.borrow_mut(); + let mut resource_table = isolate_state.resource_table.borrow_mut(); let isatty: bool = std_file_resource(&mut resource_table, rid as u32, move |r| match r { Ok(std_file) => { diff --git a/cli/ops/web_worker.rs b/cli/ops/web_worker.rs index e95eb8fe11..d2d202e91c 100644 --- a/cli/ops/web_worker.rs +++ b/cli/ops/web_worker.rs @@ -6,6 +6,7 @@ use crate::state::State; use crate::web_worker::WebWorkerHandle; use crate::worker::WorkerEvent; use deno_core::CoreIsolate; +use deno_core::CoreIsolateState; use deno_core::ZeroCopyBuf; use futures::channel::mpsc; use std::convert::From; @@ -13,7 +14,11 @@ use std::convert::From; pub fn web_worker_op( sender: mpsc::Sender, dispatcher: D, -) -> impl Fn(&mut CoreIsolate, Value, Option) -> Result +) -> impl Fn( + &mut CoreIsolateState, + Value, + Option, +) -> Result where D: Fn( &mpsc::Sender, @@ -21,7 +26,7 @@ where Option, ) -> Result, { - move |_isolate: &mut CoreIsolate, + move |_isolate_state: &mut CoreIsolateState, args: Value, zero_copy: Option| -> Result { dispatcher(&sender, args, zero_copy) } @@ -31,7 +36,11 @@ pub fn web_worker_op2( handle: WebWorkerHandle, sender: mpsc::Sender, dispatcher: D, -) -> impl Fn(&mut CoreIsolate, Value, Option) -> Result +) -> impl Fn( + &mut CoreIsolateState, + Value, + Option, +) -> Result where D: Fn( WebWorkerHandle, @@ -40,7 +49,7 @@ where Option, ) -> Result, { - move |_isolate: &mut CoreIsolate, + move |_isolate_state: &mut CoreIsolateState, args: Value, zero_copy: Option| -> Result { diff --git a/cli/ops/worker_host.rs b/cli/ops/worker_host.rs index d1b4bb80f1..ad3752ffab 100644 --- a/cli/ops/worker_host.rs +++ b/cli/ops/worker_host.rs @@ -54,7 +54,9 @@ fn create_web_worker( ); if has_deno_namespace { - let mut resource_table = worker.resource_table.borrow_mut(); + let state_rc = CoreIsolate::state(&worker.isolate); + let state = state_rc.borrow(); + let mut resource_table = state.resource_table.borrow_mut(); let (stdin, stdout, stderr) = get_stdio(); resource_table.add("stdin", Box::new(stdin)); resource_table.add("stdout", Box::new(stdout)); diff --git a/cli/state.rs b/cli/state.rs index a15d113c84..77a268fab3 100644 --- a/cli/state.rs +++ b/cli/state.rs @@ -65,7 +65,7 @@ impl State { pub fn stateful_json_op( &self, dispatcher: D, - ) -> impl Fn(&mut deno_core::CoreIsolate, &[u8], Option) -> Op + ) -> impl Fn(&mut deno_core::CoreIsolateState, &[u8], Option) -> Op where D: Fn(&State, Value, Option) -> Result, { @@ -76,10 +76,10 @@ impl State { pub fn stateful_json_op2( &self, dispatcher: D, - ) -> impl Fn(&mut deno_core::CoreIsolate, &[u8], Option) -> Op + ) -> impl Fn(&mut deno_core::CoreIsolateState, &[u8], Option) -> Op where D: Fn( - &mut deno_core::CoreIsolate, + &mut deno_core::CoreIsolateState, &State, Value, Option, @@ -95,13 +95,13 @@ impl State { pub fn core_op( &self, dispatcher: D, - ) -> impl Fn(&mut deno_core::CoreIsolate, &[u8], Option) -> Op + ) -> impl Fn(&mut deno_core::CoreIsolateState, &[u8], Option) -> Op where - D: Fn(&mut deno_core::CoreIsolate, &[u8], Option) -> Op, + D: Fn(&mut deno_core::CoreIsolateState, &[u8], Option) -> Op, { let state = self.clone(); - move |isolate: &mut deno_core::CoreIsolate, + move |isolate_state: &mut deno_core::CoreIsolateState, control: &[u8], zero_copy: Option| -> Op { @@ -109,7 +109,7 @@ impl State { let bytes_sent_zero_copy = zero_copy.as_ref().map(|b| b.len()).unwrap_or(0) as u64; - let op = dispatcher(isolate, control, zero_copy); + let op = dispatcher(isolate_state, control, zero_copy); match op { Op::Sync(buf) => { @@ -155,10 +155,10 @@ impl State { pub fn stateful_minimal_op2( &self, dispatcher: D, - ) -> impl Fn(&mut deno_core::CoreIsolate, &[u8], Option) -> Op + ) -> impl Fn(&mut deno_core::CoreIsolateState, &[u8], Option) -> Op where D: Fn( - &mut deno_core::CoreIsolate, + &mut deno_core::CoreIsolateState, &State, bool, i32, @@ -167,12 +167,12 @@ impl State { { let state = self.clone(); self.core_op(crate::ops::minimal_op( - move |isolate: &mut deno_core::CoreIsolate, + move |isolate_state: &mut deno_core::CoreIsolateState, is_sync: bool, rid: i32, zero_copy: Option| -> MinimalOp { - dispatcher(isolate, &state, is_sync, rid, zero_copy) + dispatcher(isolate_state, &state, is_sync, rid, zero_copy) }, )) } @@ -186,7 +186,7 @@ impl State { &self, dispatcher: D, ) -> impl Fn( - &mut deno_core::CoreIsolate, + &mut deno_core::CoreIsolateState, Value, Option, ) -> Result @@ -194,7 +194,7 @@ impl State { D: Fn(&State, Value, Option) -> Result, { let state = self.clone(); - move |_isolate: &mut deno_core::CoreIsolate, + move |_isolate_state: &mut deno_core::CoreIsolateState, args: Value, zero_copy: Option| -> Result { dispatcher(&state, args, zero_copy) } @@ -204,24 +204,24 @@ impl State { &self, dispatcher: D, ) -> impl Fn( - &mut deno_core::CoreIsolate, + &mut deno_core::CoreIsolateState, Value, Option, ) -> Result where D: Fn( - &mut deno_core::CoreIsolate, + &mut deno_core::CoreIsolateState, &State, Value, Option, ) -> Result, { let state = self.clone(); - move |isolate: &mut deno_core::CoreIsolate, + move |isolate_state: &mut deno_core::CoreIsolateState, args: Value, zero_copy: Option| -> Result { - dispatcher(isolate, &state, args, zero_copy) + dispatcher(isolate_state, &state, args, zero_copy) } } diff --git a/cli/web_worker.rs b/cli/web_worker.rs index 46f03da363..e060a157d6 100644 --- a/cli/web_worker.rs +++ b/cli/web_worker.rs @@ -91,12 +91,7 @@ impl WebWorker { let mut worker = Worker::new(name, startup_data, state_); let terminated = Arc::new(AtomicBool::new(false)); - let isolate_handle = worker - .isolate - .v8_isolate - .as_mut() - .unwrap() - .thread_safe_handle(); + let isolate_handle = worker.isolate.thread_safe_handle(); let (terminate_tx, terminate_rx) = mpsc::channel::<()>(1); let handle = WebWorkerHandle { diff --git a/cli/worker.rs b/cli/worker.rs index 3e338d933a..524091422d 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -4,6 +4,7 @@ use crate::inspector::DenoInspector; use crate::ops; use crate::state::State; use deno_core::Buf; +use deno_core::CoreIsolate; use deno_core::ErrBox; use deno_core::ModuleId; use deno_core::ModuleSpecifier; @@ -86,7 +87,7 @@ fn create_channels() -> (WorkerChannelsInternal, WorkerHandle) { /// - `WebWorker` pub struct Worker { pub name: String, - pub isolate: Box, + pub isolate: deno_core::EsIsolate, pub inspector: Option>, pub state: State, pub waker: AtomicWaker, @@ -101,7 +102,9 @@ impl Worker { { let global_state = state.borrow().global_state.clone(); - isolate.set_js_error_create_fn(move |core_js_error| { + let core_state_rc = CoreIsolate::state(&isolate); + let mut core_state = core_state_rc.borrow_mut(); + core_state.set_js_error_create_fn(move |core_js_error| { JSError::create(core_js_error, &global_state.ts_compiler) }); } diff --git a/core/bindings.rs b/core/bindings.rs index 22f6767e85..7bcb99a382 100644 --- a/core/bindings.rs +++ b/core/bindings.rs @@ -250,9 +250,6 @@ pub extern "C" fn host_import_module_dynamically_callback( let mut cbs = v8::CallbackScope::new_escapable(context); let mut hs = v8::EscapableHandleScope::new(cbs.enter()); let scope = hs.enter(); - let isolate = scope.isolate(); - let core_isolate: &mut EsIsolate = - unsafe { &mut *(isolate.get_data(1) as *mut EsIsolate) }; // NOTE(bartlomieju): will crash for non-UTF-8 specifier let specifier_str = specifier @@ -277,11 +274,11 @@ pub extern "C" fn host_import_module_dynamically_callback( let mut resolver_handle = v8::Global::new(); resolver_handle.set(scope, resolver); - core_isolate.dyn_import_cb( - resolver_handle, - &specifier_str, - &referrer_name_str, - ); + { + let state_rc = EsIsolate::state(scope.isolate()); + let mut state = state_rc.borrow_mut(); + state.dyn_import_cb(resolver_handle, &specifier_str, &referrer_name_str); + } &mut *scope.escape(promise) } @@ -294,14 +291,13 @@ pub extern "C" fn host_initialize_import_meta_object_callback( let mut cbs = v8::CallbackScope::new(context); let mut hs = v8::HandleScope::new(cbs.enter()); let scope = hs.enter(); - let isolate = scope.isolate(); - let core_isolate: &mut EsIsolate = - unsafe { &mut *(isolate.get_data(1) as *mut EsIsolate) }; + let state_rc = EsIsolate::state(scope.isolate()); + let state = state_rc.borrow(); let id = module.get_identity_hash(); assert_ne!(id, 0); - let info = core_isolate.modules.get_info(id).expect("Module not found"); + let info = state.modules.get_info(id).expect("Module not found"); meta.create_data_property( context, @@ -320,10 +316,10 @@ pub extern "C" fn promise_reject_callback(message: v8::PromiseRejectMessage) { let mut hs = v8::HandleScope::new(cbs.enter()); let scope = hs.enter(); - let core_isolate: &mut CoreIsolate = - unsafe { &mut *(scope.isolate().get_data(0) as *mut CoreIsolate) }; + let state_rc = CoreIsolate::state(scope.isolate()); + let mut state = state_rc.borrow_mut(); - let context = core_isolate.global_context.get(scope).unwrap(); + let context = state.global_context.get(scope).unwrap(); let mut cs = v8::ContextScope::new(scope, context); let scope = cs.enter(); @@ -335,13 +331,13 @@ pub extern "C" fn promise_reject_callback(message: v8::PromiseRejectMessage) { let error = message.get_value(); let mut error_global = v8::Global::::new(); error_global.set(scope, error); - core_isolate + state .pending_promise_exceptions .insert(promise_id, error_global); } v8::PromiseRejectEvent::PromiseHandlerAddedAfterReject => { if let Some(mut handle) = - core_isolate.pending_promise_exceptions.remove(&promise_id) + state.pending_promise_exceptions.remove(&promise_id) { handle.reset(scope); } @@ -415,17 +411,17 @@ fn recv( args: v8::FunctionCallbackArguments, _rv: v8::ReturnValue, ) { - let core_isolate: &mut CoreIsolate = - unsafe { &mut *(scope.isolate().get_data(0) as *mut CoreIsolate) }; + let state_rc = CoreIsolate::state(scope.isolate()); + let mut state = state_rc.borrow_mut(); - if !core_isolate.js_recv_cb.is_empty() { + if !state.js_recv_cb.is_empty() { let msg = v8::String::new(scope, "Deno.core.recv already called.").unwrap(); scope.isolate().throw_exception(msg.into()); return; } let recv_fn = v8::Local::::try_from(args.get(0)).unwrap(); - core_isolate.js_recv_cb.set(scope, recv_fn); + state.js_recv_cb.set(scope, recv_fn); } fn send( @@ -433,10 +429,6 @@ fn send( args: v8::FunctionCallbackArguments, mut rv: v8::ReturnValue, ) { - let core_isolate: &mut CoreIsolate = - unsafe { &mut *(scope.isolate().get_data(0) as *mut CoreIsolate) }; - assert!(!core_isolate.global_context.is_empty()); - let op_id = match v8::Local::::try_from(args.get(0)) { Ok(op_id) => op_id.value() as u32, Err(err) => { @@ -465,9 +457,12 @@ fn send( .map(ZeroCopyBuf::new) .ok(); + let state_rc = CoreIsolate::state(scope.isolate()); + let mut state = state_rc.borrow_mut(); + assert!(!state.global_context.is_empty()); + // If response is empty then it's either async op or exception was thrown - let maybe_response = - core_isolate.dispatch_op(scope, op_id, control, zero_copy); + let maybe_response = state.dispatch_op(scope, op_id, control, zero_copy); if let Some(response) = maybe_response { // Synchronous response. @@ -476,7 +471,7 @@ fn send( if !buf.is_empty() { let ui8 = boxed_slice_to_uint8array(scope, buf); - rv.set(ui8.into()) + rv.set(ui8.into()); } } } @@ -486,10 +481,10 @@ fn set_macrotask_callback( args: v8::FunctionCallbackArguments, _rv: v8::ReturnValue, ) { - let core_isolate: &mut CoreIsolate = - unsafe { &mut *(scope.isolate().get_data(0) as *mut CoreIsolate) }; + let state_rc = CoreIsolate::state(scope.isolate()); + let mut state = state_rc.borrow_mut(); - if !core_isolate.js_macrotask_cb.is_empty() { + if !state.js_macrotask_cb.is_empty() { let msg = v8::String::new(scope, "Deno.core.setMacrotaskCallback already called.") .unwrap(); @@ -499,7 +494,7 @@ fn set_macrotask_callback( let macrotask_cb_fn = v8::Local::::try_from(args.get(0)).unwrap(); - core_isolate.js_macrotask_cb.set(scope, macrotask_cb_fn); + state.js_macrotask_cb.set(scope, macrotask_cb_fn); } fn eval_context( @@ -507,10 +502,10 @@ fn eval_context( args: v8::FunctionCallbackArguments, mut rv: v8::ReturnValue, ) { - let core_isolate: &mut CoreIsolate = - unsafe { &mut *(scope.isolate().get_data(0) as *mut CoreIsolate) }; - assert!(!core_isolate.global_context.is_empty()); - let context = core_isolate.global_context.get(scope).unwrap(); + let state_rc = CoreIsolate::state(scope.isolate()); + let state = state_rc.borrow(); + assert!(!state.global_context.is_empty()); + let context = state.global_context.get(scope).unwrap(); let source = match v8::Local::::try_from(args.get(0)) { Ok(s) => s, @@ -643,10 +638,10 @@ fn format_error( args: v8::FunctionCallbackArguments, mut rv: v8::ReturnValue, ) { - let core_isolate: &mut CoreIsolate = - unsafe { &mut *(scope.isolate().get_data(0) as *mut CoreIsolate) }; let e = JSError::from_v8_exception(scope, args.get(0)); - let e = (core_isolate.js_error_create_fn)(e); + let state_rc = CoreIsolate::state(scope.isolate()); + let state = state_rc.borrow(); + let e = (state.js_error_create_fn)(e); let e = e.to_string(); let e = v8::String::new(scope, &e).unwrap(); rv.set(e.into()) @@ -734,19 +729,19 @@ fn shared_getter( _args: v8::PropertyCallbackArguments, mut rv: v8::ReturnValue, ) { - let core_isolate: &mut CoreIsolate = - unsafe { &mut *(scope.isolate().get_data(0) as *mut CoreIsolate) }; + let state_rc = CoreIsolate::state(scope.isolate()); + let mut state = state_rc.borrow_mut(); // Lazily initialize the persistent external ArrayBuffer. - if core_isolate.shared_ab.is_empty() { + if state.shared_ab.is_empty() { let ab = v8::SharedArrayBuffer::with_backing_store( scope, - core_isolate.shared.get_backing_store(), + state.shared.get_backing_store(), ); - core_isolate.shared_ab.set(scope, ab); + state.shared_ab.set(scope, ab); } - let shared_ab = core_isolate.shared_ab.get(scope).unwrap(); + let shared_ab = state.shared_ab.get(scope).unwrap(); rv.set(shared_ab.into()); } @@ -759,11 +754,11 @@ pub fn module_resolve_callback<'s>( let mut scope = v8::EscapableHandleScope::new(scope.enter()); let scope = scope.enter(); - let core_isolate: &mut EsIsolate = - unsafe { &mut *(scope.isolate().get_data(1) as *mut EsIsolate) }; + let state_rc = EsIsolate::state(scope.isolate()); + let mut state = state_rc.borrow_mut(); let referrer_id = referrer.get_identity_hash(); - let referrer_name = core_isolate + let referrer_name = state .modules .get_info(referrer_id) .expect("ModuleInfo not found") @@ -778,8 +773,8 @@ pub fn module_resolve_callback<'s>( let req_str = req.to_rust_string_lossy(scope); if req_str == specifier_str { - let id = core_isolate.module_resolve_cb(&req_str, referrer_id); - let maybe_info = core_isolate.modules.get_info(id); + let id = state.module_resolve_cb(&req_str, referrer_id); + let maybe_info = state.modules.get_info(id); if maybe_info.is_none() { let msg = format!( @@ -810,10 +805,10 @@ fn get_promise_details( args: v8::FunctionCallbackArguments, mut rv: v8::ReturnValue, ) { - let core_isolate: &mut CoreIsolate = - unsafe { &mut *(scope.isolate().get_data(0) as *mut CoreIsolate) }; - assert!(!core_isolate.global_context.is_empty()); - let context = core_isolate.global_context.get(scope).unwrap(); + let state_rc = CoreIsolate::state(scope.isolate()); + let state = state_rc.borrow(); + assert!(!state.global_context.is_empty()); + let context = state.global_context.get(scope).unwrap(); let promise = match v8::Local::::try_from(args.get(0)) { Ok(val) => val, diff --git a/core/core_isolate.rs b/core/core_isolate.rs index 12495e2d22..dff887ab35 100644 --- a/core/core_isolate.rs +++ b/core/core_isolate.rs @@ -16,20 +16,20 @@ use crate::JSError; use crate::ResourceTable; use crate::ZeroCopyBuf; use futures::future::FutureExt; -use futures::stream::select; use futures::stream::FuturesUnordered; use futures::stream::StreamExt; use futures::task::AtomicWaker; use futures::Future; -use libc::c_void; use std::cell::RefCell; use std::collections::HashMap; use std::convert::From; use std::mem::forget; +use std::ops::Deref; +use std::ops::DerefMut; use std::option::Option; use std::pin::Pin; use std::rc::Rc; -use std::sync::{Arc, Mutex, Once}; +use std::sync::Once; use std::task::Context; use std::task::Poll; @@ -72,7 +72,6 @@ pub enum StartupData<'a> { } type JSErrorCreateFn = dyn Fn(JSError) -> ErrBox; -type IsolateErrorHandleFn = dyn FnMut(ErrBox) -> Result<(), ErrBox>; /// A single execution context of JavaScript. Corresponds roughly to the "Web /// Worker" concept in the DOM. An CoreIsolate is a Future that can be used with @@ -82,28 +81,53 @@ type IsolateErrorHandleFn = dyn FnMut(ErrBox) -> Result<(), ErrBox>; /// Ops are created in JavaScript by calling Deno.core.dispatch(), and in Rust /// by implementing dispatcher function that takes control buffer and optional zero copy buffer /// as arguments. An async Op corresponds exactly to a Promise in JavaScript. -#[allow(unused)] pub struct CoreIsolate { - pub v8_isolate: Option, + // This is an Option instead of just OwnedIsolate to workaround + // an safety issue with SnapshotCreator. See CoreIsolate::drop. + v8_isolate: Option, snapshot_creator: Option, has_snapshotted: bool, + needs_init: bool, + startup_script: Option, +} + +/// Internal state for CoreIsolate which is stored in one of v8::Isolate's +/// embedder slots. +pub struct CoreIsolateState { pub resource_table: Rc>, pub global_context: v8::Global, pub(crate) shared_ab: v8::Global, pub(crate) js_recv_cb: v8::Global, pub(crate) js_macrotask_cb: v8::Global, pub(crate) pending_promise_exceptions: HashMap>, - shared_isolate_handle: Arc>>, pub(crate) js_error_create_fn: Box, - needs_init: bool, pub(crate) shared: SharedQueue, pending_ops: FuturesUnordered, pending_unref_ops: FuturesUnordered, have_unpolled_ops: bool, - startup_script: Option, pub op_registry: OpRegistry, waker: AtomicWaker, - error_handler: Option>, +} + +// TODO(ry) The trait v8::InIsolate is superfluous. HandleScope::new should just +// take &mut v8::Isolate. +impl v8::InIsolate for CoreIsolate { + fn isolate(&mut self) -> &mut v8::Isolate { + self.v8_isolate.as_mut().unwrap() + } +} + +impl Deref for CoreIsolate { + type Target = v8::Isolate; + fn deref(&self) -> &v8::Isolate { + self.v8_isolate.as_ref().unwrap() + } +} + +impl DerefMut for CoreIsolate { + fn deref_mut(&mut self) -> &mut v8::Isolate { + self.v8_isolate.as_mut().unwrap() + } } impl Drop for CoreIsolate { @@ -128,8 +152,6 @@ impl Drop for CoreIsolate { } } -static DENO_INIT: Once = Once::new(); - #[allow(clippy::missing_safety_doc)] pub unsafe fn v8_init() { let platform = v8::new_default_platform().unwrap(); @@ -150,7 +172,8 @@ pub unsafe fn v8_init() { impl CoreIsolate { /// startup_data defines the snapshot or script used at startup to initialize /// the isolate. - pub fn new(startup_data: StartupData, will_snapshot: bool) -> Box { + pub fn new(startup_data: StartupData, will_snapshot: bool) -> Self { + static DENO_INIT: Once = Once::new(); DENO_INIT.call_once(|| { unsafe { v8_init() }; }); @@ -210,44 +233,29 @@ impl CoreIsolate { (isolate, None) }; - let shared = SharedQueue::new(RECOMMENDED_SIZE); - let needs_init = true; - - let core_isolate = Self { - v8_isolate: None, + isolate.set_slot(Rc::new(RefCell::new(CoreIsolateState { global_context, resource_table: Rc::new(RefCell::new(ResourceTable::default())), pending_promise_exceptions: HashMap::new(), shared_ab: v8::Global::::new(), js_recv_cb: v8::Global::::new(), js_macrotask_cb: v8::Global::::new(), - snapshot_creator: maybe_snapshot_creator, - has_snapshotted: false, - shared_isolate_handle: Arc::new(Mutex::new(None)), js_error_create_fn: Box::new(JSError::create), - shared, - needs_init, + shared: SharedQueue::new(RECOMMENDED_SIZE), pending_ops: FuturesUnordered::new(), pending_unref_ops: FuturesUnordered::new(), have_unpolled_ops: false, - startup_script, op_registry: OpRegistry::new(), waker: AtomicWaker::new(), - error_handler: None, - }; + }))); - let mut boxed_isolate = Box::new(core_isolate); - { - let core_isolate_ptr: *mut Self = Box::into_raw(boxed_isolate); - unsafe { isolate.set_data(0, core_isolate_ptr as *mut c_void) }; - boxed_isolate = unsafe { Box::from_raw(core_isolate_ptr) }; - let shared_handle_ptr = &mut *isolate; - *boxed_isolate.shared_isolate_handle.lock().unwrap() = - Some(shared_handle_ptr); - boxed_isolate.v8_isolate = Some(isolate); + Self { + v8_isolate: Some(isolate), + snapshot_creator: maybe_snapshot_creator, + has_snapshotted: false, + needs_init: true, + startup_script, } - - boxed_isolate } fn setup_isolate(mut isolate: v8::OwnedIsolate) -> v8::OwnedIsolate { @@ -256,6 +264,101 @@ impl CoreIsolate { isolate } + pub fn state(isolate: &v8::Isolate) -> Rc> { + let s = isolate.get_slot::>>().unwrap(); + s.clone() + } + + /// Executes a bit of built-in JavaScript to provide Deno.sharedQueue. + fn shared_init(&mut self) { + if self.needs_init { + self.needs_init = false; + 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() + } + } + } + + /// Executes traditional JavaScript code (traditional = not ES modules) + /// + /// ErrBox can be downcast to a type that exposes additional information about + /// the V8 exception. By default this type is JSError, however it may be a + /// different type if CoreIsolate::set_js_error_create_fn() has been used. + pub fn execute( + &mut self, + js_filename: &str, + js_source: &str, + ) -> Result<(), ErrBox> { + self.shared_init(); + + let state_rc = Self::state(self); + let state = state_rc.borrow(); + + let mut hs = v8::HandleScope::new(self.v8_isolate.as_mut().unwrap()); + let scope = hs.enter(); + let context = state.global_context.get(scope).unwrap(); + let mut cs = v8::ContextScope::new(scope, context); + let scope = cs.enter(); + + drop(state); + + let source = v8::String::new(scope, js_source).unwrap(); + let name = v8::String::new(scope, js_filename).unwrap(); + let origin = bindings::script_origin(scope, name); + + let mut try_catch = v8::TryCatch::new(scope); + let tc = try_catch.enter(); + + let mut script = + match v8::Script::compile(scope, context, source, Some(&origin)) { + Some(script) => script, + None => { + let exception = tc.exception().unwrap(); + return exception_to_err_result(scope, exception); + } + }; + + match script.run(scope, context) { + Some(_) => Ok(()), + None => { + assert!(tc.has_caught()); + let exception = tc.exception().unwrap(); + exception_to_err_result(scope, exception) + } + } + } + + /// Takes a snapshot. The isolate should have been created with will_snapshot + /// set to true. + /// + /// ErrBox can be downcast to a type that exposes additional information about + /// the V8 exception. By default this type is JSError, however it may be a + /// different type if CoreIsolate::set_js_error_create_fn() has been used. + pub fn snapshot(&mut self) -> v8::StartupData { + assert!(self.snapshot_creator.is_some()); + let state = Self::state(self); + + // Note: create_blob() method must not be called from within a HandleScope. + // The HandleScope created here is exited at the end of the block. + // TODO(piscisaureus): The rusty_v8 type system should enforce this. + { + let v8_isolate = self.v8_isolate.as_mut().unwrap(); + let mut hs = v8::HandleScope::new(v8_isolate); + let scope = hs.enter(); + state.borrow_mut().global_context.reset(scope); + } + + let snapshot_creator = self.snapshot_creator.as_mut().unwrap(); + let snapshot = snapshot_creator + .create_blob(v8::FunctionCodeHandling::Keep) + .unwrap(); + self.has_snapshotted = true; + + snapshot + } + /// 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(). @@ -263,7 +366,125 @@ impl CoreIsolate { /// Requires runtime to explicitly ask for op ids before using any of the ops. pub fn register_op(&mut self, name: &str, op: F) -> OpId where - F: Fn(&mut CoreIsolate, &[u8], Option) -> Op + 'static, + F: Fn(&mut CoreIsolateState, &[u8], Option) -> Op + 'static, + { + let state_rc = Self::state(self); + let mut state = state_rc.borrow_mut(); + state.op_registry.register(name, op) + } +} + +impl Future for CoreIsolate { + type Output = Result<(), ErrBox>; + + fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { + let core_isolate = self.get_mut(); + core_isolate.shared_init(); + + let state_rc = Self::state(core_isolate); + { + let state = state_rc.borrow(); + state.waker.register(cx.waker()); + } + + let mut hs = v8::HandleScope::new(core_isolate); + let scope = hs.enter(); + let context = { + let state = state_rc.borrow(); + state.global_context.get(scope).unwrap() + }; + let mut cs = v8::ContextScope::new(scope, context); + let scope = cs.enter(); + + check_promise_exceptions(scope)?; + + let mut overflow_response: Option<(OpId, Buf)> = None; + + loop { + let mut state = state_rc.borrow_mut(); + // Now handle actual ops. + state.have_unpolled_ops = false; + + let pending_r = state.pending_ops.poll_next_unpin(cx); + match pending_r { + Poll::Ready(None) => break, + Poll::Pending => break, + Poll::Ready(Some((op_id, buf))) => { + let successful_push = state.shared.push(op_id, &buf); + if !successful_push { + // If we couldn't push the response to the shared queue, because + // there wasn't enough size, we will return the buffer via the + // legacy route, using the argument of deno_respond. + overflow_response = Some((op_id, buf)); + break; + } + } + }; + } + + loop { + let mut state = state_rc.borrow_mut(); + let unref_r = state.pending_unref_ops.poll_next_unpin(cx); + #[allow(clippy::match_wild_err_arm)] + match unref_r { + Poll::Ready(None) => break, + Poll::Pending => break, + Poll::Ready(Some((op_id, buf))) => { + let successful_push = state.shared.push(op_id, &buf); + if !successful_push { + // If we couldn't push the response to the shared queue, because + // there wasn't enough size, we will return the buffer via the + // legacy route, using the argument of deno_respond. + overflow_response = Some((op_id, buf)); + break; + } + } + }; + } + + { + let state = state_rc.borrow(); + if state.shared.size() > 0 { + drop(state); + async_op_response(scope, None)?; + // The other side should have shifted off all the messages. + let state = state_rc.borrow(); + assert_eq!(state.shared.size(), 0); + } + } + + { + if let Some((op_id, buf)) = overflow_response.take() { + async_op_response(scope, Some((op_id, buf)))?; + } + + drain_macrotasks(scope)?; + + check_promise_exceptions(scope)?; + } + + let state = state_rc.borrow(); + // We're idle if pending_ops is empty. + if state.pending_ops.is_empty() { + Poll::Ready(Ok(())) + } else { + if state.have_unpolled_ops { + state.waker.wake(); + } + Poll::Pending + } + } +} + +impl CoreIsolateState { + /// 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(). + /// + /// Requires runtime to explicitly ask for op ids before using any of the ops. + pub fn register_op(&mut self, name: &str, op: F) -> OpId + where + F: Fn(&mut CoreIsolateState, &[u8], Option) -> Op + 'static, { self.op_registry.register(name, op) } @@ -278,18 +499,6 @@ impl CoreIsolate { self.js_error_create_fn = Box::new(f); } - /// Executes a bit of built-in JavaScript to provide Deno.sharedQueue. - pub(crate) fn shared_init(&mut self) { - if self.needs_init { - self.needs_init = false; - 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() - } - } - } - pub fn dispatch_op<'s>( &mut self, scope: &mut impl v8::ToLocal<'s>, @@ -329,180 +538,23 @@ impl CoreIsolate { } } } - - /// Executes traditional JavaScript code (traditional = not ES modules) - /// - /// ErrBox can be downcast to a type that exposes additional information about - /// the V8 exception. By default this type is JSError, however it may be a - /// different type if CoreIsolate::set_js_error_create_fn() has been used. - pub fn execute( - &mut self, - js_filename: &str, - js_source: &str, - ) -> Result<(), ErrBox> { - self.shared_init(); - - let js_error_create_fn = &*self.js_error_create_fn; - let v8_isolate = self.v8_isolate.as_mut().unwrap(); - - let mut hs = v8::HandleScope::new(v8_isolate); - let scope = hs.enter(); - assert!(!self.global_context.is_empty()); - let context = self.global_context.get(scope).unwrap(); - let mut cs = v8::ContextScope::new(scope, context); - let scope = cs.enter(); - - let source = v8::String::new(scope, js_source).unwrap(); - let name = v8::String::new(scope, js_filename).unwrap(); - let origin = bindings::script_origin(scope, name); - - let mut try_catch = v8::TryCatch::new(scope); - let tc = try_catch.enter(); - - let mut script = - match v8::Script::compile(scope, context, source, Some(&origin)) { - Some(script) => script, - None => { - let exception = tc.exception().unwrap(); - return exception_to_err_result(scope, exception, js_error_create_fn); - } - }; - - match script.run(scope, context) { - Some(_) => Ok(()), - None => { - assert!(tc.has_caught()); - let exception = tc.exception().unwrap(); - exception_to_err_result(scope, exception, js_error_create_fn) - } - } - } - - /// Takes a snapshot. The isolate should have been created with will_snapshot - /// set to true. - /// - /// ErrBox can be downcast to a type that exposes additional information about - /// the V8 exception. By default this type is JSError, however it may be a - /// different type if CoreIsolate::set_js_error_create_fn() has been used. - pub fn snapshot(&mut self) -> v8::StartupData { - assert!(self.snapshot_creator.is_some()); - - // Note: create_blob() method must not be called from within a HandleScope. - // The HandleScope created here is exited at the end of the block. - // TODO(piscisaureus): The rusty_v8 type system should enforce this. - { - let v8_isolate = self.v8_isolate.as_mut().unwrap(); - let mut hs = v8::HandleScope::new(v8_isolate); - let scope = hs.enter(); - self.global_context.reset(scope); - } - - let snapshot_creator = self.snapshot_creator.as_mut().unwrap(); - let snapshot = snapshot_creator - .create_blob(v8::FunctionCodeHandling::Keep) - .unwrap(); - self.has_snapshotted = true; - - snapshot - } -} - -impl Future for CoreIsolate { - type Output = Result<(), ErrBox>; - - fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { - let inner = self.get_mut(); - inner.waker.register(cx.waker()); - inner.shared_init(); - - let v8_isolate = inner.v8_isolate.as_mut().unwrap(); - let js_error_create_fn = &*inner.js_error_create_fn; - let js_recv_cb = &inner.js_recv_cb; - let js_macrotask_cb = &inner.js_macrotask_cb; - let pending_promise_exceptions = &mut inner.pending_promise_exceptions; - - let mut hs = v8::HandleScope::new(v8_isolate); - let scope = hs.enter(); - let context = inner.global_context.get(scope).unwrap(); - let mut cs = v8::ContextScope::new(scope, context); - let scope = cs.enter(); - - check_promise_exceptions( - scope, - pending_promise_exceptions, - js_error_create_fn, - )?; - - let mut overflow_response: Option<(OpId, Buf)> = None; - - loop { - // Now handle actual ops. - inner.have_unpolled_ops = false; - #[allow(clippy::match_wild_err_arm)] - match select(&mut inner.pending_ops, &mut inner.pending_unref_ops) - .poll_next_unpin(cx) - { - Poll::Ready(None) => break, - Poll::Pending => break, - Poll::Ready(Some((op_id, buf))) => { - let successful_push = inner.shared.push(op_id, &buf); - if !successful_push { - // If we couldn't push the response to the shared queue, because - // there wasn't enough size, we will return the buffer via the - // legacy route, using the argument of deno_respond. - overflow_response = Some((op_id, buf)); - break; - } - } - } - } - - if inner.shared.size() > 0 { - async_op_response(scope, None, js_recv_cb, js_error_create_fn)?; - // The other side should have shifted off all the messages. - assert_eq!(inner.shared.size(), 0); - } - - if let Some((op_id, buf)) = overflow_response.take() { - async_op_response( - scope, - Some((op_id, buf)), - js_recv_cb, - js_error_create_fn, - )?; - } - - drain_macrotasks(scope, js_macrotask_cb, js_error_create_fn)?; - - check_promise_exceptions( - scope, - pending_promise_exceptions, - js_error_create_fn, - )?; - - // We're idle if pending_ops is empty. - if inner.pending_ops.is_empty() { - Poll::Ready(Ok(())) - } else { - if inner.have_unpolled_ops { - inner.waker.wake(); - } - Poll::Pending - } - } } fn async_op_response<'s>( scope: &mut impl v8::ToLocal<'s>, maybe_buf: Option<(OpId, Box<[u8]>)>, - js_recv_cb: &v8::Global, - js_error_create_fn: &JSErrorCreateFn, ) -> Result<(), ErrBox> { let context = scope.get_current_context().unwrap(); let global: v8::Local = context.global(scope).into(); - let js_recv_cb = js_recv_cb + + let state_rc = CoreIsolate::state(scope.isolate()); + let state = state_rc.borrow_mut(); + + let js_recv_cb = state + .js_recv_cb .get(scope) .expect("Deno.core.recv has not been called."); + drop(state); // TODO(piscisaureus): properly integrate TryCatch in the scope chain. let mut try_catch = v8::TryCatch::new(scope); @@ -521,20 +573,21 @@ fn async_op_response<'s>( match tc.exception() { None => Ok(()), - Some(exception) => { - exception_to_err_result(scope, exception, js_error_create_fn) - } + Some(exception) => exception_to_err_result(scope, exception), } } fn drain_macrotasks<'s>( scope: &mut impl v8::ToLocal<'s>, - js_macrotask_cb: &v8::Global, - js_error_create_fn: &JSErrorCreateFn, ) -> Result<(), ErrBox> { let context = scope.get_current_context().unwrap(); let global: v8::Local = context.global(scope).into(); - let js_macrotask_cb = js_macrotask_cb.get(scope); + + let js_macrotask_cb = { + let state_rc = CoreIsolate::state(scope.isolate()); + let state = state_rc.borrow_mut(); + state.js_macrotask_cb.get(scope) + }; if js_macrotask_cb.is_none() { return Ok(()); } @@ -550,7 +603,7 @@ fn drain_macrotasks<'s>( let is_done = js_macrotask_cb.call(scope, context, global, &[]); if let Some(exception) = tc.exception() { - return exception_to_err_result(scope, exception, js_error_create_fn); + return exception_to_err_result(scope, exception); } let is_done = is_done.unwrap(); @@ -565,7 +618,6 @@ fn drain_macrotasks<'s>( pub(crate) fn exception_to_err_result<'s, T>( scope: &mut impl v8::ToLocal<'s>, exception: v8::Local, - js_error_create_fn: &JSErrorCreateFn, ) -> Result { // TODO(piscisaureus): in rusty_v8, `is_execution_terminating()` should // also be implemented on `struct Isolate`. @@ -593,7 +645,10 @@ pub(crate) fn exception_to_err_result<'s, T>( } let js_error = JSError::from_v8_exception(scope, exception); - let js_error = (js_error_create_fn)(js_error); + + let state_rc = CoreIsolate::state(scope.isolate()); + let state = state_rc.borrow(); + let js_error = (state.js_error_create_fn)(js_error); if is_terminating_exception { // Re-enable exception termination. @@ -607,13 +662,15 @@ pub(crate) fn exception_to_err_result<'s, T>( fn check_promise_exceptions<'s>( scope: &mut impl v8::ToLocal<'s>, - pending_promise_exceptions: &mut HashMap>, - js_error_create_fn: &JSErrorCreateFn, ) -> Result<(), ErrBox> { - if let Some(&key) = pending_promise_exceptions.keys().next() { - let handle = pending_promise_exceptions.remove(&key).unwrap(); + let state_rc = CoreIsolate::state(scope.isolate()); + let mut state = state_rc.borrow_mut(); + + if let Some(&key) = state.pending_promise_exceptions.keys().next() { + let handle = state.pending_promise_exceptions.remove(&key).unwrap(); + drop(state); let exception = handle.get(scope).expect("empty error handle"); - exception_to_err_result(scope, exception, js_error_create_fn) + exception_to_err_result(scope, exception) } else { Ok(()) } @@ -632,6 +689,7 @@ pub mod tests { use futures::future::lazy; use std::ops::FnOnce; use std::sync::atomic::{AtomicUsize, Ordering}; + use std::sync::Arc; pub fn run_in_task(f: F) where @@ -666,13 +724,13 @@ pub mod tests { OverflowResAsync, } - pub fn setup(mode: Mode) -> (Box, Arc) { + pub fn setup(mode: Mode) -> (CoreIsolate, Arc) { let dispatch_count = Arc::new(AtomicUsize::new(0)); let dispatch_count_ = dispatch_count.clone(); let mut isolate = CoreIsolate::new(StartupData::None, false); - let dispatcher = move |_isolate: &mut CoreIsolate, + let dispatcher = move |_state: &mut CoreIsolateState, control: &[u8], _zero_copy: Option| -> Op { diff --git a/core/es_isolate.rs b/core/es_isolate.rs index a3775c8a43..a23af43d7f 100644 --- a/core/es_isolate.rs +++ b/core/es_isolate.rs @@ -16,7 +16,7 @@ use futures::stream::StreamExt; use futures::stream::StreamFuture; use futures::task::AtomicWaker; use futures::Future; -use libc::c_void; +use std::cell::RefCell; use std::collections::HashMap; use std::convert::TryFrom; use std::ops::{Deref, DerefMut}; @@ -46,8 +46,9 @@ use crate::StartupData; /// Creating `EsIsolate` requires to pass `loader` argument /// that implements `ModuleLoader` trait - that way actual resolution and /// loading of modules can be customized by the implementor. -pub struct EsIsolate { - core_isolate: Box, +pub struct EsIsolate(CoreIsolate); + +pub struct EsIsolateState { loader: Rc, pub modules: Modules, pub(crate) dyn_import_map: @@ -62,13 +63,13 @@ impl Deref for EsIsolate { type Target = CoreIsolate; fn deref(&self) -> &Self::Target { - &self.core_isolate + &self.0 } } impl DerefMut for EsIsolate { fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.core_isolate + &mut self.0 } } @@ -77,38 +78,27 @@ impl EsIsolate { loader: Rc, startup_data: StartupData, will_snapshot: bool, - ) -> Box { + ) -> Self { let mut core_isolate = CoreIsolate::new(startup_data, will_snapshot); { - let v8_isolate = core_isolate.v8_isolate.as_mut().unwrap(); - v8_isolate.set_host_initialize_import_meta_object_callback( + core_isolate.set_host_initialize_import_meta_object_callback( bindings::host_initialize_import_meta_object_callback, ); - v8_isolate.set_host_import_module_dynamically_callback( + core_isolate.set_host_import_module_dynamically_callback( bindings::host_import_module_dynamically_callback, ); } - let es_isolate = Self { + core_isolate.set_slot(Rc::new(RefCell::new(EsIsolateState { modules: Modules::new(), loader, - core_isolate, dyn_import_map: HashMap::new(), preparing_dyn_imports: FuturesUnordered::new(), pending_dyn_imports: FuturesUnordered::new(), waker: AtomicWaker::new(), - }; + }))); - let mut boxed_es_isolate = Box::new(es_isolate); - { - let es_isolate_ptr: *mut Self = Box::into_raw(boxed_es_isolate); - boxed_es_isolate = unsafe { Box::from_raw(es_isolate_ptr) }; - unsafe { - let v8_isolate = boxed_es_isolate.v8_isolate.as_mut().unwrap(); - v8_isolate.set_data(1, es_isolate_ptr as *mut c_void); - }; - } - boxed_es_isolate + EsIsolate(core_isolate) } /// Low-level module creation. @@ -120,14 +110,13 @@ impl EsIsolate { name: &str, source: &str, ) -> Result { - let core_isolate = &mut self.core_isolate; - let v8_isolate = core_isolate.v8_isolate.as_mut().unwrap(); - let js_error_create_fn = &*core_isolate.js_error_create_fn; + let state_rc = Self::state(self); - let mut hs = v8::HandleScope::new(v8_isolate); + let core_state_rc = CoreIsolate::state(self); + let core_state = core_state_rc.borrow(); + let mut hs = v8::HandleScope::new(&mut self.0); let scope = hs.enter(); - assert!(!core_isolate.global_context.is_empty()); - let context = core_isolate.global_context.get(scope).unwrap(); + let context = core_state.global_context.get(scope).unwrap(); let mut cs = v8::ContextScope::new(scope, context); let scope = cs.enter(); @@ -144,11 +133,7 @@ impl EsIsolate { if tc.has_caught() { assert!(maybe_module.is_none()); - return exception_to_err_result( - scope, - tc.exception().unwrap(), - js_error_create_fn, - ); + return exception_to_err_result(scope, tc.exception().unwrap()); } let module = maybe_module.unwrap(); @@ -158,16 +143,21 @@ impl EsIsolate { for i in 0..module.get_module_requests_length() { let import_specifier = module.get_module_request(i).to_rust_string_lossy(scope); + let state = state_rc.borrow(); let module_specifier = - self.loader.resolve(&import_specifier, name, false)?; + state.loader.resolve(&import_specifier, name, false)?; import_specifiers.push(module_specifier); } let mut handle = v8::Global::::new(); handle.set(scope, module); - self - .modules - .register(id, name, main, handle, import_specifiers); + + { + let mut state = state_rc.borrow_mut(); + state + .modules + .register(id, name, main, handle, import_specifiers); + } Ok(id) } @@ -177,32 +167,30 @@ impl EsIsolate { /// the V8 exception. By default this type is JSError, however it may be a /// different type if CoreIsolate::set_js_error_create_fn() has been used. fn mod_instantiate(&mut self, id: ModuleId) -> Result<(), ErrBox> { - let v8_isolate = self.core_isolate.v8_isolate.as_mut().unwrap(); - let js_error_create_fn = &*self.core_isolate.js_error_create_fn; + let state_rc = Self::state(self); + let state = state_rc.borrow(); - let mut hs = v8::HandleScope::new(v8_isolate); + let core_state_rc = CoreIsolate::state(self); + let core_state = core_state_rc.borrow(); + let mut hs = v8::HandleScope::new(&mut self.0); let scope = hs.enter(); - assert!(!self.core_isolate.global_context.is_empty()); - let context = self.core_isolate.global_context.get(scope).unwrap(); + let context = core_state.global_context.get(scope).unwrap(); let mut cs = v8::ContextScope::new(scope, context); let scope = cs.enter(); let mut try_catch = v8::TryCatch::new(scope); let tc = try_catch.enter(); - let module_info = match self.modules.get_info(id) { + let module_info = match state.modules.get_info(id) { Some(info) => info, None if id == 0 => return Ok(()), _ => panic!("module id {} not found in module table", id), }; let mut module = module_info.handle.get(scope).unwrap(); + drop(state); if module.get_status() == v8::ModuleStatus::Errored { - exception_to_err_result( - scope, - module.get_exception(), - js_error_create_fn, - )? + exception_to_err_result(scope, module.get_exception())? } let result = @@ -211,7 +199,7 @@ impl EsIsolate { Some(_) => Ok(()), None => { let exception = tc.exception().unwrap(); - exception_to_err_result(scope, exception, js_error_create_fn) + exception_to_err_result(scope, exception) } } } @@ -222,20 +210,24 @@ impl EsIsolate { /// the V8 exception. By default this type is JSError, however it may be a /// different type if CoreIsolate::set_js_error_create_fn() has been used. pub fn mod_evaluate(&mut self, id: ModuleId) -> Result<(), ErrBox> { - let core_isolate = &mut self.core_isolate; - let v8_isolate = core_isolate.v8_isolate.as_mut().unwrap(); - let js_error_create_fn = &*core_isolate.js_error_create_fn; + let state_rc = Self::state(self); + let state = state_rc.borrow(); - let mut hs = v8::HandleScope::new(v8_isolate); + let core_state_rc = CoreIsolate::state(self); + + let mut hs = v8::HandleScope::new(&mut self.0); let scope = hs.enter(); - assert!(!core_isolate.global_context.is_empty()); - let context = core_isolate.global_context.get(scope).unwrap(); + let context = { + let core_state = core_state_rc.borrow(); + core_state.global_context.get(scope).unwrap() + }; let mut cs = v8::ContextScope::new(scope, context); let scope = cs.enter(); - let info = self.modules.get_info(id).expect("ModuleInfo not found"); + let info = state.modules.get_info(id).expect("ModuleInfo not found"); let module = info.handle.get(scope).expect("Empty module handle"); let mut status = module.get_status(); + drop(state); if status == v8::ModuleStatus::Instantiated { // IMPORTANT: Top-level-await is enabled, which means that return value // of module evaluation is a promise. @@ -266,8 +258,9 @@ impl EsIsolate { let promise = v8::Local::::try_from(value) .expect("Expected to get promise as module evaluation result"); let promise_id = promise.get_identity_hash(); + let mut core_state = core_state_rc.borrow_mut(); if let Some(mut handle) = - core_isolate.pending_promise_exceptions.remove(&promise_id) + core_state.pending_promise_exceptions.remove(&promise_id) { handle.reset(scope); } @@ -280,68 +273,41 @@ impl EsIsolate { v8::ModuleStatus::Evaluated => Ok(()), v8::ModuleStatus::Errored => { let exception = module.get_exception(); - exception_to_err_result(scope, exception, js_error_create_fn) + exception_to_err_result(scope, exception) .map_err(|err| attach_handle_to_error(scope, err, exception)) } other => panic!("Unexpected module status {:?}", other), } } - // Called by V8 during `Isolate::mod_instantiate`. - pub fn module_resolve_cb( - &mut self, - specifier: &str, - referrer_id: ModuleId, - ) -> ModuleId { - let referrer = self.modules.get_name(referrer_id).unwrap(); - let specifier = self - .loader - .resolve(specifier, referrer, false) - .expect("Module should have been already resolved"); - self.modules.get_id(specifier.as_str()).unwrap_or(0) - } - - // Called by V8 during `Isolate::mod_instantiate`. - pub fn dyn_import_cb( - &mut self, - resolver_handle: v8::Global, - specifier: &str, - referrer: &str, - ) { - debug!("dyn_import specifier {} referrer {} ", specifier, referrer); - - let load = RecursiveModuleLoad::dynamic_import( - specifier, - referrer, - self.loader.clone(), - ); - self.dyn_import_map.insert(load.id, resolver_handle); - self.waker.wake(); - let fut = load.prepare().boxed_local(); - self.preparing_dyn_imports.push(fut); - } - fn dyn_import_error( &mut self, id: ModuleLoadId, err: ErrBox, ) -> Result<(), ErrBox> { - let core_isolate = &mut self.core_isolate; - let v8_isolate = core_isolate.v8_isolate.as_mut().unwrap(); + let state_rc = Self::state(self); + let mut state = state_rc.borrow_mut(); - let mut hs = v8::HandleScope::new(v8_isolate); + let core_state_rc = CoreIsolate::state(self); + let core_state = core_state_rc.borrow(); + + let mut hs = v8::HandleScope::new(&mut self.0); let scope = hs.enter(); - let context = core_isolate.global_context.get(scope).unwrap(); + let context = core_state.global_context.get(scope).unwrap(); let mut cs = v8::ContextScope::new(scope, context); let scope = cs.enter(); - let mut resolver_handle = self + drop(core_state); + + let mut resolver_handle = state .dyn_import_map .remove(&id) .expect("Invalid dyn import id"); let resolver = resolver_handle.get(scope).unwrap(); resolver_handle.reset(scope); + drop(state); + let exception = err .downcast_ref::() .and_then(|err| err.get_handle().get(scope)) @@ -361,29 +327,40 @@ impl EsIsolate { id: ModuleLoadId, mod_id: ModuleId, ) -> Result<(), ErrBox> { + let state_rc = Self::state(self); + + let core_state_rc = CoreIsolate::state(self); + let core_state = core_state_rc.borrow(); + debug!("dyn_import_done {} {:?}", id, mod_id); assert!(mod_id != 0); - let v8_isolate = self.core_isolate.v8_isolate.as_mut().unwrap(); - let mut hs = v8::HandleScope::new(v8_isolate); + let mut hs = v8::HandleScope::new(&mut self.0); let scope = hs.enter(); - assert!(!self.core_isolate.global_context.is_empty()); - let context = self.core_isolate.global_context.get(scope).unwrap(); + let context = core_state.global_context.get(scope).unwrap(); let mut cs = v8::ContextScope::new(scope, context); let scope = cs.enter(); - let mut resolver_handle = self - .dyn_import_map - .remove(&id) - .expect("Invalid dyn import id"); + let mut resolver_handle = { + let mut state = state_rc.borrow_mut(); + state + .dyn_import_map + .remove(&id) + .expect("Invalid dyn import id") + }; let resolver = resolver_handle.get(scope).unwrap(); resolver_handle.reset(scope); - let info = self - .modules - .get_info(mod_id) - .expect("Dyn import module info not found"); - // Resolution success - let mut module = info.handle.get(scope).unwrap(); + + let mut module = { + let state = state_rc.borrow(); + let info = state + .modules + .get_info(mod_id) + .expect("Dyn import module info not found"); + // Resolution success + info.handle.get(scope).unwrap() + }; assert_eq!(module.get_status(), v8::ModuleStatus::Evaluated); + let module_namespace = module.get_module_namespace(); resolver.resolve(context, module_namespace).unwrap(); scope.isolate().run_microtasks(); @@ -394,8 +371,14 @@ impl EsIsolate { &mut self, cx: &mut Context, ) -> Poll> { + let state_rc = Self::state(self); + loop { - match self.preparing_dyn_imports.poll_next_unpin(cx) { + let r = { + let mut state = state_rc.borrow_mut(); + state.preparing_dyn_imports.poll_next_unpin(cx) + }; + match r { Poll::Pending | Poll::Ready(None) => { // There are no active dynamic import loaders, or none are ready. return Poll::Ready(Ok(())); @@ -406,7 +389,8 @@ impl EsIsolate { match prepare_result { Ok(load) => { - self.pending_dyn_imports.push(load.into_future()); + let state = state_rc.borrow_mut(); + state.pending_dyn_imports.push(load.into_future()); } Err(err) => { self.dyn_import_error(dyn_import_id, err)?; @@ -418,8 +402,14 @@ impl EsIsolate { } fn poll_dyn_imports(&mut self, cx: &mut Context) -> Poll> { + let state_rc = Self::state(self); loop { - match self.pending_dyn_imports.poll_next_unpin(cx) { + let poll_result = { + let mut state = state_rc.borrow_mut(); + state.pending_dyn_imports.poll_next_unpin(cx) + }; + + match poll_result { Poll::Pending | Poll::Ready(None) => { // There are no active dynamic import loaders, or none are ready. return Poll::Ready(Ok(())); @@ -438,7 +428,8 @@ impl EsIsolate { match self.register_during_load(info, &mut load) { Ok(()) => { // Keep importing until it's fully drained - self.pending_dyn_imports.push(load.into_future()); + let state = state_rc.borrow_mut(); + state.pending_dyn_imports.push(load.into_future()); } Err(err) => self.dyn_import_error(dyn_import_id, err)?, } @@ -481,6 +472,7 @@ impl EsIsolate { let referrer_specifier = ModuleSpecifier::resolve_url(&module_url_found).unwrap(); + let state_rc = Self::state(self); // #A There are 3 cases to handle at this moment: // 1. Source code resolved result have the same module name as requested // and is not yet registered @@ -493,10 +485,18 @@ impl EsIsolate { // If necessary, register an alias. if module_url_specified != module_url_found { - self.modules.alias(&module_url_specified, &module_url_found); + let mut state = state_rc.borrow_mut(); + state + .modules + .alias(&module_url_specified, &module_url_found); } - let module_id = match self.modules.get_id(&module_url_found) { + let maybe_mod_id = { + let state = state_rc.borrow(); + state.modules.get_id(&module_url_found) + }; + + let module_id = match maybe_mod_id { Some(id) => { // Module has already been registered. debug!( @@ -510,10 +510,19 @@ impl EsIsolate { }; // Now we must iterate over all imports of the module and load them. - let imports = self.modules.get_children(module_id).unwrap(); + let imports = { + let state_rc = Self::state(self); + let state = state_rc.borrow(); + state.modules.get_children(module_id).unwrap().clone() + }; for module_specifier in imports { - if !self.modules.is_registered(module_specifier) { + let is_registered = { + let state_rc = Self::state(self); + let state = state_rc.borrow(); + state.modules.is_registered(&module_specifier) + }; + if !is_registered { load .add_import(module_specifier.to_owned(), referrer_specifier.clone()); } @@ -541,11 +550,13 @@ impl EsIsolate { specifier: &ModuleSpecifier, code: Option, ) -> Result { - let load = RecursiveModuleLoad::main( - &specifier.to_string(), - code, - self.loader.clone(), - ); + let loader = { + let state_rc = Self::state(self); + let state = state_rc.borrow(); + state.loader.clone() + }; + + let load = RecursiveModuleLoad::main(&specifier.to_string(), code, loader); let (_load_id, prepare_result) = load.prepare().await; let mut load = prepare_result?; @@ -558,30 +569,49 @@ impl EsIsolate { let root_id = load.root_module_id.expect("Root module id empty"); self.mod_instantiate(root_id).map(|_| root_id) } + + pub fn state(isolate: &v8::Isolate) -> Rc> { + let s = isolate.get_slot::>>().unwrap(); + s.clone() + } } impl Future for EsIsolate { type Output = Result<(), ErrBox>; fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { - let inner = self.get_mut(); + let es_isolate = self.get_mut(); - inner.waker.register(cx.waker()); + let state_rc = Self::state(es_isolate); - if !inner.preparing_dyn_imports.is_empty() { - let poll_imports = inner.prepare_dyn_imports(cx)?; + { + let state = state_rc.borrow(); + state.waker.register(cx.waker()); + } + + let has_preparing = { + let state = state_rc.borrow(); + !state.preparing_dyn_imports.is_empty() + }; + if has_preparing { + let poll_imports = es_isolate.prepare_dyn_imports(cx)?; assert!(poll_imports.is_ready()); } - if !inner.pending_dyn_imports.is_empty() { - let poll_imports = inner.poll_dyn_imports(cx)?; + let has_pending = { + let state = state_rc.borrow(); + !state.pending_dyn_imports.is_empty() + }; + if has_pending { + let poll_imports = es_isolate.poll_dyn_imports(cx)?; assert!(poll_imports.is_ready()); } - match ready!(inner.core_isolate.poll_unpin(cx)) { + match ready!(es_isolate.0.poll_unpin(cx)) { Ok(()) => { - if inner.pending_dyn_imports.is_empty() - && inner.preparing_dyn_imports.is_empty() + let state = state_rc.borrow(); + if state.pending_dyn_imports.is_empty() + && state.preparing_dyn_imports.is_empty() { Poll::Ready(Ok(())) } else { @@ -593,10 +623,47 @@ impl Future for EsIsolate { } } +impl EsIsolateState { + // Called by V8 during `Isolate::mod_instantiate`. + pub fn module_resolve_cb( + &mut self, + specifier: &str, + referrer_id: ModuleId, + ) -> ModuleId { + let referrer = self.modules.get_name(referrer_id).unwrap(); + let specifier = self + .loader + .resolve(specifier, referrer, false) + .expect("Module should have been already resolved"); + self.modules.get_id(specifier.as_str()).unwrap_or(0) + } + + // Called by V8 during `Isolate::mod_instantiate`. + pub fn dyn_import_cb( + &mut self, + resolver_handle: v8::Global, + specifier: &str, + referrer: &str, + ) { + debug!("dyn_import specifier {} referrer {} ", specifier, referrer); + + let load = RecursiveModuleLoad::dynamic_import( + specifier, + referrer, + self.loader.clone(), + ); + self.dyn_import_map.insert(load.id, resolver_handle); + self.waker.wake(); + let fut = load.prepare().boxed_local(); + self.preparing_dyn_imports.push(fut); + } +} + #[cfg(test)] pub mod tests { use super::*; use crate::core_isolate::tests::run_in_task; + use crate::core_isolate::CoreIsolateState; use crate::js_check; use crate::modules::ModuleSourceFuture; use crate::ops::*; @@ -643,7 +710,7 @@ pub mod tests { let mut isolate = EsIsolate::new(loader, StartupData::None, false); - let dispatcher = move |_isolate: &mut CoreIsolate, + let dispatcher = move |_state: &mut CoreIsolateState, control: &[u8], _zero_copy: Option| -> Op { @@ -684,16 +751,23 @@ pub mod tests { .unwrap(); assert_eq!(dispatch_count.load(Ordering::Relaxed), 0); - let imports = isolate.modules.get_children(mod_a); - assert_eq!( - imports, - Some(&vec![ModuleSpecifier::resolve_url("file:///b.js").unwrap()]) - ); + let state_rc = EsIsolate::state(&isolate); + { + let state = state_rc.borrow(); + let imports = state.modules.get_children(mod_a); + assert_eq!( + imports, + Some(&vec![ModuleSpecifier::resolve_url("file:///b.js").unwrap()]) + ); + } let mod_b = isolate .mod_new(false, "file:///b.js", "export function b() { return 'b' }") .unwrap(); - let imports = isolate.modules.get_children(mod_b).unwrap(); - assert_eq!(imports.len(), 0); + { + let state = state_rc.borrow(); + let imports = state.modules.get_children(mod_b).unwrap(); + assert_eq!(imports.len(), 0); + } js_check(isolate.mod_instantiate(mod_b)); assert_eq!(dispatch_count.load(Ordering::Relaxed), 0); diff --git a/core/examples/http_bench.rs b/core/examples/http_bench.rs index f728b2a69d..a52f69fcbe 100644 --- a/core/examples/http_bench.rs +++ b/core/examples/http_bench.rs @@ -4,6 +4,7 @@ extern crate derive_deref; extern crate log; use deno_core::CoreIsolate; +use deno_core::CoreIsolateState; use deno_core::Op; use deno_core::ResourceTable; use deno_core::Script; @@ -77,7 +78,7 @@ impl From for RecordBuf { } struct Isolate { - core_isolate: Box, // Unclear why CoreIsolate::new() returns a box. + core_isolate: CoreIsolate, state: State, } @@ -115,7 +116,7 @@ impl Isolate { F: 'static + Fn(State, u32, Option) -> Result, { let state = self.state.clone(); - let core_handler = move |_isolate: &mut CoreIsolate, + let core_handler = move |_isolate_state: &mut CoreIsolateState, control_buf: &[u8], zero_copy_buf: Option| -> Op { @@ -145,7 +146,7 @@ impl Isolate { >::Error: Debug, { let state = self.state.clone(); - let core_handler = move |_isolate: &mut CoreIsolate, + let core_handler = move |_isolate_state: &mut CoreIsolateState, control_buf: &[u8], zero_copy_buf: Option| -> Op { diff --git a/core/lib.rs b/core/lib.rs index 49d49e19d8..47ded645e7 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -25,12 +25,14 @@ pub use rusty_v8 as v8; pub use crate::core_isolate::js_check; pub use crate::core_isolate::CoreIsolate; +pub use crate::core_isolate::CoreIsolateState; pub use crate::core_isolate::Script; pub use crate::core_isolate::Snapshot; pub use crate::core_isolate::StartupData; pub use crate::errors::ErrBox; pub use crate::errors::JSError; pub use crate::es_isolate::EsIsolate; +pub use crate::es_isolate::EsIsolateState; pub use crate::flags::v8_set_flags; pub use crate::module_specifier::ModuleResolutionError; pub use crate::module_specifier::ModuleSpecifier; diff --git a/core/modules.rs b/core/modules.rs index 5a00d92cc2..ca850d0bb0 100644 --- a/core/modules.rs +++ b/core/modules.rs @@ -745,7 +745,9 @@ mod tests { ] ); - let modules = &isolate.modules; + let state_rc = EsIsolate::state(&isolate); + let state = state_rc.borrow(); + let modules = &state.modules; assert_eq!(modules.get_id("file:///a.js"), Some(a_id)); let b_id = modules.get_id("file:///b.js").unwrap(); let c_id = modules.get_id("file:///c.js").unwrap(); @@ -807,7 +809,9 @@ mod tests { ] ); - let modules = &isolate.modules; + let state_rc = EsIsolate::state(&isolate); + let state = state_rc.borrow(); + let modules = &state.modules; assert_eq!(modules.get_id("file:///circular1.js"), Some(circular1_id)); let circular2_id = modules.get_id("file:///circular2.js").unwrap(); @@ -878,7 +882,9 @@ mod tests { ] ); - let modules = &isolate.modules; + let state_rc = EsIsolate::state(&isolate); + let state = state_rc.borrow(); + let modules = &state.modules; assert_eq!(modules.get_id("file:///redirect1.js"), Some(redirect1_id)); @@ -1016,7 +1022,9 @@ mod tests { vec!["file:///b.js", "file:///c.js", "file:///d.js"] ); - let modules = &isolate.modules; + let state_rc = EsIsolate::state(&isolate); + let state = state_rc.borrow(); + let modules = &state.modules; assert_eq!(modules.get_id("file:///main_with_code.js"), Some(main_id)); let b_id = modules.get_id("file:///b.js").unwrap(); diff --git a/core/ops.rs b/core/ops.rs index 0361f5ee9f..ecece7355a 100644 --- a/core/ops.rs +++ b/core/ops.rs @@ -1,5 +1,5 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use crate::CoreIsolate; +use crate::core_isolate::CoreIsolateState; use crate::ZeroCopyBuf; use futures::Future; use std::collections::HashMap; @@ -22,7 +22,7 @@ pub enum Op { /// Main type describing op pub type OpDispatcher = - dyn Fn(&mut CoreIsolate, &[u8], Option) -> Op + 'static; + dyn Fn(&mut CoreIsolateState, &[u8], Option) -> Op + 'static; #[derive(Default)] pub struct OpRegistry { @@ -33,8 +33,8 @@ pub struct OpRegistry { impl OpRegistry { pub fn new() -> Self { let mut registry = Self::default(); - let op_id = registry.register("ops", |isolate, _, _| { - let buf = isolate.op_registry.json_map(); + let op_id = registry.register("ops", |state, _, _| { + let buf = state.op_registry.json_map(); Op::Sync(buf) }); assert_eq!(op_id, 0); @@ -43,7 +43,7 @@ impl OpRegistry { pub fn register(&mut self, name: &str, op: F) -> OpId where - F: Fn(&mut CoreIsolate, &[u8], Option) -> Op + 'static, + F: Fn(&mut CoreIsolateState, &[u8], Option) -> Op + 'static, { let op_id = self.dispatchers.len() as u32; @@ -68,6 +68,7 @@ impl OpRegistry { #[test] fn test_op_registry() { + use crate::CoreIsolate; use std::sync::atomic; use std::sync::Arc; let mut op_registry = OpRegistry::new(); @@ -86,10 +87,12 @@ fn test_op_registry() { expected.insert("test".to_string(), 1); assert_eq!(op_registry.name_to_id, expected); - let mut isolate = CoreIsolate::new(crate::StartupData::None, false); + let isolate = CoreIsolate::new(crate::StartupData::None, false); let dispatch = op_registry.get(test_id).unwrap(); - let res = dispatch(&mut isolate, &[], None); + let state_rc = CoreIsolate::state(&isolate); + let mut state = state_rc.borrow_mut(); + let res = dispatch(&mut state, &[], None); if let Op::Sync(buf) = res { assert_eq!(buf.len(), 0); } else { @@ -102,6 +105,7 @@ fn test_op_registry() { #[test] fn register_op_during_call() { + use crate::CoreIsolate; use std::sync::atomic; use std::sync::Arc; use std::sync::Mutex; @@ -126,13 +130,17 @@ fn register_op_during_call() { }; assert!(test_id != 0); - let mut isolate = CoreIsolate::new(crate::StartupData::None, false); + let isolate = CoreIsolate::new(crate::StartupData::None, false); let dispatcher1 = { let g = op_registry.lock().unwrap(); g.get(test_id).unwrap() }; - dispatcher1(&mut isolate, &[], None); + { + let state_rc = CoreIsolate::state(&isolate); + let mut state = state_rc.borrow_mut(); + dispatcher1(&mut state, &[], None); + } let mut expected = HashMap::new(); expected.insert("ops".to_string(), 0); @@ -147,7 +155,9 @@ fn register_op_during_call() { let g = op_registry.lock().unwrap(); g.get(2).unwrap() }; - let res = dispatcher2(&mut isolate, &[], None); + let state_rc = CoreIsolate::state(&isolate); + let mut state = state_rc.borrow_mut(); + let res = dispatcher2(&mut state, &[], None); if let Op::Sync(buf) = res { assert_eq!(buf.len(), 0); } else { diff --git a/deno_typescript/lib.rs b/deno_typescript/lib.rs index 590e299171..a56c4fa7c1 100644 --- a/deno_typescript/lib.rs +++ b/deno_typescript/lib.rs @@ -9,6 +9,7 @@ mod ops; use deno_core::js_check; pub use deno_core::v8_set_flags; use deno_core::CoreIsolate; +use deno_core::CoreIsolateState; use deno_core::ErrBox; use deno_core::ModuleSpecifier; use deno_core::Op; @@ -49,11 +50,11 @@ pub struct TSState { fn compiler_op( ts_state: Arc>, dispatcher: D, -) -> impl Fn(&mut CoreIsolate, &[u8], Option) -> Op +) -> impl Fn(&mut CoreIsolateState, &[u8], Option) -> Op where D: Fn(&mut TSState, &[u8]) -> Op, { - move |_isolate: &mut CoreIsolate, + move |_state: &mut CoreIsolateState, control: &[u8], zero_copy_buf: Option| -> Op { @@ -64,7 +65,7 @@ where } pub struct TSIsolate { - isolate: Box, + isolate: CoreIsolate, state: Arc>, } @@ -331,11 +332,11 @@ pub fn trace_serializer() { /// CoreIsolate. pub fn op_fetch_asset( custom_assets: HashMap, -) -> impl Fn(&mut CoreIsolate, &[u8], Option) -> Op { +) -> impl Fn(&mut CoreIsolateState, &[u8], Option) -> Op { for (_, path) in custom_assets.iter() { println!("cargo:rerun-if-changed={}", path.display()); } - move |_isolate: &mut CoreIsolate, + move |_state: &mut CoreIsolateState, control: &[u8], zero_copy_buf: Option| -> Op {