mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 07:14:47 -05:00
Use gotham-like state for ops (#7385)
Provides a concrete state type that can be dynamically added. This is necessary for op crates. * renames BasicState to OpState * async ops take `Rc<RefCell<OpState>>` * sync ops take `&mut OpState` * removes `OpRegistry`, `OpRouter` traits * `get_error_class_fn` moved to OpState * ResourceTable moved to OpState
This commit is contained in:
parent
6f70e6e72b
commit
7c2e7c6608
44 changed files with 1576 additions and 1348 deletions
11
cli/build.rs
11
cli/build.rs
|
@ -3,9 +3,7 @@
|
|||
mod op_fetch_asset;
|
||||
|
||||
use deno_core::js_check;
|
||||
use deno_core::BasicState;
|
||||
use deno_core::JsRuntime;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::StartupData;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
|
@ -39,8 +37,7 @@ fn create_snapshot(
|
|||
}
|
||||
|
||||
fn create_runtime_snapshot(snapshot_path: &Path, files: Vec<PathBuf>) {
|
||||
let state = BasicState::new();
|
||||
let isolate = JsRuntime::new(state, StartupData::None, true);
|
||||
let isolate = JsRuntime::new(StartupData::None, true);
|
||||
create_snapshot(isolate, snapshot_path, files);
|
||||
}
|
||||
|
||||
|
@ -73,13 +70,11 @@ fn create_compiler_snapshot(
|
|||
cwd.join("dts/lib.deno.unstable.d.ts"),
|
||||
);
|
||||
|
||||
let state = BasicState::new();
|
||||
state.register_op(
|
||||
let mut isolate = JsRuntime::new(StartupData::None, true);
|
||||
isolate.register_op(
|
||||
"op_fetch_asset",
|
||||
op_fetch_asset::op_fetch_asset(custom_libs),
|
||||
);
|
||||
|
||||
let isolate = JsRuntime::new(state, StartupData::None, true);
|
||||
create_snapshot(isolate, snapshot_path, files);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ pub static UNSTABLE_NS_LIB: &str = include_str!("dts/lib.deno.unstable.d.ts");
|
|||
#[test]
|
||||
fn cli_snapshot() {
|
||||
let mut isolate = deno_core::JsRuntime::new(
|
||||
deno_core::BasicState::new(),
|
||||
deno_core::StartupData::Snapshot(deno_core::Snapshot::Static(CLI_SNAPSHOT)),
|
||||
false,
|
||||
);
|
||||
|
@ -32,7 +31,6 @@ fn cli_snapshot() {
|
|||
#[test]
|
||||
fn compiler_snapshot() {
|
||||
let mut isolate = deno_core::JsRuntime::new(
|
||||
deno_core::BasicState::new(),
|
||||
deno_core::StartupData::Snapshot(deno_core::Snapshot::Static(
|
||||
COMPILER_SNAPSHOT,
|
||||
)),
|
||||
|
|
|
@ -71,3 +71,60 @@ impl Metrics {
|
|||
self.op_completed(bytes_received);
|
||||
}
|
||||
}
|
||||
|
||||
use deno_core::BufVec;
|
||||
use deno_core::Op;
|
||||
use deno_core::OpFn;
|
||||
use deno_core::OpState;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn metrics_op(op_fn: Box<OpFn>) -> Box<OpFn> {
|
||||
Box::new(move |op_state: Rc<RefCell<OpState>>, bufs: BufVec| -> Op {
|
||||
// TODOs:
|
||||
// * The 'bytes' metrics seem pretty useless, especially now that the
|
||||
// distinction between 'control' and 'data' buffers has become blurry.
|
||||
// * Tracking completion of async ops currently makes us put the boxed
|
||||
// future into _another_ box. Keeping some counters may not be expensive
|
||||
// in itself, but adding a heap allocation for every metric seems bad.
|
||||
let mut buf_len_iter = bufs.iter().map(|buf| buf.len());
|
||||
let bytes_sent_control = buf_len_iter.next().unwrap_or(0);
|
||||
let bytes_sent_data = buf_len_iter.sum();
|
||||
|
||||
let op = (op_fn)(op_state.clone(), bufs);
|
||||
|
||||
let cli_state = crate::ops::cli_state2(&op_state);
|
||||
let cli_state_ = cli_state.clone();
|
||||
let mut metrics = cli_state.metrics.borrow_mut();
|
||||
|
||||
use futures::future::FutureExt;
|
||||
|
||||
match op {
|
||||
Op::Sync(buf) => {
|
||||
metrics.op_sync(bytes_sent_control, bytes_sent_data, buf.len());
|
||||
Op::Sync(buf)
|
||||
}
|
||||
Op::Async(fut) => {
|
||||
metrics.op_dispatched_async(bytes_sent_control, bytes_sent_data);
|
||||
let fut = fut
|
||||
.inspect(move |buf| {
|
||||
let mut metrics = cli_state_.metrics.borrow_mut();
|
||||
metrics.op_completed_async(buf.len());
|
||||
})
|
||||
.boxed_local();
|
||||
Op::Async(fut)
|
||||
}
|
||||
Op::AsyncUnref(fut) => {
|
||||
metrics.op_dispatched_async_unref(bytes_sent_control, bytes_sent_data);
|
||||
let fut = fut
|
||||
.inspect(move |buf| {
|
||||
let mut metrics = cli_state_.metrics.borrow_mut();
|
||||
metrics.op_completed_async_unref(buf.len());
|
||||
})
|
||||
.boxed_local();
|
||||
Op::AsyncUnref(fut)
|
||||
}
|
||||
other => other,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,27 +1,31 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::state::State;
|
||||
use deno_core::OpRegistry;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub fn init(s: &Rc<State>, response: Arc<Mutex<Option<String>>>) {
|
||||
pub fn init(
|
||||
rt: &mut deno_core::JsRuntime,
|
||||
response: Arc<Mutex<Option<String>>>,
|
||||
) {
|
||||
let custom_assets = std::collections::HashMap::new();
|
||||
// TODO(ry) use None.
|
||||
// TODO(bartlomieju): is this op even required?
|
||||
s.register_op(
|
||||
rt.register_op(
|
||||
"op_fetch_asset",
|
||||
crate::op_fetch_asset::op_fetch_asset(custom_assets),
|
||||
);
|
||||
|
||||
s.register_op_json_sync("op_compiler_respond", move |_state, args, _bufs| {
|
||||
let mut response_slot = response.lock().unwrap();
|
||||
let replaced_value = response_slot.replace(args.to_string());
|
||||
assert!(
|
||||
replaced_value.is_none(),
|
||||
"op_compiler_respond found unexpected existing compiler output",
|
||||
);
|
||||
Ok(json!({}))
|
||||
});
|
||||
super::reg_json_sync(
|
||||
rt,
|
||||
"op_compiler_respond",
|
||||
move |_state, args, _bufs| {
|
||||
let mut response_slot = response.lock().unwrap();
|
||||
let replaced_value = response_slot.replace(args.to_string());
|
||||
assert!(
|
||||
replaced_value.is_none(),
|
||||
"op_compiler_respond found unexpected existing compiler output",
|
||||
);
|
||||
Ok(json!({}))
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::state::State;
|
||||
use deno_core::BufVec;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::Op;
|
||||
use deno_core::OpId;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpFn;
|
||||
use deno_core::OpState;
|
||||
use futures::future::FutureExt;
|
||||
use std::cell::RefCell;
|
||||
use std::future::Future;
|
||||
use std::iter::repeat;
|
||||
use std::mem::size_of_val;
|
||||
|
@ -132,78 +132,74 @@ fn test_parse_min_record() {
|
|||
assert_eq!(parse_min_record(&buf), None);
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn register_op_minimal<F>(self: &Rc<Self>, name: &str, op_fn: F) -> OpId
|
||||
where
|
||||
F: Fn(Rc<Self>, bool, i32, BufVec) -> MinimalOp + 'static,
|
||||
{
|
||||
let base_op_fn = move |state: Rc<Self>, bufs: BufVec| {
|
||||
let mut bufs_iter = bufs.into_iter();
|
||||
let record_buf = bufs_iter.next().expect("Expected record at position 0");
|
||||
let zero_copy = bufs_iter.collect::<BufVec>();
|
||||
pub fn minimal_op<F>(op_fn: F) -> Box<OpFn>
|
||||
where
|
||||
F: Fn(Rc<RefCell<OpState>>, bool, i32, BufVec) -> MinimalOp + 'static,
|
||||
{
|
||||
Box::new(move |state: Rc<RefCell<OpState>>, bufs: BufVec| {
|
||||
let mut bufs_iter = bufs.into_iter();
|
||||
let record_buf = bufs_iter.next().expect("Expected record at position 0");
|
||||
let zero_copy = bufs_iter.collect::<BufVec>();
|
||||
|
||||
let mut record = match parse_min_record(&record_buf) {
|
||||
Some(r) => r,
|
||||
None => {
|
||||
let error = ErrBox::type_error("Unparsable control buffer");
|
||||
let error_class = state.get_error_class_name(&error);
|
||||
let mut record = match parse_min_record(&record_buf) {
|
||||
Some(r) => r,
|
||||
None => {
|
||||
let error = ErrBox::type_error("Unparsable control buffer");
|
||||
let error_class = (state.borrow().get_error_class_fn)(&error);
|
||||
let error_record = ErrorRecord {
|
||||
promise_id: 0,
|
||||
arg: -1,
|
||||
error_len: error_class.len() as i32,
|
||||
error_class: error_class.as_bytes(),
|
||||
error_message: error.to_string().as_bytes().to_owned(),
|
||||
};
|
||||
return Op::Sync(error_record.into());
|
||||
}
|
||||
};
|
||||
let is_sync = record.promise_id == 0;
|
||||
let rid = record.arg;
|
||||
let min_op = op_fn(state.clone(), is_sync, rid, zero_copy);
|
||||
|
||||
match min_op {
|
||||
MinimalOp::Sync(sync_result) => Op::Sync(match sync_result {
|
||||
Ok(r) => {
|
||||
record.result = r;
|
||||
record.into()
|
||||
}
|
||||
Err(err) => {
|
||||
let error_class = (state.borrow().get_error_class_fn)(&err);
|
||||
let error_record = ErrorRecord {
|
||||
promise_id: 0,
|
||||
promise_id: record.promise_id,
|
||||
arg: -1,
|
||||
error_len: error_class.len() as i32,
|
||||
error_class: error_class.as_bytes(),
|
||||
error_message: error.to_string().as_bytes().to_owned(),
|
||||
error_message: err.to_string().as_bytes().to_owned(),
|
||||
};
|
||||
return Op::Sync(error_record.into());
|
||||
error_record.into()
|
||||
}
|
||||
};
|
||||
let is_sync = record.promise_id == 0;
|
||||
let rid = record.arg;
|
||||
let min_op = op_fn(state.clone(), is_sync, rid, zero_copy);
|
||||
|
||||
match min_op {
|
||||
MinimalOp::Sync(sync_result) => Op::Sync(match sync_result {
|
||||
Ok(r) => {
|
||||
record.result = r;
|
||||
record.into()
|
||||
}
|
||||
Err(err) => {
|
||||
let error_class = state.get_error_class_name(&err);
|
||||
let error_record = ErrorRecord {
|
||||
promise_id: record.promise_id,
|
||||
arg: -1,
|
||||
error_len: error_class.len() as i32,
|
||||
error_class: error_class.as_bytes(),
|
||||
error_message: err.to_string().as_bytes().to_owned(),
|
||||
};
|
||||
error_record.into()
|
||||
}
|
||||
}),
|
||||
MinimalOp::Async(min_fut) => {
|
||||
let fut = async move {
|
||||
match min_fut.await {
|
||||
Ok(r) => {
|
||||
record.result = r;
|
||||
record.into()
|
||||
}
|
||||
Err(err) => {
|
||||
let error_class = state.get_error_class_name(&err);
|
||||
let error_record = ErrorRecord {
|
||||
promise_id: record.promise_id,
|
||||
arg: -1,
|
||||
error_len: error_class.len() as i32,
|
||||
error_class: error_class.as_bytes(),
|
||||
error_message: err.to_string().as_bytes().to_owned(),
|
||||
};
|
||||
error_record.into()
|
||||
}
|
||||
}),
|
||||
MinimalOp::Async(min_fut) => {
|
||||
let fut = async move {
|
||||
match min_fut.await {
|
||||
Ok(r) => {
|
||||
record.result = r;
|
||||
record.into()
|
||||
}
|
||||
};
|
||||
Op::Async(fut.boxed_local())
|
||||
}
|
||||
Err(err) => {
|
||||
let error_class = (state.borrow().get_error_class_fn)(&err);
|
||||
let error_record = ErrorRecord {
|
||||
promise_id: record.promise_id,
|
||||
arg: -1,
|
||||
error_len: error_class.len() as i32,
|
||||
error_class: error_class.as_bytes(),
|
||||
error_message: err.to_string().as_bytes().to_owned(),
|
||||
};
|
||||
error_record.into()
|
||||
}
|
||||
}
|
||||
};
|
||||
Op::Async(fut.boxed_local())
|
||||
}
|
||||
};
|
||||
|
||||
self.register_op(name, base_op_fn)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -3,18 +3,16 @@
|
|||
use crate::diagnostics::Diagnostic;
|
||||
use crate::source_maps::get_orig_position;
|
||||
use crate::source_maps::CachedMaps;
|
||||
use crate::state::State;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpState;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use serde_derive::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn init(s: &Rc<State>) {
|
||||
s.register_op_json_sync("op_apply_source_map", op_apply_source_map);
|
||||
s.register_op_json_sync("op_format_diagnostic", op_format_diagnostic);
|
||||
pub fn init(rt: &mut deno_core::JsRuntime) {
|
||||
super::reg_json_sync(rt, "op_apply_source_map", op_apply_source_map);
|
||||
super::reg_json_sync(rt, "op_format_diagnostic", op_format_diagnostic);
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -26,7 +24,7 @@ struct ApplySourceMap {
|
|||
}
|
||||
|
||||
fn op_apply_source_map(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
@ -39,7 +37,7 @@ fn op_apply_source_map(
|
|||
args.line_number.into(),
|
||||
args.column_number.into(),
|
||||
&mut mappings_map,
|
||||
&state.global_state.ts_compiler,
|
||||
&super::cli_state(state).global_state.ts_compiler,
|
||||
);
|
||||
|
||||
Ok(json!({
|
||||
|
@ -50,7 +48,7 @@ fn op_apply_source_map(
|
|||
}
|
||||
|
||||
fn op_format_diagnostic(
|
||||
_state: &State,
|
||||
_state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
|
|
@ -2,10 +2,9 @@
|
|||
|
||||
use super::io::{StreamResource, StreamResourceHolder};
|
||||
use crate::http_util::{create_http_client, HttpBody};
|
||||
use crate::state::State;
|
||||
use deno_core::BufVec;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpState;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use http::header::HeaderName;
|
||||
use http::header::HeaderValue;
|
||||
|
@ -13,13 +12,14 @@ use http::Method;
|
|||
use reqwest::Client;
|
||||
use serde_derive::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::cell::RefCell;
|
||||
use std::convert::From;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn init(s: &Rc<State>) {
|
||||
s.register_op_json_async("op_fetch", op_fetch);
|
||||
s.register_op_json_sync("op_create_http_client", op_create_http_client);
|
||||
pub fn init(rt: &mut deno_core::JsRuntime) {
|
||||
super::reg_json_async(rt, "op_fetch", op_fetch);
|
||||
super::reg_json_sync(rt, "op_create_http_client", op_create_http_client);
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -32,7 +32,7 @@ struct FetchArgs {
|
|||
}
|
||||
|
||||
async fn op_fetch(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
data: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
@ -40,13 +40,15 @@ async fn op_fetch(
|
|||
let url = args.url;
|
||||
|
||||
let client = if let Some(rid) = args.client_rid {
|
||||
let resource_table_ = state.resource_table.borrow();
|
||||
let r = resource_table_
|
||||
let state = state.borrow();
|
||||
let r = state
|
||||
.resource_table
|
||||
.get::<HttpClientResource>(rid)
|
||||
.ok_or_else(ErrBox::bad_resource_id)?;
|
||||
r.client.clone()
|
||||
} else {
|
||||
let client_ref = state.http_client.borrow_mut();
|
||||
let cli_state = super::cli_state2(&state);
|
||||
let client_ref = cli_state.http_client.borrow();
|
||||
client_ref.clone()
|
||||
};
|
||||
|
||||
|
@ -66,7 +68,7 @@ async fn op_fetch(
|
|||
)));
|
||||
}
|
||||
|
||||
state.check_net_url(&url_)?;
|
||||
super::cli_state2(&state).check_net_url(&url_)?;
|
||||
|
||||
let mut request = client.request(method, url_);
|
||||
|
||||
|
@ -93,7 +95,7 @@ async fn op_fetch(
|
|||
}
|
||||
|
||||
let body = HttpBody::from(res);
|
||||
let rid = state.resource_table.borrow_mut().add(
|
||||
let rid = state.borrow_mut().resource_table.add(
|
||||
"httpBody",
|
||||
Box::new(StreamResourceHolder::new(StreamResource::HttpBody(
|
||||
Box::new(body),
|
||||
|
@ -128,21 +130,20 @@ struct CreateHttpClientOptions {
|
|||
}
|
||||
|
||||
fn op_create_http_client(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
let args: CreateHttpClientOptions = serde_json::from_value(args)?;
|
||||
|
||||
if let Some(ca_file) = args.ca_file.clone() {
|
||||
state.check_read(&PathBuf::from(ca_file))?;
|
||||
super::cli_state(state).check_read(&PathBuf::from(ca_file))?;
|
||||
}
|
||||
|
||||
let client = create_http_client(args.ca_file.as_deref()).unwrap();
|
||||
|
||||
let rid = state
|
||||
.resource_table
|
||||
.borrow_mut()
|
||||
.add("httpClient", Box::new(HttpClientResource::new(client)));
|
||||
Ok(json!(rid))
|
||||
}
|
||||
|
|
440
cli/ops/fs.rs
440
cli/ops/fs.rs
File diff suppressed because it is too large
Load diff
|
@ -1,9 +1,8 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::state::State;
|
||||
use deno_core::BufVec;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpState;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use futures::future::poll_fn;
|
||||
use notify::event::Event as NotifyEvent;
|
||||
|
@ -15,14 +14,15 @@ use notify::Watcher;
|
|||
use serde::Serialize;
|
||||
use serde_derive::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::cell::RefCell;
|
||||
use std::convert::From;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
pub fn init(s: &Rc<State>) {
|
||||
s.register_op_json_sync("op_fs_events_open", op_fs_events_open);
|
||||
s.register_op_json_async("op_fs_events_poll", op_fs_events_poll);
|
||||
pub fn init(rt: &mut deno_core::JsRuntime) {
|
||||
super::reg_json_sync(rt, "op_fs_events_open", op_fs_events_open);
|
||||
super::reg_json_async(rt, "op_fs_events_poll", op_fs_events_poll);
|
||||
}
|
||||
|
||||
struct FsEventsResource {
|
||||
|
@ -64,7 +64,7 @@ impl From<NotifyEvent> for FsEvent {
|
|||
}
|
||||
|
||||
fn op_fs_events_open(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
@ -90,19 +90,16 @@ fn op_fs_events_open(
|
|||
RecursiveMode::NonRecursive
|
||||
};
|
||||
for path in &args.paths {
|
||||
state.check_read(&PathBuf::from(path))?;
|
||||
super::cli_state(state).check_read(&PathBuf::from(path))?;
|
||||
watcher.watch(path, recursive_mode)?;
|
||||
}
|
||||
let resource = FsEventsResource { watcher, receiver };
|
||||
let rid = state
|
||||
.resource_table
|
||||
.borrow_mut()
|
||||
.add("fsEvents", Box::new(resource));
|
||||
let rid = state.resource_table.add("fsEvents", Box::new(resource));
|
||||
Ok(json!(rid))
|
||||
}
|
||||
|
||||
async fn op_fs_events_poll(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
_zero_copy: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
@ -112,8 +109,9 @@ async fn op_fs_events_poll(
|
|||
}
|
||||
let PollArgs { rid } = serde_json::from_value(args)?;
|
||||
poll_fn(move |cx| {
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
let watcher = resource_table
|
||||
let mut state = state.borrow_mut();
|
||||
let watcher = state
|
||||
.resource_table
|
||||
.get_mut::<FsEventsResource>(rid)
|
||||
.ok_or_else(ErrBox::bad_resource_id)?;
|
||||
watcher
|
||||
|
|
|
@ -2,18 +2,15 @@
|
|||
|
||||
//! https://url.spec.whatwg.org/#idna
|
||||
|
||||
use crate::state::State;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use idna::domain_to_ascii;
|
||||
use idna::domain_to_ascii_strict;
|
||||
use serde_derive::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn init(s: &Rc<State>) {
|
||||
s.register_op_json_sync("op_domain_to_ascii", op_domain_to_ascii);
|
||||
pub fn init(rt: &mut deno_core::JsRuntime) {
|
||||
super::reg_json_sync(rt, "op_domain_to_ascii", op_domain_to_ascii);
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -24,7 +21,7 @@ struct DomainToAscii {
|
|||
}
|
||||
|
||||
fn op_domain_to_ascii(
|
||||
_state: &State,
|
||||
_state: &mut deno_core::OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
use super::dispatch_minimal::minimal_op;
|
||||
use super::dispatch_minimal::MinimalOp;
|
||||
use crate::http_util::HttpBody;
|
||||
use crate::state::State;
|
||||
use crate::metrics::metrics_op;
|
||||
use deno_core::BufVec;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::JsRuntime;
|
||||
use deno_core::OpState;
|
||||
use futures::future::poll_fn;
|
||||
use futures::future::FutureExt;
|
||||
use futures::ready;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
|
@ -82,9 +86,9 @@ lazy_static! {
|
|||
};
|
||||
}
|
||||
|
||||
pub fn init(s: &Rc<State>) {
|
||||
s.register_op_minimal("op_read", op_read);
|
||||
s.register_op_minimal("op_write", op_write);
|
||||
pub fn init(rt: &mut JsRuntime) {
|
||||
rt.register_op("op_read", metrics_op(minimal_op(op_read)));
|
||||
rt.register_op("op_write", metrics_op(minimal_op(op_write)));
|
||||
}
|
||||
|
||||
pub fn get_stdio() -> (
|
||||
|
@ -233,7 +237,7 @@ impl DenoAsyncRead for StreamResource {
|
|||
}
|
||||
|
||||
pub fn op_read(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
is_sync: bool,
|
||||
rid: i32,
|
||||
mut zero_copy: BufVec,
|
||||
|
@ -248,7 +252,7 @@ pub fn op_read(
|
|||
if is_sync {
|
||||
MinimalOp::Sync({
|
||||
// First we look up the rid in the resource table.
|
||||
std_file_resource(&state, rid as u32, move |r| match r {
|
||||
std_file_resource(&mut state.borrow_mut(), rid as u32, move |r| match r {
|
||||
Ok(std_file) => {
|
||||
use std::io::Read;
|
||||
std_file
|
||||
|
@ -265,8 +269,9 @@ pub fn op_read(
|
|||
let mut zero_copy = zero_copy[0].clone();
|
||||
MinimalOp::Async(
|
||||
poll_fn(move |cx| {
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
let resource_holder = resource_table
|
||||
let mut state = state.borrow_mut();
|
||||
let resource_holder = state
|
||||
.resource_table
|
||||
.get_mut::<StreamResourceHolder>(rid as u32)
|
||||
.ok_or_else(ErrBox::bad_resource_id)?;
|
||||
|
||||
|
@ -352,7 +357,7 @@ impl DenoAsyncWrite for StreamResource {
|
|||
}
|
||||
|
||||
pub fn op_write(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
is_sync: bool,
|
||||
rid: i32,
|
||||
zero_copy: BufVec,
|
||||
|
@ -367,7 +372,7 @@ pub fn op_write(
|
|||
if is_sync {
|
||||
MinimalOp::Sync({
|
||||
// First we look up the rid in the resource table.
|
||||
std_file_resource(&state, rid as u32, move |r| match r {
|
||||
std_file_resource(&mut state.borrow_mut(), rid as u32, move |r| match r {
|
||||
Ok(std_file) => {
|
||||
use std::io::Write;
|
||||
std_file
|
||||
|
@ -385,8 +390,9 @@ pub fn op_write(
|
|||
MinimalOp::Async(
|
||||
async move {
|
||||
let nwritten = poll_fn(|cx| {
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
let resource_holder = resource_table
|
||||
let mut state = state.borrow_mut();
|
||||
let resource_holder = state
|
||||
.resource_table
|
||||
.get_mut::<StreamResourceHolder>(rid as u32)
|
||||
.ok_or_else(ErrBox::bad_resource_id)?;
|
||||
resource_holder.resource.poll_write(cx, &zero_copy)
|
||||
|
@ -398,8 +404,9 @@ pub fn op_write(
|
|||
// Figure out why it's needed and preferably remove it.
|
||||
// https://github.com/denoland/deno/issues/3565
|
||||
poll_fn(|cx| {
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
let resource_holder = resource_table
|
||||
let mut state = state.borrow_mut();
|
||||
let resource_holder = state
|
||||
.resource_table
|
||||
.get_mut::<StreamResourceHolder>(rid as u32)
|
||||
.ok_or_else(ErrBox::bad_resource_id)?;
|
||||
resource_holder.resource.poll_flush(cx)
|
||||
|
@ -421,7 +428,7 @@ pub fn op_write(
|
|||
///
|
||||
/// Returns ErrorKind::Busy if the resource is being used by another op.
|
||||
pub fn std_file_resource<F, T>(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
rid: u32,
|
||||
mut f: F,
|
||||
) -> Result<T, ErrBox>
|
||||
|
@ -430,8 +437,7 @@ where
|
|||
FnMut(Result<&mut std::fs::File, &mut StreamResource>) -> Result<T, ErrBox>,
|
||||
{
|
||||
// First we look up the rid in the resource table.
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
let mut r = resource_table.get_mut::<StreamResourceHolder>(rid);
|
||||
let mut r = state.resource_table.get_mut::<StreamResourceHolder>(rid);
|
||||
if let Some(ref mut resource_holder) = r {
|
||||
// Sync write only works for FsFile. It doesn't make sense to do this
|
||||
// for non-blocking sockets. So we error out if not FsFile.
|
||||
|
|
|
@ -29,3 +29,43 @@ pub mod tty;
|
|||
pub mod web_worker;
|
||||
pub mod websocket;
|
||||
pub mod worker_host;
|
||||
|
||||
use crate::metrics::metrics_op;
|
||||
use deno_core::json_op_async;
|
||||
use deno_core::json_op_sync;
|
||||
use deno_core::BufVec;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::JsRuntime;
|
||||
use deno_core::OpState;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use serde_json::Value;
|
||||
use std::cell::RefCell;
|
||||
use std::future::Future;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn reg_json_async<F, R>(rt: &mut JsRuntime, name: &'static str, op_fn: F)
|
||||
where
|
||||
F: Fn(Rc<RefCell<OpState>>, Value, BufVec) -> R + 'static,
|
||||
R: Future<Output = Result<Value, ErrBox>> + 'static,
|
||||
{
|
||||
rt.register_op(name, metrics_op(json_op_async(op_fn)));
|
||||
}
|
||||
|
||||
pub fn reg_json_sync<F>(rt: &mut JsRuntime, name: &'static str, op_fn: F)
|
||||
where
|
||||
F: Fn(&mut OpState, Value, &mut [ZeroCopyBuf]) -> Result<Value, ErrBox>
|
||||
+ 'static,
|
||||
{
|
||||
rt.register_op(name, metrics_op(json_op_sync(op_fn)));
|
||||
}
|
||||
|
||||
/// Helper for extracting the commonly used state. Used for sync ops.
|
||||
pub fn cli_state(state: &OpState) -> Rc<crate::state::State> {
|
||||
state.borrow::<Rc<crate::state::State>>().clone()
|
||||
}
|
||||
|
||||
/// Helper for extracting the commonly used state. Used for async ops.
|
||||
pub fn cli_state2(state: &Rc<RefCell<OpState>>) -> Rc<crate::state::State> {
|
||||
let state = state.borrow();
|
||||
state.borrow::<Rc<crate::state::State>>().clone()
|
||||
}
|
||||
|
|
117
cli/ops/net.rs
117
cli/ops/net.rs
|
@ -2,14 +2,14 @@
|
|||
|
||||
use crate::ops::io::{StreamResource, StreamResourceHolder};
|
||||
use crate::resolve_addr::resolve_addr;
|
||||
use crate::state::State;
|
||||
use deno_core::BufVec;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpState;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use futures::future::poll_fn;
|
||||
use serde_derive::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::cell::RefCell;
|
||||
use std::net::Shutdown;
|
||||
use std::net::SocketAddr;
|
||||
use std::rc::Rc;
|
||||
|
@ -22,13 +22,13 @@ use tokio::net::UdpSocket;
|
|||
#[cfg(unix)]
|
||||
use super::net_unix;
|
||||
|
||||
pub fn init(s: &Rc<State>) {
|
||||
s.register_op_json_async("op_accept", op_accept);
|
||||
s.register_op_json_async("op_connect", op_connect);
|
||||
s.register_op_json_sync("op_shutdown", op_shutdown);
|
||||
s.register_op_json_sync("op_listen", op_listen);
|
||||
s.register_op_json_async("op_datagram_receive", op_datagram_receive);
|
||||
s.register_op_json_async("op_datagram_send", op_datagram_send);
|
||||
pub fn init(rt: &mut deno_core::JsRuntime) {
|
||||
super::reg_json_async(rt, "op_accept", op_accept);
|
||||
super::reg_json_async(rt, "op_connect", op_connect);
|
||||
super::reg_json_sync(rt, "op_shutdown", op_shutdown);
|
||||
super::reg_json_sync(rt, "op_listen", op_listen);
|
||||
super::reg_json_async(rt, "op_datagram_receive", op_datagram_receive);
|
||||
super::reg_json_async(rt, "op_datagram_send", op_datagram_send);
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -38,15 +38,16 @@ pub(crate) struct AcceptArgs {
|
|||
}
|
||||
|
||||
async fn accept_tcp(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: AcceptArgs,
|
||||
_zero_copy: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
let rid = args.rid as u32;
|
||||
|
||||
let accept_fut = poll_fn(|cx| {
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
let listener_resource = resource_table
|
||||
let mut state = state.borrow_mut();
|
||||
let listener_resource = state
|
||||
.resource_table
|
||||
.get_mut::<TcpListenerResource>(rid)
|
||||
.ok_or_else(|| ErrBox::bad_resource("Listener has been closed"))?;
|
||||
let listener = &mut listener_resource.listener;
|
||||
|
@ -68,7 +69,9 @@ async fn accept_tcp(
|
|||
let (tcp_stream, _socket_addr) = accept_fut.await?;
|
||||
let local_addr = tcp_stream.local_addr()?;
|
||||
let remote_addr = tcp_stream.peer_addr()?;
|
||||
let rid = state.resource_table.borrow_mut().add(
|
||||
|
||||
let mut state = state.borrow_mut();
|
||||
let rid = state.resource_table.add(
|
||||
"tcpStream",
|
||||
Box::new(StreamResourceHolder::new(StreamResource::TcpStream(Some(
|
||||
tcp_stream,
|
||||
|
@ -90,7 +93,7 @@ async fn accept_tcp(
|
|||
}
|
||||
|
||||
async fn op_accept(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
bufs: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
@ -113,7 +116,7 @@ pub(crate) struct ReceiveArgs {
|
|||
}
|
||||
|
||||
async fn receive_udp(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: ReceiveArgs,
|
||||
zero_copy: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
@ -123,8 +126,9 @@ async fn receive_udp(
|
|||
let rid = args.rid as u32;
|
||||
|
||||
let receive_fut = poll_fn(|cx| {
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
let resource = resource_table
|
||||
let mut state = state.borrow_mut();
|
||||
let resource = state
|
||||
.resource_table
|
||||
.get_mut::<UdpSocketResource>(rid)
|
||||
.ok_or_else(|| ErrBox::bad_resource("Socket has been closed"))?;
|
||||
let socket = &mut resource.socket;
|
||||
|
@ -144,7 +148,7 @@ async fn receive_udp(
|
|||
}
|
||||
|
||||
async fn op_datagram_receive(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
zero_copy: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
@ -171,12 +175,13 @@ struct SendArgs {
|
|||
}
|
||||
|
||||
async fn op_datagram_send(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
zero_copy: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
assert_eq!(zero_copy.len(), 1, "Invalid number of arguments");
|
||||
let zero_copy = zero_copy[0].clone();
|
||||
let cli_state = super::cli_state2(&state);
|
||||
|
||||
match serde_json::from_value(args)? {
|
||||
SendArgs {
|
||||
|
@ -184,11 +189,12 @@ async fn op_datagram_send(
|
|||
transport,
|
||||
transport_args: ArgsEnum::Ip(args),
|
||||
} if transport == "udp" => {
|
||||
state.check_net(&args.hostname, args.port)?;
|
||||
cli_state.check_net(&args.hostname, args.port)?;
|
||||
let addr = resolve_addr(&args.hostname, args.port)?;
|
||||
poll_fn(move |cx| {
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
let resource = resource_table
|
||||
let mut state = state.borrow_mut();
|
||||
let resource = state
|
||||
.resource_table
|
||||
.get_mut::<UdpSocketResource>(rid as u32)
|
||||
.ok_or_else(|| ErrBox::bad_resource("Socket has been closed"))?;
|
||||
resource
|
||||
|
@ -206,9 +212,10 @@ async fn op_datagram_send(
|
|||
transport_args: ArgsEnum::Unix(args),
|
||||
} if transport == "unixpacket" => {
|
||||
let address_path = net_unix::Path::new(&args.path);
|
||||
state.check_read(&address_path)?;
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
let resource = resource_table
|
||||
cli_state.check_read(&address_path)?;
|
||||
let mut state = state.borrow_mut();
|
||||
let resource = state
|
||||
.resource_table
|
||||
.get_mut::<net_unix::UnixDatagramResource>(rid as u32)
|
||||
.ok_or_else(|| ErrBox::new("NotConnected", "Socket has been closed"))?;
|
||||
let socket = &mut resource.socket;
|
||||
|
@ -230,21 +237,24 @@ struct ConnectArgs {
|
|||
}
|
||||
|
||||
async fn op_connect(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
_zero_copy: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
let cli_state = super::cli_state2(&state);
|
||||
match serde_json::from_value(args)? {
|
||||
ConnectArgs {
|
||||
transport,
|
||||
transport_args: ArgsEnum::Ip(args),
|
||||
} if transport == "tcp" => {
|
||||
state.check_net(&args.hostname, args.port)?;
|
||||
cli_state.check_net(&args.hostname, args.port)?;
|
||||
let addr = resolve_addr(&args.hostname, args.port)?;
|
||||
let tcp_stream = TcpStream::connect(&addr).await?;
|
||||
let local_addr = tcp_stream.local_addr()?;
|
||||
let remote_addr = tcp_stream.peer_addr()?;
|
||||
let rid = state.resource_table.borrow_mut().add(
|
||||
|
||||
let mut state_ = state.borrow_mut();
|
||||
let rid = state_.resource_table.add(
|
||||
"tcpStream",
|
||||
Box::new(StreamResourceHolder::new(StreamResource::TcpStream(Some(
|
||||
tcp_stream,
|
||||
|
@ -270,14 +280,16 @@ async fn op_connect(
|
|||
transport_args: ArgsEnum::Unix(args),
|
||||
} if transport == "unix" => {
|
||||
let address_path = net_unix::Path::new(&args.path);
|
||||
state.check_unstable("Deno.connect");
|
||||
state.check_read(&address_path)?;
|
||||
cli_state.check_unstable("Deno.connect");
|
||||
cli_state.check_read(&address_path)?;
|
||||
let path = args.path;
|
||||
let unix_stream =
|
||||
net_unix::UnixStream::connect(net_unix::Path::new(&path)).await?;
|
||||
let local_addr = unix_stream.local_addr()?;
|
||||
let remote_addr = unix_stream.peer_addr()?;
|
||||
let rid = state.resource_table.borrow_mut().add(
|
||||
|
||||
let mut state_ = state.borrow_mut();
|
||||
let rid = state_.resource_table.add(
|
||||
"unixStream",
|
||||
Box::new(StreamResourceHolder::new(StreamResource::UnixStream(
|
||||
unix_stream,
|
||||
|
@ -306,11 +318,11 @@ struct ShutdownArgs {
|
|||
}
|
||||
|
||||
fn op_shutdown(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
state.check_unstable("Deno.shutdown");
|
||||
super::cli_state(state).check_unstable("Deno.shutdown");
|
||||
|
||||
let args: ShutdownArgs = serde_json::from_value(args)?;
|
||||
|
||||
|
@ -323,8 +335,8 @@ fn op_shutdown(
|
|||
_ => unimplemented!(),
|
||||
};
|
||||
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
let resource_holder = resource_table
|
||||
let resource_holder = state
|
||||
.resource_table
|
||||
.get_mut::<StreamResourceHolder>(rid)
|
||||
.ok_or_else(ErrBox::bad_resource_id)?;
|
||||
match resource_holder.resource {
|
||||
|
@ -416,7 +428,7 @@ struct ListenArgs {
|
|||
}
|
||||
|
||||
fn listen_tcp(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
addr: SocketAddr,
|
||||
) -> Result<(u32, SocketAddr), ErrBox> {
|
||||
let std_listener = std::net::TcpListener::bind(&addr)?;
|
||||
|
@ -429,14 +441,13 @@ fn listen_tcp(
|
|||
};
|
||||
let rid = state
|
||||
.resource_table
|
||||
.borrow_mut()
|
||||
.add("tcpListener", Box::new(listener_resource));
|
||||
|
||||
Ok((rid, local_addr))
|
||||
}
|
||||
|
||||
fn listen_udp(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
addr: SocketAddr,
|
||||
) -> Result<(u32, SocketAddr), ErrBox> {
|
||||
let std_socket = std::net::UdpSocket::bind(&addr)?;
|
||||
|
@ -445,26 +456,28 @@ fn listen_udp(
|
|||
let socket_resource = UdpSocketResource { socket };
|
||||
let rid = state
|
||||
.resource_table
|
||||
.borrow_mut()
|
||||
.add("udpSocket", Box::new(socket_resource));
|
||||
|
||||
Ok((rid, local_addr))
|
||||
}
|
||||
|
||||
fn op_listen(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
let cli_state = super::cli_state(state);
|
||||
match serde_json::from_value(args)? {
|
||||
ListenArgs {
|
||||
transport,
|
||||
transport_args: ArgsEnum::Ip(args),
|
||||
} => {
|
||||
if transport == "udp" {
|
||||
state.check_unstable("Deno.listenDatagram");
|
||||
{
|
||||
if transport == "udp" {
|
||||
cli_state.check_unstable("Deno.listenDatagram");
|
||||
}
|
||||
cli_state.check_net(&args.hostname, args.port)?;
|
||||
}
|
||||
state.check_net(&args.hostname, args.port)?;
|
||||
let addr = resolve_addr(&args.hostname, args.port)?;
|
||||
let (rid, local_addr) = if transport == "tcp" {
|
||||
listen_tcp(state, addr)?
|
||||
|
@ -491,15 +504,17 @@ fn op_listen(
|
|||
transport,
|
||||
transport_args: ArgsEnum::Unix(args),
|
||||
} if transport == "unix" || transport == "unixpacket" => {
|
||||
if transport == "unix" {
|
||||
state.check_unstable("Deno.listen");
|
||||
}
|
||||
if transport == "unixpacket" {
|
||||
state.check_unstable("Deno.listenDatagram");
|
||||
}
|
||||
let address_path = net_unix::Path::new(&args.path);
|
||||
state.check_read(&address_path)?;
|
||||
state.check_write(&address_path)?;
|
||||
{
|
||||
if transport == "unix" {
|
||||
cli_state.check_unstable("Deno.listen");
|
||||
}
|
||||
if transport == "unixpacket" {
|
||||
cli_state.check_unstable("Deno.listenDatagram");
|
||||
}
|
||||
cli_state.check_read(&address_path)?;
|
||||
cli_state.check_write(&address_path)?;
|
||||
}
|
||||
let (rid, local_addr) = if transport == "unix" {
|
||||
net_unix::listen_unix(state, &address_path)?
|
||||
} else {
|
||||
|
|
|
@ -2,15 +2,18 @@ use crate::ops::io::StreamResource;
|
|||
use crate::ops::io::StreamResourceHolder;
|
||||
use crate::ops::net::AcceptArgs;
|
||||
use crate::ops::net::ReceiveArgs;
|
||||
use crate::state::State;
|
||||
use deno_core::BufVec;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::OpState;
|
||||
use futures::future::poll_fn;
|
||||
use serde_derive::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::cell::RefCell;
|
||||
use std::fs::remove_file;
|
||||
use std::os::unix;
|
||||
pub use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
use std::task::Poll;
|
||||
use tokio::net::UnixDatagram;
|
||||
use tokio::net::UnixListener;
|
||||
pub use tokio::net::UnixStream;
|
||||
|
@ -30,25 +33,39 @@ pub struct UnixListenArgs {
|
|||
}
|
||||
|
||||
pub(crate) async fn accept_unix(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: AcceptArgs,
|
||||
_bufs: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
let rid = args.rid as u32;
|
||||
|
||||
let mut resource_table_ = state.resource_table.borrow_mut();
|
||||
let listener_resource = {
|
||||
resource_table_
|
||||
let accept_fut = poll_fn(|cx| {
|
||||
let mut state = state.borrow_mut();
|
||||
let listener_resource = state
|
||||
.resource_table
|
||||
.get_mut::<UnixListenerResource>(rid)
|
||||
.ok_or_else(|| ErrBox::bad_resource("Listener has been closed"))?
|
||||
};
|
||||
let (unix_stream, _socket_addr) = listener_resource.listener.accept().await?;
|
||||
drop(resource_table_);
|
||||
.ok_or_else(|| ErrBox::bad_resource("Listener has been closed"))?;
|
||||
let listener = &mut listener_resource.listener;
|
||||
use futures::StreamExt;
|
||||
match listener.poll_next_unpin(cx) {
|
||||
Poll::Ready(Some(stream)) => {
|
||||
//listener_resource.untrack_task();
|
||||
Poll::Ready(stream)
|
||||
}
|
||||
Poll::Ready(None) => todo!(),
|
||||
Poll::Pending => {
|
||||
//listener_resource.track_task(cx)?;
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
.map_err(ErrBox::from)
|
||||
});
|
||||
let unix_stream = accept_fut.await?;
|
||||
|
||||
let local_addr = unix_stream.local_addr()?;
|
||||
let remote_addr = unix_stream.peer_addr()?;
|
||||
let mut resource_table_ = state.resource_table.borrow_mut();
|
||||
let rid = resource_table_.add(
|
||||
let mut state = state.borrow_mut();
|
||||
let rid = state.resource_table.add(
|
||||
"unixStream",
|
||||
Box::new(StreamResourceHolder::new(StreamResource::UnixStream(
|
||||
unix_stream,
|
||||
|
@ -68,7 +85,7 @@ pub(crate) async fn accept_unix(
|
|||
}
|
||||
|
||||
pub(crate) async fn receive_unix_packet(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: ReceiveArgs,
|
||||
bufs: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
@ -77,8 +94,9 @@ pub(crate) async fn receive_unix_packet(
|
|||
let rid = args.rid as u32;
|
||||
let mut buf = bufs.into_iter().next().unwrap();
|
||||
|
||||
let mut resource_table_ = state.resource_table.borrow_mut();
|
||||
let resource = resource_table_
|
||||
let mut state = state.borrow_mut();
|
||||
let resource = state
|
||||
.resource_table
|
||||
.get_mut::<UnixDatagramResource>(rid)
|
||||
.ok_or_else(|| ErrBox::bad_resource("Socket has been closed"))?;
|
||||
let (size, remote_addr) = resource.socket.recv_from(&mut buf).await?;
|
||||
|
@ -92,7 +110,7 @@ pub(crate) async fn receive_unix_packet(
|
|||
}
|
||||
|
||||
pub fn listen_unix(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
addr: &Path,
|
||||
) -> Result<(u32, unix::net::SocketAddr), ErrBox> {
|
||||
if addr.exists() {
|
||||
|
@ -103,14 +121,13 @@ pub fn listen_unix(
|
|||
let listener_resource = UnixListenerResource { listener };
|
||||
let rid = state
|
||||
.resource_table
|
||||
.borrow_mut()
|
||||
.add("unixListener", Box::new(listener_resource));
|
||||
|
||||
Ok((rid, local_addr))
|
||||
}
|
||||
|
||||
pub fn listen_unix_packet(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
addr: &Path,
|
||||
) -> Result<(u32, unix::net::SocketAddr), ErrBox> {
|
||||
if addr.exists() {
|
||||
|
@ -124,7 +141,6 @@ pub fn listen_unix_packet(
|
|||
};
|
||||
let rid = state
|
||||
.resource_table
|
||||
.borrow_mut()
|
||||
.add("unixDatagram", Box::new(datagram_resource));
|
||||
|
||||
Ok((rid, local_addr))
|
||||
|
|
|
@ -1,36 +1,35 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::state::State;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpState;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use serde_derive::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::rc::Rc;
|
||||
use url::Url;
|
||||
|
||||
pub fn init(s: &Rc<State>) {
|
||||
s.register_op_json_sync("op_exit", op_exit);
|
||||
s.register_op_json_sync("op_env", op_env);
|
||||
s.register_op_json_sync("op_exec_path", op_exec_path);
|
||||
s.register_op_json_sync("op_set_env", op_set_env);
|
||||
s.register_op_json_sync("op_get_env", op_get_env);
|
||||
s.register_op_json_sync("op_delete_env", op_delete_env);
|
||||
s.register_op_json_sync("op_hostname", op_hostname);
|
||||
s.register_op_json_sync("op_loadavg", op_loadavg);
|
||||
s.register_op_json_sync("op_os_release", op_os_release);
|
||||
s.register_op_json_sync("op_system_memory_info", op_system_memory_info);
|
||||
pub fn init(rt: &mut deno_core::JsRuntime) {
|
||||
super::reg_json_sync(rt, "op_exit", op_exit);
|
||||
super::reg_json_sync(rt, "op_env", op_env);
|
||||
super::reg_json_sync(rt, "op_exec_path", op_exec_path);
|
||||
super::reg_json_sync(rt, "op_set_env", op_set_env);
|
||||
super::reg_json_sync(rt, "op_get_env", op_get_env);
|
||||
super::reg_json_sync(rt, "op_delete_env", op_delete_env);
|
||||
super::reg_json_sync(rt, "op_hostname", op_hostname);
|
||||
super::reg_json_sync(rt, "op_loadavg", op_loadavg);
|
||||
super::reg_json_sync(rt, "op_os_release", op_os_release);
|
||||
super::reg_json_sync(rt, "op_system_memory_info", op_system_memory_info);
|
||||
}
|
||||
|
||||
fn op_exec_path(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
_args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
let current_exe = env::current_exe().unwrap();
|
||||
state.check_read_blind(¤t_exe, "exec_path")?;
|
||||
let cli_state = super::cli_state(state);
|
||||
cli_state.check_read_blind(¤t_exe, "exec_path")?;
|
||||
// Now apply URL parser to current exe to get fully resolved path, otherwise
|
||||
// we might get `./` and `../` bits in `exec_path`
|
||||
let exe_url = Url::from_file_path(current_exe).unwrap();
|
||||
|
@ -45,22 +44,24 @@ struct SetEnv {
|
|||
}
|
||||
|
||||
fn op_set_env(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
let args: SetEnv = serde_json::from_value(args)?;
|
||||
state.check_env()?;
|
||||
let cli_state = super::cli_state(state);
|
||||
cli_state.check_env()?;
|
||||
env::set_var(args.key, args.value);
|
||||
Ok(json!({}))
|
||||
}
|
||||
|
||||
fn op_env(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
_args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
state.check_env()?;
|
||||
let cli_state = super::cli_state(state);
|
||||
cli_state.check_env()?;
|
||||
let v = env::vars().collect::<HashMap<String, String>>();
|
||||
Ok(json!(v))
|
||||
}
|
||||
|
@ -71,12 +72,13 @@ struct GetEnv {
|
|||
}
|
||||
|
||||
fn op_get_env(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
let args: GetEnv = serde_json::from_value(args)?;
|
||||
state.check_env()?;
|
||||
let cli_state = super::cli_state(state);
|
||||
cli_state.check_env()?;
|
||||
let r = match env::var(args.key) {
|
||||
Err(env::VarError::NotPresent) => json!([]),
|
||||
v => json!([v?]),
|
||||
|
@ -90,12 +92,13 @@ struct DeleteEnv {
|
|||
}
|
||||
|
||||
fn op_delete_env(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
let args: DeleteEnv = serde_json::from_value(args)?;
|
||||
state.check_env()?;
|
||||
let cli_state = super::cli_state(state);
|
||||
cli_state.check_env()?;
|
||||
env::remove_var(args.key);
|
||||
Ok(json!({}))
|
||||
}
|
||||
|
@ -106,7 +109,7 @@ struct Exit {
|
|||
}
|
||||
|
||||
fn op_exit(
|
||||
_state: &State,
|
||||
_state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
@ -115,12 +118,13 @@ fn op_exit(
|
|||
}
|
||||
|
||||
fn op_loadavg(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
_args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
state.check_unstable("Deno.loadavg");
|
||||
state.check_env()?;
|
||||
let cli_state = super::cli_state(state);
|
||||
cli_state.check_unstable("Deno.loadavg");
|
||||
cli_state.check_env()?;
|
||||
match sys_info::loadavg() {
|
||||
Ok(loadavg) => Ok(json!([loadavg.one, loadavg.five, loadavg.fifteen])),
|
||||
Err(_) => Ok(json!([0f64, 0f64, 0f64])),
|
||||
|
@ -128,34 +132,37 @@ fn op_loadavg(
|
|||
}
|
||||
|
||||
fn op_hostname(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
_args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
state.check_unstable("Deno.hostname");
|
||||
state.check_env()?;
|
||||
let cli_state = super::cli_state(state);
|
||||
cli_state.check_unstable("Deno.hostname");
|
||||
cli_state.check_env()?;
|
||||
let hostname = sys_info::hostname().unwrap_or_else(|_| "".to_string());
|
||||
Ok(json!(hostname))
|
||||
}
|
||||
|
||||
fn op_os_release(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
_args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
state.check_unstable("Deno.osRelease");
|
||||
state.check_env()?;
|
||||
let cli_state = super::cli_state(state);
|
||||
cli_state.check_unstable("Deno.osRelease");
|
||||
cli_state.check_env()?;
|
||||
let release = sys_info::os_release().unwrap_or_else(|_| "".to_string());
|
||||
Ok(json!(release))
|
||||
}
|
||||
|
||||
fn op_system_memory_info(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
_args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
state.check_unstable("Deno.systemMemoryInfo");
|
||||
state.check_env()?;
|
||||
let cli_state = super::cli_state(state);
|
||||
cli_state.check_unstable("Deno.systemMemoryInfo");
|
||||
cli_state.check_env()?;
|
||||
match sys_info::mem_info() {
|
||||
Ok(info) => Ok(json!({
|
||||
"total": info.total,
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::state::State;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpState;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use serde_derive::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn init(s: &Rc<State>) {
|
||||
s.register_op_json_sync("op_query_permission", op_query_permission);
|
||||
s.register_op_json_sync("op_revoke_permission", op_revoke_permission);
|
||||
s.register_op_json_sync("op_request_permission", op_request_permission);
|
||||
pub fn init(rt: &mut deno_core::JsRuntime) {
|
||||
super::reg_json_sync(rt, "op_query_permission", op_query_permission);
|
||||
super::reg_json_sync(rt, "op_revoke_permission", op_revoke_permission);
|
||||
super::reg_json_sync(rt, "op_request_permission", op_request_permission);
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -23,12 +21,13 @@ struct PermissionArgs {
|
|||
}
|
||||
|
||||
pub fn op_query_permission(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
let args: PermissionArgs = serde_json::from_value(args)?;
|
||||
let permissions = state.permissions.borrow();
|
||||
let cli_state = super::cli_state(state);
|
||||
let permissions = cli_state.permissions.borrow();
|
||||
let path = args.path.as_deref();
|
||||
let perm = match args.name.as_ref() {
|
||||
"read" => permissions.query_read(&path.as_deref().map(Path::new)),
|
||||
|
@ -49,12 +48,13 @@ pub fn op_query_permission(
|
|||
}
|
||||
|
||||
pub fn op_revoke_permission(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
let args: PermissionArgs = serde_json::from_value(args)?;
|
||||
let mut permissions = state.permissions.borrow_mut();
|
||||
let cli_state = super::cli_state(state);
|
||||
let mut permissions = cli_state.permissions.borrow_mut();
|
||||
let path = args.path.as_deref();
|
||||
let perm = match args.name.as_ref() {
|
||||
"read" => permissions.revoke_read(&path.as_deref().map(Path::new)),
|
||||
|
@ -75,12 +75,13 @@ pub fn op_revoke_permission(
|
|||
}
|
||||
|
||||
pub fn op_request_permission(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
let args: PermissionArgs = serde_json::from_value(args)?;
|
||||
let permissions = &mut state.permissions.borrow_mut();
|
||||
let cli_state = super::cli_state(state);
|
||||
let permissions = &mut cli_state.permissions.borrow_mut();
|
||||
let path = args.path.as_deref();
|
||||
let perm = match args.name.as_ref() {
|
||||
"read" => permissions.request_read(&path.as_deref().map(Path::new)),
|
||||
|
|
|
@ -1,26 +1,28 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::state::State;
|
||||
use crate::metrics::metrics_op;
|
||||
use deno_core::plugin_api;
|
||||
use deno_core::BufVec;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::JsRuntime;
|
||||
use deno_core::Op;
|
||||
use deno_core::OpAsyncFuture;
|
||||
use deno_core::OpId;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpState;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use dlopen::symbor::Library;
|
||||
use futures::prelude::*;
|
||||
use serde_derive::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::cell::RefCell;
|
||||
use std::path::PathBuf;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::task::Context;
|
||||
use std::task::Poll;
|
||||
|
||||
pub fn init(s: &Rc<State>) {
|
||||
s.register_op_json_sync("op_open_plugin", op_open_plugin);
|
||||
pub fn init(rt: &mut JsRuntime) {
|
||||
super::reg_json_sync(rt, "op_open_plugin", op_open_plugin);
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -30,16 +32,16 @@ struct OpenPluginArgs {
|
|||
}
|
||||
|
||||
pub fn op_open_plugin(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
state.check_unstable("Deno.openPlugin");
|
||||
|
||||
let args: OpenPluginArgs = serde_json::from_value(args).unwrap();
|
||||
let args: OpenPluginArgs = serde_json::from_value(args)?;
|
||||
let filename = PathBuf::from(&args.filename);
|
||||
|
||||
state.check_plugin(&filename)?;
|
||||
let cli_state = super::cli_state(state);
|
||||
cli_state.check_unstable("Deno.openPlugin");
|
||||
cli_state.check_plugin(&filename)?;
|
||||
|
||||
debug!("Loading Plugin: {:#?}", filename);
|
||||
let plugin_lib = Library::open(filename).map(Rc::new)?;
|
||||
|
@ -48,10 +50,12 @@ pub fn op_open_plugin(
|
|||
let rid;
|
||||
let deno_plugin_init;
|
||||
{
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
rid = resource_table.add("plugin", Box::new(plugin_resource));
|
||||
rid = state
|
||||
.resource_table
|
||||
.add("plugin", Box::new(plugin_resource));
|
||||
deno_plugin_init = *unsafe {
|
||||
resource_table
|
||||
state
|
||||
.resource_table
|
||||
.get::<PluginResource>(rid)
|
||||
.unwrap()
|
||||
.lib
|
||||
|
@ -77,12 +81,12 @@ impl PluginResource {
|
|||
}
|
||||
|
||||
struct PluginInterface<'a> {
|
||||
state: &'a State,
|
||||
state: &'a mut OpState,
|
||||
plugin_lib: &'a Rc<Library>,
|
||||
}
|
||||
|
||||
impl<'a> PluginInterface<'a> {
|
||||
fn new(state: &'a State, plugin_lib: &'a Rc<Library>) -> Self {
|
||||
fn new(state: &'a mut OpState, plugin_lib: &'a Rc<Library>) -> Self {
|
||||
Self { state, plugin_lib }
|
||||
}
|
||||
}
|
||||
|
@ -99,23 +103,24 @@ impl<'a> plugin_api::Interface for PluginInterface<'a> {
|
|||
dispatch_op_fn: plugin_api::DispatchOpFn,
|
||||
) -> OpId {
|
||||
let plugin_lib = self.plugin_lib.clone();
|
||||
self.state.register_op(
|
||||
name,
|
||||
move |state: Rc<State>, mut zero_copy: BufVec| {
|
||||
let mut interface = PluginInterface::new(&state, &plugin_lib);
|
||||
let op = dispatch_op_fn(&mut interface, &mut zero_copy);
|
||||
match op {
|
||||
sync_op @ Op::Sync(..) => sync_op,
|
||||
Op::Async(fut) => {
|
||||
Op::Async(PluginOpAsyncFuture::new(&plugin_lib, fut))
|
||||
}
|
||||
Op::AsyncUnref(fut) => {
|
||||
Op::AsyncUnref(PluginOpAsyncFuture::new(&plugin_lib, fut))
|
||||
}
|
||||
_ => unreachable!(),
|
||||
let plugin_op_fn = move |state_rc: Rc<RefCell<OpState>>,
|
||||
mut zero_copy: BufVec| {
|
||||
let mut state = state_rc.borrow_mut();
|
||||
let mut interface = PluginInterface::new(&mut state, &plugin_lib);
|
||||
let op = dispatch_op_fn(&mut interface, &mut zero_copy);
|
||||
match op {
|
||||
sync_op @ Op::Sync(..) => sync_op,
|
||||
Op::Async(fut) => Op::Async(PluginOpAsyncFuture::new(&plugin_lib, fut)),
|
||||
Op::AsyncUnref(fut) => {
|
||||
Op::AsyncUnref(PluginOpAsyncFuture::new(&plugin_lib, fut))
|
||||
}
|
||||
},
|
||||
)
|
||||
_ => unreachable!(),
|
||||
}
|
||||
};
|
||||
self
|
||||
.state
|
||||
.op_table
|
||||
.register_op(name, metrics_op(Box::new(plugin_op_fn)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,28 +2,28 @@
|
|||
|
||||
use super::io::{std_file_resource, StreamResource, StreamResourceHolder};
|
||||
use crate::signal::kill;
|
||||
use crate::state::State;
|
||||
use deno_core::BufVec;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpState;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use futures::future::poll_fn;
|
||||
use futures::future::FutureExt;
|
||||
use serde_derive::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use tokio::process::Command;
|
||||
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::process::ExitStatusExt;
|
||||
|
||||
pub fn init(s: &Rc<State>) {
|
||||
s.register_op_json_sync("op_run", op_run);
|
||||
s.register_op_json_async("op_run_status", op_run_status);
|
||||
s.register_op_json_sync("op_kill", op_kill);
|
||||
pub fn init(rt: &mut deno_core::JsRuntime) {
|
||||
super::reg_json_sync(rt, "op_run", op_run);
|
||||
super::reg_json_async(rt, "op_run_status", op_run_status);
|
||||
super::reg_json_sync(rt, "op_kill", op_kill);
|
||||
}
|
||||
|
||||
fn clone_file(state: &State, rid: u32) -> Result<std::fs::File, ErrBox> {
|
||||
fn clone_file(state: &mut OpState, rid: u32) -> Result<std::fs::File, ErrBox> {
|
||||
std_file_resource(state, rid, move |r| match r {
|
||||
Ok(std_file) => std_file.try_clone().map_err(ErrBox::from),
|
||||
Err(_) => Err(ErrBox::bad_resource_id()),
|
||||
|
@ -58,13 +58,12 @@ struct ChildResource {
|
|||
}
|
||||
|
||||
fn op_run(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
let run_args: RunArgs = serde_json::from_value(args)?;
|
||||
|
||||
state.check_run()?;
|
||||
super::cli_state(state).check_run()?;
|
||||
|
||||
let args = run_args.cmd;
|
||||
let env = run_args.env;
|
||||
|
@ -111,7 +110,7 @@ fn op_run(
|
|||
|
||||
let stdin_rid = match child.stdin.take() {
|
||||
Some(child_stdin) => {
|
||||
let rid = state.resource_table.borrow_mut().add(
|
||||
let rid = state.resource_table.add(
|
||||
"childStdin",
|
||||
Box::new(StreamResourceHolder::new(StreamResource::ChildStdin(
|
||||
child_stdin,
|
||||
|
@ -124,7 +123,7 @@ fn op_run(
|
|||
|
||||
let stdout_rid = match child.stdout.take() {
|
||||
Some(child_stdout) => {
|
||||
let rid = state.resource_table.borrow_mut().add(
|
||||
let rid = state.resource_table.add(
|
||||
"childStdout",
|
||||
Box::new(StreamResourceHolder::new(StreamResource::ChildStdout(
|
||||
child_stdout,
|
||||
|
@ -137,7 +136,7 @@ fn op_run(
|
|||
|
||||
let stderr_rid = match child.stderr.take() {
|
||||
Some(child_stderr) => {
|
||||
let rid = state.resource_table.borrow_mut().add(
|
||||
let rid = state.resource_table.add(
|
||||
"childStderr",
|
||||
Box::new(StreamResourceHolder::new(StreamResource::ChildStderr(
|
||||
child_stderr,
|
||||
|
@ -149,10 +148,7 @@ fn op_run(
|
|||
};
|
||||
|
||||
let child_resource = ChildResource { child };
|
||||
let child_rid = state
|
||||
.resource_table
|
||||
.borrow_mut()
|
||||
.add("child", Box::new(child_resource));
|
||||
let child_rid = state.resource_table.add("child", Box::new(child_resource));
|
||||
|
||||
Ok(json!({
|
||||
"rid": child_rid,
|
||||
|
@ -170,18 +166,19 @@ struct RunStatusArgs {
|
|||
}
|
||||
|
||||
async fn op_run_status(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
_zero_copy: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
let args: RunStatusArgs = serde_json::from_value(args)?;
|
||||
let rid = args.rid as u32;
|
||||
|
||||
state.check_run()?;
|
||||
super::cli_state2(&state).check_run()?;
|
||||
|
||||
let run_status = poll_fn(|cx| {
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
let child_resource = resource_table
|
||||
let mut state = state.borrow_mut();
|
||||
let child_resource = state
|
||||
.resource_table
|
||||
.get_mut::<ChildResource>(rid)
|
||||
.ok_or_else(ErrBox::bad_resource_id)?;
|
||||
let child = &mut child_resource.child;
|
||||
|
@ -215,12 +212,13 @@ struct KillArgs {
|
|||
}
|
||||
|
||||
fn op_kill(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
state.check_unstable("Deno.kill");
|
||||
state.check_run()?;
|
||||
let cli_state = super::cli_state(state);
|
||||
cli_state.check_unstable("Deno.kill");
|
||||
cli_state.check_run()?;
|
||||
|
||||
let args: KillArgs = serde_json::from_value(args)?;
|
||||
kill(args.pid, args.signo)?;
|
||||
|
|
|
@ -1,26 +1,24 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::state::State;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpState;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use rand::thread_rng;
|
||||
use rand::Rng;
|
||||
use serde_json::Value;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn init(s: &Rc<State>) {
|
||||
s.register_op_json_sync("op_get_random_values", op_get_random_values);
|
||||
pub fn init(rt: &mut deno_core::JsRuntime) {
|
||||
super::reg_json_sync(rt, "op_get_random_values", op_get_random_values);
|
||||
}
|
||||
|
||||
fn op_get_random_values(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
_args: Value,
|
||||
zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
assert_eq!(zero_copy.len(), 1);
|
||||
|
||||
if let Some(seeded_rng) = &state.seeded_rng {
|
||||
let cli_state = super::cli_state(state);
|
||||
if let Some(seeded_rng) = &cli_state.seeded_rng {
|
||||
seeded_rng.borrow_mut().fill(&mut *zero_copy[0]);
|
||||
} else {
|
||||
let mut rng = thread_rng();
|
||||
|
|
|
@ -2,20 +2,20 @@
|
|||
|
||||
use crate::repl;
|
||||
use crate::repl::Repl;
|
||||
use crate::state::State;
|
||||
use deno_core::BufVec;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpState;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use serde_derive::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub fn init(s: &Rc<State>) {
|
||||
s.register_op_json_sync("op_repl_start", op_repl_start);
|
||||
s.register_op_json_async("op_repl_readline", op_repl_readline);
|
||||
pub fn init(rt: &mut deno_core::JsRuntime) {
|
||||
super::reg_json_sync(rt, "op_repl_start", op_repl_start);
|
||||
super::reg_json_async(rt, "op_repl_readline", op_repl_readline);
|
||||
}
|
||||
|
||||
struct ReplResource(Arc<Mutex<Repl>>);
|
||||
|
@ -27,20 +27,19 @@ struct ReplStartArgs {
|
|||
}
|
||||
|
||||
fn op_repl_start(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
let args: ReplStartArgs = serde_json::from_value(args)?;
|
||||
debug!("op_repl_start {}", args.history_file);
|
||||
let history_path =
|
||||
repl::history_path(&state.global_state.dir, &args.history_file);
|
||||
let history_path = {
|
||||
let cli_state = super::cli_state(state);
|
||||
repl::history_path(&cli_state.global_state.dir, &args.history_file)
|
||||
};
|
||||
let repl = repl::Repl::new(history_path);
|
||||
let resource = ReplResource(Arc::new(Mutex::new(repl)));
|
||||
let rid = state
|
||||
.resource_table
|
||||
.borrow_mut()
|
||||
.add("repl", Box::new(resource));
|
||||
let rid = state.resource_table.add("repl", Box::new(resource));
|
||||
Ok(json!(rid))
|
||||
}
|
||||
|
||||
|
@ -51,7 +50,7 @@ struct ReplReadlineArgs {
|
|||
}
|
||||
|
||||
async fn op_repl_readline(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
_zero_copy: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
@ -59,12 +58,14 @@ async fn op_repl_readline(
|
|||
let rid = args.rid as u32;
|
||||
let prompt = args.prompt;
|
||||
debug!("op_repl_readline {} {}", rid, prompt);
|
||||
let resource_table = state.resource_table.borrow();
|
||||
let resource = resource_table
|
||||
.get::<ReplResource>(rid)
|
||||
.ok_or_else(ErrBox::bad_resource_id)?;
|
||||
let repl = resource.0.clone();
|
||||
drop(resource_table);
|
||||
let repl = {
|
||||
let state = state.borrow();
|
||||
let resource = state
|
||||
.resource_table
|
||||
.get::<ReplResource>(rid)
|
||||
.ok_or_else(ErrBox::bad_resource_id)?;
|
||||
resource.0.clone()
|
||||
};
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let line = repl.lock().unwrap().readline(&prompt)?;
|
||||
Ok(json!(line))
|
||||
|
|
|
@ -1,31 +1,28 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::state::State;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpState;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use serde_derive::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn init(s: &Rc<State>) {
|
||||
s.register_op_json_sync("op_resources", op_resources);
|
||||
s.register_op_json_sync("op_close", op_close);
|
||||
pub fn init(rt: &mut deno_core::JsRuntime) {
|
||||
super::reg_json_sync(rt, "op_resources", op_resources);
|
||||
super::reg_json_sync(rt, "op_close", op_close);
|
||||
}
|
||||
|
||||
fn op_resources(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
_args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
let resource_table = state.resource_table.borrow();
|
||||
let serialized_resources = resource_table.entries();
|
||||
let serialized_resources = state.resource_table.entries();
|
||||
Ok(json!(serialized_resources))
|
||||
}
|
||||
|
||||
/// op_close removes a resource from the resource table.
|
||||
fn op_close(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
@ -36,7 +33,6 @@ fn op_close(
|
|||
let args: CloseArgs = serde_json::from_value(args)?;
|
||||
state
|
||||
.resource_table
|
||||
.borrow_mut()
|
||||
.close(args.rid as u32)
|
||||
.ok_or_else(ErrBox::bad_resource_id)?;
|
||||
Ok(json!({}))
|
||||
|
|
|
@ -1,29 +1,27 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::colors;
|
||||
use crate::state::State;
|
||||
use crate::version;
|
||||
use crate::DenoSubcommand;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpState;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use serde_json::Value;
|
||||
use std::env;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn init(s: &Rc<State>) {
|
||||
s.register_op_json_sync("op_start", op_start);
|
||||
s.register_op_json_sync("op_main_module", op_main_module);
|
||||
s.register_op_json_sync("op_metrics", op_metrics);
|
||||
pub fn init(rt: &mut deno_core::JsRuntime) {
|
||||
super::reg_json_sync(rt, "op_start", op_start);
|
||||
super::reg_json_sync(rt, "op_main_module", op_main_module);
|
||||
super::reg_json_sync(rt, "op_metrics", op_metrics);
|
||||
}
|
||||
|
||||
fn op_start(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
_args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
let gs = &state.global_state;
|
||||
let gs = &super::cli_state(state).global_state;
|
||||
|
||||
Ok(json!({
|
||||
// TODO(bartlomieju): `cwd` field is not used in JS, remove?
|
||||
|
@ -44,25 +42,27 @@ fn op_start(
|
|||
}
|
||||
|
||||
fn op_main_module(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
_args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
let main = &state.main_module.to_string();
|
||||
let cli_state = super::cli_state(state);
|
||||
let main = &cli_state.main_module.to_string();
|
||||
let main_url = ModuleSpecifier::resolve_url_or_path(&main)?;
|
||||
if main_url.as_url().scheme() == "file" {
|
||||
let main_path = std::env::current_dir().unwrap().join(main_url.to_string());
|
||||
state.check_read_blind(&main_path, "main_module")?;
|
||||
cli_state.check_read_blind(&main_path, "main_module")?;
|
||||
}
|
||||
Ok(json!(&main))
|
||||
}
|
||||
|
||||
fn op_metrics(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
_args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
let m = &state.metrics.borrow();
|
||||
let cli_state = super::cli_state(state);
|
||||
let m = &cli_state.metrics.borrow();
|
||||
|
||||
Ok(json!({
|
||||
"opsDispatched": m.ops_dispatched,
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::futures::FutureExt;
|
||||
use crate::state::State;
|
||||
use crate::tsc::runtime_bundle;
|
||||
use crate::tsc::runtime_compile;
|
||||
use crate::tsc::runtime_transpile;
|
||||
use deno_core::BufVec;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpState;
|
||||
use serde_derive::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn init(s: &Rc<State>) {
|
||||
s.register_op_json_async("op_compile", op_compile);
|
||||
s.register_op_json_async("op_transpile", op_transpile);
|
||||
pub fn init(rt: &mut deno_core::JsRuntime) {
|
||||
super::reg_json_async(rt, "op_compile", op_compile);
|
||||
super::reg_json_async(rt, "op_transpile", op_transpile);
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
|
@ -28,14 +28,15 @@ struct CompileArgs {
|
|||
}
|
||||
|
||||
async fn op_compile(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
_data: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
state.check_unstable("Deno.compile");
|
||||
let cli_state = super::cli_state2(&state);
|
||||
cli_state.check_unstable("Deno.compile");
|
||||
let args: CompileArgs = serde_json::from_value(args)?;
|
||||
let global_state = state.global_state.clone();
|
||||
let permissions = state.permissions.borrow().clone();
|
||||
let global_state = cli_state.global_state.clone();
|
||||
let permissions = cli_state.permissions.borrow().clone();
|
||||
let fut = if args.bundle {
|
||||
runtime_bundle(
|
||||
&global_state,
|
||||
|
@ -66,14 +67,15 @@ struct TranspileArgs {
|
|||
}
|
||||
|
||||
async fn op_transpile(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
_data: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
state.check_unstable("Deno.transpile");
|
||||
let cli_state = super::cli_state2(&state);
|
||||
cli_state.check_unstable("Deno.transpile");
|
||||
let args: TranspileArgs = serde_json::from_value(args)?;
|
||||
let global_state = state.global_state.clone();
|
||||
let permissions = state.permissions.borrow().clone();
|
||||
let global_state = cli_state.global_state.clone();
|
||||
let permissions = cli_state.permissions.borrow().clone();
|
||||
let result =
|
||||
runtime_transpile(&global_state, permissions, &args.sources, &args.options)
|
||||
.await?;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::state::State;
|
||||
use deno_core::BufVec;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpState;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use serde_json::Value;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[cfg(unix)]
|
||||
|
@ -17,10 +17,10 @@ use std::task::Waker;
|
|||
#[cfg(unix)]
|
||||
use tokio::signal::unix::{signal, Signal, SignalKind};
|
||||
|
||||
pub fn init(s: &Rc<State>) {
|
||||
s.register_op_json_sync("op_signal_bind", op_signal_bind);
|
||||
s.register_op_json_sync("op_signal_unbind", op_signal_unbind);
|
||||
s.register_op_json_async("op_signal_poll", op_signal_poll);
|
||||
pub fn init(rt: &mut deno_core::JsRuntime) {
|
||||
super::reg_json_sync(rt, "op_signal_bind", op_signal_bind);
|
||||
super::reg_json_sync(rt, "op_signal_unbind", op_signal_unbind);
|
||||
super::reg_json_async(rt, "op_signal_poll", op_signal_poll);
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
|
@ -42,13 +42,13 @@ struct SignalArgs {
|
|||
|
||||
#[cfg(unix)]
|
||||
fn op_signal_bind(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
state.check_unstable("Deno.signal");
|
||||
super::cli_state(state).check_unstable("Deno.signal");
|
||||
let args: BindSignalArgs = serde_json::from_value(args)?;
|
||||
let rid = state.resource_table.borrow_mut().add(
|
||||
let rid = state.resource_table.add(
|
||||
"signal",
|
||||
Box::new(SignalStreamResource(
|
||||
signal(SignalKind::from_raw(args.signo)).expect(""),
|
||||
|
@ -62,18 +62,18 @@ fn op_signal_bind(
|
|||
|
||||
#[cfg(unix)]
|
||||
async fn op_signal_poll(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
_zero_copy: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
state.check_unstable("Deno.signal");
|
||||
super::cli_state2(&state).check_unstable("Deno.signal");
|
||||
let args: SignalArgs = serde_json::from_value(args)?;
|
||||
let rid = args.rid as u32;
|
||||
|
||||
let future = poll_fn(move |cx| {
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
let mut state = state.borrow_mut();
|
||||
if let Some(mut signal) =
|
||||
resource_table.get_mut::<SignalStreamResource>(rid)
|
||||
state.resource_table.get_mut::<SignalStreamResource>(rid)
|
||||
{
|
||||
signal.1 = Some(cx.waker().clone());
|
||||
return signal.0.poll_recv(cx);
|
||||
|
@ -86,15 +86,14 @@ async fn op_signal_poll(
|
|||
|
||||
#[cfg(unix)]
|
||||
pub fn op_signal_unbind(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
state.check_unstable("Deno.signal");
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
super::cli_state(state).check_unstable("Deno.signal");
|
||||
let args: SignalArgs = serde_json::from_value(args)?;
|
||||
let rid = args.rid as u32;
|
||||
let resource = resource_table.get_mut::<SignalStreamResource>(rid);
|
||||
let resource = state.resource_table.get_mut::<SignalStreamResource>(rid);
|
||||
if let Some(signal) = resource {
|
||||
if let Some(waker) = &signal.1 {
|
||||
// Wakes up the pending poll if exists.
|
||||
|
@ -102,7 +101,8 @@ pub fn op_signal_unbind(
|
|||
waker.clone().wake();
|
||||
}
|
||||
}
|
||||
resource_table
|
||||
state
|
||||
.resource_table
|
||||
.close(rid)
|
||||
.ok_or_else(ErrBox::bad_resource_id)?;
|
||||
Ok(json!({}))
|
||||
|
@ -110,7 +110,7 @@ pub fn op_signal_unbind(
|
|||
|
||||
#[cfg(not(unix))]
|
||||
pub fn op_signal_bind(
|
||||
_state: &State,
|
||||
_state: &mut OpState,
|
||||
_args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
@ -119,7 +119,7 @@ pub fn op_signal_bind(
|
|||
|
||||
#[cfg(not(unix))]
|
||||
fn op_signal_unbind(
|
||||
_state: &State,
|
||||
_state: &mut OpState,
|
||||
_args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
@ -128,7 +128,7 @@ fn op_signal_unbind(
|
|||
|
||||
#[cfg(not(unix))]
|
||||
async fn op_signal_poll(
|
||||
_state: Rc<State>,
|
||||
_state: Rc<RefCell<OpState>>,
|
||||
_args: Value,
|
||||
_zero_copy: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
|
|
@ -1,29 +1,30 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::state::State;
|
||||
use deno_core::BufVec;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpState;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use futures::future::FutureExt;
|
||||
use serde_derive::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::time::Duration;
|
||||
use std::time::Instant;
|
||||
|
||||
pub fn init(s: &Rc<State>) {
|
||||
s.register_op_json_sync("op_global_timer_stop", op_global_timer_stop);
|
||||
s.register_op_json_async("op_global_timer", op_global_timer);
|
||||
s.register_op_json_sync("op_now", op_now);
|
||||
pub fn init(rt: &mut deno_core::JsRuntime) {
|
||||
super::reg_json_sync(rt, "op_global_timer_stop", op_global_timer_stop);
|
||||
super::reg_json_async(rt, "op_global_timer", op_global_timer);
|
||||
super::reg_json_sync(rt, "op_now", op_now);
|
||||
}
|
||||
|
||||
fn op_global_timer_stop(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
_args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
state.global_timer.borrow_mut().cancel();
|
||||
let cli_state = super::cli_state(state);
|
||||
cli_state.global_timer.borrow_mut().cancel();
|
||||
Ok(json!({}))
|
||||
}
|
||||
|
||||
|
@ -33,7 +34,7 @@ struct GlobalTimerArgs {
|
|||
}
|
||||
|
||||
async fn op_global_timer(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
_zero_copy: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
@ -41,11 +42,13 @@ async fn op_global_timer(
|
|||
let val = args.timeout;
|
||||
|
||||
let deadline = Instant::now() + Duration::from_millis(val);
|
||||
let timer_fut = state
|
||||
.global_timer
|
||||
.borrow_mut()
|
||||
.new_timeout(deadline)
|
||||
.boxed_local();
|
||||
let timer_fut = {
|
||||
super::cli_state2(&state)
|
||||
.global_timer
|
||||
.borrow_mut()
|
||||
.new_timeout(deadline)
|
||||
.boxed_local()
|
||||
};
|
||||
let _ = timer_fut.await;
|
||||
Ok(json!({}))
|
||||
}
|
||||
|
@ -55,18 +58,19 @@ async fn op_global_timer(
|
|||
// If the High precision flag is not set, the
|
||||
// nanoseconds are rounded on 2ms.
|
||||
fn op_now(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
_args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
let seconds = state.start_time.elapsed().as_secs();
|
||||
let mut subsec_nanos = state.start_time.elapsed().subsec_nanos();
|
||||
let cli_state = super::cli_state(state);
|
||||
let seconds = cli_state.start_time.elapsed().as_secs();
|
||||
let mut subsec_nanos = cli_state.start_time.elapsed().subsec_nanos();
|
||||
let reduced_time_precision = 2_000_000; // 2ms in nanoseconds
|
||||
|
||||
// If the permission is not enabled
|
||||
// Round the nano result on 2 milliseconds
|
||||
// see: https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp#Reduced_time_precision
|
||||
if state.check_hrtime().is_err() {
|
||||
if cli_state.check_hrtime().is_err() {
|
||||
subsec_nanos -= subsec_nanos % reduced_time_precision;
|
||||
}
|
||||
|
||||
|
|
107
cli/ops/tls.rs
107
cli/ops/tls.rs
|
@ -2,14 +2,14 @@
|
|||
|
||||
use super::io::{StreamResource, StreamResourceHolder};
|
||||
use crate::resolve_addr::resolve_addr;
|
||||
use crate::state::State;
|
||||
use deno_core::BufVec;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpState;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use futures::future::poll_fn;
|
||||
use serde_derive::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::cell::RefCell;
|
||||
use std::convert::From;
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
|
@ -31,11 +31,11 @@ use tokio_rustls::{
|
|||
};
|
||||
use webpki::DNSNameRef;
|
||||
|
||||
pub fn init(s: &Rc<State>) {
|
||||
s.register_op_json_async("op_start_tls", op_start_tls);
|
||||
s.register_op_json_async("op_connect_tls", op_connect_tls);
|
||||
s.register_op_json_sync("op_listen_tls", op_listen_tls);
|
||||
s.register_op_json_async("op_accept_tls", op_accept_tls);
|
||||
pub fn init(rt: &mut deno_core::JsRuntime) {
|
||||
super::reg_json_async(rt, "op_start_tls", op_start_tls);
|
||||
super::reg_json_async(rt, "op_connect_tls", op_connect_tls);
|
||||
super::reg_json_sync(rt, "op_listen_tls", op_listen_tls);
|
||||
super::reg_json_async(rt, "op_accept_tls", op_accept_tls);
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -56,11 +56,10 @@ struct StartTLSArgs {
|
|||
}
|
||||
|
||||
async fn op_start_tls(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
_zero_copy: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
state.check_unstable("Deno.startTls");
|
||||
let args: StartTLSArgs = serde_json::from_value(args)?;
|
||||
let rid = args.rid as u32;
|
||||
let cert_file = args.cert_file.clone();
|
||||
|
@ -69,15 +68,17 @@ async fn op_start_tls(
|
|||
if domain.is_empty() {
|
||||
domain.push_str("localhost");
|
||||
}
|
||||
|
||||
state.check_net(&domain, 0)?;
|
||||
if let Some(path) = cert_file.clone() {
|
||||
state.check_read(Path::new(&path))?;
|
||||
{
|
||||
let cli_state = super::cli_state2(&state);
|
||||
cli_state.check_unstable("Deno.startTls");
|
||||
cli_state.check_net(&domain, 0)?;
|
||||
if let Some(path) = cert_file.clone() {
|
||||
cli_state.check_read(Path::new(&path))?;
|
||||
}
|
||||
}
|
||||
|
||||
let mut resource_holder = {
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
match resource_table.remove::<StreamResourceHolder>(rid) {
|
||||
let mut state_ = state.borrow_mut();
|
||||
match state_.resource_table.remove::<StreamResourceHolder>(rid) {
|
||||
Some(resource) => *resource,
|
||||
None => return Err(ErrBox::bad_resource_id()),
|
||||
}
|
||||
|
@ -104,13 +105,15 @@ async fn op_start_tls(
|
|||
DNSNameRef::try_from_ascii_str(&domain).expect("Invalid DNS lookup");
|
||||
let tls_stream = tls_connector.connect(dnsname, tcp_stream).await?;
|
||||
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
let rid = resource_table.add(
|
||||
"clientTlsStream",
|
||||
Box::new(StreamResourceHolder::new(StreamResource::ClientTlsStream(
|
||||
Box::new(tls_stream),
|
||||
))),
|
||||
);
|
||||
let rid = {
|
||||
let mut state_ = state.borrow_mut();
|
||||
state_.resource_table.add(
|
||||
"clientTlsStream",
|
||||
Box::new(StreamResourceHolder::new(StreamResource::ClientTlsStream(
|
||||
Box::new(tls_stream),
|
||||
))),
|
||||
)
|
||||
};
|
||||
Ok(json!({
|
||||
"rid": rid,
|
||||
"localAddr": {
|
||||
|
@ -130,17 +133,19 @@ async fn op_start_tls(
|
|||
}
|
||||
|
||||
async fn op_connect_tls(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
_zero_copy: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
let args: ConnectTLSArgs = serde_json::from_value(args)?;
|
||||
let cert_file = args.cert_file.clone();
|
||||
state.check_net(&args.hostname, args.port)?;
|
||||
if let Some(path) = cert_file.clone() {
|
||||
state.check_read(Path::new(&path))?;
|
||||
{
|
||||
let cli_state = super::cli_state2(&state);
|
||||
cli_state.check_net(&args.hostname, args.port)?;
|
||||
if let Some(path) = cert_file.clone() {
|
||||
cli_state.check_read(Path::new(&path))?;
|
||||
}
|
||||
}
|
||||
|
||||
let mut domain = args.hostname.clone();
|
||||
if domain.is_empty() {
|
||||
domain.push_str("localhost");
|
||||
|
@ -163,13 +168,15 @@ async fn op_connect_tls(
|
|||
let dnsname =
|
||||
DNSNameRef::try_from_ascii_str(&domain).expect("Invalid DNS lookup");
|
||||
let tls_stream = tls_connector.connect(dnsname, tcp_stream).await?;
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
let rid = resource_table.add(
|
||||
"clientTlsStream",
|
||||
Box::new(StreamResourceHolder::new(StreamResource::ClientTlsStream(
|
||||
Box::new(tls_stream),
|
||||
))),
|
||||
);
|
||||
let rid = {
|
||||
let mut state_ = state.borrow_mut();
|
||||
state_.resource_table.add(
|
||||
"clientTlsStream",
|
||||
Box::new(StreamResourceHolder::new(StreamResource::ClientTlsStream(
|
||||
Box::new(tls_stream),
|
||||
))),
|
||||
)
|
||||
};
|
||||
Ok(json!({
|
||||
"rid": rid,
|
||||
"localAddr": {
|
||||
|
@ -298,7 +305,7 @@ struct ListenTlsArgs {
|
|||
}
|
||||
|
||||
fn op_listen_tls(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
@ -307,11 +314,12 @@ fn op_listen_tls(
|
|||
|
||||
let cert_file = args.cert_file;
|
||||
let key_file = args.key_file;
|
||||
|
||||
state.check_net(&args.hostname, args.port)?;
|
||||
state.check_read(Path::new(&cert_file))?;
|
||||
state.check_read(Path::new(&key_file))?;
|
||||
|
||||
{
|
||||
let cli_state = super::cli_state(state);
|
||||
cli_state.check_net(&args.hostname, args.port)?;
|
||||
cli_state.check_read(Path::new(&cert_file))?;
|
||||
cli_state.check_read(Path::new(&key_file))?;
|
||||
}
|
||||
let mut config = ServerConfig::new(NoClientAuth::new());
|
||||
config
|
||||
.set_single_cert(load_certs(&cert_file)?, load_keys(&key_file)?.remove(0))
|
||||
|
@ -330,7 +338,6 @@ fn op_listen_tls(
|
|||
|
||||
let rid = state
|
||||
.resource_table
|
||||
.borrow_mut()
|
||||
.add("tlsListener", Box::new(tls_listener_resource));
|
||||
|
||||
Ok(json!({
|
||||
|
@ -349,15 +356,16 @@ struct AcceptTlsArgs {
|
|||
}
|
||||
|
||||
async fn op_accept_tls(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
_zero_copy: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
let args: AcceptTlsArgs = serde_json::from_value(args)?;
|
||||
let rid = args.rid as u32;
|
||||
let accept_fut = poll_fn(|cx| {
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
let listener_resource = resource_table
|
||||
let mut state = state.borrow_mut();
|
||||
let listener_resource = state
|
||||
.resource_table
|
||||
.get_mut::<TlsListenerResource>(rid)
|
||||
.ok_or_else(|| ErrBox::bad_resource("Listener has been closed"))?;
|
||||
let listener = &mut listener_resource.listener;
|
||||
|
@ -380,8 +388,9 @@ async fn op_accept_tls(
|
|||
let local_addr = tcp_stream.local_addr()?;
|
||||
let remote_addr = tcp_stream.peer_addr()?;
|
||||
let tls_acceptor = {
|
||||
let resource_table = state.resource_table.borrow();
|
||||
let resource = resource_table
|
||||
let state_ = state.borrow();
|
||||
let resource = state_
|
||||
.resource_table
|
||||
.get::<TlsListenerResource>(rid)
|
||||
.ok_or_else(ErrBox::bad_resource_id)
|
||||
.expect("Can't find tls listener");
|
||||
|
@ -389,8 +398,8 @@ async fn op_accept_tls(
|
|||
};
|
||||
let tls_stream = tls_acceptor.accept(tcp_stream).await?;
|
||||
let rid = {
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
resource_table.add(
|
||||
let mut state_ = state.borrow_mut();
|
||||
state_.resource_table.add(
|
||||
"serverTlsStream",
|
||||
Box::new(StreamResourceHolder::new(StreamResource::ServerTlsStream(
|
||||
Box::new(tls_stream),
|
||||
|
|
|
@ -2,15 +2,13 @@
|
|||
|
||||
use super::io::std_file_resource;
|
||||
use super::io::{StreamResource, StreamResourceHolder};
|
||||
use crate::state::State;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpState;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
#[cfg(unix)]
|
||||
use nix::sys::termios;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[cfg(windows)]
|
||||
use winapi::shared::minwindef::DWORD;
|
||||
|
@ -20,6 +18,7 @@ use winapi::um::wincon;
|
|||
const RAW_MODE_MASK: DWORD = wincon::ENABLE_LINE_INPUT
|
||||
| wincon::ENABLE_ECHO_INPUT
|
||||
| wincon::ENABLE_PROCESSED_INPUT;
|
||||
|
||||
#[cfg(windows)]
|
||||
fn get_windows_handle(
|
||||
f: &std::fs::File,
|
||||
|
@ -36,10 +35,10 @@ fn get_windows_handle(
|
|||
Ok(handle)
|
||||
}
|
||||
|
||||
pub fn init(s: &Rc<State>) {
|
||||
s.register_op_json_sync("op_set_raw", op_set_raw);
|
||||
s.register_op_json_sync("op_isatty", op_isatty);
|
||||
s.register_op_json_sync("op_console_size", op_console_size);
|
||||
pub fn init(rt: &mut deno_core::JsRuntime) {
|
||||
super::reg_json_sync(rt, "op_set_raw", op_set_raw);
|
||||
super::reg_json_sync(rt, "op_isatty", op_isatty);
|
||||
super::reg_json_sync(rt, "op_console_size", op_console_size);
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -49,11 +48,12 @@ struct SetRawArgs {
|
|||
}
|
||||
|
||||
fn op_set_raw(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
state.check_unstable("Deno.setRaw");
|
||||
super::cli_state(state).check_unstable("Deno.setRaw");
|
||||
|
||||
let args: SetRawArgs = serde_json::from_value(args)?;
|
||||
let rid = args.rid;
|
||||
let is_raw = args.mode;
|
||||
|
@ -69,8 +69,8 @@ fn op_set_raw(
|
|||
use winapi::shared::minwindef::FALSE;
|
||||
use winapi::um::{consoleapi, handleapi};
|
||||
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
let resource_holder = resource_table.get_mut::<StreamResourceHolder>(rid);
|
||||
let resource_holder =
|
||||
state.resource_table.get_mut::<StreamResourceHolder>(rid);
|
||||
if resource_holder.is_none() {
|
||||
return Err(ErrBox::bad_resource_id());
|
||||
}
|
||||
|
@ -135,8 +135,8 @@ fn op_set_raw(
|
|||
{
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
let resource_holder = resource_table.get_mut::<StreamResourceHolder>(rid);
|
||||
let resource_holder =
|
||||
state.resource_table.get_mut::<StreamResourceHolder>(rid);
|
||||
if resource_holder.is_none() {
|
||||
return Err(ErrBox::bad_resource_id());
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ struct IsattyArgs {
|
|||
}
|
||||
|
||||
fn op_isatty(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
@ -261,11 +261,12 @@ struct ConsoleSize {
|
|||
}
|
||||
|
||||
fn op_console_size(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_zero_copy: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
state.check_unstable("Deno.consoleSize");
|
||||
super::cli_state(state).check_unstable("Deno.consoleSize");
|
||||
|
||||
let args: ConsoleSizeArgs = serde_json::from_value(args)?;
|
||||
let rid = args.rid;
|
||||
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::state::State;
|
||||
use crate::web_worker::WebWorkerHandle;
|
||||
use crate::worker::WorkerEvent;
|
||||
use deno_core::OpRegistry;
|
||||
use futures::channel::mpsc;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn init(
|
||||
s: &Rc<State>,
|
||||
sender: &mpsc::Sender<WorkerEvent>,
|
||||
rt: &mut deno_core::JsRuntime,
|
||||
sender: mpsc::Sender<WorkerEvent>,
|
||||
handle: WebWorkerHandle,
|
||||
) {
|
||||
// Post message to host as guest worker.
|
||||
let sender_ = sender.clone();
|
||||
s.register_op_json_sync(
|
||||
super::reg_json_sync(
|
||||
rt,
|
||||
"op_worker_post_message",
|
||||
move |_state, _args, bufs| {
|
||||
assert_eq!(bufs.len(), 1, "Invalid number of arguments");
|
||||
|
@ -28,10 +26,9 @@ pub fn init(
|
|||
);
|
||||
|
||||
// Notify host that guest worker closes.
|
||||
let sender_ = sender.clone();
|
||||
s.register_op_json_sync("op_worker_close", move |_state, _args, _bufs| {
|
||||
super::reg_json_sync(rt, "op_worker_close", move |_state, _args, _bufs| {
|
||||
// Notify parent that we're finished
|
||||
sender_.clone().close_channel();
|
||||
sender.clone().close_channel();
|
||||
// Terminate execution of current worker
|
||||
handle.terminate();
|
||||
Ok(json!({}))
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::state::State;
|
||||
use core::task::Poll;
|
||||
use deno_core::BufVec;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpState;
|
||||
use futures::future::poll_fn;
|
||||
use futures::StreamExt;
|
||||
use futures::{ready, SinkExt};
|
||||
|
@ -12,6 +11,7 @@ use http::{Method, Request, Uri};
|
|||
use serde_derive::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
use std::rc::Rc;
|
||||
|
@ -26,11 +26,11 @@ use tokio_tungstenite::tungstenite::{
|
|||
use tokio_tungstenite::{client_async, WebSocketStream};
|
||||
use webpki::DNSNameRef;
|
||||
|
||||
pub fn init(s: &Rc<State>) {
|
||||
s.register_op_json_async("op_ws_create", op_ws_create);
|
||||
s.register_op_json_async("op_ws_send", op_ws_send);
|
||||
s.register_op_json_async("op_ws_close", op_ws_close);
|
||||
s.register_op_json_async("op_ws_next_event", op_ws_next_event);
|
||||
pub fn init(rt: &mut deno_core::JsRuntime) {
|
||||
super::reg_json_async(rt, "op_ws_create", op_ws_create);
|
||||
super::reg_json_async(rt, "op_ws_send", op_ws_send);
|
||||
super::reg_json_async(rt, "op_ws_close", op_ws_close);
|
||||
super::reg_json_async(rt, "op_ws_next_event", op_ws_next_event);
|
||||
}
|
||||
|
||||
type MaybeTlsStream =
|
||||
|
@ -46,13 +46,16 @@ struct CreateArgs {
|
|||
}
|
||||
|
||||
pub async fn op_ws_create(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
_bufs: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
let args: CreateArgs = serde_json::from_value(args)?;
|
||||
state.check_net_url(&url::Url::parse(&args.url)?)?;
|
||||
let ca_file = state.global_state.flags.ca_file.clone();
|
||||
let ca_file = {
|
||||
let cli_state = super::cli_state2(&state);
|
||||
cli_state.check_net_url(&url::Url::parse(&args.url)?)?;
|
||||
cli_state.global_state.flags.ca_file.clone()
|
||||
};
|
||||
let uri: Uri = args.url.parse().unwrap();
|
||||
let request = Request::builder()
|
||||
.method(Method::GET)
|
||||
|
@ -99,9 +102,9 @@ pub async fn op_ws_create(
|
|||
let (stream, response): (WsStream, Response) =
|
||||
client_async(request, socket).await.unwrap();
|
||||
|
||||
let mut state = state.borrow_mut();
|
||||
let rid = state
|
||||
.resource_table
|
||||
.borrow_mut()
|
||||
.add("webSocketStream", Box::new(stream));
|
||||
|
||||
let protocol = match response.headers().get("Sec-WebSocket-Protocol") {
|
||||
|
@ -130,7 +133,7 @@ struct SendArgs {
|
|||
}
|
||||
|
||||
pub async fn op_ws_send(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
bufs: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
@ -143,8 +146,9 @@ pub async fn op_ws_send(
|
|||
let rid = args.rid;
|
||||
|
||||
poll_fn(move |cx| {
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
let stream = resource_table
|
||||
let mut state = state.borrow_mut();
|
||||
let stream = state
|
||||
.resource_table
|
||||
.get_mut::<WsStream>(rid)
|
||||
.ok_or_else(ErrBox::bad_resource_id)?;
|
||||
|
||||
|
@ -171,7 +175,7 @@ struct CloseArgs {
|
|||
}
|
||||
|
||||
pub async fn op_ws_close(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
_bufs: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
@ -186,8 +190,9 @@ pub async fn op_ws_close(
|
|||
})));
|
||||
|
||||
poll_fn(move |cx| {
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
let stream = resource_table
|
||||
let mut state = state.borrow_mut();
|
||||
let stream = state
|
||||
.resource_table
|
||||
.get_mut::<WsStream>(rid)
|
||||
.ok_or_else(ErrBox::bad_resource_id)?;
|
||||
|
||||
|
@ -213,14 +218,15 @@ struct NextEventArgs {
|
|||
}
|
||||
|
||||
pub async fn op_ws_next_event(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
_bufs: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
let args: NextEventArgs = serde_json::from_value(args)?;
|
||||
poll_fn(move |cx| {
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
let stream = resource_table
|
||||
let mut state = state.borrow_mut();
|
||||
let stream = state
|
||||
.resource_table
|
||||
.get_mut::<WsStream>(args.rid)
|
||||
.ok_or_else(ErrBox::bad_resource_id)?;
|
||||
stream
|
||||
|
@ -248,7 +254,7 @@ pub async fn op_ws_next_event(
|
|||
Some(Ok(Message::Pong(_))) => json!({"type": "pong"}),
|
||||
Some(Err(_)) => json!({"type": "error"}),
|
||||
None => {
|
||||
resource_table.close(args.rid).unwrap();
|
||||
state.resource_table.close(args.rid).unwrap();
|
||||
json!({"type": "closed"})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ use crate::global_state::GlobalState;
|
|||
use crate::ops::io::get_stdio;
|
||||
use crate::permissions::Permissions;
|
||||
use crate::startup_data;
|
||||
use crate::state::State;
|
||||
use crate::tokio_util::create_basic_runtime;
|
||||
use crate::web_worker::WebWorker;
|
||||
use crate::web_worker::WebWorkerHandle;
|
||||
|
@ -13,21 +12,26 @@ use crate::worker::WorkerEvent;
|
|||
use deno_core::BufVec;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpState;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use futures::future::FutureExt;
|
||||
use serde_derive::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::cell::RefCell;
|
||||
use std::convert::From;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::thread::JoinHandle;
|
||||
|
||||
pub fn init(s: &Rc<State>) {
|
||||
s.register_op_json_sync("op_create_worker", op_create_worker);
|
||||
s.register_op_json_sync("op_host_terminate_worker", op_host_terminate_worker);
|
||||
s.register_op_json_sync("op_host_post_message", op_host_post_message);
|
||||
s.register_op_json_async("op_host_get_message", op_host_get_message);
|
||||
pub fn init(rt: &mut deno_core::JsRuntime) {
|
||||
super::reg_json_sync(rt, "op_create_worker", op_create_worker);
|
||||
super::reg_json_sync(
|
||||
rt,
|
||||
"op_host_terminate_worker",
|
||||
op_host_terminate_worker,
|
||||
);
|
||||
super::reg_json_sync(rt, "op_host_post_message", op_host_post_message);
|
||||
super::reg_json_async(rt, "op_host_get_message", op_host_get_message);
|
||||
}
|
||||
|
||||
fn create_web_worker(
|
||||
|
@ -38,27 +42,31 @@ fn create_web_worker(
|
|||
specifier: ModuleSpecifier,
|
||||
has_deno_namespace: bool,
|
||||
) -> Result<WebWorker, ErrBox> {
|
||||
let state =
|
||||
State::new_for_worker(global_state, Some(permissions), specifier)?;
|
||||
let cli_state = crate::state::State::new_for_worker(
|
||||
global_state,
|
||||
Some(permissions),
|
||||
specifier,
|
||||
)?;
|
||||
|
||||
let mut worker = WebWorker::new(
|
||||
name.clone(),
|
||||
startup_data::deno_isolate_init(),
|
||||
&state,
|
||||
&cli_state,
|
||||
has_deno_namespace,
|
||||
);
|
||||
|
||||
if has_deno_namespace {
|
||||
let mut resource_table = state.resource_table.borrow_mut();
|
||||
let state = worker.isolate.op_state();
|
||||
let mut state = state.borrow_mut();
|
||||
let (stdin, stdout, stderr) = get_stdio();
|
||||
if let Some(stream) = stdin {
|
||||
resource_table.add("stdin", Box::new(stream));
|
||||
state.resource_table.add("stdin", Box::new(stream));
|
||||
}
|
||||
if let Some(stream) = stdout {
|
||||
resource_table.add("stdout", Box::new(stream));
|
||||
state.resource_table.add("stdout", Box::new(stream));
|
||||
}
|
||||
if let Some(stream) = stderr {
|
||||
resource_table.add("stderr", Box::new(stream));
|
||||
state.resource_table.add("stderr", Box::new(stream));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,10 +180,11 @@ struct CreateWorkerArgs {
|
|||
|
||||
/// Create worker as the host
|
||||
fn op_create_worker(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_data: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
let cli_state = super::cli_state(state);
|
||||
let args: CreateWorkerArgs = serde_json::from_value(args)?;
|
||||
|
||||
let specifier = args.specifier.clone();
|
||||
|
@ -187,12 +196,12 @@ fn op_create_worker(
|
|||
let args_name = args.name;
|
||||
let use_deno_namespace = args.use_deno_namespace;
|
||||
if use_deno_namespace {
|
||||
state.check_unstable("Worker.deno");
|
||||
cli_state.check_unstable("Worker.deno");
|
||||
}
|
||||
let global_state = state.global_state.clone();
|
||||
let permissions = state.permissions.borrow().clone();
|
||||
let worker_id = state.next_worker_id.get();
|
||||
state.next_worker_id.set(worker_id + 1);
|
||||
let global_state = cli_state.global_state.clone();
|
||||
let permissions = cli_state.permissions.borrow().clone();
|
||||
let worker_id = cli_state.next_worker_id.get();
|
||||
cli_state.next_worker_id.set(worker_id + 1);
|
||||
|
||||
let module_specifier = ModuleSpecifier::resolve_url(&specifier)?;
|
||||
let worker_name = args_name.unwrap_or_else(|| "".to_string());
|
||||
|
@ -208,7 +217,8 @@ fn op_create_worker(
|
|||
)?;
|
||||
// At this point all interactions with worker happen using thread
|
||||
// safe handler returned from previous function call
|
||||
state
|
||||
let cli_state = super::cli_state(state);
|
||||
cli_state
|
||||
.workers
|
||||
.borrow_mut()
|
||||
.insert(worker_id, (join_handle, worker_handle));
|
||||
|
@ -222,13 +232,14 @@ struct WorkerArgs {
|
|||
}
|
||||
|
||||
fn op_host_terminate_worker(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_data: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
let args: WorkerArgs = serde_json::from_value(args)?;
|
||||
let id = args.id as u32;
|
||||
let (join_handle, worker_handle) = state
|
||||
let cli_state = super::cli_state(state);
|
||||
let (join_handle, worker_handle) = cli_state
|
||||
.workers
|
||||
.borrow_mut()
|
||||
.remove(&id)
|
||||
|
@ -290,40 +301,41 @@ fn serialize_worker_event(event: WorkerEvent) -> Value {
|
|||
|
||||
/// Get message from guest worker as host
|
||||
async fn op_host_get_message(
|
||||
state: Rc<State>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
_zero_copy: BufVec,
|
||||
) -> Result<Value, ErrBox> {
|
||||
let args: WorkerArgs = serde_json::from_value(args)?;
|
||||
let id = args.id as u32;
|
||||
let state = state.clone();
|
||||
let cli_state = super::cli_state2(&state);
|
||||
|
||||
let workers_table = state.workers.borrow();
|
||||
let maybe_handle = workers_table.get(&id);
|
||||
let worker_handle = if let Some(handle) = maybe_handle {
|
||||
handle.1.clone()
|
||||
} else {
|
||||
// If handle was not found it means worker has already shutdown
|
||||
return Ok(json!({ "type": "close" }));
|
||||
let worker_handle = {
|
||||
let workers_table = cli_state.workers.borrow();
|
||||
let maybe_handle = workers_table.get(&id);
|
||||
if let Some(handle) = maybe_handle {
|
||||
handle.1.clone()
|
||||
} else {
|
||||
// If handle was not found it means worker has already shutdown
|
||||
return Ok(json!({ "type": "close" }));
|
||||
}
|
||||
};
|
||||
drop(workers_table);
|
||||
|
||||
let response = match worker_handle.get_event().await? {
|
||||
Some(event) => {
|
||||
// Terminal error means that worker should be removed from worker table.
|
||||
if let WorkerEvent::TerminalError(_) = &event {
|
||||
if let Some((join_handle, mut worker_handle)) =
|
||||
state.workers.borrow_mut().remove(&id)
|
||||
cli_state.workers.borrow_mut().remove(&id)
|
||||
{
|
||||
worker_handle.sender.close_channel();
|
||||
join_handle.join().expect("Worker thread panicked");
|
||||
}
|
||||
};
|
||||
}
|
||||
serialize_worker_event(event)
|
||||
}
|
||||
None => {
|
||||
// Worker shuts down
|
||||
let mut workers = state.workers.borrow_mut();
|
||||
let mut workers = cli_state.workers.borrow_mut();
|
||||
// Try to remove worker from workers table - NOTE: `Worker.terminate()` might have been called
|
||||
// already meaning that we won't find worker in table - in that case ignore.
|
||||
if let Some((join_handle, mut worker_handle)) = workers.remove(&id) {
|
||||
|
@ -338,7 +350,7 @@ async fn op_host_get_message(
|
|||
|
||||
/// Post message to guest worker as host
|
||||
fn op_host_post_message(
|
||||
state: &State,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
data: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
@ -348,7 +360,8 @@ fn op_host_post_message(
|
|||
let msg = Vec::from(&*data[0]).into_boxed_slice();
|
||||
|
||||
debug!("post message to worker {}", id);
|
||||
let workers = state.workers.borrow();
|
||||
let cli_state = super::cli_state(state);
|
||||
let workers = cli_state.workers.borrow();
|
||||
let worker_handle = workers[&id].1.clone();
|
||||
worker_handle.post_message(msg)?;
|
||||
Ok(json!({}))
|
||||
|
|
90
cli/state.rs
90
cli/state.rs
|
@ -1,6 +1,5 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::errors::get_error_class_name;
|
||||
use crate::file_fetcher::SourceFileFetcher;
|
||||
use crate::global_state::GlobalState;
|
||||
use crate::global_timer::GlobalTimer;
|
||||
|
@ -10,17 +9,10 @@ use crate::metrics::Metrics;
|
|||
use crate::permissions::Permissions;
|
||||
use crate::tsc::TargetLib;
|
||||
use crate::web_worker::WebWorkerHandle;
|
||||
use deno_core::BufVec;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::ModuleLoadId;
|
||||
use deno_core::ModuleLoader;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use deno_core::Op;
|
||||
use deno_core::OpId;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpRouter;
|
||||
use deno_core::OpTable;
|
||||
use deno_core::ResourceTable;
|
||||
use futures::future::FutureExt;
|
||||
use futures::Future;
|
||||
use rand::rngs::StdRng;
|
||||
|
@ -36,6 +28,7 @@ use std::sync::Arc;
|
|||
use std::thread::JoinHandle;
|
||||
use std::time::Instant;
|
||||
|
||||
// TODO(ry) Rename to CliState to avoid confusion with other states.
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(stutter))]
|
||||
pub struct State {
|
||||
pub global_state: Arc<GlobalState>,
|
||||
|
@ -54,8 +47,6 @@ pub struct State {
|
|||
pub is_main: bool,
|
||||
pub is_internal: bool,
|
||||
pub http_client: RefCell<reqwest::Client>,
|
||||
pub resource_table: RefCell<ResourceTable>,
|
||||
pub op_table: RefCell<OpTable<Self>>,
|
||||
}
|
||||
|
||||
impl State {
|
||||
|
@ -202,8 +193,6 @@ impl State {
|
|||
is_main: true,
|
||||
is_internal,
|
||||
http_client: create_http_client(fl.ca_file.as_deref())?.into(),
|
||||
resource_table: Default::default(),
|
||||
op_table: Default::default(),
|
||||
};
|
||||
Ok(Rc::new(state))
|
||||
}
|
||||
|
@ -232,8 +221,6 @@ impl State {
|
|||
is_main: false,
|
||||
is_internal: false,
|
||||
http_client: create_http_client(fl.ca_file.as_deref())?.into(),
|
||||
resource_table: Default::default(),
|
||||
op_table: Default::default(),
|
||||
};
|
||||
Ok(Rc::new(state))
|
||||
}
|
||||
|
@ -331,78 +318,3 @@ impl State {
|
|||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl OpRouter for State {
|
||||
fn route_op(self: Rc<Self>, op_id: OpId, bufs: BufVec) -> Op {
|
||||
// TODOs:
|
||||
// * The 'bytes' metrics seem pretty useless, especially now that the
|
||||
// distinction between 'control' and 'data' buffers has become blurry.
|
||||
// * Tracking completion of async ops currently makes us put the boxed
|
||||
// future into _another_ box. Keeping some counters may not be expensive
|
||||
// in itself, but adding a heap allocation for every metric seems bad.
|
||||
let mut buf_len_iter = bufs.iter().map(|buf| buf.len());
|
||||
let bytes_sent_control = buf_len_iter.next().unwrap_or(0);
|
||||
let bytes_sent_data = buf_len_iter.sum();
|
||||
|
||||
let op_fn = self
|
||||
.op_table
|
||||
.borrow()
|
||||
.get_index(op_id)
|
||||
.map(|(_, op_fn)| op_fn.clone())
|
||||
.unwrap();
|
||||
|
||||
let self_ = self.clone();
|
||||
let op = (op_fn)(self_, bufs);
|
||||
|
||||
let self_ = self.clone();
|
||||
let mut metrics = self_.metrics.borrow_mut();
|
||||
match op {
|
||||
Op::Sync(buf) => {
|
||||
metrics.op_sync(bytes_sent_control, bytes_sent_data, buf.len());
|
||||
Op::Sync(buf)
|
||||
}
|
||||
Op::Async(fut) => {
|
||||
metrics.op_dispatched_async(bytes_sent_control, bytes_sent_data);
|
||||
let fut = fut
|
||||
.inspect(move |buf| {
|
||||
self.metrics.borrow_mut().op_completed_async(buf.len());
|
||||
})
|
||||
.boxed_local();
|
||||
Op::Async(fut)
|
||||
}
|
||||
Op::AsyncUnref(fut) => {
|
||||
metrics.op_dispatched_async_unref(bytes_sent_control, bytes_sent_data);
|
||||
let fut = fut
|
||||
.inspect(move |buf| {
|
||||
self
|
||||
.metrics
|
||||
.borrow_mut()
|
||||
.op_completed_async_unref(buf.len());
|
||||
})
|
||||
.boxed_local();
|
||||
Op::AsyncUnref(fut)
|
||||
}
|
||||
other => other,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OpRegistry for State {
|
||||
fn get_op_catalog(self: Rc<Self>) -> HashMap<String, OpId> {
|
||||
self.op_table.borrow().get_op_catalog()
|
||||
}
|
||||
|
||||
fn register_op<F>(&self, name: &str, op_fn: F) -> OpId
|
||||
where
|
||||
F: Fn(Rc<Self>, BufVec) -> Op + 'static,
|
||||
{
|
||||
let mut op_table = self.op_table.borrow_mut();
|
||||
let (op_id, prev) = op_table.insert_full(name.to_owned(), Rc::new(op_fn));
|
||||
assert!(prev.is_none());
|
||||
op_id
|
||||
}
|
||||
|
||||
fn get_error_class_name(&self, err: &ErrBox) -> &'static str {
|
||||
get_error_class_name(err)
|
||||
}
|
||||
}
|
||||
|
|
13
cli/tsc.rs
13
cli/tsc.rs
|
@ -139,15 +139,12 @@ impl CompilerWorker {
|
|||
startup_data: StartupData,
|
||||
state: &Rc<State>,
|
||||
) -> Self {
|
||||
let worker = Worker::new(name, startup_data, state);
|
||||
let mut worker = Worker::new(name, startup_data, state);
|
||||
let response = Arc::new(Mutex::new(None));
|
||||
{
|
||||
ops::runtime::init(&state);
|
||||
ops::errors::init(&state);
|
||||
ops::timers::init(&state);
|
||||
ops::compiler::init(&state, response.clone());
|
||||
}
|
||||
|
||||
ops::runtime::init(&mut worker);
|
||||
ops::errors::init(&mut worker);
|
||||
ops::timers::init(&mut worker);
|
||||
ops::compiler::init(&mut worker, response.clone());
|
||||
Self { worker, response }
|
||||
}
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ impl WebWorker {
|
|||
terminate_tx,
|
||||
};
|
||||
|
||||
let web_worker = Self {
|
||||
let mut web_worker = Self {
|
||||
worker,
|
||||
event_loop_idle: false,
|
||||
terminate_rx,
|
||||
|
@ -110,37 +110,33 @@ impl WebWorker {
|
|||
has_deno_namespace,
|
||||
};
|
||||
|
||||
let handle = web_worker.thread_safe_handle();
|
||||
|
||||
{
|
||||
ops::runtime::init(&state);
|
||||
ops::web_worker::init(
|
||||
&state,
|
||||
&web_worker.worker.internal_channels.sender,
|
||||
handle,
|
||||
);
|
||||
ops::worker_host::init(&state);
|
||||
ops::idna::init(&state);
|
||||
ops::io::init(&state);
|
||||
ops::resources::init(&state);
|
||||
ops::errors::init(&state);
|
||||
ops::timers::init(&state);
|
||||
ops::fetch::init(&state);
|
||||
ops::websocket::init(&state);
|
||||
ops::runtime::init(&mut web_worker.worker);
|
||||
let sender = web_worker.worker.internal_channels.sender.clone();
|
||||
let handle = web_worker.thread_safe_handle();
|
||||
ops::web_worker::init(&mut web_worker.worker, sender, handle);
|
||||
ops::worker_host::init(&mut web_worker.worker);
|
||||
ops::idna::init(&mut web_worker.worker);
|
||||
ops::io::init(&mut web_worker.worker);
|
||||
ops::resources::init(&mut web_worker.worker);
|
||||
ops::errors::init(&mut web_worker.worker);
|
||||
ops::timers::init(&mut web_worker.worker);
|
||||
ops::fetch::init(&mut web_worker.worker);
|
||||
ops::websocket::init(&mut web_worker.worker);
|
||||
|
||||
if has_deno_namespace {
|
||||
ops::runtime_compiler::init(&state);
|
||||
ops::fs::init(&state);
|
||||
ops::fs_events::init(&state);
|
||||
ops::plugin::init(&state);
|
||||
ops::net::init(&state);
|
||||
ops::tls::init(&state);
|
||||
ops::os::init(&state);
|
||||
ops::permissions::init(&state);
|
||||
ops::process::init(&state);
|
||||
ops::random::init(&state);
|
||||
ops::signal::init(&state);
|
||||
ops::tty::init(&state);
|
||||
ops::runtime_compiler::init(&mut web_worker.worker);
|
||||
ops::fs::init(&mut web_worker.worker);
|
||||
ops::fs_events::init(&mut web_worker.worker);
|
||||
ops::plugin::init(&mut web_worker.worker);
|
||||
ops::net::init(&mut web_worker.worker);
|
||||
ops::tls::init(&mut web_worker.worker);
|
||||
ops::os::init(&mut web_worker.worker);
|
||||
ops::permissions::init(&mut web_worker.worker);
|
||||
ops::process::init(&mut web_worker.worker);
|
||||
ops::random::init(&mut web_worker.worker);
|
||||
ops::signal::init(&mut web_worker.worker);
|
||||
ops::tty::init(&mut web_worker.worker);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ fn create_channels() -> (WorkerChannelsInternal, WorkerHandle) {
|
|||
/// - `WebWorker`
|
||||
pub struct Worker {
|
||||
pub name: String,
|
||||
pub isolate: deno_core::JsRuntime,
|
||||
pub isolate: JsRuntime,
|
||||
pub inspector: Option<Box<DenoInspector>>,
|
||||
pub state: Rc<State>,
|
||||
pub waker: AtomicWaker,
|
||||
|
@ -105,22 +105,22 @@ impl Worker {
|
|||
startup_data: StartupData,
|
||||
state: &Rc<State>,
|
||||
) -> Self {
|
||||
let mut isolate = deno_core::JsRuntime::new_with_loader(
|
||||
state.clone(),
|
||||
state.clone(),
|
||||
startup_data,
|
||||
false,
|
||||
);
|
||||
|
||||
let mut isolate =
|
||||
JsRuntime::new_with_loader(state.clone(), startup_data, false);
|
||||
{
|
||||
let global_state = state.global_state.clone();
|
||||
let core_state_rc = JsRuntime::state(&isolate);
|
||||
let mut core_state = core_state_rc.borrow_mut();
|
||||
core_state.set_js_error_create_fn(move |core_js_error| {
|
||||
let js_runtime_state = JsRuntime::state(&isolate);
|
||||
let mut js_runtime_state = js_runtime_state.borrow_mut();
|
||||
js_runtime_state.set_js_error_create_fn(move |core_js_error| {
|
||||
JsError::create(core_js_error, &global_state.ts_compiler)
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let op_state = isolate.op_state();
|
||||
let mut op_state = op_state.borrow_mut();
|
||||
op_state.get_error_class_fn = &crate::errors::get_error_class_name;
|
||||
op_state.put(state.clone());
|
||||
}
|
||||
let inspector = {
|
||||
let global_state = &state.global_state;
|
||||
global_state
|
||||
|
@ -235,7 +235,7 @@ impl Future for Worker {
|
|||
}
|
||||
|
||||
impl Deref for Worker {
|
||||
type Target = deno_core::JsRuntime;
|
||||
type Target = JsRuntime;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.isolate
|
||||
}
|
||||
|
@ -258,30 +258,30 @@ pub struct MainWorker(Worker);
|
|||
impl MainWorker {
|
||||
// TODO(ry) combine MainWorker::new and MainWorker::create.
|
||||
fn new(name: String, startup_data: StartupData, state: &Rc<State>) -> Self {
|
||||
let worker = Worker::new(name, startup_data, state);
|
||||
let mut worker = Worker::new(name, startup_data, state);
|
||||
{
|
||||
ops::runtime::init(&state);
|
||||
ops::runtime_compiler::init(&state);
|
||||
ops::errors::init(&state);
|
||||
ops::fetch::init(&state);
|
||||
ops::websocket::init(&state);
|
||||
ops::fs::init(&state);
|
||||
ops::fs_events::init(&state);
|
||||
ops::idna::init(&state);
|
||||
ops::io::init(&state);
|
||||
ops::plugin::init(&state);
|
||||
ops::net::init(&state);
|
||||
ops::tls::init(&state);
|
||||
ops::os::init(&state);
|
||||
ops::permissions::init(&state);
|
||||
ops::process::init(&state);
|
||||
ops::random::init(&state);
|
||||
ops::repl::init(&state);
|
||||
ops::resources::init(&state);
|
||||
ops::signal::init(&state);
|
||||
ops::timers::init(&state);
|
||||
ops::tty::init(&state);
|
||||
ops::worker_host::init(&state);
|
||||
ops::runtime::init(&mut worker);
|
||||
ops::runtime_compiler::init(&mut worker);
|
||||
ops::errors::init(&mut worker);
|
||||
ops::fetch::init(&mut worker);
|
||||
ops::websocket::init(&mut worker);
|
||||
ops::fs::init(&mut worker);
|
||||
ops::fs_events::init(&mut worker);
|
||||
ops::idna::init(&mut worker);
|
||||
ops::io::init(&mut worker);
|
||||
ops::plugin::init(&mut worker);
|
||||
ops::net::init(&mut worker);
|
||||
ops::tls::init(&mut worker);
|
||||
ops::os::init(&mut worker);
|
||||
ops::permissions::init(&mut worker);
|
||||
ops::process::init(&mut worker);
|
||||
ops::random::init(&mut worker);
|
||||
ops::repl::init(&mut worker);
|
||||
ops::resources::init(&mut worker);
|
||||
ops::signal::init(&mut worker);
|
||||
ops::timers::init(&mut worker);
|
||||
ops::tty::init(&mut worker);
|
||||
ops::worker_host::init(&mut worker);
|
||||
}
|
||||
Self(worker)
|
||||
}
|
||||
|
@ -303,7 +303,9 @@ impl MainWorker {
|
|||
&state,
|
||||
);
|
||||
{
|
||||
let mut t = state.resource_table.borrow_mut();
|
||||
let op_state = worker.op_state();
|
||||
let mut op_state = op_state.borrow_mut();
|
||||
let t = &mut op_state.resource_table;
|
||||
let (stdin, stdout, stderr) = get_stdio();
|
||||
if let Some(stream) = stdin {
|
||||
t.add("stdin", Box::new(stream));
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::BufVec;
|
||||
use crate::Op;
|
||||
use crate::OpId;
|
||||
use crate::OpRegistry;
|
||||
use crate::OpRouter;
|
||||
use crate::OpTable;
|
||||
use crate::ResourceTable;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
/// A minimal state struct for use by tests, examples etc. It contains
|
||||
/// an OpTable and ResourceTable, and implements the relevant traits
|
||||
/// for working with ops in the most straightforward way possible.
|
||||
#[derive(Default)]
|
||||
pub struct BasicState {
|
||||
pub op_table: RefCell<OpTable<Self>>,
|
||||
pub resource_table: RefCell<ResourceTable>,
|
||||
}
|
||||
|
||||
impl BasicState {
|
||||
pub fn new() -> Rc<Self> {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl OpRegistry for BasicState {
|
||||
fn get_op_catalog(self: Rc<Self>) -> HashMap<String, OpId> {
|
||||
self.op_table.borrow().get_op_catalog()
|
||||
}
|
||||
|
||||
fn register_op<F>(&self, name: &str, op_fn: F) -> OpId
|
||||
where
|
||||
F: Fn(Rc<Self>, BufVec) -> Op + 'static,
|
||||
{
|
||||
let mut op_table = self.op_table.borrow_mut();
|
||||
let (op_id, prev) = op_table.insert_full(name.to_owned(), Rc::new(op_fn));
|
||||
assert!(prev.is_none());
|
||||
op_id
|
||||
}
|
||||
}
|
||||
|
||||
impl OpRouter for BasicState {
|
||||
fn route_op(self: Rc<Self>, op_id: OpId, bufs: BufVec) -> Op {
|
||||
let op_fn = self
|
||||
.op_table
|
||||
.borrow()
|
||||
.get_index(op_id)
|
||||
.map(|(_, op_fn)| op_fn.clone())
|
||||
.unwrap();
|
||||
(op_fn)(self, bufs)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_basic_state_ops() {
|
||||
let state = BasicState::new();
|
||||
|
||||
let foo_id = state.register_op("foo", |_, _| Op::Sync(b"oof!"[..].into()));
|
||||
assert_eq!(foo_id, 1);
|
||||
|
||||
let bar_id = state.register_op("bar", |_, _| Op::Sync(b"rab!"[..].into()));
|
||||
assert_eq!(bar_id, 2);
|
||||
|
||||
let state_ = state.clone();
|
||||
let foo_res = state_.route_op(foo_id, Default::default());
|
||||
assert!(matches!(foo_res, Op::Sync(buf) if &*buf == b"oof!"));
|
||||
|
||||
let state_ = state.clone();
|
||||
let bar_res = state_.route_op(bar_id, Default::default());
|
||||
assert!(matches!(bar_res, Op::Sync(buf) if &*buf == b"rab!"));
|
||||
|
||||
let catalog_res = state.route_op(0, Default::default());
|
||||
let mut catalog_entries = match catalog_res {
|
||||
Op::Sync(buf) => serde_json::from_slice::<HashMap<String, OpId>>(&buf)
|
||||
.map(|map| map.into_iter().collect::<Vec<_>>())
|
||||
.unwrap(),
|
||||
_ => panic!("unexpected `Op` variant"),
|
||||
};
|
||||
catalog_entries.sort_by(|(_, id1), (_, id2)| id1.partial_cmp(id2).unwrap());
|
||||
assert_eq!(
|
||||
catalog_entries,
|
||||
vec![
|
||||
("ops".to_owned(), 0),
|
||||
("foo".to_owned(), 1),
|
||||
("bar".to_owned(), 2)
|
||||
]
|
||||
)
|
||||
}
|
|
@ -6,6 +6,7 @@ use crate::JsRuntime;
|
|||
use crate::JsRuntimeState;
|
||||
use crate::Op;
|
||||
use crate::OpId;
|
||||
use crate::OpTable;
|
||||
use crate::ZeroCopyBuf;
|
||||
use futures::future::FutureExt;
|
||||
use rusty_v8 as v8;
|
||||
|
@ -426,8 +427,7 @@ fn send<'s>(
|
|||
}
|
||||
};
|
||||
|
||||
let op_router = state.op_router.clone();
|
||||
let op = op_router.route_op(op_id, bufs);
|
||||
let op = OpTable::route_op(op_id, state.op_state.clone(), bufs);
|
||||
assert_eq!(state.shared.size(), 0);
|
||||
match op {
|
||||
Op::Sync(buf) if !buf.is_empty() => {
|
||||
|
|
|
@ -2,11 +2,10 @@
|
|||
extern crate log;
|
||||
|
||||
use deno_core::js_check;
|
||||
use deno_core::BasicState;
|
||||
use deno_core::BufVec;
|
||||
use deno_core::JsRuntime;
|
||||
use deno_core::Op;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpState;
|
||||
use deno_core::Script;
|
||||
use deno_core::StartupData;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
|
@ -14,6 +13,7 @@ use futures::future::poll_fn;
|
|||
use futures::future::FutureExt;
|
||||
use futures::future::TryFuture;
|
||||
use futures::future::TryFutureExt;
|
||||
use std::cell::RefCell;
|
||||
use std::convert::TryInto;
|
||||
use std::env;
|
||||
use std::fmt::Debug;
|
||||
|
@ -78,23 +78,22 @@ impl From<Record> for RecordBuf {
|
|||
}
|
||||
|
||||
fn create_isolate() -> JsRuntime {
|
||||
let state = BasicState::new();
|
||||
register_op_bin_sync(&state, "listen", op_listen);
|
||||
register_op_bin_sync(&state, "close", op_close);
|
||||
register_op_bin_async(&state, "accept", op_accept);
|
||||
register_op_bin_async(&state, "read", op_read);
|
||||
register_op_bin_async(&state, "write", op_write);
|
||||
|
||||
let startup_data = StartupData::Script(Script {
|
||||
source: include_str!("http_bench_bin_ops.js"),
|
||||
filename: "http_bench_bin_ops.js",
|
||||
});
|
||||
|
||||
JsRuntime::new(state, startup_data, false)
|
||||
let mut isolate = JsRuntime::new(startup_data, false);
|
||||
register_op_bin_sync(&mut isolate, "listen", op_listen);
|
||||
register_op_bin_sync(&mut isolate, "close", op_close);
|
||||
register_op_bin_async(&mut isolate, "accept", op_accept);
|
||||
register_op_bin_async(&mut isolate, "read", op_read);
|
||||
register_op_bin_async(&mut isolate, "write", op_write);
|
||||
isolate
|
||||
}
|
||||
|
||||
fn op_listen(
|
||||
state: &BasicState,
|
||||
state: &mut OpState,
|
||||
_rid: u32,
|
||||
_bufs: &mut [ZeroCopyBuf],
|
||||
) -> Result<u32, Error> {
|
||||
|
@ -102,36 +101,33 @@ fn op_listen(
|
|||
let addr = "127.0.0.1:4544".parse::<SocketAddr>().unwrap();
|
||||
let std_listener = std::net::TcpListener::bind(&addr)?;
|
||||
let listener = TcpListener::from_std(std_listener)?;
|
||||
let rid = state
|
||||
.resource_table
|
||||
.borrow_mut()
|
||||
.add("tcpListener", Box::new(listener));
|
||||
let rid = state.resource_table.add("tcpListener", Box::new(listener));
|
||||
Ok(rid)
|
||||
}
|
||||
|
||||
fn op_close(
|
||||
state: &BasicState,
|
||||
state: &mut OpState,
|
||||
rid: u32,
|
||||
_bufs: &mut [ZeroCopyBuf],
|
||||
) -> Result<u32, Error> {
|
||||
debug!("close rid={}", rid);
|
||||
state
|
||||
.resource_table
|
||||
.borrow_mut()
|
||||
.close(rid)
|
||||
.map(|_| 0)
|
||||
.ok_or_else(bad_resource_id)
|
||||
}
|
||||
|
||||
fn op_accept(
|
||||
state: Rc<BasicState>,
|
||||
async fn op_accept(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
rid: u32,
|
||||
_bufs: BufVec,
|
||||
) -> impl TryFuture<Ok = u32, Error = Error> {
|
||||
) -> Result<u32, Error> {
|
||||
debug!("accept rid={}", rid);
|
||||
|
||||
poll_fn(move |cx| {
|
||||
let resource_table = &mut state.resource_table.borrow_mut();
|
||||
let resource_table = &mut state.borrow_mut().resource_table;
|
||||
|
||||
let listener = resource_table
|
||||
.get_mut::<TcpListener>(rid)
|
||||
.ok_or_else(bad_resource_id)?;
|
||||
|
@ -139,10 +135,11 @@ fn op_accept(
|
|||
resource_table.add("tcpStream", Box::new(stream))
|
||||
})
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
fn op_read(
|
||||
state: Rc<BasicState>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
rid: u32,
|
||||
bufs: BufVec,
|
||||
) -> impl TryFuture<Ok = usize, Error = Error> {
|
||||
|
@ -152,7 +149,8 @@ fn op_read(
|
|||
debug!("read rid={}", rid);
|
||||
|
||||
poll_fn(move |cx| {
|
||||
let resource_table = &mut state.resource_table.borrow_mut();
|
||||
let resource_table = &mut state.borrow_mut().resource_table;
|
||||
|
||||
let stream = resource_table
|
||||
.get_mut::<TcpStream>(rid)
|
||||
.ok_or_else(bad_resource_id)?;
|
||||
|
@ -161,7 +159,7 @@ fn op_read(
|
|||
}
|
||||
|
||||
fn op_write(
|
||||
state: Rc<BasicState>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
rid: u32,
|
||||
bufs: BufVec,
|
||||
) -> impl TryFuture<Ok = usize, Error = Error> {
|
||||
|
@ -170,7 +168,8 @@ fn op_write(
|
|||
debug!("write rid={}", rid);
|
||||
|
||||
poll_fn(move |cx| {
|
||||
let resource_table = &mut state.resource_table.borrow_mut();
|
||||
let resource_table = &mut state.borrow_mut().resource_table;
|
||||
|
||||
let stream = resource_table
|
||||
.get_mut::<TcpStream>(rid)
|
||||
.ok_or_else(bad_resource_id)?;
|
||||
|
@ -178,35 +177,42 @@ fn op_write(
|
|||
})
|
||||
}
|
||||
|
||||
fn register_op_bin_sync<F>(state: &BasicState, name: &'static str, op_fn: F)
|
||||
where
|
||||
F: Fn(&BasicState, u32, &mut [ZeroCopyBuf]) -> Result<u32, Error> + 'static,
|
||||
fn register_op_bin_sync<F>(
|
||||
isolate: &mut JsRuntime,
|
||||
name: &'static str,
|
||||
op_fn: F,
|
||||
) where
|
||||
F: Fn(&mut OpState, u32, &mut [ZeroCopyBuf]) -> Result<u32, Error> + 'static,
|
||||
{
|
||||
let base_op_fn = move |state: Rc<BasicState>, mut bufs: BufVec| -> Op {
|
||||
let base_op_fn = move |state: Rc<RefCell<OpState>>, mut bufs: BufVec| -> Op {
|
||||
let record = Record::from(bufs[0].as_ref());
|
||||
let is_sync = record.promise_id == 0;
|
||||
assert!(is_sync);
|
||||
|
||||
let zero_copy_bufs = &mut bufs[1..];
|
||||
let result: i32 = match op_fn(&state, record.rid, zero_copy_bufs) {
|
||||
Ok(r) => r as i32,
|
||||
Err(_) => -1,
|
||||
};
|
||||
let result: i32 =
|
||||
match op_fn(&mut state.borrow_mut(), record.rid, zero_copy_bufs) {
|
||||
Ok(r) => r as i32,
|
||||
Err(_) => -1,
|
||||
};
|
||||
let buf = RecordBuf::from(Record { result, ..record })[..].into();
|
||||
Op::Sync(buf)
|
||||
};
|
||||
|
||||
state.register_op(name, base_op_fn);
|
||||
isolate.register_op(name, base_op_fn);
|
||||
}
|
||||
|
||||
fn register_op_bin_async<F, R>(state: &BasicState, name: &'static str, op_fn: F)
|
||||
where
|
||||
F: Fn(Rc<BasicState>, u32, BufVec) -> R + Copy + 'static,
|
||||
fn register_op_bin_async<F, R>(
|
||||
isolate: &mut JsRuntime,
|
||||
name: &'static str,
|
||||
op_fn: F,
|
||||
) where
|
||||
F: Fn(Rc<RefCell<OpState>>, u32, BufVec) -> R + Copy + 'static,
|
||||
R: TryFuture,
|
||||
R::Ok: TryInto<i32>,
|
||||
<R::Ok as TryInto<i32>>::Error: Debug,
|
||||
{
|
||||
let base_op_fn = move |state: Rc<BasicState>, bufs: BufVec| -> Op {
|
||||
let base_op_fn = move |state: Rc<RefCell<OpState>>, bufs: BufVec| -> Op {
|
||||
let mut bufs_iter = bufs.into_iter();
|
||||
let record_buf = bufs_iter.next().unwrap();
|
||||
let zero_copy_bufs = bufs_iter.collect::<BufVec>();
|
||||
|
@ -227,7 +233,7 @@ where
|
|||
Op::Async(fut.boxed_local())
|
||||
};
|
||||
|
||||
state.register_op(name, base_op_fn);
|
||||
isolate.register_op(name, base_op_fn);
|
||||
}
|
||||
|
||||
fn bad_resource_id() -> Error {
|
||||
|
|
|
@ -2,17 +2,17 @@
|
|||
extern crate log;
|
||||
|
||||
use deno_core::js_check;
|
||||
use deno_core::BasicState;
|
||||
use deno_core::BufVec;
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::JsRuntime;
|
||||
use deno_core::OpRegistry;
|
||||
use deno_core::OpState;
|
||||
use deno_core::Script;
|
||||
use deno_core::StartupData;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use futures::future::poll_fn;
|
||||
use futures::future::Future;
|
||||
use serde_json::Value;
|
||||
use std::cell::RefCell;
|
||||
use std::convert::TryInto;
|
||||
use std::env;
|
||||
use std::net::SocketAddr;
|
||||
|
@ -42,23 +42,21 @@ impl log::Log for Logger {
|
|||
}
|
||||
|
||||
fn create_isolate() -> JsRuntime {
|
||||
let state = BasicState::new();
|
||||
state.register_op_json_sync("listen", op_listen);
|
||||
state.register_op_json_sync("close", op_close);
|
||||
state.register_op_json_async("accept", op_accept);
|
||||
state.register_op_json_async("read", op_read);
|
||||
state.register_op_json_async("write", op_write);
|
||||
|
||||
let startup_data = StartupData::Script(Script {
|
||||
source: include_str!("http_bench_json_ops.js"),
|
||||
filename: "http_bench_json_ops.js",
|
||||
});
|
||||
|
||||
JsRuntime::new(state, startup_data, false)
|
||||
let mut runtime = JsRuntime::new(startup_data, false);
|
||||
runtime.register_op("listen", deno_core::json_op_sync(op_listen));
|
||||
runtime.register_op("close", deno_core::json_op_sync(op_close));
|
||||
runtime.register_op("accept", deno_core::json_op_async(op_accept));
|
||||
runtime.register_op("read", deno_core::json_op_async(op_read));
|
||||
runtime.register_op("write", deno_core::json_op_async(op_write));
|
||||
runtime
|
||||
}
|
||||
|
||||
fn op_listen(
|
||||
state: &BasicState,
|
||||
state: &mut OpState,
|
||||
_args: Value,
|
||||
_bufs: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
@ -66,15 +64,12 @@ fn op_listen(
|
|||
let addr = "127.0.0.1:4544".parse::<SocketAddr>().unwrap();
|
||||
let std_listener = std::net::TcpListener::bind(&addr)?;
|
||||
let listener = TcpListener::from_std(std_listener)?;
|
||||
let rid = state
|
||||
.resource_table
|
||||
.borrow_mut()
|
||||
.add("tcpListener", Box::new(listener));
|
||||
let rid = state.resource_table.add("tcpListener", Box::new(listener));
|
||||
Ok(serde_json::json!({ "rid": rid }))
|
||||
}
|
||||
|
||||
fn op_close(
|
||||
state: &BasicState,
|
||||
state: &mut OpState,
|
||||
args: Value,
|
||||
_buf: &mut [ZeroCopyBuf],
|
||||
) -> Result<Value, ErrBox> {
|
||||
|
@ -86,17 +81,15 @@ fn op_close(
|
|||
.try_into()
|
||||
.unwrap();
|
||||
debug!("close rid={}", rid);
|
||||
|
||||
state
|
||||
.resource_table
|
||||
.borrow_mut()
|
||||
.close(rid)
|
||||
.map(|_| serde_json::json!(()))
|
||||
.ok_or_else(ErrBox::bad_resource_id)
|
||||
}
|
||||
|
||||
fn op_accept(
|
||||
state: Rc<BasicState>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
_bufs: BufVec,
|
||||
) -> impl Future<Output = Result<Value, ErrBox>> {
|
||||
|
@ -110,7 +103,8 @@ fn op_accept(
|
|||
debug!("accept rid={}", rid);
|
||||
|
||||
poll_fn(move |cx| {
|
||||
let resource_table = &mut state.resource_table.borrow_mut();
|
||||
let resource_table = &mut state.borrow_mut().resource_table;
|
||||
|
||||
let listener = resource_table
|
||||
.get_mut::<TcpListener>(rid)
|
||||
.ok_or_else(ErrBox::bad_resource_id)?;
|
||||
|
@ -122,7 +116,7 @@ fn op_accept(
|
|||
}
|
||||
|
||||
fn op_read(
|
||||
state: Rc<BasicState>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
mut bufs: BufVec,
|
||||
) -> impl Future<Output = Result<Value, ErrBox>> {
|
||||
|
@ -138,7 +132,8 @@ fn op_read(
|
|||
debug!("read rid={}", rid);
|
||||
|
||||
poll_fn(move |cx| -> Poll<Result<Value, ErrBox>> {
|
||||
let resource_table = &mut state.resource_table.borrow_mut();
|
||||
let resource_table = &mut state.borrow_mut().resource_table;
|
||||
|
||||
let stream = resource_table
|
||||
.get_mut::<TcpStream>(rid)
|
||||
.ok_or_else(ErrBox::bad_resource_id)?;
|
||||
|
@ -149,7 +144,7 @@ fn op_read(
|
|||
}
|
||||
|
||||
fn op_write(
|
||||
state: Rc<BasicState>,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
bufs: BufVec,
|
||||
) -> impl Future<Output = Result<Value, ErrBox>> {
|
||||
|
@ -165,7 +160,8 @@ fn op_write(
|
|||
debug!("write rid={}", rid);
|
||||
|
||||
poll_fn(move |cx| {
|
||||
let resource_table = &mut state.resource_table.borrow_mut();
|
||||
let resource_table = &mut state.borrow_mut().resource_table;
|
||||
|
||||
let stream = resource_table
|
||||
.get_mut::<TcpStream>(rid)
|
||||
.ok_or_else(ErrBox::bad_resource_id)?;
|
||||
|
|
167
core/gotham_state.rs
Normal file
167
core/gotham_state.rs
Normal file
|
@ -0,0 +1,167 @@
|
|||
// Forked from Gotham:
|
||||
// https://github.com/gotham-rs/gotham/blob/bcbbf8923789e341b7a0e62c59909428ca4e22e2/gotham/src/state/mod.rs
|
||||
// Copyright 2017 Gotham Project Developers. MIT license.
|
||||
|
||||
use std::any::Any;
|
||||
use std::any::TypeId;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct GothamState {
|
||||
data: HashMap<TypeId, Box<dyn Any>>,
|
||||
}
|
||||
|
||||
impl GothamState {
|
||||
/// Puts a value into the `GothamState` storage. One value of each type is retained.
|
||||
/// Successive calls to `put` will overwrite the existing value of the same
|
||||
/// type.
|
||||
pub fn put<T: 'static>(&mut self, t: T) {
|
||||
let type_id = TypeId::of::<T>();
|
||||
trace!(" inserting record to state for type_id `{:?}`", type_id);
|
||||
self.data.insert(type_id, Box::new(t));
|
||||
}
|
||||
|
||||
/// Determines if the current value exists in `GothamState` storage.
|
||||
pub fn has<T: 'static>(&self) -> bool {
|
||||
let type_id = TypeId::of::<T>();
|
||||
self.data.get(&type_id).is_some()
|
||||
}
|
||||
|
||||
/// Tries to borrow a value from the `GothamState` storage.
|
||||
pub fn try_borrow<T: 'static>(&self) -> Option<&T> {
|
||||
let type_id = TypeId::of::<T>();
|
||||
trace!(" borrowing state data for type_id `{:?}`", type_id);
|
||||
self.data.get(&type_id).and_then(|b| b.downcast_ref())
|
||||
}
|
||||
|
||||
/// Borrows a value from the `GothamState` storage.
|
||||
pub fn borrow<T: 'static>(&self) -> &T {
|
||||
self
|
||||
.try_borrow()
|
||||
.expect("required type is not present in GothamState container")
|
||||
}
|
||||
|
||||
/// Tries to mutably borrow a value from the `GothamState` storage.
|
||||
pub fn try_borrow_mut<T: 'static>(&mut self) -> Option<&mut T> {
|
||||
let type_id = TypeId::of::<T>();
|
||||
trace!(" mutably borrowing state data for type_id `{:?}`", type_id);
|
||||
self.data.get_mut(&type_id).and_then(|b| b.downcast_mut())
|
||||
}
|
||||
|
||||
/// Mutably borrows a value from the `GothamState` storage.
|
||||
pub fn borrow_mut<T: 'static>(&mut self) -> &mut T {
|
||||
self
|
||||
.try_borrow_mut()
|
||||
.expect("required type is not present in GothamState container")
|
||||
}
|
||||
|
||||
/// Tries to move a value out of the `GothamState` storage and return ownership.
|
||||
pub fn try_take<T: 'static>(&mut self) -> Option<T> {
|
||||
let type_id = TypeId::of::<T>();
|
||||
trace!(
|
||||
" taking ownership from state data for type_id `{:?}`",
|
||||
type_id
|
||||
);
|
||||
self
|
||||
.data
|
||||
.remove(&type_id)
|
||||
.and_then(|b| b.downcast().ok())
|
||||
.map(|b| *b)
|
||||
}
|
||||
|
||||
/// Moves a value out of the `GothamState` storage and returns ownership.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// If a value of type `T` is not present in `GothamState`.
|
||||
pub fn take<T: 'static>(&mut self) -> T {
|
||||
self
|
||||
.try_take()
|
||||
.expect("required type is not present in GothamState container")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::GothamState;
|
||||
|
||||
struct MyStruct {
|
||||
value: i32,
|
||||
}
|
||||
|
||||
struct AnotherStruct {
|
||||
value: &'static str,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn put_borrow1() {
|
||||
let mut state = GothamState::default();
|
||||
state.put(MyStruct { value: 1 });
|
||||
assert_eq!(state.borrow::<MyStruct>().value, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn put_borrow2() {
|
||||
let mut state = GothamState::default();
|
||||
assert!(!state.has::<AnotherStruct>());
|
||||
state.put(AnotherStruct { value: "a string" });
|
||||
assert!(state.has::<AnotherStruct>());
|
||||
assert!(!state.has::<MyStruct>());
|
||||
state.put(MyStruct { value: 100 });
|
||||
assert!(state.has::<MyStruct>());
|
||||
assert_eq!(state.borrow::<MyStruct>().value, 100);
|
||||
assert_eq!(state.borrow::<AnotherStruct>().value, "a string");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_borrow() {
|
||||
let mut state = GothamState::default();
|
||||
state.put(MyStruct { value: 100 });
|
||||
assert!(state.try_borrow::<MyStruct>().is_some());
|
||||
assert_eq!(state.try_borrow::<MyStruct>().unwrap().value, 100);
|
||||
assert!(state.try_borrow::<AnotherStruct>().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_borrow_mut() {
|
||||
let mut state = GothamState::default();
|
||||
state.put(MyStruct { value: 100 });
|
||||
if let Some(a) = state.try_borrow_mut::<MyStruct>() {
|
||||
a.value += 10;
|
||||
}
|
||||
assert_eq!(state.borrow::<MyStruct>().value, 110);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn borrow_mut() {
|
||||
let mut state = GothamState::default();
|
||||
state.put(MyStruct { value: 100 });
|
||||
{
|
||||
let a = state.borrow_mut::<MyStruct>();
|
||||
a.value += 10;
|
||||
}
|
||||
assert_eq!(state.borrow::<MyStruct>().value, 110);
|
||||
assert!(state.try_borrow_mut::<AnotherStruct>().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_take() {
|
||||
let mut state = GothamState::default();
|
||||
state.put(MyStruct { value: 100 });
|
||||
assert_eq!(state.try_take::<MyStruct>().unwrap().value, 100);
|
||||
assert!(state.try_take::<MyStruct>().is_none());
|
||||
assert!(state.try_borrow_mut::<MyStruct>().is_none());
|
||||
assert!(state.try_borrow::<MyStruct>().is_none());
|
||||
assert!(state.try_take::<AnotherStruct>().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take() {
|
||||
let mut state = GothamState::default();
|
||||
state.put(MyStruct { value: 110 });
|
||||
assert_eq!(state.take::<MyStruct>().value, 110);
|
||||
assert!(state.try_take::<MyStruct>().is_none());
|
||||
assert!(state.try_borrow_mut::<MyStruct>().is_none());
|
||||
assert!(state.try_borrow::<MyStruct>().is_none());
|
||||
}
|
||||
}
|
|
@ -8,10 +8,10 @@ extern crate lazy_static;
|
|||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
mod basic_state;
|
||||
mod bindings;
|
||||
mod errors;
|
||||
mod flags;
|
||||
mod gotham_state;
|
||||
mod module_specifier;
|
||||
mod modules;
|
||||
mod normalize_path;
|
||||
|
@ -24,7 +24,6 @@ mod zero_copy_buf;
|
|||
|
||||
pub use rusty_v8 as v8;
|
||||
|
||||
pub use crate::basic_state::BasicState;
|
||||
pub use crate::errors::AnyError;
|
||||
pub use crate::errors::ErrBox;
|
||||
pub use crate::errors::JsError;
|
||||
|
@ -38,12 +37,13 @@ pub use crate::modules::ModuleSource;
|
|||
pub use crate::modules::ModuleSourceFuture;
|
||||
pub use crate::modules::RecursiveModuleLoad;
|
||||
pub use crate::normalize_path::normalize_path;
|
||||
pub use crate::ops::json_op_async;
|
||||
pub use crate::ops::json_op_sync;
|
||||
pub use crate::ops::Op;
|
||||
pub use crate::ops::OpAsyncFuture;
|
||||
pub use crate::ops::OpFn;
|
||||
pub use crate::ops::OpId;
|
||||
pub use crate::ops::OpRegistry;
|
||||
pub use crate::ops::OpRouter;
|
||||
pub use crate::ops::OpState;
|
||||
pub use crate::ops::OpTable;
|
||||
pub use crate::resources::ResourceTable;
|
||||
pub use crate::runtime::js_check;
|
||||
|
|
|
@ -441,7 +441,6 @@ impl Modules {
|
|||
mod tests {
|
||||
use super::*;
|
||||
use crate::js_check;
|
||||
use crate::BasicState;
|
||||
use crate::JsRuntime;
|
||||
use crate::StartupData;
|
||||
use futures::future::FutureExt;
|
||||
|
@ -620,12 +619,8 @@ mod tests {
|
|||
fn test_recursive_load() {
|
||||
let loader = MockLoader::new();
|
||||
let loads = loader.loads.clone();
|
||||
let mut runtime = JsRuntime::new_with_loader(
|
||||
loader,
|
||||
BasicState::new(),
|
||||
StartupData::None,
|
||||
false,
|
||||
);
|
||||
let mut runtime =
|
||||
JsRuntime::new_with_loader(loader, StartupData::None, false);
|
||||
let spec = ModuleSpecifier::resolve_url("file:///a.js").unwrap();
|
||||
let a_id_fut = runtime.load_module(&spec, None);
|
||||
let a_id = futures::executor::block_on(a_id_fut).expect("Failed to load");
|
||||
|
@ -687,12 +682,8 @@ mod tests {
|
|||
fn test_circular_load() {
|
||||
let loader = MockLoader::new();
|
||||
let loads = loader.loads.clone();
|
||||
let mut runtime = JsRuntime::new_with_loader(
|
||||
loader,
|
||||
BasicState::new(),
|
||||
StartupData::None,
|
||||
false,
|
||||
);
|
||||
let mut runtime =
|
||||
JsRuntime::new_with_loader(loader, StartupData::None, false);
|
||||
|
||||
let fut = async move {
|
||||
let spec = ModuleSpecifier::resolve_url("file:///circular1.js").unwrap();
|
||||
|
@ -765,12 +756,8 @@ mod tests {
|
|||
fn test_redirect_load() {
|
||||
let loader = MockLoader::new();
|
||||
let loads = loader.loads.clone();
|
||||
let mut runtime = JsRuntime::new_with_loader(
|
||||
loader,
|
||||
BasicState::new(),
|
||||
StartupData::None,
|
||||
false,
|
||||
);
|
||||
let mut runtime =
|
||||
JsRuntime::new_with_loader(loader, StartupData::None, false);
|
||||
|
||||
let fut = async move {
|
||||
let spec = ModuleSpecifier::resolve_url("file:///redirect1.js").unwrap();
|
||||
|
@ -834,12 +821,8 @@ mod tests {
|
|||
run_in_task(|mut cx| {
|
||||
let loader = MockLoader::new();
|
||||
let loads = loader.loads.clone();
|
||||
let mut runtime = JsRuntime::new_with_loader(
|
||||
loader,
|
||||
BasicState::new(),
|
||||
StartupData::None,
|
||||
false,
|
||||
);
|
||||
let mut runtime =
|
||||
JsRuntime::new_with_loader(loader, StartupData::None, false);
|
||||
let spec = ModuleSpecifier::resolve_url("file:///main.js").unwrap();
|
||||
let mut recursive_load = runtime.load_module(&spec, None).boxed_local();
|
||||
|
||||
|
@ -884,12 +867,8 @@ mod tests {
|
|||
fn loader_disappears_after_error() {
|
||||
run_in_task(|mut cx| {
|
||||
let loader = MockLoader::new();
|
||||
let mut runtime = JsRuntime::new_with_loader(
|
||||
loader,
|
||||
BasicState::new(),
|
||||
StartupData::None,
|
||||
false,
|
||||
);
|
||||
let mut runtime =
|
||||
JsRuntime::new_with_loader(loader, StartupData::None, false);
|
||||
let spec = ModuleSpecifier::resolve_url("file:///bad_import.js").unwrap();
|
||||
let mut load_fut = runtime.load_module(&spec, None).boxed_local();
|
||||
let result = load_fut.poll_unpin(&mut cx);
|
||||
|
@ -917,12 +896,8 @@ mod tests {
|
|||
fn recursive_load_main_with_code() {
|
||||
let loader = MockLoader::new();
|
||||
let loads = loader.loads.clone();
|
||||
let mut runtime = JsRuntime::new_with_loader(
|
||||
loader,
|
||||
BasicState::new(),
|
||||
StartupData::None,
|
||||
false,
|
||||
);
|
||||
let mut runtime =
|
||||
JsRuntime::new_with_loader(loader, StartupData::None, false);
|
||||
// In default resolution code should be empty.
|
||||
// Instead we explicitly pass in our own code.
|
||||
// The behavior should be very similar to /a.js.
|
||||
|
|
266
core/ops.rs
266
core/ops.rs
|
@ -1,13 +1,13 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::gotham_state::GothamState;
|
||||
use crate::BufVec;
|
||||
use crate::ErrBox;
|
||||
use crate::ZeroCopyBuf;
|
||||
use futures::Future;
|
||||
use futures::FutureExt;
|
||||
use indexmap::IndexMap;
|
||||
use serde_json::json;
|
||||
use serde_json::Value;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::iter::once;
|
||||
use std::ops::Deref;
|
||||
|
@ -16,7 +16,7 @@ use std::pin::Pin;
|
|||
use std::rc::Rc;
|
||||
|
||||
pub type OpAsyncFuture = Pin<Box<dyn Future<Output = Box<[u8]>>>>;
|
||||
pub type OpFn<S> = dyn Fn(Rc<S>, BufVec) -> Op + 'static;
|
||||
pub type OpFn = dyn Fn(Rc<RefCell<OpState>>, BufVec) -> Op + 'static;
|
||||
pub type OpId = usize;
|
||||
|
||||
pub enum Op {
|
||||
|
@ -28,119 +28,191 @@ pub enum Op {
|
|||
NotFound,
|
||||
}
|
||||
|
||||
pub trait OpRouter {
|
||||
fn route_op(self: Rc<Self>, op_id: OpId, bufs: BufVec) -> Op;
|
||||
pub struct OpState {
|
||||
pub resource_table: crate::ResourceTable,
|
||||
pub op_table: OpTable,
|
||||
pub get_error_class_fn: crate::runtime::GetErrorClassFn,
|
||||
gotham_state: GothamState,
|
||||
}
|
||||
|
||||
pub trait OpRegistry: OpRouter + 'static {
|
||||
fn get_op_catalog(self: Rc<Self>) -> HashMap<String, OpId>;
|
||||
impl Default for OpState {
|
||||
// TODO(ry) Only deno_core should be able to construct an OpState. But I don't
|
||||
// know how to make default private. Maybe rename to
|
||||
// pub(crate) fn new() -> OpState
|
||||
fn default() -> OpState {
|
||||
OpState {
|
||||
resource_table: crate::ResourceTable::default(),
|
||||
op_table: OpTable::default(),
|
||||
get_error_class_fn: &|_| "Error",
|
||||
gotham_state: GothamState::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn register_op<F>(&self, name: &str, op_fn: F) -> OpId
|
||||
where
|
||||
F: Fn(Rc<Self>, BufVec) -> Op + 'static;
|
||||
impl Deref for OpState {
|
||||
type Target = GothamState;
|
||||
|
||||
fn register_op_json_sync<F>(self: &Rc<Self>, name: &str, op_fn: F) -> OpId
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.gotham_state
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for OpState {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.gotham_state
|
||||
}
|
||||
}
|
||||
|
||||
/// Collection for storing registered ops. The special 'get_op_catalog'
|
||||
/// op with OpId `0` is automatically added when the OpTable is created.
|
||||
pub struct OpTable(IndexMap<String, Rc<OpFn>>);
|
||||
|
||||
impl OpTable {
|
||||
pub fn register_op<F>(&mut self, name: &str, op_fn: F) -> OpId
|
||||
where
|
||||
F: Fn(&Self, Value, &mut [ZeroCopyBuf]) -> Result<Value, ErrBox> + 'static,
|
||||
F: Fn(Rc<RefCell<OpState>>, BufVec) -> Op + 'static,
|
||||
{
|
||||
let base_op_fn = move |state: Rc<Self>, mut bufs: BufVec| -> Op {
|
||||
let result = serde_json::from_slice(&bufs[0])
|
||||
.map_err(ErrBox::from)
|
||||
.and_then(|args| op_fn(&state, args, &mut bufs[1..]));
|
||||
let buf = state.json_serialize_op_result(None, result);
|
||||
Op::Sync(buf)
|
||||
};
|
||||
|
||||
self.register_op(name, base_op_fn)
|
||||
let (op_id, prev) = self.0.insert_full(name.to_owned(), Rc::new(op_fn));
|
||||
assert!(prev.is_none());
|
||||
op_id
|
||||
}
|
||||
|
||||
fn register_op_json_async<F, R>(self: &Rc<Self>, name: &str, op_fn: F) -> OpId
|
||||
where
|
||||
F: Fn(Rc<Self>, Value, BufVec) -> R + 'static,
|
||||
R: Future<Output = Result<Value, ErrBox>> + 'static,
|
||||
pub fn route_op(
|
||||
op_id: OpId,
|
||||
state: Rc<RefCell<OpState>>,
|
||||
bufs: BufVec,
|
||||
) -> Op {
|
||||
if op_id == 0 {
|
||||
let ops: HashMap<String, OpId> =
|
||||
state.borrow().op_table.0.keys().cloned().zip(0..).collect();
|
||||
let buf = serde_json::to_vec(&ops).map(Into::into).unwrap();
|
||||
Op::Sync(buf)
|
||||
} else {
|
||||
let op_fn = state
|
||||
.borrow()
|
||||
.op_table
|
||||
.0
|
||||
.get_index(op_id)
|
||||
.map(|(_, op_fn)| op_fn.clone());
|
||||
match op_fn {
|
||||
Some(f) => (f)(state, bufs),
|
||||
None => Op::NotFound,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for OpTable {
|
||||
fn default() -> Self {
|
||||
fn dummy(_state: Rc<RefCell<OpState>>, _bufs: BufVec) -> Op {
|
||||
unreachable!()
|
||||
}
|
||||
Self(once(("ops".to_owned(), Rc::new(dummy) as _)).collect())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_table() {
|
||||
let state = Rc::new(RefCell::new(OpState::default()));
|
||||
|
||||
let foo_id;
|
||||
let bar_id;
|
||||
{
|
||||
let try_dispatch_op = move |state: Rc<Self>,
|
||||
bufs: BufVec|
|
||||
-> Result<Op, ErrBox> {
|
||||
let op_table = &mut state.borrow_mut().op_table;
|
||||
foo_id = op_table.register_op("foo", |_, _| Op::Sync(b"oof!"[..].into()));
|
||||
assert_eq!(foo_id, 1);
|
||||
bar_id = op_table.register_op("bar", |_, _| Op::Sync(b"rab!"[..].into()));
|
||||
assert_eq!(bar_id, 2);
|
||||
}
|
||||
|
||||
let foo_res = OpTable::route_op(foo_id, state.clone(), Default::default());
|
||||
assert!(matches!(foo_res, Op::Sync(buf) if &*buf == b"oof!"));
|
||||
let bar_res = OpTable::route_op(bar_id, state.clone(), Default::default());
|
||||
assert!(matches!(bar_res, Op::Sync(buf) if &*buf == b"rab!"));
|
||||
|
||||
let catalog_res = OpTable::route_op(0, state, Default::default());
|
||||
let mut catalog_entries = match catalog_res {
|
||||
Op::Sync(buf) => serde_json::from_slice::<HashMap<String, OpId>>(&buf)
|
||||
.map(|map| map.into_iter().collect::<Vec<_>>())
|
||||
.unwrap(),
|
||||
_ => panic!("unexpected `Op` variant"),
|
||||
};
|
||||
catalog_entries.sort_by(|(_, id1), (_, id2)| id1.partial_cmp(id2).unwrap());
|
||||
assert_eq!(
|
||||
catalog_entries,
|
||||
vec![
|
||||
("ops".to_owned(), 0),
|
||||
("foo".to_owned(), 1),
|
||||
("bar".to_owned(), 2)
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
pub fn json_op_sync<F>(op_fn: F) -> Box<OpFn>
|
||||
where
|
||||
F: Fn(&mut OpState, Value, &mut [ZeroCopyBuf]) -> Result<Value, ErrBox>
|
||||
+ 'static,
|
||||
{
|
||||
Box::new(move |state: Rc<RefCell<OpState>>, mut bufs: BufVec| -> Op {
|
||||
let result = serde_json::from_slice(&bufs[0])
|
||||
.map_err(crate::ErrBox::from)
|
||||
.and_then(|args| op_fn(&mut state.borrow_mut(), args, &mut bufs[1..]));
|
||||
let buf =
|
||||
json_serialize_op_result(None, result, state.borrow().get_error_class_fn);
|
||||
Op::Sync(buf)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn json_op_async<F, R>(op_fn: F) -> Box<OpFn>
|
||||
where
|
||||
F: Fn(Rc<RefCell<OpState>>, Value, BufVec) -> R + 'static,
|
||||
R: Future<Output = Result<Value, ErrBox>> + 'static,
|
||||
{
|
||||
let try_dispatch_op =
|
||||
move |state: Rc<RefCell<OpState>>, bufs: BufVec| -> Result<Op, ErrBox> {
|
||||
let args: Value = serde_json::from_slice(&bufs[0])?;
|
||||
let promise_id = args
|
||||
.get("promiseId")
|
||||
.and_then(Value::as_u64)
|
||||
.ok_or_else(|| ErrBox::type_error("missing or invalid `promiseId`"))?;
|
||||
let bufs = bufs[1..].into();
|
||||
use crate::futures::FutureExt;
|
||||
let fut = op_fn(state.clone(), args, bufs).map(move |result| {
|
||||
state.json_serialize_op_result(Some(promise_id), result)
|
||||
json_serialize_op_result(
|
||||
Some(promise_id),
|
||||
result,
|
||||
state.borrow().get_error_class_fn,
|
||||
)
|
||||
});
|
||||
Ok(Op::Async(Box::pin(fut)))
|
||||
};
|
||||
|
||||
let base_op_fn = move |state: Rc<Self>, bufs: BufVec| -> Op {
|
||||
match try_dispatch_op(state.clone(), bufs) {
|
||||
Ok(op) => op,
|
||||
Err(err) => Op::Sync(state.json_serialize_op_result(None, Err(err))),
|
||||
Box::new(move |state: Rc<RefCell<OpState>>, bufs: BufVec| -> Op {
|
||||
match try_dispatch_op(state.clone(), bufs) {
|
||||
Ok(op) => op,
|
||||
Err(err) => Op::Sync(json_serialize_op_result(
|
||||
None,
|
||||
Err(err),
|
||||
state.borrow().get_error_class_fn,
|
||||
)),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn json_serialize_op_result(
|
||||
promise_id: Option<u64>,
|
||||
result: Result<serde_json::Value, crate::ErrBox>,
|
||||
get_error_class_fn: crate::runtime::GetErrorClassFn,
|
||||
) -> Box<[u8]> {
|
||||
let value = match result {
|
||||
Ok(v) => serde_json::json!({ "ok": v, "promiseId": promise_id }),
|
||||
Err(err) => serde_json::json!({
|
||||
"promiseId": promise_id ,
|
||||
"err": {
|
||||
"className": (get_error_class_fn)(&err),
|
||||
"message": err.to_string(),
|
||||
}
|
||||
};
|
||||
|
||||
self.register_op(name, base_op_fn)
|
||||
}
|
||||
|
||||
fn json_serialize_op_result(
|
||||
&self,
|
||||
promise_id: Option<u64>,
|
||||
result: Result<Value, ErrBox>,
|
||||
) -> Box<[u8]> {
|
||||
let value = match result {
|
||||
Ok(v) => json!({ "ok": v, "promiseId": promise_id }),
|
||||
Err(err) => json!({
|
||||
"promiseId": promise_id ,
|
||||
"err": {
|
||||
"className": self.get_error_class_name(&err),
|
||||
"message": err.to_string(),
|
||||
}
|
||||
}),
|
||||
};
|
||||
serde_json::to_vec(&value).unwrap().into_boxed_slice()
|
||||
}
|
||||
|
||||
fn get_error_class_name(&self, _err: &ErrBox) -> &'static str {
|
||||
"Error"
|
||||
}
|
||||
}
|
||||
|
||||
/// Collection for storing registered ops. The special 'get_op_catalog'
|
||||
/// op with OpId `0` is automatically added when the OpTable is created.
|
||||
pub struct OpTable<S>(IndexMap<String, Rc<OpFn<S>>>);
|
||||
|
||||
impl<S: OpRegistry> OpTable<S> {
|
||||
pub fn get_op_catalog(&self) -> HashMap<String, OpId> {
|
||||
self.keys().cloned().zip(0..).collect()
|
||||
}
|
||||
|
||||
fn op_get_op_catalog(state: Rc<S>, _bufs: BufVec) -> Op {
|
||||
let ops = state.get_op_catalog();
|
||||
let buf = serde_json::to_vec(&ops).map(Into::into).unwrap();
|
||||
Op::Sync(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: OpRegistry> Default for OpTable<S> {
|
||||
fn default() -> Self {
|
||||
Self(
|
||||
once(("ops".to_owned(), Rc::new(Self::op_get_op_catalog) as _)).collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> Deref for OpTable<S> {
|
||||
type Target = IndexMap<String, Rc<OpFn<S>>>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> DerefMut for OpTable<S> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}),
|
||||
};
|
||||
serde_json::to_vec(&value).unwrap().into_boxed_slice()
|
||||
}
|
||||
|
|
249
core/runtime.rs
249
core/runtime.rs
|
@ -19,9 +19,10 @@ use crate::modules::RecursiveModuleLoad;
|
|||
use crate::ops::*;
|
||||
use crate::shared_queue::SharedQueue;
|
||||
use crate::shared_queue::RECOMMENDED_SIZE;
|
||||
use crate::BufVec;
|
||||
use crate::ErrBox;
|
||||
use crate::JsError;
|
||||
use crate::OpRouter;
|
||||
use crate::OpState;
|
||||
use futures::stream::FuturesUnordered;
|
||||
use futures::stream::StreamExt;
|
||||
use futures::stream::StreamFuture;
|
||||
|
@ -94,7 +95,7 @@ impl StartupData<'_> {
|
|||
|
||||
type JsErrorCreateFn = dyn Fn(JsError) -> ErrBox;
|
||||
|
||||
pub type GetErrorClassFn = dyn for<'e> Fn(&'e ErrBox) -> &'static str;
|
||||
pub type GetErrorClassFn = &'static dyn for<'e> Fn(&'e ErrBox) -> &'static str;
|
||||
|
||||
/// Objects that need to live as long as the isolate
|
||||
#[derive(Default)]
|
||||
|
@ -137,7 +138,8 @@ pub struct JsRuntimeState {
|
|||
pub(crate) pending_ops: FuturesUnordered<PendingOpFuture>,
|
||||
pub(crate) pending_unref_ops: FuturesUnordered<PendingOpFuture>,
|
||||
pub(crate) have_unpolled_ops: Cell<bool>,
|
||||
pub(crate) op_router: Rc<dyn OpRouter>,
|
||||
//pub(crate) op_table: OpTable,
|
||||
pub(crate) op_state: Rc<RefCell<OpState>>,
|
||||
loader: Rc<dyn ModuleLoader>,
|
||||
pub modules: Modules,
|
||||
pub(crate) dyn_import_map:
|
||||
|
@ -219,7 +221,6 @@ pub struct HeapLimits {
|
|||
|
||||
pub(crate) struct IsolateOptions {
|
||||
loader: Rc<dyn ModuleLoader>,
|
||||
op_router: Rc<dyn OpRouter>,
|
||||
startup_script: Option<OwnedScript>,
|
||||
startup_snapshot: Option<Snapshot>,
|
||||
will_snapshot: bool,
|
||||
|
@ -229,15 +230,10 @@ pub(crate) struct IsolateOptions {
|
|||
impl JsRuntime {
|
||||
/// startup_data defines the snapshot or script used at startup to initialize
|
||||
/// the isolate.
|
||||
pub fn new(
|
||||
op_router: Rc<dyn OpRouter>,
|
||||
startup_data: StartupData,
|
||||
will_snapshot: bool,
|
||||
) -> Self {
|
||||
pub fn new(startup_data: StartupData, will_snapshot: bool) -> Self {
|
||||
let (startup_script, startup_snapshot) = startup_data.into_options();
|
||||
let options = IsolateOptions {
|
||||
loader: Rc::new(NoopModuleLoader),
|
||||
op_router,
|
||||
startup_script,
|
||||
startup_snapshot,
|
||||
will_snapshot,
|
||||
|
@ -251,14 +247,12 @@ impl JsRuntime {
|
|||
/// Create new isolate that can load and execute ESModules.
|
||||
pub fn new_with_loader(
|
||||
loader: Rc<dyn ModuleLoader>,
|
||||
op_router: Rc<dyn OpRouter>,
|
||||
startup_data: StartupData,
|
||||
will_snapshot: bool,
|
||||
) -> Self {
|
||||
let (startup_script, startup_snapshot) = startup_data.into_options();
|
||||
let options = IsolateOptions {
|
||||
loader,
|
||||
op_router,
|
||||
startup_script,
|
||||
startup_snapshot,
|
||||
will_snapshot,
|
||||
|
@ -275,14 +269,12 @@ impl JsRuntime {
|
|||
/// Make sure to use [`add_near_heap_limit_callback`](#method.add_near_heap_limit_callback)
|
||||
/// to prevent v8 from crashing when reaching the upper limit.
|
||||
pub fn with_heap_limits(
|
||||
op_router: Rc<dyn OpRouter>,
|
||||
startup_data: StartupData,
|
||||
heap_limits: HeapLimits,
|
||||
) -> Self {
|
||||
let (startup_script, startup_snapshot) = startup_data.into_options();
|
||||
let options = IsolateOptions {
|
||||
loader: Rc::new(NoopModuleLoader),
|
||||
op_router,
|
||||
startup_script,
|
||||
startup_snapshot,
|
||||
will_snapshot: false,
|
||||
|
@ -347,6 +339,8 @@ impl JsRuntime {
|
|||
(isolate, None)
|
||||
};
|
||||
|
||||
let op_state = OpState::default();
|
||||
|
||||
isolate.set_slot(Rc::new(RefCell::new(JsRuntimeState {
|
||||
global_context: Some(global_context),
|
||||
pending_promise_exceptions: HashMap::new(),
|
||||
|
@ -357,8 +351,8 @@ impl JsRuntime {
|
|||
shared: SharedQueue::new(RECOMMENDED_SIZE),
|
||||
pending_ops: FuturesUnordered::new(),
|
||||
pending_unref_ops: FuturesUnordered::new(),
|
||||
op_state: Rc::new(RefCell::new(op_state)),
|
||||
have_unpolled_ops: Cell::new(false),
|
||||
op_router: options.op_router,
|
||||
modules: Modules::new(),
|
||||
loader: options.loader,
|
||||
dyn_import_map: HashMap::new(),
|
||||
|
@ -406,6 +400,12 @@ impl JsRuntime {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn op_state(&mut self) -> Rc<RefCell<OpState>> {
|
||||
let state_rc = Self::state(self);
|
||||
let state = state_rc.borrow();
|
||||
state.op_state.clone()
|
||||
}
|
||||
|
||||
/// Executes traditional JavaScript code (traditional = not ES modules)
|
||||
///
|
||||
/// ErrBox can be downcast to a type that exposes additional information about
|
||||
|
@ -477,6 +477,18 @@ impl JsRuntime {
|
|||
snapshot
|
||||
}
|
||||
|
||||
pub fn register_op<F>(&mut self, name: &str, op_fn: F) -> OpId
|
||||
where
|
||||
F: Fn(Rc<RefCell<OpState>>, BufVec) -> Op + 'static,
|
||||
{
|
||||
Self::state(self)
|
||||
.borrow_mut()
|
||||
.op_state
|
||||
.borrow_mut()
|
||||
.op_table
|
||||
.register_op(name, op_fn)
|
||||
}
|
||||
|
||||
/// Registers a callback on the isolate when the memory limits are approached.
|
||||
/// Use this to prevent V8 from crashing the process when reaching the limit.
|
||||
///
|
||||
|
@ -1283,8 +1295,6 @@ impl JsRuntime {
|
|||
pub mod tests {
|
||||
use super::*;
|
||||
use crate::modules::ModuleSourceFuture;
|
||||
use crate::ops::*;
|
||||
use crate::BasicState;
|
||||
use crate::BufVec;
|
||||
use futures::future::lazy;
|
||||
use futures::FutureExt;
|
||||
|
@ -1328,89 +1338,89 @@ pub mod tests {
|
|||
OverflowResAsync,
|
||||
}
|
||||
|
||||
struct TestOpRouter {
|
||||
struct TestState {
|
||||
mode: Mode,
|
||||
dispatch_count: Arc<AtomicUsize>,
|
||||
}
|
||||
|
||||
impl OpRouter for TestOpRouter {
|
||||
fn route_op(self: Rc<Self>, op_id: OpId, bufs: BufVec) -> Op {
|
||||
if op_id != 1 {
|
||||
return Op::NotFound;
|
||||
fn dispatch(op_state: Rc<RefCell<OpState>>, bufs: BufVec) -> Op {
|
||||
let op_state_ = op_state.borrow();
|
||||
let test_state = op_state_.borrow::<TestState>();
|
||||
test_state.dispatch_count.fetch_add(1, Ordering::Relaxed);
|
||||
match test_state.mode {
|
||||
Mode::Async => {
|
||||
assert_eq!(bufs.len(), 1);
|
||||
assert_eq!(bufs[0].len(), 1);
|
||||
assert_eq!(bufs[0][0], 42);
|
||||
let buf = vec![43u8].into_boxed_slice();
|
||||
Op::Async(futures::future::ready(buf).boxed())
|
||||
}
|
||||
self.dispatch_count.fetch_add(1, Ordering::Relaxed);
|
||||
match self.mode {
|
||||
Mode::Async => {
|
||||
assert_eq!(bufs.len(), 1);
|
||||
assert_eq!(bufs[0].len(), 1);
|
||||
assert_eq!(bufs[0][0], 42);
|
||||
let buf = vec![43u8].into_boxed_slice();
|
||||
Op::Async(futures::future::ready(buf).boxed())
|
||||
}
|
||||
Mode::AsyncUnref => {
|
||||
assert_eq!(bufs.len(), 1);
|
||||
assert_eq!(bufs[0].len(), 1);
|
||||
assert_eq!(bufs[0][0], 42);
|
||||
let fut = async {
|
||||
// This future never finish.
|
||||
futures::future::pending::<()>().await;
|
||||
vec![43u8].into_boxed_slice()
|
||||
};
|
||||
Op::AsyncUnref(fut.boxed())
|
||||
}
|
||||
Mode::AsyncZeroCopy(count) => {
|
||||
assert_eq!(bufs.len(), count as usize);
|
||||
bufs.iter().enumerate().for_each(|(idx, buf)| {
|
||||
assert_eq!(buf.len(), 1);
|
||||
assert_eq!(idx, buf[0] as usize);
|
||||
});
|
||||
Mode::AsyncUnref => {
|
||||
assert_eq!(bufs.len(), 1);
|
||||
assert_eq!(bufs[0].len(), 1);
|
||||
assert_eq!(bufs[0][0], 42);
|
||||
let fut = async {
|
||||
// This future never finish.
|
||||
futures::future::pending::<()>().await;
|
||||
vec![43u8].into_boxed_slice()
|
||||
};
|
||||
Op::AsyncUnref(fut.boxed())
|
||||
}
|
||||
Mode::AsyncZeroCopy(count) => {
|
||||
assert_eq!(bufs.len(), count as usize);
|
||||
bufs.iter().enumerate().for_each(|(idx, buf)| {
|
||||
assert_eq!(buf.len(), 1);
|
||||
assert_eq!(idx, buf[0] as usize);
|
||||
});
|
||||
|
||||
let buf = vec![43u8].into_boxed_slice();
|
||||
Op::Async(futures::future::ready(buf).boxed())
|
||||
}
|
||||
Mode::OverflowReqSync => {
|
||||
assert_eq!(bufs.len(), 1);
|
||||
assert_eq!(bufs[0].len(), 100 * 1024 * 1024);
|
||||
let buf = vec![43u8].into_boxed_slice();
|
||||
Op::Sync(buf)
|
||||
}
|
||||
Mode::OverflowResSync => {
|
||||
assert_eq!(bufs.len(), 1);
|
||||
assert_eq!(bufs[0].len(), 1);
|
||||
assert_eq!(bufs[0][0], 42);
|
||||
let mut vec = Vec::<u8>::new();
|
||||
vec.resize(100 * 1024 * 1024, 0);
|
||||
vec[0] = 99;
|
||||
let buf = vec.into_boxed_slice();
|
||||
Op::Sync(buf)
|
||||
}
|
||||
Mode::OverflowReqAsync => {
|
||||
assert_eq!(bufs.len(), 1);
|
||||
assert_eq!(bufs[0].len(), 100 * 1024 * 1024);
|
||||
let buf = vec![43u8].into_boxed_slice();
|
||||
Op::Async(futures::future::ready(buf).boxed())
|
||||
}
|
||||
Mode::OverflowResAsync => {
|
||||
assert_eq!(bufs.len(), 1);
|
||||
assert_eq!(bufs[0].len(), 1);
|
||||
assert_eq!(bufs[0][0], 42);
|
||||
let mut vec = Vec::<u8>::new();
|
||||
vec.resize(100 * 1024 * 1024, 0);
|
||||
vec[0] = 4;
|
||||
let buf = vec.into_boxed_slice();
|
||||
Op::Async(futures::future::ready(buf).boxed())
|
||||
}
|
||||
let buf = vec![43u8].into_boxed_slice();
|
||||
Op::Async(futures::future::ready(buf).boxed())
|
||||
}
|
||||
Mode::OverflowReqSync => {
|
||||
assert_eq!(bufs.len(), 1);
|
||||
assert_eq!(bufs[0].len(), 100 * 1024 * 1024);
|
||||
let buf = vec![43u8].into_boxed_slice();
|
||||
Op::Sync(buf)
|
||||
}
|
||||
Mode::OverflowResSync => {
|
||||
assert_eq!(bufs.len(), 1);
|
||||
assert_eq!(bufs[0].len(), 1);
|
||||
assert_eq!(bufs[0][0], 42);
|
||||
let mut vec = Vec::<u8>::new();
|
||||
vec.resize(100 * 1024 * 1024, 0);
|
||||
vec[0] = 99;
|
||||
let buf = vec.into_boxed_slice();
|
||||
Op::Sync(buf)
|
||||
}
|
||||
Mode::OverflowReqAsync => {
|
||||
assert_eq!(bufs.len(), 1);
|
||||
assert_eq!(bufs[0].len(), 100 * 1024 * 1024);
|
||||
let buf = vec![43u8].into_boxed_slice();
|
||||
Op::Async(futures::future::ready(buf).boxed())
|
||||
}
|
||||
Mode::OverflowResAsync => {
|
||||
assert_eq!(bufs.len(), 1);
|
||||
assert_eq!(bufs[0].len(), 1);
|
||||
assert_eq!(bufs[0][0], 42);
|
||||
let mut vec = Vec::<u8>::new();
|
||||
vec.resize(100 * 1024 * 1024, 0);
|
||||
vec[0] = 4;
|
||||
let buf = vec.into_boxed_slice();
|
||||
Op::Async(futures::future::ready(buf).boxed())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn setup(mode: Mode) -> (JsRuntime, Arc<AtomicUsize>) {
|
||||
let dispatch_count = Arc::new(AtomicUsize::new(0));
|
||||
let test_state = Rc::new(TestOpRouter {
|
||||
let mut runtime = JsRuntime::new(StartupData::None, false);
|
||||
let op_state = runtime.op_state();
|
||||
op_state.borrow_mut().put(TestState {
|
||||
mode,
|
||||
dispatch_count: dispatch_count.clone(),
|
||||
});
|
||||
let mut runtime = JsRuntime::new(test_state, StartupData::None, false);
|
||||
|
||||
runtime.register_op("test", dispatch);
|
||||
|
||||
js_check(runtime.execute(
|
||||
"setup.js",
|
||||
|
@ -1774,8 +1784,7 @@ pub mod tests {
|
|||
|
||||
#[test]
|
||||
fn syntax_error() {
|
||||
let mut runtime =
|
||||
JsRuntime::new(BasicState::new(), StartupData::None, false);
|
||||
let mut runtime = JsRuntime::new(StartupData::None, false);
|
||||
let src = "hocuspocus(";
|
||||
let r = runtime.execute("i.js", src);
|
||||
let e = r.unwrap_err();
|
||||
|
@ -1800,29 +1809,27 @@ pub mod tests {
|
|||
#[test]
|
||||
fn will_snapshot() {
|
||||
let snapshot = {
|
||||
let mut runtime =
|
||||
JsRuntime::new(BasicState::new(), StartupData::None, true);
|
||||
let mut runtime = JsRuntime::new(StartupData::None, true);
|
||||
js_check(runtime.execute("a.js", "a = 1 + 2"));
|
||||
runtime.snapshot()
|
||||
};
|
||||
|
||||
let startup_data = StartupData::Snapshot(Snapshot::JustCreated(snapshot));
|
||||
let mut runtime2 = JsRuntime::new(BasicState::new(), startup_data, false);
|
||||
let mut runtime2 = JsRuntime::new(startup_data, false);
|
||||
js_check(runtime2.execute("check.js", "if (a != 3) throw Error('x')"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_boxed_snapshot() {
|
||||
let snapshot = {
|
||||
let mut runtime =
|
||||
JsRuntime::new(BasicState::new(), StartupData::None, true);
|
||||
let mut runtime = JsRuntime::new(StartupData::None, true);
|
||||
js_check(runtime.execute("a.js", "a = 1 + 2"));
|
||||
let snap: &[u8] = &*runtime.snapshot();
|
||||
Vec::from(snap).into_boxed_slice()
|
||||
};
|
||||
|
||||
let startup_data = StartupData::Snapshot(Snapshot::Boxed(snapshot));
|
||||
let mut runtime2 = JsRuntime::new(BasicState::new(), startup_data, false);
|
||||
let mut runtime2 = JsRuntime::new(startup_data, false);
|
||||
js_check(runtime2.execute("check.js", "if (a != 3) throw Error('x')"));
|
||||
}
|
||||
|
||||
|
@ -1832,11 +1839,8 @@ pub mod tests {
|
|||
initial: 0,
|
||||
max: 20 * 1024, // 20 kB
|
||||
};
|
||||
let mut runtime = JsRuntime::with_heap_limits(
|
||||
BasicState::new(),
|
||||
StartupData::None,
|
||||
heap_limits,
|
||||
);
|
||||
let mut runtime =
|
||||
JsRuntime::with_heap_limits(StartupData::None, heap_limits);
|
||||
let cb_handle = runtime.thread_safe_handle();
|
||||
|
||||
let callback_invoke_count = Rc::new(AtomicUsize::default());
|
||||
|
@ -1864,8 +1868,7 @@ pub mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_heap_limit_cb_remove() {
|
||||
let mut runtime =
|
||||
JsRuntime::new(BasicState::new(), StartupData::None, false);
|
||||
let mut runtime = JsRuntime::new(StartupData::None, false);
|
||||
|
||||
runtime.add_near_heap_limit_callback(|current_limit, _initial_limit| {
|
||||
current_limit * 2
|
||||
|
@ -1880,11 +1883,8 @@ pub mod tests {
|
|||
initial: 0,
|
||||
max: 20 * 1024, // 20 kB
|
||||
};
|
||||
let mut runtime = JsRuntime::with_heap_limits(
|
||||
BasicState::new(),
|
||||
StartupData::None,
|
||||
heap_limits,
|
||||
);
|
||||
let mut runtime =
|
||||
JsRuntime::with_heap_limits(StartupData::None, heap_limits);
|
||||
let cb_handle = runtime.thread_safe_handle();
|
||||
|
||||
let callback_invoke_count_first = Rc::new(AtomicUsize::default());
|
||||
|
@ -1952,13 +1952,12 @@ pub mod tests {
|
|||
}
|
||||
|
||||
let loader = Rc::new(ModsLoader::default());
|
||||
let state = BasicState::new();
|
||||
|
||||
let resolve_count = loader.count.clone();
|
||||
let dispatch_count = Arc::new(AtomicUsize::new(0));
|
||||
let dispatch_count_ = dispatch_count.clone();
|
||||
|
||||
let dispatcher = move |_state: Rc<BasicState>, bufs: BufVec| -> Op {
|
||||
let dispatcher = move |_state: Rc<RefCell<OpState>>, bufs: BufVec| -> Op {
|
||||
dispatch_count_.fetch_add(1, Ordering::Relaxed);
|
||||
assert_eq!(bufs.len(), 1);
|
||||
assert_eq!(bufs[0].len(), 1);
|
||||
|
@ -1966,10 +1965,10 @@ pub mod tests {
|
|||
let buf = [43u8, 0, 0, 0][..].into();
|
||||
Op::Async(futures::future::ready(buf).boxed())
|
||||
};
|
||||
state.register_op("test", dispatcher);
|
||||
|
||||
let mut runtime =
|
||||
JsRuntime::new_with_loader(loader, state, StartupData::None, false);
|
||||
JsRuntime::new_with_loader(loader, StartupData::None, false);
|
||||
runtime.register_op("test", dispatcher);
|
||||
|
||||
js_check(runtime.execute(
|
||||
"setup.js",
|
||||
|
@ -2063,12 +2062,8 @@ pub mod tests {
|
|||
run_in_task(|cx| {
|
||||
let loader = Rc::new(DynImportErrLoader::default());
|
||||
let count = loader.count.clone();
|
||||
let mut runtime = JsRuntime::new_with_loader(
|
||||
loader,
|
||||
BasicState::new(),
|
||||
StartupData::None,
|
||||
false,
|
||||
);
|
||||
let mut runtime =
|
||||
JsRuntime::new_with_loader(loader, StartupData::None, false);
|
||||
|
||||
js_check(runtime.execute(
|
||||
"file:///dyn_import2.js",
|
||||
|
@ -2145,12 +2140,8 @@ pub mod tests {
|
|||
let prepare_load_count = loader.prepare_load_count.clone();
|
||||
let resolve_count = loader.resolve_count.clone();
|
||||
let load_count = loader.load_count.clone();
|
||||
let mut runtime = JsRuntime::new_with_loader(
|
||||
loader,
|
||||
BasicState::new(),
|
||||
StartupData::None,
|
||||
false,
|
||||
);
|
||||
let mut runtime =
|
||||
JsRuntime::new_with_loader(loader, StartupData::None, false);
|
||||
|
||||
// Dynamically import mod_b
|
||||
js_check(runtime.execute(
|
||||
|
@ -2190,12 +2181,8 @@ pub mod tests {
|
|||
run_in_task(|cx| {
|
||||
let loader = Rc::new(DynImportOkLoader::default());
|
||||
let prepare_load_count = loader.prepare_load_count.clone();
|
||||
let mut runtime = JsRuntime::new_with_loader(
|
||||
loader,
|
||||
BasicState::new(),
|
||||
StartupData::None,
|
||||
false,
|
||||
);
|
||||
let mut runtime =
|
||||
JsRuntime::new_with_loader(loader, StartupData::None, false);
|
||||
js_check(runtime.execute(
|
||||
"file:///dyn_import3.js",
|
||||
r#"
|
||||
|
@ -2246,12 +2233,8 @@ pub mod tests {
|
|||
}
|
||||
|
||||
let loader = std::rc::Rc::new(ModsLoader::default());
|
||||
let mut runtime = JsRuntime::new_with_loader(
|
||||
loader,
|
||||
BasicState::new(),
|
||||
StartupData::None,
|
||||
true,
|
||||
);
|
||||
let mut runtime =
|
||||
JsRuntime::new_with_loader(loader, StartupData::None, true);
|
||||
|
||||
let specifier = ModuleSpecifier::resolve_url("file:///main.js").unwrap();
|
||||
let source_code = "Deno.core.print('hello\\n')".to_string();
|
||||
|
|
|
@ -33,7 +33,6 @@ pub fn get_declaration() -> PathBuf {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use deno_core::js_check;
|
||||
use deno_core::BasicState;
|
||||
use deno_core::JsRuntime;
|
||||
use deno_core::StartupData;
|
||||
use futures::future::lazy;
|
||||
|
@ -49,8 +48,7 @@ mod tests {
|
|||
}
|
||||
|
||||
fn setup() -> JsRuntime {
|
||||
let mut isolate =
|
||||
JsRuntime::new(BasicState::new(), StartupData::None, false);
|
||||
let mut isolate = JsRuntime::new(StartupData::None, false);
|
||||
crate::init(&mut isolate);
|
||||
isolate
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue