core: Rename Behavior to Dispatch (#2082)

And rename IsolateState to ThreadSafeState.

Also make ThreadSafeState directly implement Dispatch. This is simpler.
This commit is contained in:
Ryan Dahl 2019-04-09 13:11:25 -04:00 committed by GitHub
parent e43da28b28
commit d2579f4564
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 206 additions and 214 deletions

View file

@ -1,28 +0,0 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
use crate::isolate_state::*;
use crate::ops;
use deno::deno_buf;
use deno::Behavior;
use deno::Op;
use std::sync::Arc;
/// Implements deno::Behavior for the main Deno command-line.
pub struct CliBehavior {
pub state: Arc<IsolateState>,
}
impl CliBehavior {
pub fn new(state: Arc<IsolateState>) -> Self {
Self { state }
}
}
impl Behavior for CliBehavior {
fn dispatch(
&mut self,
control: &[u8],
zero_copy: deno_buf,
) -> (bool, Box<Op>) {
ops::dispatch_all(&self.state, control, zero_copy, ops::op_selector_std)
}
}

View file

@ -1,12 +1,11 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
use crate::cli_behavior::CliBehavior;
use crate::isolate_state::*;
use crate::js_errors; use crate::js_errors;
use crate::js_errors::JSErrorColor; use crate::js_errors::JSErrorColor;
use crate::msg; use crate::msg;
use crate::resources; use crate::resources;
use crate::resources::ResourceId; use crate::resources::ResourceId;
use crate::startup_data; use crate::startup_data;
use crate::state::*;
use crate::tokio_util; use crate::tokio_util;
use crate::worker::Worker; use crate::worker::Worker;
use deno::js_check; use deno::js_check;
@ -21,7 +20,6 @@ use std::collections::HashMap;
use std::str; use std::str;
use std::sync::atomic::AtomicUsize; use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering; use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::sync::Mutex; use std::sync::Mutex;
use tokio::runtime::Runtime; use tokio::runtime::Runtime;
@ -88,22 +86,21 @@ fn parse_cmd_id(res_json: &str) -> CmdId {
} }
} }
fn lazy_start(parent_state: Arc<IsolateState>) -> ResourceId { fn lazy_start(parent_state: ThreadSafeState) -> ResourceId {
let mut cell = C_RID.lock().unwrap(); let mut cell = C_RID.lock().unwrap();
cell cell
.get_or_insert_with(|| { .get_or_insert_with(|| {
let child_state = Arc::new(IsolateState::new( let child_state = ThreadSafeState::new(
parent_state.flags.clone(), parent_state.flags.clone(),
parent_state.argv.clone(), parent_state.argv.clone(),
)); );
let rid = child_state.resource.rid; let rid = child_state.resource.rid;
let resource = child_state.resource.clone(); let resource = child_state.resource.clone();
let behavior = CliBehavior::new(child_state);
let mut worker = Worker::new( let mut worker = Worker::new(
"TS".to_string(), "TS".to_string(),
startup_data::compiler_isolate_init(), startup_data::compiler_isolate_init(),
behavior, child_state,
); );
js_check(worker.execute("denoMain()")); js_check(worker.execute("denoMain()"));
@ -160,7 +157,7 @@ fn req(specifier: &str, referrer: &str, cmd_id: u32) -> Buf {
} }
pub fn compile_async( pub fn compile_async(
parent_state: Arc<IsolateState>, parent_state: ThreadSafeState,
specifier: &str, specifier: &str,
referrer: &str, referrer: &str,
module_meta_data: &ModuleMetaData, module_meta_data: &ModuleMetaData,
@ -248,7 +245,7 @@ pub fn compile_async(
} }
pub fn compile_sync( pub fn compile_sync(
parent_state: Arc<IsolateState>, parent_state: ThreadSafeState,
specifier: &str, specifier: &str,
referrer: &str, referrer: &str,
module_meta_data: &ModuleMetaData, module_meta_data: &ModuleMetaData,
@ -286,12 +283,8 @@ mod tests {
maybe_source_map: None, maybe_source_map: None,
}; };
out = compile_sync( out = compile_sync(ThreadSafeState::mock(), specifier, &referrer, &out)
Arc::new(IsolateState::mock()), .unwrap();
specifier,
&referrer,
&out,
).unwrap();
assert!( assert!(
out out
.maybe_output_code .maybe_output_code

View file

@ -11,7 +11,6 @@ extern crate clap;
extern crate deno; extern crate deno;
mod ansi; mod ansi;
pub mod cli_behavior;
pub mod compiler; pub mod compiler;
pub mod deno_dir; pub mod deno_dir;
pub mod errors; pub mod errors;
@ -20,7 +19,6 @@ mod fs;
mod global_timer; mod global_timer;
mod http_body; mod http_body;
mod http_util; mod http_util;
pub mod isolate_state;
pub mod js_errors; pub mod js_errors;
pub mod modules; pub mod modules;
pub mod msg; pub mod msg;
@ -31,20 +29,19 @@ mod repl;
pub mod resolve_addr; pub mod resolve_addr;
pub mod resources; pub mod resources;
mod startup_data; mod startup_data;
pub mod state;
mod tokio_util; mod tokio_util;
mod tokio_write; mod tokio_write;
pub mod version; pub mod version;
pub mod worker; pub mod worker;
use crate::cli_behavior::CliBehavior;
use crate::errors::RustOrJsError; use crate::errors::RustOrJsError;
use crate::isolate_state::IsolateState; use crate::state::ThreadSafeState;
use crate::worker::Worker; use crate::worker::Worker;
use futures::lazy; use futures::lazy;
use futures::Future; use futures::Future;
use log::{LevelFilter, Metadata, Record}; use log::{LevelFilter, Metadata, Record};
use std::env; use std::env;
use std::sync::Arc;
static LOGGER: Logger = Logger; static LOGGER: Logger = Logger;
@ -104,11 +101,12 @@ fn main() {
let should_prefetch = flags.prefetch || flags.info; let should_prefetch = flags.prefetch || flags.info;
let should_display_info = flags.info; let should_display_info = flags.info;
let state = Arc::new(IsolateState::new(flags, rest_argv)); let state = ThreadSafeState::new(flags, rest_argv);
let state_ = state.clone(); let mut main_worker = Worker::new(
let cli = CliBehavior::new(state_); "main".to_string(),
let mut main_worker = startup_data::deno_isolate_init(),
Worker::new("main".to_string(), startup_data::deno_isolate_init(), cli); state.clone(),
);
let main_future = lazy(move || { let main_future = lazy(move || {
// Setup runtime. // Setup runtime.

View file

@ -5,7 +5,7 @@
feature = "cargo-clippy", feature = "cargo-clippy",
allow(clippy::all, clippy::pedantic) allow(clippy::all, clippy::pedantic)
)] )]
use crate::isolate_state; use crate::state;
use flatbuffers; use flatbuffers;
use std::sync::atomic::Ordering; use std::sync::atomic::Ordering;
@ -13,8 +13,8 @@ use std::sync::atomic::Ordering;
// build_extra/rust/run.py (for the GN+Ninja build). // build_extra/rust/run.py (for the GN+Ninja build).
include!(concat!(env!("GN_OUT_DIR"), "/gen/cli/msg_generated.rs")); include!(concat!(env!("GN_OUT_DIR"), "/gen/cli/msg_generated.rs"));
impl<'a> From<&'a isolate_state::Metrics> for MetricsResArgs { impl<'a> From<&'a state::Metrics> for MetricsResArgs {
fn from(m: &'a isolate_state::Metrics) -> Self { fn from(m: &'a state::Metrics) -> Self {
MetricsResArgs { MetricsResArgs {
ops_dispatched: m.ops_dispatched.load(Ordering::SeqCst) as u64, ops_dispatched: m.ops_dispatched.load(Ordering::SeqCst) as u64,
ops_completed: m.ops_completed.load(Ordering::SeqCst) as u64, ops_completed: m.ops_completed.load(Ordering::SeqCst) as u64,

View file

@ -1,12 +1,10 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
use atty; use atty;
use crate::ansi; use crate::ansi;
use crate::cli_behavior::CliBehavior;
use crate::errors; use crate::errors;
use crate::errors::{DenoError, DenoResult, ErrorKind}; use crate::errors::{DenoError, DenoResult, ErrorKind};
use crate::fs as deno_fs; use crate::fs as deno_fs;
use crate::http_util; use crate::http_util;
use crate::isolate_state::IsolateState;
use crate::js_errors::apply_source_map; use crate::js_errors::apply_source_map;
use crate::js_errors::JSErrorColor; use crate::js_errors::JSErrorColor;
use crate::msg; use crate::msg;
@ -17,6 +15,7 @@ use crate::resources;
use crate::resources::table_entries; use crate::resources::table_entries;
use crate::resources::Resource; use crate::resources::Resource;
use crate::startup_data; use crate::startup_data;
use crate::state::ThreadSafeState;
use crate::tokio_util; use crate::tokio_util;
use crate::tokio_write; use crate::tokio_write;
use crate::version; use crate::version;
@ -42,7 +41,6 @@ use std::net::Shutdown;
use std::path::Path; use std::path::Path;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::Command; use std::process::Command;
use std::sync::Arc;
use std::time::{Duration, Instant, UNIX_EPOCH}; use std::time::{Duration, Instant, UNIX_EPOCH};
use tokio; use tokio;
use tokio::net::TcpListener; use tokio::net::TcpListener;
@ -62,7 +60,7 @@ pub type OpWithError = dyn Future<Item = Buf, Error = DenoError> + Send;
// TODO Ideally we wouldn't have to box the OpWithError being returned. // TODO Ideally we wouldn't have to box the OpWithError being returned.
// The box is just to make it easier to get a prototype refactor working. // The box is just to make it easier to get a prototype refactor working.
type OpCreator = type OpCreator =
fn(state: &Arc<IsolateState>, base: &msg::Base<'_>, data: deno_buf) fn(state: &ThreadSafeState, base: &msg::Base<'_>, data: deno_buf)
-> Box<OpWithError>; -> Box<OpWithError>;
type OpSelector = fn(inner_type: msg::Any) -> Option<OpCreator>; type OpSelector = fn(inner_type: msg::Any) -> Option<OpCreator>;
@ -77,7 +75,7 @@ fn empty_buf() -> Buf {
/// control corresponds to the first argument of Deno.core.dispatch(). /// control corresponds to the first argument of Deno.core.dispatch().
/// data corresponds to the second argument of Deno.core.dispatch(). /// data corresponds to the second argument of Deno.core.dispatch().
pub fn dispatch_all( pub fn dispatch_all(
state: &Arc<IsolateState>, state: &ThreadSafeState,
control: &[u8], control: &[u8],
zero_copy: deno_buf, zero_copy: deno_buf,
op_selector: OpSelector, op_selector: OpSelector,
@ -209,7 +207,7 @@ pub fn op_selector_std(inner_type: msg::Any) -> Option<OpCreator> {
// If the High precision flag is not set, the // If the High precision flag is not set, the
// nanoseconds are rounded on 2ms. // nanoseconds are rounded on 2ms.
fn op_now( fn op_now(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -245,7 +243,7 @@ fn op_now(
} }
fn op_is_tty( fn op_is_tty(
_state: &Arc<IsolateState>, _state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
_data: deno_buf, _data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -270,7 +268,7 @@ fn op_is_tty(
} }
fn op_exit( fn op_exit(
_state: &Arc<IsolateState>, _state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
_data: deno_buf, _data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -279,7 +277,7 @@ fn op_exit(
} }
fn op_start( fn op_start(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -335,7 +333,7 @@ fn op_start(
} }
fn op_format_error( fn op_format_error(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -394,7 +392,7 @@ pub fn odd_future(err: DenoError) -> Box<OpWithError> {
// https://github.com/denoland/deno/blob/golang/os.go#L100-L154 // https://github.com/denoland/deno/blob/golang/os.go#L100-L154
fn op_fetch_module_meta_data( fn op_fetch_module_meta_data(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -435,7 +433,7 @@ fn op_fetch_module_meta_data(
} }
fn op_chdir( fn op_chdir(
_state: &Arc<IsolateState>, _state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -449,7 +447,7 @@ fn op_chdir(
} }
fn op_global_timer_stop( fn op_global_timer_stop(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -462,7 +460,7 @@ fn op_global_timer_stop(
} }
fn op_global_timer( fn op_global_timer(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -495,7 +493,7 @@ fn op_global_timer(
} }
fn op_set_env( fn op_set_env(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -511,7 +509,7 @@ fn op_set_env(
} }
fn op_env( fn op_env(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -543,7 +541,7 @@ fn op_env(
} }
fn op_permissions( fn op_permissions(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -573,7 +571,7 @@ fn op_permissions(
} }
fn op_revoke_permission( fn op_revoke_permission(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -596,7 +594,7 @@ fn op_revoke_permission(
} }
fn op_fetch( fn op_fetch(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -683,7 +681,7 @@ where
} }
fn op_make_temp_dir( fn op_make_temp_dir(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -732,7 +730,7 @@ fn op_make_temp_dir(
} }
fn op_mkdir( fn op_mkdir(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -754,7 +752,7 @@ fn op_mkdir(
} }
fn op_chmod( fn op_chmod(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -793,7 +791,7 @@ fn op_chmod(
} }
fn op_open( fn op_open(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -883,7 +881,7 @@ fn op_open(
} }
fn op_close( fn op_close(
_state: &Arc<IsolateState>, _state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -900,7 +898,7 @@ fn op_close(
} }
fn op_shutdown( fn op_shutdown(
_state: &Arc<IsolateState>, _state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -926,7 +924,7 @@ fn op_shutdown(
} }
fn op_read( fn op_read(
_state: &Arc<IsolateState>, _state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -964,7 +962,7 @@ fn op_read(
} }
fn op_write( fn op_write(
_state: &Arc<IsolateState>, _state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1001,7 +999,7 @@ fn op_write(
} }
fn op_seek( fn op_seek(
_state: &Arc<IsolateState>, _state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1023,7 +1021,7 @@ fn op_seek(
} }
fn op_remove( fn op_remove(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1052,7 +1050,7 @@ fn op_remove(
} }
fn op_copy_file( fn op_copy_file(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1108,7 +1106,7 @@ fn get_mode(_perm: &fs::Permissions) -> u32 {
} }
fn op_cwd( fn op_cwd(
_state: &Arc<IsolateState>, _state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1134,7 +1132,7 @@ fn op_cwd(
} }
fn op_stat( fn op_stat(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1186,7 +1184,7 @@ fn op_stat(
} }
fn op_read_dir( fn op_read_dir(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1247,7 +1245,7 @@ fn op_read_dir(
} }
fn op_rename( fn op_rename(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1267,7 +1265,7 @@ fn op_rename(
} }
fn op_link( fn op_link(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1289,7 +1287,7 @@ fn op_link(
} }
fn op_symlink( fn op_symlink(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1318,7 +1316,7 @@ fn op_symlink(
} }
fn op_read_link( fn op_read_link(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1356,7 +1354,7 @@ fn op_read_link(
} }
fn op_repl_start( fn op_repl_start(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1387,7 +1385,7 @@ fn op_repl_start(
} }
fn op_repl_readline( fn op_repl_readline(
_state: &Arc<IsolateState>, _state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1423,7 +1421,7 @@ fn op_repl_readline(
} }
fn op_truncate( fn op_truncate(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1446,7 +1444,7 @@ fn op_truncate(
} }
fn op_listen( fn op_listen(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1508,7 +1506,7 @@ fn new_conn(cmd_id: u32, tcp_stream: TcpStream) -> OpResult {
} }
fn op_accept( fn op_accept(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1534,7 +1532,7 @@ fn op_accept(
} }
fn op_dial( fn op_dial(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1560,7 +1558,7 @@ fn op_dial(
} }
fn op_metrics( fn op_metrics(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1584,7 +1582,7 @@ fn op_metrics(
} }
fn op_resources( fn op_resources(
_state: &Arc<IsolateState>, _state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1636,7 +1634,7 @@ fn subprocess_stdio_map(v: msg::ProcessStdio) -> std::process::Stdio {
} }
fn op_run( fn op_run(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1709,7 +1707,7 @@ fn op_run(
} }
fn op_run_status( fn op_run_status(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1765,7 +1763,7 @@ fn op_run_status(
} }
struct GetMessageFuture { struct GetMessageFuture {
pub state: Arc<IsolateState>, pub state: ThreadSafeState,
} }
impl Future for GetMessageFuture { impl Future for GetMessageFuture {
@ -1782,7 +1780,7 @@ impl Future for GetMessageFuture {
/// Get message from host as guest worker /// Get message from host as guest worker
fn op_worker_get_message( fn op_worker_get_message(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1817,7 +1815,7 @@ fn op_worker_get_message(
/// Post message to host as guest worker /// Post message to host as guest worker
fn op_worker_post_message( fn op_worker_post_message(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1847,7 +1845,7 @@ fn op_worker_post_message(
/// Create worker as the host /// Create worker as the host
fn op_create_worker( fn op_create_worker(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1859,16 +1857,15 @@ fn op_create_worker(
Box::new(futures::future::result(move || -> OpResult { Box::new(futures::future::result(move || -> OpResult {
let parent_state = state.clone(); let parent_state = state.clone();
let child_state = Arc::new(IsolateState::new( let child_state = ThreadSafeState::new(
parent_state.flags.clone(), parent_state.flags.clone(),
parent_state.argv.clone(), parent_state.argv.clone(),
)); );
let rid = child_state.resource.rid; let rid = child_state.resource.rid;
let behavior = CliBehavior::new(child_state);
let name = format!("USER-WORKER-{}", specifier); let name = format!("USER-WORKER-{}", specifier);
let mut worker = let mut worker =
Worker::new(name, startup_data::deno_isolate_init(), behavior); Worker::new(name, startup_data::deno_isolate_init(), child_state);
js_check(worker.execute("denoMain()")); js_check(worker.execute("denoMain()"));
js_check(worker.execute("workerMain()")); js_check(worker.execute("workerMain()"));
let result = worker.execute_mod(specifier, false); let result = worker.execute_mod(specifier, false);
@ -1899,7 +1896,7 @@ fn op_create_worker(
/// Return when the worker closes /// Return when the worker closes
fn op_host_get_worker_closed( fn op_host_get_worker_closed(
state: &Arc<IsolateState>, state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1930,7 +1927,7 @@ fn op_host_get_worker_closed(
/// Get message from guest worker as host /// Get message from guest worker as host
fn op_host_get_message( fn op_host_get_message(
_state: &Arc<IsolateState>, _state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {
@ -1964,7 +1961,7 @@ fn op_host_get_message(
/// Post message to guest worker as host /// Post message to guest worker as host
fn op_host_post_message( fn op_host_post_message(
_state: &Arc<IsolateState>, _state: &ThreadSafeState,
base: &msg::Base<'_>, base: &msg::Base<'_>,
data: deno_buf, data: deno_buf,
) -> Box<OpWithError> { ) -> Box<OpWithError> {

View file

@ -13,8 +13,8 @@ use crate::errors::bad_resource;
use crate::errors::DenoError; use crate::errors::DenoError;
use crate::errors::DenoResult; use crate::errors::DenoResult;
use crate::http_body::HttpBody; use crate::http_body::HttpBody;
use crate::isolate_state::WorkerChannels;
use crate::repl::Repl; use crate::repl::Repl;
use crate::state::WorkerChannels;
use deno::Buf; use deno::Buf;

View file

@ -4,16 +4,22 @@ use crate::errors::DenoResult;
use crate::flags; use crate::flags;
use crate::global_timer::GlobalTimer; use crate::global_timer::GlobalTimer;
use crate::modules::Modules; use crate::modules::Modules;
use crate::ops;
use crate::permissions::DenoPermissions; use crate::permissions::DenoPermissions;
use crate::resources; use crate::resources;
use crate::resources::ResourceId; use crate::resources::ResourceId;
use crate::worker::Worker; use crate::worker::Worker;
use deno::deno_buf;
use deno::Buf; use deno::Buf;
use deno::Dispatch;
use deno::Op;
use futures::future::Shared; use futures::future::Shared;
use std; use std;
use std::collections::HashMap; use std::collections::HashMap;
use std::env; use std::env;
use std::ops::Deref;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use std::sync::Mutex; use std::sync::Mutex;
use std::time::Instant; use std::time::Instant;
use tokio::sync::mpsc as async_mpsc; use tokio::sync::mpsc as async_mpsc;
@ -34,12 +40,15 @@ pub struct Metrics {
pub resolve_count: AtomicUsize, pub resolve_count: AtomicUsize,
} }
// Isolate cannot be passed between threads but IsolateState can. // Wrap State so that it can implement Dispatch.
// IsolateState satisfies Send and Sync. pub struct ThreadSafeState(Arc<State>);
// Isolate cannot be passed between threads but ThreadSafeState can.
// ThreadSafeState satisfies Send and Sync.
// So any state that needs to be accessed outside the main V8 thread should be // So any state that needs to be accessed outside the main V8 thread should be
// inside IsolateState. // inside ThreadSafeState.
#[cfg_attr(feature = "cargo-clippy", allow(stutter))] #[cfg_attr(feature = "cargo-clippy", allow(stutter))]
pub struct IsolateState { pub struct State {
pub dir: deno_dir::DenoDir, pub dir: deno_dir::DenoDir,
pub argv: Vec<String>, pub argv: Vec<String>,
pub permissions: DenoPermissions, pub permissions: DenoPermissions,
@ -53,7 +62,30 @@ pub struct IsolateState {
pub resource: resources::Resource, pub resource: resources::Resource,
} }
impl IsolateState { impl Clone for ThreadSafeState {
fn clone(&self) -> Self {
ThreadSafeState(self.0.clone())
}
}
impl Deref for ThreadSafeState {
type Target = Arc<State>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Dispatch for ThreadSafeState {
fn dispatch(
&mut self,
control: &[u8],
zero_copy: deno_buf,
) -> (bool, Box<Op>) {
ops::dispatch_all(self, control, zero_copy, ops::op_selector_std)
}
}
impl ThreadSafeState {
pub fn new(flags: flags::DenoFlags, argv_rest: Vec<String>) -> Self { pub fn new(flags: flags::DenoFlags, argv_rest: Vec<String>) -> Self {
let custom_root = env::var("DENO_DIR").map(|s| s.into()).ok(); let custom_root = env::var("DENO_DIR").map(|s| s.into()).ok();
@ -63,7 +95,7 @@ impl IsolateState {
let external_channels = (worker_in_tx, worker_out_rx); let external_channels = (worker_in_tx, worker_out_rx);
let resource = resources::add_worker(external_channels); let resource = resources::add_worker(external_channels);
Self { ThreadSafeState(Arc::new(State {
dir: deno_dir::DenoDir::new(custom_root).unwrap(), dir: deno_dir::DenoDir::new(custom_root).unwrap(),
argv: argv_rest, argv: argv_rest,
permissions: DenoPermissions::from_flags(&flags), permissions: DenoPermissions::from_flags(&flags),
@ -75,7 +107,7 @@ impl IsolateState {
workers: Mutex::new(UserWorkerTable::new()), workers: Mutex::new(UserWorkerTable::new()),
start_time: Instant::now(), start_time: Instant::now(),
resource, resource,
} }))
} }
/// Read main module from argv /// Read main module from argv
@ -121,11 +153,11 @@ impl IsolateState {
} }
#[cfg(test)] #[cfg(test)]
pub fn mock() -> IsolateState { pub fn mock() -> ThreadSafeState {
let argv = vec![String::from("./deno"), String::from("hello.js")]; let argv = vec![String::from("./deno"), String::from("hello.js")];
// For debugging: argv.push_back(String::from("-D")); // For debugging: argv.push_back(String::from("-D"));
let (flags, rest_argv) = flags::set_flags(argv).unwrap(); let (flags, rest_argv) = flags::set_flags(argv).unwrap();
IsolateState::new(flags, rest_argv) ThreadSafeState::new(flags, rest_argv)
} }
pub fn metrics_op_dispatched( pub fn metrics_op_dispatched(
@ -152,3 +184,9 @@ impl IsolateState {
.fetch_add(bytes_received, Ordering::SeqCst); .fetch_add(bytes_received, Ordering::SeqCst);
} }
} }
#[test]
fn thread_safe() {
fn f<S: Send + Sync>(_: S) {}
f(ThreadSafeState::mock());
}

View file

@ -1,13 +1,12 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
use crate::cli_behavior::CliBehavior;
use crate::compiler::compile_async; use crate::compiler::compile_async;
use crate::compiler::ModuleMetaData; use crate::compiler::ModuleMetaData;
use crate::errors::DenoError; use crate::errors::DenoError;
use crate::errors::RustOrJsError; use crate::errors::RustOrJsError;
use crate::isolate_state::IsolateState;
use crate::js_errors; use crate::js_errors;
use crate::js_errors::JSErrorColor; use crate::js_errors::JSErrorColor;
use crate::msg; use crate::msg;
use crate::state::ThreadSafeState;
use crate::tokio_util; use crate::tokio_util;
use deno; use deno;
use deno::deno_mod; use deno::deno_mod;
@ -17,24 +16,23 @@ use futures::future::Either;
use futures::Async; use futures::Async;
use futures::Future; use futures::Future;
use std::sync::atomic::Ordering; use std::sync::atomic::Ordering;
use std::sync::Arc;
/// Wraps deno::Isolate to provide source maps, ops for the CLI, and /// Wraps deno::Isolate to provide source maps, ops for the CLI, and
/// high-level module loading /// high-level module loading
pub struct Worker { pub struct Worker {
inner: deno::Isolate<CliBehavior>, inner: deno::Isolate<ThreadSafeState>,
state: Arc<IsolateState>, state: ThreadSafeState,
} }
impl Worker { impl Worker {
pub fn new( pub fn new(
_name: String, _name: String,
startup_data: StartupData, startup_data: StartupData,
behavior: CliBehavior, state: ThreadSafeState,
) -> Worker { ) -> Worker {
let state = behavior.state.clone(); let state_ = state.clone();
Self { Self {
inner: deno::Isolate::new(startup_data, behavior), inner: deno::Isolate::new(startup_data, state_),
state, state,
} }
} }
@ -107,7 +105,7 @@ impl Worker {
js_filename: &str, js_filename: &str,
is_prefetch: bool, is_prefetch: bool,
) -> Result<(), RustOrJsError> { ) -> Result<(), RustOrJsError> {
// TODO move isolate_state::execute_mod impl here. // TODO move state::execute_mod impl here.
self self
.execute_mod_inner(js_filename, is_prefetch) .execute_mod_inner(js_filename, is_prefetch)
.map_err(|err| match err { .map_err(|err| match err {
@ -204,7 +202,7 @@ impl Future for Worker {
} }
fn fetch_module_meta_data_and_maybe_compile_async( fn fetch_module_meta_data_and_maybe_compile_async(
state: &Arc<IsolateState>, state: &ThreadSafeState,
specifier: &str, specifier: &str,
referrer: &str, referrer: &str,
) -> impl Future<Item = ModuleMetaData, Error = DenoError> { ) -> impl Future<Item = ModuleMetaData, Error = DenoError> {
@ -239,7 +237,7 @@ fn fetch_module_meta_data_and_maybe_compile_async(
} }
fn fetch_module_meta_data_and_maybe_compile( fn fetch_module_meta_data_and_maybe_compile(
state: &Arc<IsolateState>, state: &ThreadSafeState,
specifier: &str, specifier: &str,
referrer: &str, referrer: &str,
) -> Result<ModuleMetaData, DenoError> { ) -> Result<ModuleMetaData, DenoError> {
@ -251,11 +249,10 @@ fn fetch_module_meta_data_and_maybe_compile(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::cli_behavior::CliBehavior;
use crate::flags; use crate::flags;
use crate::isolate_state::IsolateState;
use crate::resources; use crate::resources;
use crate::startup_data; use crate::startup_data;
use crate::state::ThreadSafeState;
use crate::tokio_util; use crate::tokio_util;
use deno::js_check; use deno::js_check;
use futures::future::lazy; use futures::future::lazy;
@ -272,11 +269,11 @@ mod tests {
let argv = vec![String::from("./deno"), filename.clone()]; let argv = vec![String::from("./deno"), filename.clone()];
let (flags, rest_argv) = flags::set_flags(argv).unwrap(); let (flags, rest_argv) = flags::set_flags(argv).unwrap();
let state = Arc::new(IsolateState::new(flags, rest_argv)); let state = ThreadSafeState::new(flags, rest_argv);
let state_ = state.clone(); let state_ = state.clone();
tokio_util::run(lazy(move || { tokio_util::run(lazy(move || {
let cli = CliBehavior::new(state.clone()); let mut worker =
let mut worker = Worker::new("TEST".to_string(), StartupData::None, cli); Worker::new("TEST".to_string(), StartupData::None, state);
if let Err(err) = worker.execute_mod(&filename, false) { if let Err(err) = worker.execute_mod(&filename, false) {
eprintln!("execute_mod err {:?}", err); eprintln!("execute_mod err {:?}", err);
} }
@ -295,11 +292,11 @@ mod tests {
let argv = vec![String::from("./deno"), filename.clone()]; let argv = vec![String::from("./deno"), filename.clone()];
let (flags, rest_argv) = flags::set_flags(argv).unwrap(); let (flags, rest_argv) = flags::set_flags(argv).unwrap();
let state = Arc::new(IsolateState::new(flags, rest_argv)); let state = ThreadSafeState::new(flags, rest_argv);
let state_ = state.clone(); let state_ = state.clone();
tokio_util::run(lazy(move || { tokio_util::run(lazy(move || {
let cli = CliBehavior::new(state.clone()); let mut worker =
let mut worker = Worker::new("TEST".to_string(), StartupData::None, cli); Worker::new("TEST".to_string(), StartupData::None, state);
if let Err(err) = worker.execute_mod(&filename, false) { if let Err(err) = worker.execute_mod(&filename, false) {
eprintln!("execute_mod err {:?}", err); eprintln!("execute_mod err {:?}", err);
} }
@ -311,10 +308,9 @@ mod tests {
} }
fn create_test_worker() -> Worker { fn create_test_worker() -> Worker {
let state = Arc::new(IsolateState::mock()); let state = ThreadSafeState::mock();
let cli = CliBehavior::new(state.clone());
let mut worker = let mut worker =
Worker::new("TEST".to_string(), startup_data::deno_isolate_init(), cli); Worker::new("TEST".to_string(), startup_data::deno_isolate_init(), state);
js_check(worker.execute("denoMain()")); js_check(worker.execute("denoMain()"));
js_check(worker.execute("workerMain()")); js_check(worker.execute("workerMain()"));
worker worker

View file

@ -4,7 +4,7 @@ This Rust crate contains the essential V8 bindings for Deno's command-line
interface (Deno CLI). The main abstraction here is the Isolate which proivdes a interface (Deno CLI). The main abstraction here is the Isolate which proivdes a
way to execute JavaScript. The Isolate is modeled as a way to execute JavaScript. The Isolate is modeled as a
`Future<Item=(), Error=JSError>` which completes once all of its ops have `Future<Item=(), Error=JSError>` which completes once all of its ops have
completed. The user must define what an Op is by implementing the `Behavior` completed. The user must define what an Op is by implementing the `Dispatch`
trait, and by doing so define any "built-in" functionality that would be trait, and by doing so define any "built-in" functionality that would be
provided by the VM. Ops are triggered by `Deno.core.dispatch()`. provided by the VM. Ops are triggered by `Deno.core.dispatch()`.

View file

@ -98,7 +98,7 @@ pub type HttpBenchOp = dyn Future<Item = i32, Error = std::io::Error> + Send;
struct HttpBench(); struct HttpBench();
impl Behavior for HttpBench { impl Dispatch for HttpBench {
fn dispatch( fn dispatch(
&mut self, &mut self,
control: &[u8], control: &[u8],

View file

@ -66,10 +66,8 @@ pub enum StartupData<'a> {
None, None,
} }
/// Defines the behavior of an Isolate. /// Defines the how Deno.core.dispatch() acts.
// TODO(ry) Now that Behavior only has the dispatch method, it should be renamed pub trait Dispatch {
// to Dispatcher.
pub trait Behavior {
/// Called whenever Deno.core.dispatch() is called in JavaScript. zero_copy_buf /// Called whenever Deno.core.dispatch() is called in JavaScript. zero_copy_buf
/// corresponds to the second argument of Deno.core.dispatch(). /// corresponds to the second argument of Deno.core.dispatch().
fn dispatch( fn dispatch(
@ -85,21 +83,21 @@ pub trait Behavior {
/// pending ops have completed. /// pending ops have completed.
/// ///
/// Ops are created in JavaScript by calling Deno.core.dispatch(), and in Rust /// Ops are created in JavaScript by calling Deno.core.dispatch(), and in Rust
/// by implementing deno::Behavior::dispatch. An Op corresponds exactly to a /// by implementing deno::Dispatch::dispatch. An Op corresponds exactly to a
/// Promise in JavaScript. /// Promise in JavaScript.
pub struct Isolate<B: Behavior> { pub struct Isolate<B: Dispatch> {
libdeno_isolate: *const libdeno::isolate, libdeno_isolate: *const libdeno::isolate,
shared_libdeno_isolate: Arc<Mutex<Option<*const libdeno::isolate>>>, shared_libdeno_isolate: Arc<Mutex<Option<*const libdeno::isolate>>>,
behavior: B, dispatcher: B,
needs_init: bool, needs_init: bool,
shared: SharedQueue, shared: SharedQueue,
pending_ops: VecDeque<PendingOp>, pending_ops: VecDeque<PendingOp>,
polled_recently: bool, polled_recently: bool,
} }
unsafe impl<B: Behavior> Send for Isolate<B> {} unsafe impl<B: Dispatch> Send for Isolate<B> {}
impl<B: Behavior> Drop for Isolate<B> { impl<B: Dispatch> Drop for Isolate<B> {
fn drop(&mut self) { fn drop(&mut self) {
// remove shared_libdeno_isolate reference // remove shared_libdeno_isolate reference
*self.shared_libdeno_isolate.lock().unwrap() = None; *self.shared_libdeno_isolate.lock().unwrap() = None;
@ -110,10 +108,10 @@ impl<B: Behavior> Drop for Isolate<B> {
static DENO_INIT: Once = ONCE_INIT; static DENO_INIT: Once = ONCE_INIT;
impl<B: Behavior> Isolate<B> { impl<B: Dispatch> Isolate<B> {
/// startup_data defines the snapshot or script used at startup to initalize /// startup_data defines the snapshot or script used at startup to initalize
/// the isolate. /// the isolate.
pub fn new(startup_data: StartupData, behavior: B) -> Self { pub fn new(startup_data: StartupData, dispatcher: B) -> Self {
DENO_INIT.call_once(|| { DENO_INIT.call_once(|| {
unsafe { libdeno::deno_init() }; unsafe { libdeno::deno_init() };
}); });
@ -141,7 +139,7 @@ impl<B: Behavior> Isolate<B> {
let mut core_isolate = Self { let mut core_isolate = Self {
libdeno_isolate, libdeno_isolate,
shared_libdeno_isolate: Arc::new(Mutex::new(Some(libdeno_isolate))), shared_libdeno_isolate: Arc::new(Mutex::new(Some(libdeno_isolate))),
behavior, dispatcher,
shared, shared,
needs_init, needs_init,
pending_ops: VecDeque::new(), pending_ops: VecDeque::new(),
@ -186,11 +184,11 @@ impl<B: Behavior> Isolate<B> {
let (is_sync, op) = if control_argv0.len() > 0 { let (is_sync, op) = if control_argv0.len() > 0 {
// The user called Deno.core.send(control) // The user called Deno.core.send(control)
isolate isolate
.behavior .dispatcher
.dispatch(control_argv0.as_ref(), zero_copy_buf) .dispatch(control_argv0.as_ref(), zero_copy_buf)
} else if let Some(c) = control_shared { } else if let Some(c) = control_shared {
// The user called Deno.sharedQueue.push(control) // The user called Deno.sharedQueue.push(control)
isolate.behavior.dispatch(&c, zero_copy_buf) isolate.dispatcher.dispatch(&c, zero_copy_buf)
} else { } else {
// The sharedQueue is empty. The shouldn't happen usually, but it's also // The sharedQueue is empty. The shouldn't happen usually, but it's also
// not technically a failure. // not technically a failure.
@ -366,7 +364,7 @@ impl<'a> ResolveContext<'a> {
} }
} }
impl<B: Behavior> Isolate<B> { impl<B: Dispatch> Isolate<B> {
pub fn mod_instantiate( pub fn mod_instantiate(
&mut self, &mut self,
id: deno_mod, id: deno_mod,
@ -432,7 +430,7 @@ impl Drop for LockerScope {
} }
} }
impl<B: Behavior> Future for Isolate<B> { impl<B: Dispatch> Future for Isolate<B> {
type Item = (); type Item = ();
type Error = JSError; type Error = JSError;
@ -540,7 +538,7 @@ pub mod tests {
use super::*; use super::*;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
pub enum TestBehaviorMode { pub enum TestDispatchMode {
AsyncImmediate, AsyncImmediate,
OverflowReqSync, OverflowReqSync,
OverflowResSync, OverflowResSync,
@ -548,16 +546,16 @@ pub mod tests {
OverflowResAsync, OverflowResAsync,
} }
pub struct TestBehavior { pub struct TestDispatch {
pub dispatch_count: usize, pub dispatch_count: usize,
mode: TestBehaviorMode, mode: TestDispatchMode,
} }
impl TestBehavior { impl TestDispatch {
pub fn setup(mode: TestBehaviorMode) -> Isolate<Self> { pub fn setup(mode: TestDispatchMode) -> Isolate<Self> {
let mut isolate = Isolate::new( let mut isolate = Isolate::new(
StartupData::None, StartupData::None,
TestBehavior { TestDispatch {
dispatch_count: 0, dispatch_count: 0,
mode, mode,
}, },
@ -572,12 +570,12 @@ pub mod tests {
} }
"#, "#,
)); ));
assert_eq!(isolate.behavior.dispatch_count, 0); assert_eq!(isolate.dispatcher.dispatch_count, 0);
isolate isolate
} }
} }
impl Behavior for TestBehavior { impl Dispatch for TestDispatch {
fn dispatch( fn dispatch(
&mut self, &mut self,
control: &[u8], control: &[u8],
@ -585,18 +583,18 @@ pub mod tests {
) -> (bool, Box<Op>) { ) -> (bool, Box<Op>) {
self.dispatch_count += 1; self.dispatch_count += 1;
match self.mode { match self.mode {
TestBehaviorMode::AsyncImmediate => { TestDispatchMode::AsyncImmediate => {
assert_eq!(control.len(), 1); assert_eq!(control.len(), 1);
assert_eq!(control[0], 42); assert_eq!(control[0], 42);
let buf = vec![43u8].into_boxed_slice(); let buf = vec![43u8].into_boxed_slice();
(false, Box::new(futures::future::ok(buf))) (false, Box::new(futures::future::ok(buf)))
} }
TestBehaviorMode::OverflowReqSync => { TestDispatchMode::OverflowReqSync => {
assert_eq!(control.len(), 100 * 1024 * 1024); assert_eq!(control.len(), 100 * 1024 * 1024);
let buf = vec![43u8].into_boxed_slice(); let buf = vec![43u8].into_boxed_slice();
(true, Box::new(futures::future::ok(buf))) (true, Box::new(futures::future::ok(buf)))
} }
TestBehaviorMode::OverflowResSync => { TestDispatchMode::OverflowResSync => {
assert_eq!(control.len(), 1); assert_eq!(control.len(), 1);
assert_eq!(control[0], 42); assert_eq!(control[0], 42);
let mut vec = Vec::<u8>::new(); let mut vec = Vec::<u8>::new();
@ -605,12 +603,12 @@ pub mod tests {
let buf = vec.into_boxed_slice(); let buf = vec.into_boxed_slice();
(true, Box::new(futures::future::ok(buf))) (true, Box::new(futures::future::ok(buf)))
} }
TestBehaviorMode::OverflowReqAsync => { TestDispatchMode::OverflowReqAsync => {
assert_eq!(control.len(), 100 * 1024 * 1024); assert_eq!(control.len(), 100 * 1024 * 1024);
let buf = vec![43u8].into_boxed_slice(); let buf = vec![43u8].into_boxed_slice();
(false, Box::new(futures::future::ok(buf))) (false, Box::new(futures::future::ok(buf)))
} }
TestBehaviorMode::OverflowResAsync => { TestDispatchMode::OverflowResAsync => {
assert_eq!(control.len(), 1); assert_eq!(control.len(), 1);
assert_eq!(control[0], 42); assert_eq!(control[0], 42);
let mut vec = Vec::<u8>::new(); let mut vec = Vec::<u8>::new();
@ -625,7 +623,7 @@ pub mod tests {
#[test] #[test]
fn test_dispatch() { fn test_dispatch() {
let mut isolate = TestBehavior::setup(TestBehaviorMode::AsyncImmediate); let mut isolate = TestDispatch::setup(TestDispatchMode::AsyncImmediate);
js_check(isolate.execute( js_check(isolate.execute(
"filename.js", "filename.js",
r#" r#"
@ -637,12 +635,12 @@ pub mod tests {
main(); main();
"#, "#,
)); ));
assert_eq!(isolate.behavior.dispatch_count, 2); assert_eq!(isolate.dispatcher.dispatch_count, 2);
} }
#[test] #[test]
fn test_mods() { fn test_mods() {
let mut isolate = TestBehavior::setup(TestBehaviorMode::AsyncImmediate); let mut isolate = TestDispatch::setup(TestDispatchMode::AsyncImmediate);
let mod_a = isolate let mod_a = isolate
.mod_new( .mod_new(
true, true,
@ -654,7 +652,7 @@ pub mod tests {
Deno.core.send(control); Deno.core.send(control);
"#, "#,
).unwrap(); ).unwrap();
assert_eq!(isolate.behavior.dispatch_count, 0); assert_eq!(isolate.dispatcher.dispatch_count, 0);
let imports = isolate.mod_get_imports(mod_a); let imports = isolate.mod_get_imports(mod_a);
assert_eq!(imports, vec!["b.js".to_string()]); assert_eq!(imports, vec!["b.js".to_string()]);
@ -675,21 +673,21 @@ pub mod tests {
}; };
js_check(isolate.mod_instantiate(mod_b, &mut resolve)); js_check(isolate.mod_instantiate(mod_b, &mut resolve));
assert_eq!(isolate.behavior.dispatch_count, 0); assert_eq!(isolate.dispatcher.dispatch_count, 0);
assert_eq!(resolve_count.load(Ordering::SeqCst), 0); assert_eq!(resolve_count.load(Ordering::SeqCst), 0);
js_check(isolate.mod_instantiate(mod_a, &mut resolve)); js_check(isolate.mod_instantiate(mod_a, &mut resolve));
assert_eq!(isolate.behavior.dispatch_count, 0); assert_eq!(isolate.dispatcher.dispatch_count, 0);
assert_eq!(resolve_count.load(Ordering::SeqCst), 1); assert_eq!(resolve_count.load(Ordering::SeqCst), 1);
js_check(isolate.mod_evaluate(mod_a)); js_check(isolate.mod_evaluate(mod_a));
assert_eq!(isolate.behavior.dispatch_count, 1); assert_eq!(isolate.dispatcher.dispatch_count, 1);
assert_eq!(resolve_count.load(Ordering::SeqCst), 1); assert_eq!(resolve_count.load(Ordering::SeqCst), 1);
} }
#[test] #[test]
fn test_poll_async_immediate_ops() { fn test_poll_async_immediate_ops() {
let mut isolate = TestBehavior::setup(TestBehaviorMode::AsyncImmediate); let mut isolate = TestDispatch::setup(TestDispatchMode::AsyncImmediate);
js_check(isolate.execute( js_check(isolate.execute(
"setup2.js", "setup2.js",
@ -700,7 +698,7 @@ pub mod tests {
}); });
"#, "#,
)); ));
assert_eq!(isolate.behavior.dispatch_count, 0); assert_eq!(isolate.dispatcher.dispatch_count, 0);
js_check(isolate.execute( js_check(isolate.execute(
"check1.js", "check1.js",
r#" r#"
@ -710,9 +708,9 @@ pub mod tests {
assert(nrecv == 0); assert(nrecv == 0);
"#, "#,
)); ));
assert_eq!(isolate.behavior.dispatch_count, 1); assert_eq!(isolate.dispatcher.dispatch_count, 1);
assert_eq!(Ok(Async::Ready(())), isolate.poll()); assert_eq!(Ok(Async::Ready(())), isolate.poll());
assert_eq!(isolate.behavior.dispatch_count, 1); assert_eq!(isolate.dispatcher.dispatch_count, 1);
js_check(isolate.execute( js_check(isolate.execute(
"check2.js", "check2.js",
r#" r#"
@ -721,17 +719,17 @@ pub mod tests {
assert(nrecv == 1); assert(nrecv == 1);
"#, "#,
)); ));
assert_eq!(isolate.behavior.dispatch_count, 2); assert_eq!(isolate.dispatcher.dispatch_count, 2);
assert_eq!(Ok(Async::Ready(())), isolate.poll()); assert_eq!(Ok(Async::Ready(())), isolate.poll());
js_check(isolate.execute("check3.js", "assert(nrecv == 2)")); js_check(isolate.execute("check3.js", "assert(nrecv == 2)"));
assert_eq!(isolate.behavior.dispatch_count, 2); assert_eq!(isolate.dispatcher.dispatch_count, 2);
// We are idle, so the next poll should be the last. // We are idle, so the next poll should be the last.
assert_eq!(Ok(Async::Ready(())), isolate.poll()); assert_eq!(Ok(Async::Ready(())), isolate.poll());
} }
#[test] #[test]
fn test_shared() { fn test_shared() {
let mut isolate = TestBehavior::setup(TestBehaviorMode::AsyncImmediate); let mut isolate = TestDispatch::setup(TestDispatchMode::AsyncImmediate);
js_check(isolate.execute( js_check(isolate.execute(
"setup2.js", "setup2.js",
@ -744,7 +742,7 @@ pub mod tests {
}); });
"#, "#,
)); ));
assert_eq!(isolate.behavior.dispatch_count, 0); assert_eq!(isolate.dispatcher.dispatch_count, 0);
js_check(isolate.execute( js_check(isolate.execute(
"send1.js", "send1.js",
@ -759,7 +757,7 @@ pub mod tests {
assert(nrecv === 0); assert(nrecv === 0);
"#, "#,
)); ));
assert_eq!(isolate.behavior.dispatch_count, 2); assert_eq!(isolate.dispatcher.dispatch_count, 2);
assert_eq!(Ok(Async::Ready(())), isolate.poll()); assert_eq!(Ok(Async::Ready(())), isolate.poll());
js_check(isolate.execute("send1.js", "assert(nrecv === 2);")); js_check(isolate.execute("send1.js", "assert(nrecv === 2);"));
@ -770,7 +768,7 @@ pub mod tests {
let (tx, rx) = std::sync::mpsc::channel::<bool>(); let (tx, rx) = std::sync::mpsc::channel::<bool>();
let tx_clone = tx.clone(); let tx_clone = tx.clone();
let mut isolate = TestBehavior::setup(TestBehaviorMode::AsyncImmediate); let mut isolate = TestDispatch::setup(TestDispatchMode::AsyncImmediate);
let shared = isolate.shared_isolate_handle(); let shared = isolate.shared_isolate_handle();
let t1 = std::thread::spawn(move || { let t1 = std::thread::spawn(move || {
@ -827,7 +825,7 @@ pub mod tests {
fn dangling_shared_isolate() { fn dangling_shared_isolate() {
let shared = { let shared = {
// isolate is dropped at the end of this block // isolate is dropped at the end of this block
let mut isolate = TestBehavior::setup(TestBehaviorMode::AsyncImmediate); let mut isolate = TestDispatch::setup(TestDispatchMode::AsyncImmediate);
isolate.shared_isolate_handle() isolate.shared_isolate_handle()
}; };
@ -837,7 +835,7 @@ pub mod tests {
#[test] #[test]
fn overflow_req_sync() { fn overflow_req_sync() {
let mut isolate = TestBehavior::setup(TestBehaviorMode::OverflowReqSync); let mut isolate = TestDispatch::setup(TestDispatchMode::OverflowReqSync);
js_check(isolate.execute( js_check(isolate.execute(
"overflow_req_sync.js", "overflow_req_sync.js",
r#" r#"
@ -852,14 +850,14 @@ pub mod tests {
assert(asyncRecv == 0); assert(asyncRecv == 0);
"#, "#,
)); ));
assert_eq!(isolate.behavior.dispatch_count, 1); assert_eq!(isolate.dispatcher.dispatch_count, 1);
} }
#[test] #[test]
fn overflow_res_sync() { fn overflow_res_sync() {
// TODO(ry) This test is quite slow due to memcpy-ing 100MB into JS. We // TODO(ry) This test is quite slow due to memcpy-ing 100MB into JS. We
// should optimize this. // should optimize this.
let mut isolate = TestBehavior::setup(TestBehaviorMode::OverflowResSync); let mut isolate = TestDispatch::setup(TestDispatchMode::OverflowResSync);
js_check(isolate.execute( js_check(isolate.execute(
"overflow_res_sync.js", "overflow_res_sync.js",
r#" r#"
@ -874,12 +872,12 @@ pub mod tests {
assert(asyncRecv == 0); assert(asyncRecv == 0);
"#, "#,
)); ));
assert_eq!(isolate.behavior.dispatch_count, 1); assert_eq!(isolate.dispatcher.dispatch_count, 1);
} }
#[test] #[test]
fn overflow_req_async() { fn overflow_req_async() {
let mut isolate = TestBehavior::setup(TestBehaviorMode::OverflowReqAsync); let mut isolate = TestDispatch::setup(TestDispatchMode::OverflowReqAsync);
js_check(isolate.execute( js_check(isolate.execute(
"overflow_req_async.js", "overflow_req_async.js",
r#" r#"
@ -897,7 +895,7 @@ pub mod tests {
assert(asyncRecv == 0); assert(asyncRecv == 0);
"#, "#,
)); ));
assert_eq!(isolate.behavior.dispatch_count, 1); assert_eq!(isolate.dispatcher.dispatch_count, 1);
assert_eq!(Ok(Async::Ready(())), isolate.poll()); assert_eq!(Ok(Async::Ready(())), isolate.poll());
js_check(isolate.execute("check.js", "assert(asyncRecv == 1);")); js_check(isolate.execute("check.js", "assert(asyncRecv == 1);"));
} }
@ -906,7 +904,7 @@ pub mod tests {
fn overflow_res_async() { fn overflow_res_async() {
// TODO(ry) This test is quite slow due to memcpy-ing 100MB into JS. We // TODO(ry) This test is quite slow due to memcpy-ing 100MB into JS. We
// should optimize this. // should optimize this.
let mut isolate = TestBehavior::setup(TestBehaviorMode::OverflowResAsync); let mut isolate = TestDispatch::setup(TestDispatchMode::OverflowResAsync);
js_check(isolate.execute( js_check(isolate.execute(
"overflow_res_async.js", "overflow_res_async.js",
r#" r#"
@ -923,7 +921,7 @@ pub mod tests {
assert(asyncRecv == 0); assert(asyncRecv == 0);
"#, "#,
)); ));
assert_eq!(isolate.behavior.dispatch_count, 1); assert_eq!(isolate.dispatcher.dispatch_count, 1);
assert_eq!(Ok(Async::Ready(())), isolate.poll()); assert_eq!(Ok(Async::Ready(())), isolate.poll());
js_check(isolate.execute("check.js", "assert(asyncRecv == 1);")); js_check(isolate.execute("check.js", "assert(asyncRecv == 1);"));
} }
@ -932,7 +930,7 @@ pub mod tests {
fn overflow_res_multiple_dispatch_async() { fn overflow_res_multiple_dispatch_async() {
// TODO(ry) This test is quite slow due to memcpy-ing 100MB into JS. We // TODO(ry) This test is quite slow due to memcpy-ing 100MB into JS. We
// should optimize this. // should optimize this.
let mut isolate = TestBehavior::setup(TestBehaviorMode::OverflowResAsync); let mut isolate = TestDispatch::setup(TestDispatchMode::OverflowResAsync);
js_check(isolate.execute( js_check(isolate.execute(
"overflow_res_multiple_dispatch_async.js", "overflow_res_multiple_dispatch_async.js",
r#" r#"
@ -952,14 +950,14 @@ pub mod tests {
Deno.core.dispatch(control); Deno.core.dispatch(control);
"#, "#,
)); ));
assert_eq!(isolate.behavior.dispatch_count, 2); assert_eq!(isolate.dispatcher.dispatch_count, 2);
assert_eq!(Ok(Async::Ready(())), isolate.poll()); assert_eq!(Ok(Async::Ready(())), isolate.poll());
js_check(isolate.execute("check.js", "assert(asyncRecv == 2);")); js_check(isolate.execute("check.js", "assert(asyncRecv == 2);"));
} }
#[test] #[test]
fn test_js() { fn test_js() {
let mut isolate = TestBehavior::setup(TestBehaviorMode::AsyncImmediate); let mut isolate = TestDispatch::setup(TestDispatchMode::AsyncImmediate);
js_check( js_check(
isolate isolate
.execute("shared_queue_test.js", include_str!("shared_queue_test.js")), .execute("shared_queue_test.js", include_str!("shared_queue_test.js")),

View file

@ -18,7 +18,7 @@ use std::collections::HashMap;
pub type SourceCodeFuture<E> = dyn Future<Item = String, Error = E> + Send; pub type SourceCodeFuture<E> = dyn Future<Item = String, Error = E> + Send;
pub trait Loader { pub trait Loader {
type Behavior: crate::isolate::Behavior; type Dispatch: crate::isolate::Dispatch;
type Error: std::error::Error + 'static; type Error: std::error::Error + 'static;
/// Returns an absolute URL. /// Returns an absolute URL.
@ -32,9 +32,9 @@ pub trait Loader {
fn isolate_and_modules<'a: 'b + 'c, 'b, 'c>( fn isolate_and_modules<'a: 'b + 'c, 'b, 'c>(
&'a mut self, &'a mut self,
) -> (&'b mut Isolate<Self::Behavior>, &'c mut Modules); ) -> (&'b mut Isolate<Self::Dispatch>, &'c mut Modules);
fn isolate<'a: 'b, 'b>(&'a mut self) -> &'b mut Isolate<Self::Behavior> { fn isolate<'a: 'b, 'b>(&'a mut self) -> &'b mut Isolate<Self::Dispatch> {
let (isolate, _) = self.isolate_and_modules(); let (isolate, _) = self.isolate_and_modules();
isolate isolate
} }
@ -262,14 +262,14 @@ mod tests {
struct MockLoader { struct MockLoader {
pub loads: Vec<String>, pub loads: Vec<String>,
pub isolate: Isolate<TestBehavior>, pub isolate: Isolate<TestDispatch>,
pub modules: Modules, pub modules: Modules,
} }
impl MockLoader { impl MockLoader {
fn new() -> Self { fn new() -> Self {
let modules = Modules::new(); let modules = Modules::new();
let isolate = TestBehavior::setup(TestBehaviorMode::AsyncImmediate); let isolate = TestDispatch::setup(TestDispatchMode::AsyncImmediate);
Self { Self {
loads: Vec::new(), loads: Vec::new(),
isolate, isolate,
@ -279,7 +279,7 @@ mod tests {
} }
impl Loader for MockLoader { impl Loader for MockLoader {
type Behavior = TestBehavior; type Dispatch = TestDispatch;
type Error = std::io::Error; type Error = std::io::Error;
fn resolve(specifier: &str, _referrer: &str) -> String { fn resolve(specifier: &str, _referrer: &str) -> String {
@ -304,7 +304,7 @@ mod tests {
fn isolate_and_modules<'a: 'b + 'c, 'b, 'c>( fn isolate_and_modules<'a: 'b + 'c, 'b, 'c>(
&'a mut self, &'a mut self,
) -> (&'b mut Isolate<Self::Behavior>, &'c mut Modules) { ) -> (&'b mut Isolate<Self::Dispatch>, &'c mut Modules) {
(&mut self.isolate, &mut self.modules) (&mut self.isolate, &mut self.modules)
} }
} }