1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-25 15:29:32 -05:00

refactor: Split isolate and state using safe get_slot() (#5929)

This commit is contained in:
Ryan Dahl 2020-05-29 17:41:39 -04:00 committed by GitHub
parent 106b001738
commit d4b05dd89e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 758 additions and 579 deletions

View file

@ -375,14 +375,10 @@ impl DenoInspector {
isolate: &mut deno_core::CoreIsolate,
host: SocketAddr,
) -> Box<Self> {
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);

View file

@ -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 {

View file

@ -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: D,
) -> impl Fn(&mut CoreIsolate, &[u8], Option<ZeroCopyBuf>) -> Op
) -> impl Fn(&mut CoreIsolateState, &[u8], Option<ZeroCopyBuf>) -> Op
where
D:
Fn(&mut CoreIsolate, Value, Option<ZeroCopyBuf>) -> Result<JsonOp, OpError>,
D: Fn(
&mut CoreIsolateState,
Value,
Option<ZeroCopyBuf>,
) -> Result<JsonOp, OpError>,
{
move |isolate: &mut CoreIsolate,
move |isolate_state: &mut CoreIsolateState,
control: &[u8],
zero_copy: Option<ZeroCopyBuf>| {
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 {

View file

@ -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: D,
) -> impl Fn(&mut CoreIsolate, &[u8], Option<ZeroCopyBuf>) -> Op
) -> impl Fn(&mut CoreIsolateState, &[u8], Option<ZeroCopyBuf>) -> Op
where
D: Fn(&mut CoreIsolate, bool, i32, Option<ZeroCopyBuf>) -> MinimalOp,
D: Fn(&mut CoreIsolateState, bool, i32, Option<ZeroCopyBuf>) -> MinimalOp,
{
move |isolate: &mut CoreIsolate,
move |isolate_state: &mut CoreIsolateState,
control: &[u8],
zero_copy: Option<ZeroCopyBuf>| {
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 {

View file

@ -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<ZeroCopyBuf>,
@ -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);

View file

@ -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<ZeroCopyBuf>,
) -> Result<JsonOp, OpError> {
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<ZeroCopyBuf>,
@ -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 {

View file

@ -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<NotifyEvent> for FsEvent {
}
pub fn op_fs_events_open(
isolate: &mut CoreIsolate,
isolate_state: &mut CoreIsolateState,
state: &State,
args: Value,
_zero_copy: Option<ZeroCopyBuf>,
@ -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<ZeroCopyBuf>,
@ -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

View file

@ -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| {

View file

@ -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<ZeroCopyBuf>,
) -> Result<JsonOp, OpError> {
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<ZeroCopyBuf>,
) -> Result<JsonOp, OpError> {
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<ZeroCopyBuf>,
@ -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<ZeroCopyBuf>,
@ -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<ZeroCopyBuf>,
) -> Result<JsonOp, OpError> {
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<ZeroCopyBuf>,
) -> Result<JsonOp, OpError> {
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<ZeroCopyBuf>,
@ -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::<StreamResourceHolder>(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<ZeroCopyBuf>,
) -> Result<JsonOp, OpError> {
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,

View file

@ -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<ZeroCopyBuf>,
) -> Result<JsonOp, OpError> {
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<ZeroCopyBuf>,
) -> Result<JsonOp, OpError> {
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();

View file

@ -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<ZeroCopyBuf>,
@ -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::<PluginResource>(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<Library>,
}
impl<'a> PluginInterface<'a> {
fn new(isolate: &'a mut CoreIsolate, plugin_lib: &'a Rc<Library>) -> Self {
fn new(
isolate_state: &'a mut CoreIsolateState,
plugin_lib: &'a Rc<Library>,
) -> 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,

View file

@ -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<ZeroCopyBuf>,
@ -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<ZeroCopyBuf>,
@ -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| {

View file

@ -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<ZeroCopyBuf>,
@ -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<ZeroCopyBuf>,
@ -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::<ReplResource>(rid)
.ok_or_else(OpError::bad_resource_id)?;

View file

@ -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<ZeroCopyBuf>,
) -> Result<JsonOp, OpError> {
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<ZeroCopyBuf>,
@ -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)?;

View file

@ -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<ZeroCopyBuf>,
) -> Result<JsonOp, OpError> {
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<ZeroCopyBuf>,
@ -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<ZeroCopyBuf>,
@ -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::<SignalStreamResource>(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<ZeroCopyBuf>,
@ -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<ZeroCopyBuf>,
@ -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<ZeroCopyBuf>,

View file

@ -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<ZeroCopyBuf>,
@ -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<ZeroCopyBuf>,
) -> Result<JsonOp, OpError> {
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<ZeroCopyBuf>,
@ -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<ZeroCopyBuf>,
) -> Result<JsonOp, OpError> {
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();

View file

@ -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<ZeroCopyBuf>,
@ -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::<StreamResourceHolder>(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::<StreamResourceHolder>(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<ZeroCopyBuf>,
@ -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) => {

View file

@ -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<D>(
sender: mpsc::Sender<WorkerEvent>,
dispatcher: D,
) -> impl Fn(&mut CoreIsolate, Value, Option<ZeroCopyBuf>) -> Result<JsonOp, OpError>
) -> impl Fn(
&mut CoreIsolateState,
Value,
Option<ZeroCopyBuf>,
) -> Result<JsonOp, OpError>
where
D: Fn(
&mpsc::Sender<WorkerEvent>,
@ -21,7 +26,7 @@ where
Option<ZeroCopyBuf>,
) -> Result<JsonOp, OpError>,
{
move |_isolate: &mut CoreIsolate,
move |_isolate_state: &mut CoreIsolateState,
args: Value,
zero_copy: Option<ZeroCopyBuf>|
-> Result<JsonOp, OpError> { dispatcher(&sender, args, zero_copy) }
@ -31,7 +36,11 @@ pub fn web_worker_op2<D>(
handle: WebWorkerHandle,
sender: mpsc::Sender<WorkerEvent>,
dispatcher: D,
) -> impl Fn(&mut CoreIsolate, Value, Option<ZeroCopyBuf>) -> Result<JsonOp, OpError>
) -> impl Fn(
&mut CoreIsolateState,
Value,
Option<ZeroCopyBuf>,
) -> Result<JsonOp, OpError>
where
D: Fn(
WebWorkerHandle,
@ -40,7 +49,7 @@ where
Option<ZeroCopyBuf>,
) -> Result<JsonOp, OpError>,
{
move |_isolate: &mut CoreIsolate,
move |_isolate_state: &mut CoreIsolateState,
args: Value,
zero_copy: Option<ZeroCopyBuf>|
-> Result<JsonOp, OpError> {

View file

@ -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));

View file

@ -65,7 +65,7 @@ impl State {
pub fn stateful_json_op<D>(
&self,
dispatcher: D,
) -> impl Fn(&mut deno_core::CoreIsolate, &[u8], Option<ZeroCopyBuf>) -> Op
) -> impl Fn(&mut deno_core::CoreIsolateState, &[u8], Option<ZeroCopyBuf>) -> Op
where
D: Fn(&State, Value, Option<ZeroCopyBuf>) -> Result<JsonOp, OpError>,
{
@ -76,10 +76,10 @@ impl State {
pub fn stateful_json_op2<D>(
&self,
dispatcher: D,
) -> impl Fn(&mut deno_core::CoreIsolate, &[u8], Option<ZeroCopyBuf>) -> Op
) -> impl Fn(&mut deno_core::CoreIsolateState, &[u8], Option<ZeroCopyBuf>) -> Op
where
D: Fn(
&mut deno_core::CoreIsolate,
&mut deno_core::CoreIsolateState,
&State,
Value,
Option<ZeroCopyBuf>,
@ -95,13 +95,13 @@ impl State {
pub fn core_op<D>(
&self,
dispatcher: D,
) -> impl Fn(&mut deno_core::CoreIsolate, &[u8], Option<ZeroCopyBuf>) -> Op
) -> impl Fn(&mut deno_core::CoreIsolateState, &[u8], Option<ZeroCopyBuf>) -> Op
where
D: Fn(&mut deno_core::CoreIsolate, &[u8], Option<ZeroCopyBuf>) -> Op,
D: Fn(&mut deno_core::CoreIsolateState, &[u8], Option<ZeroCopyBuf>) -> Op,
{
let state = self.clone();
move |isolate: &mut deno_core::CoreIsolate,
move |isolate_state: &mut deno_core::CoreIsolateState,
control: &[u8],
zero_copy: Option<ZeroCopyBuf>|
-> 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<D>(
&self,
dispatcher: D,
) -> impl Fn(&mut deno_core::CoreIsolate, &[u8], Option<ZeroCopyBuf>) -> Op
) -> impl Fn(&mut deno_core::CoreIsolateState, &[u8], Option<ZeroCopyBuf>) -> 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<ZeroCopyBuf>|
-> 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<ZeroCopyBuf>,
) -> Result<JsonOp, OpError>
@ -194,7 +194,7 @@ impl State {
D: Fn(&State, Value, Option<ZeroCopyBuf>) -> Result<JsonOp, OpError>,
{
let state = self.clone();
move |_isolate: &mut deno_core::CoreIsolate,
move |_isolate_state: &mut deno_core::CoreIsolateState,
args: Value,
zero_copy: Option<ZeroCopyBuf>|
-> Result<JsonOp, OpError> { 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<ZeroCopyBuf>,
) -> Result<JsonOp, OpError>
where
D: Fn(
&mut deno_core::CoreIsolate,
&mut deno_core::CoreIsolateState,
&State,
Value,
Option<ZeroCopyBuf>,
) -> Result<JsonOp, OpError>,
{
let state = self.clone();
move |isolate: &mut deno_core::CoreIsolate,
move |isolate_state: &mut deno_core::CoreIsolateState,
args: Value,
zero_copy: Option<ZeroCopyBuf>|
-> Result<JsonOp, OpError> {
dispatcher(isolate, &state, args, zero_copy)
dispatcher(isolate_state, &state, args, zero_copy)
}
}

View file

@ -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 {

View file

@ -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<deno_core::EsIsolate>,
pub isolate: deno_core::EsIsolate,
pub inspector: Option<Box<DenoInspector>>,
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)
});
}

View file

@ -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::<v8::Value>::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::<v8::Function>::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::<v8::Uint32>::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::<v8::Function>::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::<v8::String>::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::<v8::Promise>::try_from(args.get(0)) {
Ok(val) => val,

View file

@ -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<v8::OwnedIsolate>,
// This is an Option<OwnedIsolate> instead of just OwnedIsolate to workaround
// an safety issue with SnapshotCreator. See CoreIsolate::drop.
v8_isolate: Option<v8::OwnedIsolate>,
snapshot_creator: Option<v8::SnapshotCreator>,
has_snapshotted: bool,
needs_init: bool,
startup_script: Option<OwnedScript>,
}
/// Internal state for CoreIsolate which is stored in one of v8::Isolate's
/// embedder slots.
pub struct CoreIsolateState {
pub resource_table: Rc<RefCell<ResourceTable>>,
pub global_context: v8::Global<v8::Context>,
pub(crate) shared_ab: v8::Global<v8::SharedArrayBuffer>,
pub(crate) js_recv_cb: v8::Global<v8::Function>,
pub(crate) js_macrotask_cb: v8::Global<v8::Function>,
pub(crate) pending_promise_exceptions: HashMap<i32, v8::Global<v8::Value>>,
shared_isolate_handle: Arc<Mutex<Option<*mut v8::Isolate>>>,
pub(crate) js_error_create_fn: Box<JSErrorCreateFn>,
needs_init: bool,
pub(crate) shared: SharedQueue,
pending_ops: FuturesUnordered<PendingOpFuture>,
pending_unref_ops: FuturesUnordered<PendingOpFuture>,
have_unpolled_ops: bool,
startup_script: Option<OwnedScript>,
pub op_registry: OpRegistry,
waker: AtomicWaker,
error_handler: Option<Box<IsolateErrorHandleFn>>,
}
// 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<Self> {
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::<v8::SharedArrayBuffer>::new(),
js_recv_cb: v8::Global::<v8::Function>::new(),
js_macrotask_cb: v8::Global::<v8::Function>::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<RefCell<CoreIsolateState>> {
let s = isolate.get_slot::<Rc<RefCell<CoreIsolateState>>>().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<F>(&mut self, name: &str, op: F) -> OpId
where
F: Fn(&mut CoreIsolate, &[u8], Option<ZeroCopyBuf>) -> Op + 'static,
F: Fn(&mut CoreIsolateState, &[u8], Option<ZeroCopyBuf>) -> 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<Self::Output> {
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<F>(&mut self, name: &str, op: F) -> OpId
where
F: Fn(&mut CoreIsolateState, &[u8], Option<ZeroCopyBuf>) -> 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<Self::Output> {
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<v8::Function>,
js_error_create_fn: &JSErrorCreateFn,
) -> Result<(), ErrBox> {
let context = scope.get_current_context().unwrap();
let global: v8::Local<v8::Value> = 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<v8::Function>,
js_error_create_fn: &JSErrorCreateFn,
) -> Result<(), ErrBox> {
let context = scope.get_current_context().unwrap();
let global: v8::Local<v8::Value> = 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<v8::Value>,
js_error_create_fn: &JSErrorCreateFn,
) -> Result<T, ErrBox> {
// 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<i32, v8::Global<v8::Value>>,
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: F)
where
@ -666,13 +724,13 @@ pub mod tests {
OverflowResAsync,
}
pub fn setup(mode: Mode) -> (Box<CoreIsolate>, Arc<AtomicUsize>) {
pub fn setup(mode: Mode) -> (CoreIsolate, Arc<AtomicUsize>) {
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<ZeroCopyBuf>|
-> Op {

View file

@ -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<CoreIsolate>,
pub struct EsIsolate(CoreIsolate);
pub struct EsIsolateState {
loader: Rc<dyn ModuleLoader>,
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<dyn ModuleLoader>,
startup_data: StartupData,
will_snapshot: bool,
) -> Box<Self> {
) -> 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<ModuleId, 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 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::<v8::Module>::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::<v8::Promise>::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<v8::PromiseResolver>,
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::<ErrWithV8Handle>()
.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<Result<(), ErrBox>> {
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<Result<(), ErrBox>> {
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<String>,
) -> Result<ModuleId, ErrBox> {
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<RefCell<EsIsolateState>> {
let s = isolate.get_slot::<Rc<RefCell<EsIsolateState>>>().unwrap();
s.clone()
}
}
impl Future for EsIsolate {
type Output = Result<(), ErrBox>;
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
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<v8::PromiseResolver>,
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<ZeroCopyBuf>|
-> 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);

View file

@ -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<Record> for RecordBuf {
}
struct Isolate {
core_isolate: Box<CoreIsolate>, // Unclear why CoreIsolate::new() returns a box.
core_isolate: CoreIsolate,
state: State,
}
@ -115,7 +116,7 @@ impl Isolate {
F: 'static + Fn(State, u32, Option<ZeroCopyBuf>) -> Result<u32, Error>,
{
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<ZeroCopyBuf>|
-> Op {
@ -145,7 +146,7 @@ impl Isolate {
<F::Ok as TryInto<i32>>::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<ZeroCopyBuf>|
-> Op {

View file

@ -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;

View file

@ -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();

View file

@ -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<ZeroCopyBuf>) -> Op + 'static;
dyn Fn(&mut CoreIsolateState, &[u8], Option<ZeroCopyBuf>) -> 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<F>(&mut self, name: &str, op: F) -> OpId
where
F: Fn(&mut CoreIsolate, &[u8], Option<ZeroCopyBuf>) -> Op + 'static,
F: Fn(&mut CoreIsolateState, &[u8], Option<ZeroCopyBuf>) -> 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 {

View file

@ -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<D>(
ts_state: Arc<Mutex<TSState>>,
dispatcher: D,
) -> impl Fn(&mut CoreIsolate, &[u8], Option<ZeroCopyBuf>) -> Op
) -> impl Fn(&mut CoreIsolateState, &[u8], Option<ZeroCopyBuf>) -> Op
where
D: Fn(&mut TSState, &[u8]) -> Op,
{
move |_isolate: &mut CoreIsolate,
move |_state: &mut CoreIsolateState,
control: &[u8],
zero_copy_buf: Option<ZeroCopyBuf>|
-> Op {
@ -64,7 +65,7 @@ where
}
pub struct TSIsolate {
isolate: Box<CoreIsolate>,
isolate: CoreIsolate,
state: Arc<Mutex<TSState>>,
}
@ -331,11 +332,11 @@ pub fn trace_serializer() {
/// CoreIsolate.
pub fn op_fetch_asset<S: ::std::hash::BuildHasher>(
custom_assets: HashMap<String, PathBuf, S>,
) -> impl Fn(&mut CoreIsolate, &[u8], Option<ZeroCopyBuf>) -> Op {
) -> impl Fn(&mut CoreIsolateState, &[u8], Option<ZeroCopyBuf>) -> 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<ZeroCopyBuf>|
-> Op {