mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
use Isolate::register_op in deno_cli (#3039)
This commit is contained in:
parent
ffbf0c20cc
commit
75eeac03f3
8 changed files with 453 additions and 472 deletions
|
@ -1,5 +1,4 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
use crate::state::ThreadSafeState;
|
||||
use crate::tokio_util;
|
||||
use deno::*;
|
||||
use futures::Future;
|
||||
|
@ -23,12 +22,6 @@ fn json_err(err: ErrBox) -> Value {
|
|||
})
|
||||
}
|
||||
|
||||
pub type Dispatcher = fn(
|
||||
state: &ThreadSafeState,
|
||||
args: Value,
|
||||
zero_copy: Option<PinnedBuf>,
|
||||
) -> Result<JsonOp, ErrBox>;
|
||||
|
||||
fn serialize_result(
|
||||
promise_id: Option<u64>,
|
||||
result: Result<Value, ErrBox>,
|
||||
|
@ -50,37 +43,39 @@ struct AsyncArgs {
|
|||
promise_id: Option<u64>,
|
||||
}
|
||||
|
||||
pub fn dispatch(
|
||||
d: Dispatcher,
|
||||
state: &ThreadSafeState,
|
||||
control: &[u8],
|
||||
zero_copy: Option<PinnedBuf>,
|
||||
) -> CoreOp {
|
||||
let async_args: AsyncArgs = serde_json::from_slice(control).unwrap();
|
||||
let promise_id = async_args.promise_id;
|
||||
let is_sync = promise_id.is_none();
|
||||
pub fn json_op<D>(d: D) -> impl Fn(&[u8], Option<PinnedBuf>) -> CoreOp
|
||||
where
|
||||
D: Fn(Value, Option<PinnedBuf>) -> Result<JsonOp, ErrBox>,
|
||||
{
|
||||
move |control: &[u8], zero_copy: Option<PinnedBuf>| {
|
||||
let async_args: AsyncArgs = serde_json::from_slice(control).unwrap();
|
||||
let promise_id = async_args.promise_id;
|
||||
let is_sync = promise_id.is_none();
|
||||
|
||||
let result = serde_json::from_slice(control)
|
||||
.map_err(ErrBox::from)
|
||||
.and_then(move |args| d(state, args, zero_copy));
|
||||
match result {
|
||||
Ok(JsonOp::Sync(sync_value)) => {
|
||||
assert!(promise_id.is_none());
|
||||
CoreOp::Sync(serialize_result(promise_id, Ok(sync_value)))
|
||||
}
|
||||
Ok(JsonOp::Async(fut)) => {
|
||||
assert!(promise_id.is_some());
|
||||
let fut2 = Box::new(fut.then(move |result| -> Result<Buf, ()> {
|
||||
Ok(serialize_result(promise_id, result))
|
||||
}));
|
||||
CoreOp::Async(fut2)
|
||||
}
|
||||
Err(sync_err) => {
|
||||
let buf = serialize_result(promise_id, Err(sync_err));
|
||||
if is_sync {
|
||||
CoreOp::Sync(buf)
|
||||
} else {
|
||||
CoreOp::Async(Box::new(futures::future::ok(buf)))
|
||||
let result = serde_json::from_slice(control)
|
||||
.map_err(ErrBox::from)
|
||||
.and_then(|args| d(args, zero_copy));
|
||||
|
||||
// Convert to CoreOp
|
||||
match result {
|
||||
Ok(JsonOp::Sync(sync_value)) => {
|
||||
assert!(promise_id.is_none());
|
||||
CoreOp::Sync(serialize_result(promise_id, Ok(sync_value)))
|
||||
}
|
||||
Ok(JsonOp::Async(fut)) => {
|
||||
assert!(promise_id.is_some());
|
||||
let fut2 = Box::new(fut.then(move |result| -> Result<Buf, ()> {
|
||||
Ok(serialize_result(promise_id, result))
|
||||
}));
|
||||
CoreOp::Async(fut2)
|
||||
}
|
||||
Err(sync_err) => {
|
||||
let buf = serialize_result(promise_id, Err(sync_err));
|
||||
if is_sync {
|
||||
CoreOp::Sync(buf)
|
||||
} else {
|
||||
CoreOp::Async(Box::new(futures::future::ok(buf)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
//! alternative to flatbuffers using a very simple list of int32s to lay out
|
||||
//! messages. The first i32 is used to determine if a message a flatbuffer
|
||||
//! message or a "minimal" message.
|
||||
use crate::state::ThreadSafeState;
|
||||
use deno::Buf;
|
||||
use deno::CoreOp;
|
||||
use deno::ErrBox;
|
||||
|
@ -72,40 +71,40 @@ fn test_parse_min_record() {
|
|||
assert_eq!(parse_min_record(&buf), None);
|
||||
}
|
||||
|
||||
pub fn dispatch(
|
||||
pub fn minimal_op(
|
||||
d: Dispatcher,
|
||||
_state: &ThreadSafeState,
|
||||
control: &[u8],
|
||||
zero_copy: Option<PinnedBuf>,
|
||||
) -> CoreOp {
|
||||
let mut record = parse_min_record(control).unwrap();
|
||||
let is_sync = record.promise_id == 0;
|
||||
let rid = record.arg;
|
||||
let min_op = d(rid, zero_copy);
|
||||
) -> impl Fn(&[u8], Option<PinnedBuf>) -> CoreOp {
|
||||
move |control: &[u8], zero_copy: Option<PinnedBuf>| {
|
||||
let mut record = parse_min_record(control).unwrap();
|
||||
let is_sync = record.promise_id == 0;
|
||||
let rid = record.arg;
|
||||
let min_op = d(rid, zero_copy);
|
||||
|
||||
let fut = Box::new(min_op.then(move |result| -> Result<Buf, ()> {
|
||||
match result {
|
||||
Ok(r) => {
|
||||
record.result = r;
|
||||
}
|
||||
Err(err) => {
|
||||
// TODO(ry) The dispatch_minimal doesn't properly pipe errors back to
|
||||
// the caller.
|
||||
debug!("swallowed err {}", err);
|
||||
record.result = -1;
|
||||
// Convert to CoreOp
|
||||
let fut = Box::new(min_op.then(move |result| -> Result<Buf, ()> {
|
||||
match result {
|
||||
Ok(r) => {
|
||||
record.result = r;
|
||||
}
|
||||
Err(err) => {
|
||||
// TODO(ry) The dispatch_minimal doesn't properly pipe errors back to
|
||||
// the caller.
|
||||
debug!("swallowed err {}", err);
|
||||
record.result = -1;
|
||||
}
|
||||
}
|
||||
Ok(record.into())
|
||||
}));
|
||||
|
||||
if is_sync {
|
||||
// Warning! Possible deadlocks can occur if we try to wait for a future
|
||||
// while in a future. The safe but expensive alternative is to use
|
||||
// tokio_util::block_on.
|
||||
// This block is only exercised for readSync and writeSync, which I think
|
||||
// works since they're simple polling futures.
|
||||
Op::Sync(fut.wait().unwrap())
|
||||
} else {
|
||||
Op::Async(fut)
|
||||
}
|
||||
Ok(record.into())
|
||||
}));
|
||||
|
||||
if is_sync {
|
||||
// Warning! Possible deadlocks can occur if we try to wait for a future
|
||||
// while in a future. The safe but expensive alternative is to use
|
||||
// tokio_util::block_on.
|
||||
// This block is only exercised for readSync and writeSync, which I think
|
||||
// works since they're simple polling futures.
|
||||
Op::Sync(fut.wait().unwrap())
|
||||
} else {
|
||||
Op::Async(fut)
|
||||
}
|
||||
}
|
||||
|
|
347
cli/ops/mod.rs
347
cli/ops/mod.rs
|
@ -1,332 +1,25 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
use crate::state::ThreadSafeState;
|
||||
use deno::*;
|
||||
|
||||
mod compiler;
|
||||
mod dispatch_json;
|
||||
mod dispatch_minimal;
|
||||
mod errors;
|
||||
mod fetch;
|
||||
mod files;
|
||||
mod fs;
|
||||
mod io;
|
||||
mod metrics;
|
||||
mod net;
|
||||
mod os;
|
||||
mod performance;
|
||||
mod permissions;
|
||||
mod process;
|
||||
mod random;
|
||||
mod repl;
|
||||
mod resources;
|
||||
mod timers;
|
||||
mod tls;
|
||||
mod workers;
|
||||
|
||||
// Warning! These values are duplicated in the TypeScript code (js/dispatch.ts),
|
||||
// update with care.
|
||||
pub const OP_READ: OpId = 1;
|
||||
pub const OP_WRITE: OpId = 2;
|
||||
pub const OP_EXIT: OpId = 3;
|
||||
pub const OP_IS_TTY: OpId = 4;
|
||||
pub const OP_ENV: OpId = 5;
|
||||
pub const OP_EXEC_PATH: OpId = 6;
|
||||
pub const OP_UTIME: OpId = 7;
|
||||
pub const OP_SET_ENV: OpId = 8;
|
||||
pub const OP_HOME_DIR: OpId = 9;
|
||||
pub const OP_START: OpId = 10;
|
||||
pub const OP_APPLY_SOURCE_MAP: OpId = 11;
|
||||
pub const OP_FORMAT_ERROR: OpId = 12;
|
||||
pub const OP_CACHE: OpId = 13;
|
||||
pub const OP_FETCH_SOURCE_FILES: OpId = 14;
|
||||
pub const OP_OPEN: OpId = 15;
|
||||
pub const OP_CLOSE: OpId = 16;
|
||||
pub const OP_SEEK: OpId = 17;
|
||||
pub const OP_FETCH: OpId = 18;
|
||||
pub const OP_METRICS: OpId = 19;
|
||||
pub const OP_REPL_START: OpId = 20;
|
||||
pub const OP_REPL_READLINE: OpId = 21;
|
||||
pub const OP_ACCEPT: OpId = 22;
|
||||
pub const OP_DIAL: OpId = 23;
|
||||
pub const OP_SHUTDOWN: OpId = 24;
|
||||
pub const OP_LISTEN: OpId = 25;
|
||||
pub const OP_RESOURCES: OpId = 26;
|
||||
pub const OP_GET_RANDOM_VALUES: OpId = 27;
|
||||
pub const OP_GLOBAL_TIMER_STOP: OpId = 28;
|
||||
pub const OP_GLOBAL_TIMER: OpId = 29;
|
||||
pub const OP_NOW: OpId = 30;
|
||||
pub const OP_PERMISSIONS: OpId = 31;
|
||||
pub const OP_REVOKE_PERMISSION: OpId = 32;
|
||||
pub const OP_CREATE_WORKER: OpId = 33;
|
||||
pub const OP_HOST_GET_WORKER_CLOSED: OpId = 34;
|
||||
pub const OP_HOST_POST_MESSAGE: OpId = 35;
|
||||
pub const OP_HOST_GET_MESSAGE: OpId = 36;
|
||||
pub const OP_WORKER_POST_MESSAGE: OpId = 37;
|
||||
pub const OP_WORKER_GET_MESSAGE: OpId = 38;
|
||||
pub const OP_RUN: OpId = 39;
|
||||
pub const OP_RUN_STATUS: OpId = 40;
|
||||
pub const OP_KILL: OpId = 41;
|
||||
pub const OP_CHDIR: OpId = 42;
|
||||
pub const OP_MKDIR: OpId = 43;
|
||||
pub const OP_CHMOD: OpId = 44;
|
||||
pub const OP_CHOWN: OpId = 45;
|
||||
pub const OP_REMOVE: OpId = 46;
|
||||
pub const OP_COPY_FILE: OpId = 47;
|
||||
pub const OP_STAT: OpId = 48;
|
||||
pub const OP_READ_DIR: OpId = 49;
|
||||
pub const OP_RENAME: OpId = 50;
|
||||
pub const OP_LINK: OpId = 51;
|
||||
pub const OP_SYMLINK: OpId = 52;
|
||||
pub const OP_READ_LINK: OpId = 53;
|
||||
pub const OP_TRUNCATE: OpId = 54;
|
||||
pub const OP_MAKE_TEMP_DIR: OpId = 55;
|
||||
pub const OP_CWD: OpId = 56;
|
||||
pub const OP_FETCH_ASSET: OpId = 57;
|
||||
pub const OP_DIAL_TLS: OpId = 58;
|
||||
pub const OP_HOSTNAME: OpId = 59;
|
||||
pub use dispatch_json::json_op;
|
||||
pub use dispatch_json::JsonOp;
|
||||
pub use dispatch_minimal::minimal_op;
|
||||
|
||||
pub fn dispatch(
|
||||
state: &ThreadSafeState,
|
||||
op_id: OpId,
|
||||
control: &[u8],
|
||||
zero_copy: Option<PinnedBuf>,
|
||||
) -> CoreOp {
|
||||
let bytes_sent_control = control.len();
|
||||
let bytes_sent_zero_copy = zero_copy.as_ref().map(|b| b.len()).unwrap_or(0);
|
||||
|
||||
let op = match op_id {
|
||||
OP_READ => {
|
||||
dispatch_minimal::dispatch(io::op_read, state, control, zero_copy)
|
||||
}
|
||||
OP_WRITE => {
|
||||
dispatch_minimal::dispatch(io::op_write, state, control, zero_copy)
|
||||
}
|
||||
OP_EXIT => dispatch_json::dispatch(os::op_exit, state, control, zero_copy),
|
||||
OP_IS_TTY => {
|
||||
dispatch_json::dispatch(os::op_is_tty, state, control, zero_copy)
|
||||
}
|
||||
OP_ENV => dispatch_json::dispatch(os::op_env, state, control, zero_copy),
|
||||
OP_EXEC_PATH => {
|
||||
dispatch_json::dispatch(os::op_exec_path, state, control, zero_copy)
|
||||
}
|
||||
OP_HOME_DIR => {
|
||||
dispatch_json::dispatch(os::op_home_dir, state, control, zero_copy)
|
||||
}
|
||||
OP_UTIME => {
|
||||
dispatch_json::dispatch(fs::op_utime, state, control, zero_copy)
|
||||
}
|
||||
OP_SET_ENV => {
|
||||
dispatch_json::dispatch(os::op_set_env, state, control, zero_copy)
|
||||
}
|
||||
OP_START => {
|
||||
dispatch_json::dispatch(os::op_start, state, control, zero_copy)
|
||||
}
|
||||
OP_APPLY_SOURCE_MAP => dispatch_json::dispatch(
|
||||
errors::op_apply_source_map,
|
||||
state,
|
||||
control,
|
||||
zero_copy,
|
||||
),
|
||||
OP_FORMAT_ERROR => dispatch_json::dispatch(
|
||||
errors::op_format_error,
|
||||
state,
|
||||
control,
|
||||
zero_copy,
|
||||
),
|
||||
OP_CACHE => {
|
||||
dispatch_json::dispatch(compiler::op_cache, state, control, zero_copy)
|
||||
}
|
||||
OP_FETCH_SOURCE_FILES => dispatch_json::dispatch(
|
||||
compiler::op_fetch_source_files,
|
||||
state,
|
||||
control,
|
||||
zero_copy,
|
||||
),
|
||||
OP_OPEN => {
|
||||
dispatch_json::dispatch(files::op_open, state, control, zero_copy)
|
||||
}
|
||||
OP_CLOSE => {
|
||||
dispatch_json::dispatch(files::op_close, state, control, zero_copy)
|
||||
}
|
||||
OP_SEEK => {
|
||||
dispatch_json::dispatch(files::op_seek, state, control, zero_copy)
|
||||
}
|
||||
OP_METRICS => {
|
||||
dispatch_json::dispatch(metrics::op_metrics, state, control, zero_copy)
|
||||
}
|
||||
OP_FETCH => {
|
||||
dispatch_json::dispatch(fetch::op_fetch, state, control, zero_copy)
|
||||
}
|
||||
OP_REPL_START => {
|
||||
dispatch_json::dispatch(repl::op_repl_start, state, control, zero_copy)
|
||||
}
|
||||
OP_REPL_READLINE => {
|
||||
dispatch_json::dispatch(repl::op_repl_readline, state, control, zero_copy)
|
||||
}
|
||||
OP_ACCEPT => {
|
||||
dispatch_json::dispatch(net::op_accept, state, control, zero_copy)
|
||||
}
|
||||
OP_DIAL => dispatch_json::dispatch(net::op_dial, state, control, zero_copy),
|
||||
OP_SHUTDOWN => {
|
||||
dispatch_json::dispatch(net::op_shutdown, state, control, zero_copy)
|
||||
}
|
||||
OP_LISTEN => {
|
||||
dispatch_json::dispatch(net::op_listen, state, control, zero_copy)
|
||||
}
|
||||
OP_RESOURCES => dispatch_json::dispatch(
|
||||
resources::op_resources,
|
||||
state,
|
||||
control,
|
||||
zero_copy,
|
||||
),
|
||||
OP_GET_RANDOM_VALUES => dispatch_json::dispatch(
|
||||
random::op_get_random_values,
|
||||
state,
|
||||
control,
|
||||
zero_copy,
|
||||
),
|
||||
OP_GLOBAL_TIMER_STOP => dispatch_json::dispatch(
|
||||
timers::op_global_timer_stop,
|
||||
state,
|
||||
control,
|
||||
zero_copy,
|
||||
),
|
||||
OP_GLOBAL_TIMER => dispatch_json::dispatch(
|
||||
timers::op_global_timer,
|
||||
state,
|
||||
control,
|
||||
zero_copy,
|
||||
),
|
||||
OP_NOW => {
|
||||
dispatch_json::dispatch(performance::op_now, state, control, zero_copy)
|
||||
}
|
||||
OP_PERMISSIONS => dispatch_json::dispatch(
|
||||
permissions::op_permissions,
|
||||
state,
|
||||
control,
|
||||
zero_copy,
|
||||
),
|
||||
OP_REVOKE_PERMISSION => dispatch_json::dispatch(
|
||||
permissions::op_revoke_permission,
|
||||
state,
|
||||
control,
|
||||
zero_copy,
|
||||
),
|
||||
OP_CREATE_WORKER => dispatch_json::dispatch(
|
||||
workers::op_create_worker,
|
||||
state,
|
||||
control,
|
||||
zero_copy,
|
||||
),
|
||||
OP_HOST_GET_WORKER_CLOSED => dispatch_json::dispatch(
|
||||
workers::op_host_get_worker_closed,
|
||||
state,
|
||||
control,
|
||||
zero_copy,
|
||||
),
|
||||
OP_HOST_POST_MESSAGE => dispatch_json::dispatch(
|
||||
workers::op_host_post_message,
|
||||
state,
|
||||
control,
|
||||
zero_copy,
|
||||
),
|
||||
OP_HOST_GET_MESSAGE => dispatch_json::dispatch(
|
||||
workers::op_host_get_message,
|
||||
state,
|
||||
control,
|
||||
zero_copy,
|
||||
),
|
||||
// TODO: make sure these two ops are only accessible to appropriate Workers
|
||||
OP_WORKER_POST_MESSAGE => dispatch_json::dispatch(
|
||||
workers::op_worker_post_message,
|
||||
state,
|
||||
control,
|
||||
zero_copy,
|
||||
),
|
||||
OP_WORKER_GET_MESSAGE => dispatch_json::dispatch(
|
||||
workers::op_worker_get_message,
|
||||
state,
|
||||
control,
|
||||
zero_copy,
|
||||
),
|
||||
OP_RUN => {
|
||||
dispatch_json::dispatch(process::op_run, state, control, zero_copy)
|
||||
}
|
||||
OP_RUN_STATUS => {
|
||||
dispatch_json::dispatch(process::op_run_status, state, control, zero_copy)
|
||||
}
|
||||
OP_KILL => {
|
||||
dispatch_json::dispatch(process::op_kill, state, control, zero_copy)
|
||||
}
|
||||
OP_CHDIR => {
|
||||
dispatch_json::dispatch(fs::op_chdir, state, control, zero_copy)
|
||||
}
|
||||
OP_MKDIR => {
|
||||
dispatch_json::dispatch(fs::op_mkdir, state, control, zero_copy)
|
||||
}
|
||||
OP_CHMOD => {
|
||||
dispatch_json::dispatch(fs::op_chmod, state, control, zero_copy)
|
||||
}
|
||||
OP_CHOWN => {
|
||||
dispatch_json::dispatch(fs::op_chown, state, control, zero_copy)
|
||||
}
|
||||
OP_REMOVE => {
|
||||
dispatch_json::dispatch(fs::op_remove, state, control, zero_copy)
|
||||
}
|
||||
OP_COPY_FILE => {
|
||||
dispatch_json::dispatch(fs::op_copy_file, state, control, zero_copy)
|
||||
}
|
||||
OP_STAT => dispatch_json::dispatch(fs::op_stat, state, control, zero_copy),
|
||||
OP_READ_DIR => {
|
||||
dispatch_json::dispatch(fs::op_read_dir, state, control, zero_copy)
|
||||
}
|
||||
OP_RENAME => {
|
||||
dispatch_json::dispatch(fs::op_rename, state, control, zero_copy)
|
||||
}
|
||||
OP_LINK => dispatch_json::dispatch(fs::op_link, state, control, zero_copy),
|
||||
OP_SYMLINK => {
|
||||
dispatch_json::dispatch(fs::op_symlink, state, control, zero_copy)
|
||||
}
|
||||
OP_READ_LINK => {
|
||||
dispatch_json::dispatch(fs::op_read_link, state, control, zero_copy)
|
||||
}
|
||||
OP_TRUNCATE => {
|
||||
dispatch_json::dispatch(fs::op_truncate, state, control, zero_copy)
|
||||
}
|
||||
OP_MAKE_TEMP_DIR => {
|
||||
dispatch_json::dispatch(fs::op_make_temp_dir, state, control, zero_copy)
|
||||
}
|
||||
OP_CWD => dispatch_json::dispatch(fs::op_cwd, state, control, zero_copy),
|
||||
OP_FETCH_ASSET => dispatch_json::dispatch(
|
||||
compiler::op_fetch_asset,
|
||||
state,
|
||||
control,
|
||||
zero_copy,
|
||||
),
|
||||
OP_DIAL_TLS => {
|
||||
dispatch_json::dispatch(tls::op_dial_tls, state, control, zero_copy)
|
||||
}
|
||||
OP_HOSTNAME => {
|
||||
dispatch_json::dispatch(os::op_hostname, state, control, zero_copy)
|
||||
}
|
||||
_ => panic!("bad op_id"),
|
||||
};
|
||||
|
||||
state.metrics_op_dispatched(bytes_sent_control, bytes_sent_zero_copy);
|
||||
|
||||
match op {
|
||||
Op::Sync(buf) => {
|
||||
state.metrics_op_completed(buf.len());
|
||||
Op::Sync(buf)
|
||||
}
|
||||
Op::Async(fut) => {
|
||||
use crate::futures::Future;
|
||||
let state = state.clone();
|
||||
let result_fut = Box::new(fut.map(move |buf: Buf| {
|
||||
state.clone().metrics_op_completed(buf.len());
|
||||
buf
|
||||
}));
|
||||
Op::Async(result_fut)
|
||||
}
|
||||
}
|
||||
}
|
||||
pub mod compiler;
|
||||
pub mod errors;
|
||||
pub mod fetch;
|
||||
pub mod files;
|
||||
pub mod fs;
|
||||
pub mod io;
|
||||
pub mod metrics;
|
||||
pub mod net;
|
||||
pub mod os;
|
||||
pub mod performance;
|
||||
pub mod permissions;
|
||||
pub mod process;
|
||||
pub mod random;
|
||||
pub mod repl;
|
||||
pub mod resources;
|
||||
pub mod timers;
|
||||
pub mod workers;
|
||||
|
|
63
cli/state.rs
63
cli/state.rs
|
@ -10,7 +10,7 @@ use crate::flags;
|
|||
use crate::global_timer::GlobalTimer;
|
||||
use crate::import_map::ImportMap;
|
||||
use crate::msg;
|
||||
use crate::ops;
|
||||
use crate::ops::JsonOp;
|
||||
use crate::permissions::DenoPermissions;
|
||||
use crate::progress::Progress;
|
||||
use crate::resources;
|
||||
|
@ -21,12 +21,13 @@ use deno::CoreOp;
|
|||
use deno::ErrBox;
|
||||
use deno::Loader;
|
||||
use deno::ModuleSpecifier;
|
||||
use deno::OpId;
|
||||
use deno::Op;
|
||||
use deno::PinnedBuf;
|
||||
use futures::future::Shared;
|
||||
use futures::Future;
|
||||
use rand::rngs::StdRng;
|
||||
use rand::SeedableRng;
|
||||
use serde_json::Value;
|
||||
use std;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
|
@ -103,13 +104,59 @@ impl Deref for ThreadSafeState {
|
|||
}
|
||||
|
||||
impl ThreadSafeState {
|
||||
pub fn dispatch(
|
||||
// TODO: better name welcome
|
||||
/// Wrap core `OpDispatcher` to collect metrics.
|
||||
pub fn cli_op<D>(
|
||||
&self,
|
||||
op_id: OpId,
|
||||
control: &[u8],
|
||||
zero_copy: Option<PinnedBuf>,
|
||||
) -> CoreOp {
|
||||
ops::dispatch(self, op_id, control, zero_copy)
|
||||
dispatcher: D,
|
||||
) -> impl Fn(&[u8], Option<PinnedBuf>) -> CoreOp
|
||||
where
|
||||
D: Fn(&[u8], Option<PinnedBuf>) -> CoreOp,
|
||||
{
|
||||
let state = self.clone();
|
||||
|
||||
move |control: &[u8], zero_copy: Option<PinnedBuf>| -> CoreOp {
|
||||
let bytes_sent_control = control.len();
|
||||
let bytes_sent_zero_copy =
|
||||
zero_copy.as_ref().map(|b| b.len()).unwrap_or(0);
|
||||
|
||||
let op = dispatcher(control, zero_copy);
|
||||
state.metrics_op_dispatched(bytes_sent_control, bytes_sent_zero_copy);
|
||||
|
||||
match op {
|
||||
Op::Sync(buf) => {
|
||||
state.metrics_op_completed(buf.len());
|
||||
Op::Sync(buf)
|
||||
}
|
||||
Op::Async(fut) => {
|
||||
let state = state.clone();
|
||||
let result_fut = Box::new(fut.map(move |buf: Buf| {
|
||||
state.clone().metrics_op_completed(buf.len());
|
||||
buf
|
||||
}));
|
||||
Op::Async(result_fut)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This is a special function that provides `state` argument to dispatcher.
|
||||
///
|
||||
/// NOTE: This only works with JSON dispatcher.
|
||||
/// This is a band-aid for transition to `Isolate.register_op` API as most of our
|
||||
/// ops require `state` argument.
|
||||
pub fn stateful_op<D>(
|
||||
&self,
|
||||
dispatcher: D,
|
||||
) -> impl Fn(Value, Option<PinnedBuf>) -> Result<JsonOp, ErrBox>
|
||||
where
|
||||
D: Fn(&ThreadSafeState, Value, Option<PinnedBuf>) -> Result<JsonOp, ErrBox>,
|
||||
{
|
||||
let state = self.clone();
|
||||
|
||||
move |args: Value, zero_copy: Option<PinnedBuf>| -> Result<JsonOp, ErrBox> {
|
||||
dispatcher(&state, args, zero_copy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
251
cli/worker.rs
251
cli/worker.rs
|
@ -1,5 +1,8 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
use crate::fmt_errors::JSError;
|
||||
use crate::ops::json_op;
|
||||
use crate::ops::minimal_op;
|
||||
use crate::ops::*;
|
||||
use crate::state::ThreadSafeState;
|
||||
use crate::tokio_util;
|
||||
use deno;
|
||||
|
@ -31,11 +34,251 @@ impl Worker {
|
|||
let isolate = Arc::new(Mutex::new(deno::Isolate::new(startup_data, false)));
|
||||
{
|
||||
let mut i = isolate.lock().unwrap();
|
||||
|
||||
let state_ = state.clone();
|
||||
i.set_dispatch(move |op_id, control_buf, zero_copy_buf| {
|
||||
state_.dispatch(op_id, control_buf, zero_copy_buf)
|
||||
});
|
||||
|
||||
i.register_op("read", state_.cli_op(minimal_op(io::op_read)));
|
||||
i.register_op("write", state_.cli_op(minimal_op(io::op_write)));
|
||||
|
||||
i.register_op(
|
||||
"exit",
|
||||
state_.cli_op(json_op(state_.stateful_op(os::op_exit))),
|
||||
);
|
||||
i.register_op(
|
||||
"is_tty",
|
||||
state_.cli_op(json_op(state_.stateful_op(os::op_is_tty))),
|
||||
);
|
||||
i.register_op(
|
||||
"env",
|
||||
state_.cli_op(json_op(state_.stateful_op(os::op_env))),
|
||||
);
|
||||
i.register_op(
|
||||
"exec_path",
|
||||
state_.cli_op(json_op(state_.stateful_op(os::op_exec_path))),
|
||||
);
|
||||
i.register_op(
|
||||
"utime",
|
||||
state_.cli_op(json_op(state_.stateful_op(fs::op_utime))),
|
||||
);
|
||||
i.register_op(
|
||||
"set_env",
|
||||
state_.cli_op(json_op(state_.stateful_op(os::op_set_env))),
|
||||
);
|
||||
i.register_op(
|
||||
"home_dir",
|
||||
state_.cli_op(json_op(state_.stateful_op(os::op_home_dir))),
|
||||
);
|
||||
i.register_op(
|
||||
"start",
|
||||
state_.cli_op(json_op(state_.stateful_op(os::op_start))),
|
||||
);
|
||||
i.register_op(
|
||||
"apply_source_map",
|
||||
state_.cli_op(json_op(state_.stateful_op(errors::op_apply_source_map))),
|
||||
);
|
||||
i.register_op(
|
||||
"format_error",
|
||||
state_.cli_op(json_op(state_.stateful_op(errors::op_format_error))),
|
||||
);
|
||||
i.register_op(
|
||||
"cache",
|
||||
state_.cli_op(json_op(state_.stateful_op(compiler::op_cache))),
|
||||
);
|
||||
i.register_op(
|
||||
"fetch_source_files",
|
||||
state_
|
||||
.cli_op(json_op(state_.stateful_op(compiler::op_fetch_source_files))),
|
||||
);
|
||||
i.register_op(
|
||||
"open",
|
||||
state_.cli_op(json_op(state_.stateful_op(files::op_open))),
|
||||
);
|
||||
i.register_op(
|
||||
"close",
|
||||
state_.cli_op(json_op(state_.stateful_op(files::op_close))),
|
||||
);
|
||||
i.register_op(
|
||||
"seek",
|
||||
state_.cli_op(json_op(state_.stateful_op(files::op_seek))),
|
||||
);
|
||||
i.register_op(
|
||||
"fetch",
|
||||
state_.cli_op(json_op(state_.stateful_op(fetch::op_fetch))),
|
||||
);
|
||||
i.register_op(
|
||||
"metrics",
|
||||
state_.cli_op(json_op(state_.stateful_op(metrics::op_metrics))),
|
||||
);
|
||||
i.register_op(
|
||||
"repl_start",
|
||||
state_.cli_op(json_op(state_.stateful_op(repl::op_repl_start))),
|
||||
);
|
||||
i.register_op(
|
||||
"repl_readline",
|
||||
state_.cli_op(json_op(state_.stateful_op(repl::op_repl_readline))),
|
||||
);
|
||||
i.register_op(
|
||||
"accept",
|
||||
state_.cli_op(json_op(state_.stateful_op(net::op_accept))),
|
||||
);
|
||||
i.register_op(
|
||||
"dial",
|
||||
state_.cli_op(json_op(state_.stateful_op(net::op_dial))),
|
||||
);
|
||||
i.register_op(
|
||||
"dial_tls",
|
||||
state_.cli_op(json_op(state_.stateful_op(net::op_dial))),
|
||||
);
|
||||
i.register_op(
|
||||
"shutdown",
|
||||
state_.cli_op(json_op(state_.stateful_op(net::op_shutdown))),
|
||||
);
|
||||
i.register_op(
|
||||
"listen",
|
||||
state_.cli_op(json_op(state_.stateful_op(net::op_listen))),
|
||||
);
|
||||
i.register_op(
|
||||
"resources",
|
||||
state_.cli_op(json_op(state_.stateful_op(resources::op_resources))),
|
||||
);
|
||||
i.register_op(
|
||||
"get_random_values",
|
||||
state_
|
||||
.cli_op(json_op(state_.stateful_op(random::op_get_random_values))),
|
||||
);
|
||||
i.register_op(
|
||||
"global_timer_stop",
|
||||
state_
|
||||
.cli_op(json_op(state_.stateful_op(timers::op_global_timer_stop))),
|
||||
);
|
||||
i.register_op(
|
||||
"global_timer",
|
||||
state_.cli_op(json_op(state_.stateful_op(timers::op_global_timer))),
|
||||
);
|
||||
i.register_op(
|
||||
"now",
|
||||
state_.cli_op(json_op(state_.stateful_op(performance::op_now))),
|
||||
);
|
||||
i.register_op(
|
||||
"permissions",
|
||||
state_.cli_op(json_op(state_.stateful_op(permissions::op_permissions))),
|
||||
);
|
||||
i.register_op(
|
||||
"revoke_permission",
|
||||
state_.cli_op(json_op(
|
||||
state_.stateful_op(permissions::op_revoke_permission),
|
||||
)),
|
||||
);
|
||||
i.register_op(
|
||||
"create_worker",
|
||||
state_.cli_op(json_op(state_.stateful_op(workers::op_create_worker))),
|
||||
);
|
||||
i.register_op(
|
||||
"host_get_worker_closed",
|
||||
state_.cli_op(json_op(
|
||||
state_.stateful_op(workers::op_host_get_worker_closed),
|
||||
)),
|
||||
);
|
||||
i.register_op(
|
||||
"host_post_message",
|
||||
state_
|
||||
.cli_op(json_op(state_.stateful_op(workers::op_host_post_message))),
|
||||
);
|
||||
i.register_op(
|
||||
"host_get_message",
|
||||
state_
|
||||
.cli_op(json_op(state_.stateful_op(workers::op_host_get_message))),
|
||||
);
|
||||
// TODO: make sure these two ops are only accessible to appropriate Worker
|
||||
i.register_op(
|
||||
"worker_post_message",
|
||||
state_
|
||||
.cli_op(json_op(state_.stateful_op(workers::op_worker_post_message))),
|
||||
);
|
||||
i.register_op(
|
||||
"worker_get_message",
|
||||
state_
|
||||
.cli_op(json_op(state_.stateful_op(workers::op_worker_get_message))),
|
||||
);
|
||||
i.register_op(
|
||||
"run",
|
||||
state_.cli_op(json_op(state_.stateful_op(process::op_run))),
|
||||
);
|
||||
i.register_op(
|
||||
"run_status",
|
||||
state_.cli_op(json_op(state_.stateful_op(process::op_run_status))),
|
||||
);
|
||||
i.register_op(
|
||||
"kill",
|
||||
state_.cli_op(json_op(state_.stateful_op(process::op_kill))),
|
||||
);
|
||||
i.register_op(
|
||||
"chdir",
|
||||
state_.cli_op(json_op(state_.stateful_op(fs::op_chdir))),
|
||||
);
|
||||
i.register_op(
|
||||
"mkdir",
|
||||
state_.cli_op(json_op(state_.stateful_op(fs::op_mkdir))),
|
||||
);
|
||||
i.register_op(
|
||||
"chmod",
|
||||
state_.cli_op(json_op(state_.stateful_op(fs::op_chmod))),
|
||||
);
|
||||
i.register_op(
|
||||
"chown",
|
||||
state_.cli_op(json_op(state_.stateful_op(fs::op_chown))),
|
||||
);
|
||||
i.register_op(
|
||||
"remove",
|
||||
state_.cli_op(json_op(state_.stateful_op(fs::op_remove))),
|
||||
);
|
||||
i.register_op(
|
||||
"copy_file",
|
||||
state_.cli_op(json_op(state_.stateful_op(fs::op_copy_file))),
|
||||
);
|
||||
i.register_op(
|
||||
"stat",
|
||||
state_.cli_op(json_op(state_.stateful_op(fs::op_stat))),
|
||||
);
|
||||
i.register_op(
|
||||
"read_dir",
|
||||
state_.cli_op(json_op(state_.stateful_op(fs::op_read_dir))),
|
||||
);
|
||||
i.register_op(
|
||||
"rename",
|
||||
state_.cli_op(json_op(state_.stateful_op(fs::op_rename))),
|
||||
);
|
||||
i.register_op(
|
||||
"link",
|
||||
state_.cli_op(json_op(state_.stateful_op(fs::op_link))),
|
||||
);
|
||||
i.register_op(
|
||||
"symlink",
|
||||
state_.cli_op(json_op(state_.stateful_op(fs::op_symlink))),
|
||||
);
|
||||
i.register_op(
|
||||
"read_link",
|
||||
state_.cli_op(json_op(state_.stateful_op(fs::op_read_link))),
|
||||
);
|
||||
i.register_op(
|
||||
"truncate",
|
||||
state_.cli_op(json_op(state_.stateful_op(fs::op_truncate))),
|
||||
);
|
||||
i.register_op(
|
||||
"make_temp_dir",
|
||||
state_.cli_op(json_op(state_.stateful_op(fs::op_make_temp_dir))),
|
||||
);
|
||||
i.register_op(
|
||||
"cwd",
|
||||
state_.cli_op(json_op(state_.stateful_op(fs::op_cwd))),
|
||||
);
|
||||
i.register_op(
|
||||
"fetch_asset",
|
||||
state_.cli_op(json_op(state_.stateful_op(compiler::op_fetch_asset))),
|
||||
);
|
||||
i.register_op(
|
||||
"hostname",
|
||||
state_.cli_op(json_op(state_.stateful_op(os::op_hostname))),
|
||||
);
|
||||
|
||||
let state_ = state.clone();
|
||||
i.set_dyn_import(move |id, specifier, referrer| {
|
||||
|
|
5
deno_typescript/lib.deno_core.d.ts
vendored
5
deno_typescript/lib.deno_core.d.ts
vendored
|
@ -37,10 +37,7 @@ declare interface DenoCore {
|
|||
shift(): Uint8Array | null;
|
||||
};
|
||||
|
||||
ops: {
|
||||
init(): void;
|
||||
get(name: string): number;
|
||||
};
|
||||
ops(): Record<string, number>;
|
||||
|
||||
recv(cb: MessageCallback): void;
|
||||
|
||||
|
|
118
js/dispatch.ts
118
js/dispatch.ts
|
@ -3,65 +3,65 @@ import * as minimal from "./dispatch_minimal.ts";
|
|||
import * as json from "./dispatch_json.ts";
|
||||
|
||||
// These consts are shared with Rust. Update with care.
|
||||
export const OP_READ = 1;
|
||||
export const OP_WRITE = 2;
|
||||
export const OP_EXIT = 3;
|
||||
export const OP_IS_TTY = 4;
|
||||
export const OP_ENV = 5;
|
||||
export const OP_EXEC_PATH = 6;
|
||||
export const OP_UTIME = 7;
|
||||
export const OP_SET_ENV = 8;
|
||||
export const OP_HOME_DIR = 9;
|
||||
export const OP_START = 10;
|
||||
export const OP_APPLY_SOURCE_MAP = 11;
|
||||
export const OP_FORMAT_ERROR = 12;
|
||||
export const OP_CACHE = 13;
|
||||
export const OP_FETCH_SOURCE_FILES = 14;
|
||||
export const OP_OPEN = 15;
|
||||
export const OP_CLOSE = 16;
|
||||
export const OP_SEEK = 17;
|
||||
export const OP_FETCH = 18;
|
||||
export const OP_METRICS = 19;
|
||||
export const OP_REPL_START = 20;
|
||||
export const OP_REPL_READLINE = 21;
|
||||
export const OP_ACCEPT = 22;
|
||||
export const OP_DIAL = 23;
|
||||
export const OP_SHUTDOWN = 24;
|
||||
export const OP_LISTEN = 25;
|
||||
export const OP_RESOURCES = 26;
|
||||
export const OP_GET_RANDOM_VALUES = 27;
|
||||
export const OP_GLOBAL_TIMER_STOP = 28;
|
||||
export const OP_GLOBAL_TIMER = 29;
|
||||
export const OP_NOW = 30;
|
||||
export const OP_PERMISSIONS = 31;
|
||||
export const OP_REVOKE_PERMISSION = 32;
|
||||
export const OP_CREATE_WORKER = 33;
|
||||
export const OP_HOST_GET_WORKER_CLOSED = 34;
|
||||
export const OP_HOST_POST_MESSAGE = 35;
|
||||
export const OP_HOST_GET_MESSAGE = 36;
|
||||
export const OP_WORKER_POST_MESSAGE = 37;
|
||||
export const OP_WORKER_GET_MESSAGE = 38;
|
||||
export const OP_RUN = 39;
|
||||
export const OP_RUN_STATUS = 40;
|
||||
export const OP_KILL = 41;
|
||||
export const OP_CHDIR = 42;
|
||||
export const OP_MKDIR = 43;
|
||||
export const OP_CHMOD = 44;
|
||||
export const OP_CHOWN = 45;
|
||||
export const OP_REMOVE = 46;
|
||||
export const OP_COPY_FILE = 47;
|
||||
export const OP_STAT = 48;
|
||||
export const OP_READ_DIR = 49;
|
||||
export const OP_RENAME = 50;
|
||||
export const OP_LINK = 51;
|
||||
export const OP_SYMLINK = 52;
|
||||
export const OP_READ_LINK = 53;
|
||||
export const OP_TRUNCATE = 54;
|
||||
export const OP_MAKE_TEMP_DIR = 55;
|
||||
export const OP_CWD = 56;
|
||||
export const OP_FETCH_ASSET = 57;
|
||||
export const OP_DIAL_TLS = 58;
|
||||
export const OP_HOSTNAME = 59;
|
||||
export let OP_READ: number;
|
||||
export let OP_WRITE: number;
|
||||
export let OP_EXIT: number;
|
||||
export let OP_IS_TTY: number;
|
||||
export let OP_ENV: number;
|
||||
export let OP_EXEC_PATH: number;
|
||||
export let OP_UTIME: number;
|
||||
export let OP_SET_ENV: number;
|
||||
export let OP_HOME_DIR: number;
|
||||
export let OP_START: number;
|
||||
export let OP_APPLY_SOURCE_MAP: number;
|
||||
export let OP_FORMAT_ERROR: number;
|
||||
export let OP_CACHE: number;
|
||||
export let OP_FETCH_SOURCE_FILES: number;
|
||||
export let OP_OPEN: number;
|
||||
export let OP_CLOSE: number;
|
||||
export let OP_SEEK: number;
|
||||
export let OP_FETCH: number;
|
||||
export let OP_METRICS: number;
|
||||
export let OP_REPL_START: number;
|
||||
export let OP_REPL_READLINE: number;
|
||||
export let OP_ACCEPT: number;
|
||||
export let OP_DIAL: number;
|
||||
export let OP_SHUTDOWN: number;
|
||||
export let OP_LISTEN: number;
|
||||
export let OP_RESOURCES: number;
|
||||
export let OP_GET_RANDOM_VALUES: number;
|
||||
export let OP_GLOBAL_TIMER_STOP: number;
|
||||
export let OP_GLOBAL_TIMER: number;
|
||||
export let OP_NOW: number;
|
||||
export let OP_PERMISSIONS: number;
|
||||
export let OP_REVOKE_PERMISSION: number;
|
||||
export let OP_CREATE_WORKER: number;
|
||||
export let OP_HOST_GET_WORKER_CLOSED: number;
|
||||
export let OP_HOST_POST_MESSAGE: number;
|
||||
export let OP_HOST_GET_MESSAGE: number;
|
||||
export let OP_WORKER_POST_MESSAGE: number;
|
||||
export let OP_WORKER_GET_MESSAGE: number;
|
||||
export let OP_RUN: number;
|
||||
export let OP_RUN_STATUS: number;
|
||||
export let OP_KILL: number;
|
||||
export let OP_CHDIR: number;
|
||||
export let OP_MKDIR: number;
|
||||
export let OP_CHMOD: number;
|
||||
export let OP_CHOWN: number;
|
||||
export let OP_REMOVE: number;
|
||||
export let OP_COPY_FILE: number;
|
||||
export let OP_STAT: number;
|
||||
export let OP_READ_DIR: number;
|
||||
export let OP_RENAME: number;
|
||||
export let OP_LINK: number;
|
||||
export let OP_SYMLINK: number;
|
||||
export let OP_READ_LINK: number;
|
||||
export let OP_TRUNCATE: number;
|
||||
export let OP_MAKE_TEMP_DIR: number;
|
||||
export let OP_CWD: number;
|
||||
export let OP_FETCH_ASSET: number;
|
||||
export let OP_DIAL_TLS: number;
|
||||
export let OP_HOSTNAME: number;
|
||||
|
||||
export function asyncMsgFromRust(opId: number, ui8: Uint8Array): void {
|
||||
switch (opId) {
|
||||
|
|
9
js/os.ts
9
js/os.ts
|
@ -81,7 +81,14 @@ interface Start {
|
|||
// @internal
|
||||
export function start(preserveDenoNamespace = true, source?: string): Start {
|
||||
core.setAsyncHandler(dispatch.asyncMsgFromRust);
|
||||
|
||||
const ops = core.ops();
|
||||
// TODO(bartlomieju): this is a prototype, we should come up with
|
||||
// something a bit more sophisticated
|
||||
for (const [name, opId] of Object.entries(ops)) {
|
||||
const opName = `OP_${name.toUpperCase()}`;
|
||||
// Assign op ids to actual variables
|
||||
dispatch[opName] = opId;
|
||||
}
|
||||
// First we send an empty `Start` message to let the privileged side know we
|
||||
// are ready. The response should be a `StartRes` message containing the CLI
|
||||
// args and other info.
|
||||
|
|
Loading…
Reference in a new issue