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:
parent
106b001738
commit
d4b05dd89e
30 changed files with 758 additions and 579 deletions
|
@ -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);
|
||||
|
||||
|
|
11
cli/main.rs
11
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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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| {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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| {
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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));
|
||||
|
|
34
cli/state.rs
34
cli/state.rs
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
});
|
||||
}
|
||||
|
|
103
core/bindings.rs
103
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::<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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
30
core/ops.rs
30
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<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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue