0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 17:34:47 -05:00

Move JSON ops to deno_core (#7336)

This commit is contained in:
Bert Belder 2020-09-06 02:34:02 +02:00 committed by GitHub
parent 849431eb1d
commit c821e8f2f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
78 changed files with 1492 additions and 2204 deletions

1
Cargo.lock generated
View file

@ -453,6 +453,7 @@ version = "0.56.0"
dependencies = [ dependencies = [
"downcast-rs", "downcast-rs",
"futures", "futures",
"indexmap",
"lazy_static", "lazy_static",
"libc", "libc",
"log", "log",

View file

@ -45,7 +45,7 @@ futures = "0.3.5"
filetime = "0.2.12" filetime = "0.2.12"
http = "0.2.1" http = "0.2.1"
idna = "0.2.0" idna = "0.2.0"
indexmap = "1.5.1" indexmap = "1.5.2"
jsonc-parser = "0.14.0" jsonc-parser = "0.14.0"
lazy_static = "1.4.0" lazy_static = "1.4.0"
libc = "0.2.74" libc = "0.2.74"

View file

@ -11,12 +11,12 @@ use std::{
mod http; mod http;
mod throughput; mod throughput;
fn read_json(filename: &str) -> Result<serde_json::Value> { fn read_json(filename: &str) -> Result<Value> {
let f = fs::File::open(filename)?; let f = fs::File::open(filename)?;
Ok(serde_json::from_reader(f)?) Ok(serde_json::from_reader(f)?)
} }
fn write_json(filename: &str, value: &serde_json::Value) -> Result<()> { fn write_json(filename: &str, value: &Value) -> Result<()> {
let f = fs::File::create(filename)?; let f = fs::File::create(filename)?;
serde_json::to_writer(f, value)?; serde_json::to_writer(f, value)?;
Ok(()) Ok(())

View file

@ -1,8 +1,11 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
mod op_fetch_asset; mod op_fetch_asset;
use deno_core::js_check; use deno_core::js_check;
use deno_core::BasicState;
use deno_core::CoreIsolate; use deno_core::CoreIsolate;
use deno_core::OpRegistry;
use deno_core::StartupData; use deno_core::StartupData;
use std::collections::HashMap; use std::collections::HashMap;
use std::env; use std::env;
@ -28,8 +31,9 @@ fn create_snapshot(
} }
fn create_runtime_snapshot(snapshot_path: &Path, files: Vec<String>) { fn create_runtime_snapshot(snapshot_path: &Path, files: Vec<String>) {
let runtime_isolate = CoreIsolate::new(StartupData::None, true); let state = BasicState::new();
create_snapshot(runtime_isolate, snapshot_path, files); let isolate = CoreIsolate::new(state, StartupData::None, true);
create_snapshot(isolate, snapshot_path, files);
} }
fn create_compiler_snapshot( fn create_compiler_snapshot(
@ -37,7 +41,6 @@ fn create_compiler_snapshot(
files: Vec<String>, files: Vec<String>,
cwd: &Path, cwd: &Path,
) { ) {
let mut runtime_isolate = CoreIsolate::new(StartupData::None, true);
let mut custom_libs: HashMap<String, PathBuf> = HashMap::new(); let mut custom_libs: HashMap<String, PathBuf> = HashMap::new();
custom_libs custom_libs
.insert("lib.deno.web.d.ts".to_string(), deno_web::get_declaration()); .insert("lib.deno.web.d.ts".to_string(), deno_web::get_declaration());
@ -61,11 +64,15 @@ fn create_compiler_snapshot(
"lib.deno.unstable.d.ts".to_string(), "lib.deno.unstable.d.ts".to_string(),
cwd.join("dts/lib.deno.unstable.d.ts"), cwd.join("dts/lib.deno.unstable.d.ts"),
); );
runtime_isolate.register_op(
let state = BasicState::new();
state.register_op(
"op_fetch_asset", "op_fetch_asset",
op_fetch_asset::op_fetch_asset(custom_libs), op_fetch_asset::op_fetch_asset(custom_libs),
); );
create_snapshot(runtime_isolate, snapshot_path, files);
let isolate = CoreIsolate::new(state, StartupData::None, true);
create_snapshot(isolate, snapshot_path, files);
} }
fn ts_version() -> String { fn ts_version() -> String {

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use regex::Regex; use regex::Regex;
use std::env; use std::env;
use std::fmt; use std::fmt;

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::disk_cache::DiskCache; use crate::disk_cache::DiskCache;
use std::path::PathBuf; use std::path::PathBuf;

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::colors; use crate::colors;
use dissimilar::{diff as difference, Chunk}; use dissimilar::{diff as difference, Chunk};
use std::fmt; use std::fmt;

View file

@ -168,7 +168,7 @@ fn get_nix_error_class(error: &nix::Error) -> &'static str {
} }
} }
pub fn get_error_class(e: &ErrBox) -> &'static str { pub(crate) fn get_error_class_name(e: &ErrBox) -> &'static str {
use ErrBox::*; use ErrBox::*;
match e { match e {
Simple { class, .. } => Some(*class), Simple { class, .. } => Some(*class),

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::colors; use crate::colors;
use crate::http_cache::HttpCache; use crate::http_cache::HttpCache;
use crate::http_util; use crate::http_util;

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use clap::App; use clap::App;
use clap::AppSettings; use clap::AppSettings;
use clap::Arg; use clap::Arg;

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
pub use deno_core::normalize_path; pub use deno_core::normalize_path;
use deno_core::ErrBox; use deno_core::ErrBox;
use std::env::current_dir; use std::env::current_dir;

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::deno_dir; use crate::deno_dir;
use crate::file_fetcher::SourceFileFetcher; use crate::file_fetcher::SourceFileFetcher;
use crate::flags; use crate::flags;

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::version; use crate::version;
use bytes::Bytes; use bytes::Bytes;
use deno_core::ErrBox; use deno_core::ErrBox;

View file

@ -17,6 +17,7 @@ use futures::stream::FuturesUnordered;
use futures::task; use futures::task;
use futures::task::Context; use futures::task::Context;
use futures::task::Poll; use futures::task::Poll;
use serde_json::Value;
use std::cell::BorrowMutError; use std::cell::BorrowMutError;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
@ -95,7 +96,7 @@ struct InspectorInfo {
} }
impl InspectorInfo { impl InspectorInfo {
fn get_json_metadata(&self) -> serde_json::Value { fn get_json_metadata(&self) -> Value {
json!({ json!({
"description": "deno", "description": "deno",
"devtoolsFrontendUrl": self.get_frontend_url(), "devtoolsFrontendUrl": self.get_frontend_url(),

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::flags::Flags; use crate::flags::Flags;
use crate::global_state::GlobalState; use crate::global_state::GlobalState;
use deno_core::ErrBox; use deno_core::ErrBox;

View file

@ -14,6 +14,7 @@ pub static UNSTABLE_NS_LIB: &str = include_str!("dts/lib.deno.unstable.d.ts");
#[test] #[test]
fn cli_snapshot() { fn cli_snapshot() {
let mut isolate = deno_core::CoreIsolate::new( let mut isolate = deno_core::CoreIsolate::new(
deno_core::BasicState::new(),
deno_core::StartupData::Snapshot(deno_core::Snapshot::Static(CLI_SNAPSHOT)), deno_core::StartupData::Snapshot(deno_core::Snapshot::Static(CLI_SNAPSHOT)),
false, false,
); );
@ -31,6 +32,7 @@ fn cli_snapshot() {
#[test] #[test]
fn compiler_snapshot() { fn compiler_snapshot() {
let mut isolate = deno_core::CoreIsolate::new( let mut isolate = deno_core::CoreIsolate::new(
deno_core::BasicState::new(),
deno_core::StartupData::Snapshot(deno_core::Snapshot::Static( deno_core::StartupData::Snapshot(deno_core::Snapshot::Static(
COMPILER_SNAPSHOT, COMPILER_SNAPSHOT,
)), )),

View file

@ -1,5 +1,4 @@
use serde_json::json; use serde_json::json;
pub use serde_json::Value;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::io::Result; use std::io::Result;

View file

@ -1,5 +1,4 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
#![deny(warnings)]
extern crate dissimilar; extern crate dissimilar;
#[macro_use] #[macro_use]

View file

@ -16,22 +16,26 @@ pub struct Metrics {
} }
impl Metrics { impl Metrics {
fn op_dispatched(&mut self, bytes_sent_control: u64, bytes_sent_data: u64) { fn op_dispatched(
&mut self,
bytes_sent_control: usize,
bytes_sent_data: usize,
) {
self.ops_dispatched += 1; self.ops_dispatched += 1;
self.bytes_sent_control += bytes_sent_control; self.bytes_sent_control += bytes_sent_control as u64;
self.bytes_sent_data += bytes_sent_data; self.bytes_sent_data += bytes_sent_data as u64;
} }
fn op_completed(&mut self, bytes_received: u64) { fn op_completed(&mut self, bytes_received: usize) {
self.ops_completed += 1; self.ops_completed += 1;
self.bytes_received += bytes_received; self.bytes_received += bytes_received as u64;
} }
pub fn op_sync( pub fn op_sync(
&mut self, &mut self,
bytes_sent_control: u64, bytes_sent_control: usize,
bytes_sent_data: u64, bytes_sent_data: usize,
bytes_received: u64, bytes_received: usize,
) { ) {
self.ops_dispatched_sync += 1; self.ops_dispatched_sync += 1;
self.op_dispatched(bytes_sent_control, bytes_sent_data); self.op_dispatched(bytes_sent_control, bytes_sent_data);
@ -41,8 +45,8 @@ impl Metrics {
pub fn op_dispatched_async( pub fn op_dispatched_async(
&mut self, &mut self,
bytes_sent_control: u64, bytes_sent_control: usize,
bytes_sent_data: u64, bytes_sent_data: usize,
) { ) {
self.ops_dispatched_async += 1; self.ops_dispatched_async += 1;
self.op_dispatched(bytes_sent_control, bytes_sent_data) self.op_dispatched(bytes_sent_control, bytes_sent_data)
@ -50,19 +54,19 @@ impl Metrics {
pub fn op_dispatched_async_unref( pub fn op_dispatched_async_unref(
&mut self, &mut self,
bytes_sent_control: u64, bytes_sent_control: usize,
bytes_sent_data: u64, bytes_sent_data: usize,
) { ) {
self.ops_dispatched_async_unref += 1; self.ops_dispatched_async_unref += 1;
self.op_dispatched(bytes_sent_control, bytes_sent_data) self.op_dispatched(bytes_sent_control, bytes_sent_data)
} }
pub fn op_completed_async(&mut self, bytes_received: u64) { pub fn op_completed_async(&mut self, bytes_received: usize) {
self.ops_completed_async += 1; self.ops_completed_async += 1;
self.op_completed(bytes_received); self.op_completed(bytes_received);
} }
pub fn op_completed_async_unref(&mut self, bytes_received: u64) { pub fn op_completed_async_unref(&mut self, bytes_received: usize) {
self.ops_completed_async_unref += 1; self.ops_completed_async_unref += 1;
self.op_completed(bytes_received); self.op_completed(bytes_received);
} }

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::checksum; use crate::checksum;
use crate::file_fetcher::map_file_extension; use crate::file_fetcher::map_file_extension;
use crate::file_fetcher::SourceFile; use crate::file_fetcher::SourceFile;

View file

@ -2,11 +2,11 @@
// Note: this module is used both in build.rs and main.rs. // Note: this module is used both in build.rs and main.rs.
pub use deno_core::v8_set_flags; pub use deno_core::v8_set_flags;
use deno_core::CoreIsolateState; use deno_core::BufVec;
use deno_core::Op; use deno_core::Op;
use deno_core::ZeroCopyBuf;
use std::collections::HashMap; use std::collections::HashMap;
use std::path::PathBuf; use std::path::PathBuf;
use std::rc::Rc;
fn get_asset(name: &str) -> Option<&'static str> { fn get_asset(name: &str) -> Option<&'static str> {
macro_rules! inc { macro_rules! inc {
@ -82,17 +82,15 @@ fn get_asset(name: &str) -> Option<&'static str> {
/// Warning: Returns a non-JSON op dispatcher. Must be manually attached to /// Warning: Returns a non-JSON op dispatcher. Must be manually attached to
/// CoreIsolate. /// CoreIsolate.
pub fn op_fetch_asset<S: ::std::hash::BuildHasher>( pub fn op_fetch_asset<H: std::hash::BuildHasher, S>(
custom_assets: HashMap<String, PathBuf, S>, custom_assets: HashMap<String, PathBuf, H>,
) -> impl Fn(&mut deno_core::CoreIsolateState, &mut [ZeroCopyBuf]) -> Op { ) -> impl Fn(Rc<S>, BufVec) -> Op {
for (_, path) in custom_assets.iter() { for (_, path) in custom_assets.iter() {
println!("cargo:rerun-if-changed={}", path.display()); println!("cargo:rerun-if-changed={}", path.display());
} }
move |_state: &mut CoreIsolateState, move |_state: Rc<S>, bufs: BufVec| -> Op {
zero_copy_bufs: &mut [ZeroCopyBuf]| assert_eq!(bufs.len(), 1, "Invalid number of arguments");
-> Op { let name = std::str::from_utf8(&bufs[0]).unwrap();
assert_eq!(zero_copy_bufs.len(), 1, "Invalid number of arguments");
let name = std::str::from_utf8(&zero_copy_bufs[0]).unwrap();
let asset_code = if let Some(source_code) = get_asset(name) { let asset_code = if let Some(source_code) = get_asset(name) {
source_code.to_string() source_code.to_string()

View file

@ -1,67 +1,27 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::{JsonOp, Value};
use crate::ops::json_op;
use crate::state::State; use crate::state::State;
use deno_core::CoreIsolate; use deno_core::OpRegistry;
use deno_core::CoreIsolateState;
use deno_core::ErrBox;
use deno_core::ZeroCopyBuf;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex; use std::sync::Mutex;
pub fn init( pub fn init(s: &Rc<State>, response: Arc<Mutex<Option<String>>>) {
i: &mut CoreIsolate,
_s: &Rc<State>,
response: Arc<Mutex<Option<String>>>,
) {
let custom_assets = std::collections::HashMap::new(); let custom_assets = std::collections::HashMap::new();
// TODO(ry) use None. // TODO(ry) use None.
// TODO(bartlomieju): is this op even required? // TODO(bartlomieju): is this op even required?
i.register_op( s.register_op(
"op_fetch_asset", "op_fetch_asset",
crate::op_fetch_asset::op_fetch_asset(custom_assets), crate::op_fetch_asset::op_fetch_asset(custom_assets),
); );
i.register_op( s.register_op_json_sync("op_compiler_respond", move |_state, args, _bufs| {
"op_compiler_respond", let mut response_slot = response.lock().unwrap();
json_op(compiler_op(response, op_compiler_respond)), let replaced_value = response_slot.replace(args.to_string());
); assert!(
} replaced_value.is_none(),
"op_compiler_respond found unexpected existing compiler output",
pub fn compiler_op<D>( );
response: Arc<Mutex<Option<String>>>, Ok(json!({}))
dispatcher: D, });
) -> impl Fn(
&mut deno_core::CoreIsolateState,
Value,
&mut [ZeroCopyBuf],
) -> Result<JsonOp, ErrBox>
where
D: Fn(
Arc<Mutex<Option<String>>>,
Value,
&mut [ZeroCopyBuf],
) -> Result<JsonOp, ErrBox>,
{
move |_isolate_state: &mut CoreIsolateState,
args: Value,
zero_copy: &mut [ZeroCopyBuf]|
-> Result<JsonOp, ErrBox> {
dispatcher(response.clone(), args, zero_copy)
}
}
fn op_compiler_respond(
response: Arc<Mutex<Option<String>>>,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<JsonOp, ErrBox> {
let mut r = response.lock().unwrap();
assert!(
r.is_none(),
"op_compiler_respond found unexpected existing compiler output"
);
*r = Some(args.to_string());
Ok(JsonOp::Sync(json!({})))
} }

View file

@ -1,121 +0,0 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use deno_core::Buf;
use deno_core::CoreIsolateState;
use deno_core::ErrBox;
use deno_core::Op;
use deno_core::ZeroCopyBuf;
use futures::future::FutureExt;
pub use serde_derive::Deserialize;
use serde_json::json;
pub use serde_json::Value;
use std::future::Future;
use std::pin::Pin;
pub type JsonResult = Result<Value, ErrBox>;
pub type AsyncJsonOp = Pin<Box<dyn Future<Output = JsonResult>>>;
pub enum JsonOp {
Sync(Value),
Async(AsyncJsonOp),
/// AsyncUnref is the variation of Async, which doesn't block the program
/// exiting.
AsyncUnref(AsyncJsonOp),
}
pub fn serialize_result(
promise_id: Option<u64>,
result: JsonResult,
get_error_class_fn: deno_core::GetErrorClassFn,
) -> Buf {
let value = match result {
Ok(v) => json!({ "ok": v, "promiseId": promise_id }),
Err(err) => json!({
"err": {
"className": (get_error_class_fn)(&err),
"message": err.to_string()
},
"promiseId": promise_id
}),
};
serde_json::to_vec(&value).unwrap().into_boxed_slice()
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct AsyncArgs {
promise_id: Option<u64>,
}
pub fn json_op<D>(
d: D,
) -> impl Fn(&mut CoreIsolateState, &mut [ZeroCopyBuf]) -> Op
where
D: Fn(
&mut CoreIsolateState,
Value,
&mut [ZeroCopyBuf],
) -> Result<JsonOp, ErrBox>,
{
move |isolate_state: &mut CoreIsolateState, zero_copy: &mut [ZeroCopyBuf]| {
let get_error_class_fn = isolate_state.get_error_class_fn;
assert!(!zero_copy.is_empty(), "Expected JSON string at position 0");
let async_args: AsyncArgs = match serde_json::from_slice(&zero_copy[0]) {
Ok(args) => args,
Err(e) => {
let buf = serialize_result(None, Err(e.into()), get_error_class_fn);
return Op::Sync(buf);
}
};
let promise_id = async_args.promise_id;
let is_sync = promise_id.is_none();
let result = serde_json::from_slice(&zero_copy[0])
.map_err(ErrBox::from)
.and_then(|args| d(isolate_state, args, &mut zero_copy[1..]));
// Convert to Op
match result {
Ok(JsonOp::Sync(sync_value)) => {
assert!(promise_id.is_none());
Op::Sync(serialize_result(
promise_id,
Ok(sync_value),
get_error_class_fn,
))
}
Ok(JsonOp::Async(fut)) => {
assert!(promise_id.is_some());
let fut2 = fut.then(move |result| {
futures::future::ready(serialize_result(
promise_id,
result,
get_error_class_fn,
))
});
Op::Async(fut2.boxed_local())
}
Ok(JsonOp::AsyncUnref(fut)) => {
assert!(promise_id.is_some());
let fut2 = fut.then(move |result| {
futures::future::ready(serialize_result(
promise_id,
result,
get_error_class_fn,
))
});
Op::AsyncUnref(fut2.boxed_local())
}
Err(sync_err) => {
let buf =
serialize_result(promise_id, Err(sync_err), get_error_class_fn);
if is_sync {
Op::Sync(buf)
} else {
Op::Async(futures::future::ready(buf).boxed_local())
}
}
}
}
}

View file

@ -1,20 +1,17 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
// Do not add flatbuffer dependencies to this module.
//! Connects to js/dispatch_minimal.ts sendAsyncMinimal This acts as a faster use crate::state::State;
//! alternative to flatbuffers using a very simple list of int32s to lay out use deno_core::BufVec;
//! messages. The first i32 is used to determine if a message a flatbuffer
//! message or a "minimal" message.
use crate::errors::get_error_class;
use deno_core::Buf;
use deno_core::CoreIsolateState;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::Op; use deno_core::Op;
use deno_core::ZeroCopyBuf; use deno_core::OpId;
use deno_core::OpRegistry;
use futures::future::FutureExt; use futures::future::FutureExt;
use std::future::Future; use std::future::Future;
use std::iter::repeat; use std::iter::repeat;
use std::mem::size_of_val; use std::mem::size_of_val;
use std::pin::Pin; use std::pin::Pin;
use std::rc::Rc;
use std::slice; use std::slice;
pub enum MinimalOp { pub enum MinimalOp {
@ -30,8 +27,8 @@ pub struct Record {
pub result: i32, pub result: i32,
} }
impl Into<Buf> for Record { impl Into<Box<[u8]>> for Record {
fn into(self) -> Buf { fn into(self) -> Box<[u8]> {
let vec = vec![self.promise_id, self.arg, self.result]; let vec = vec![self.promise_id, self.arg, self.result];
let buf32 = vec.into_boxed_slice(); let buf32 = vec.into_boxed_slice();
let ptr = Box::into_raw(buf32) as *mut [u8; 3 * 4]; let ptr = Box::into_raw(buf32) as *mut [u8; 3 * 4];
@ -47,8 +44,8 @@ pub struct ErrorRecord {
pub error_message: Vec<u8>, pub error_message: Vec<u8>,
} }
impl Into<Buf> for ErrorRecord { impl Into<Box<[u8]>> for ErrorRecord {
fn into(self) -> Buf { fn into(self) -> Box<[u8]> {
let Self { let Self {
promise_id, promise_id,
arg, arg,
@ -91,7 +88,7 @@ fn test_error_record() {
error_class: b"BadResource", error_class: b"BadResource",
error_message: b"Error".to_vec(), error_message: b"Error".to_vec(),
}; };
let buf: Buf = err_record.into(); let buf: Box<[u8]> = err_record.into();
assert_eq!(buf, expected.into_boxed_slice()); assert_eq!(buf, expected.into_boxed_slice());
} }
@ -124,7 +121,7 @@ fn test_parse_min_record() {
Some(Record { Some(Record {
promise_id: 1, promise_id: 1,
arg: 3, arg: 3,
result: 4, result: 4
}) })
); );
@ -135,73 +132,78 @@ fn test_parse_min_record() {
assert_eq!(parse_min_record(&buf), None); assert_eq!(parse_min_record(&buf), None);
} }
pub fn minimal_op<D>( impl State {
d: D, pub fn register_op_minimal<F>(self: &Rc<Self>, name: &str, op_fn: F) -> OpId
) -> impl Fn(&mut CoreIsolateState, &mut [ZeroCopyBuf]) -> Op where
where F: Fn(Rc<Self>, bool, i32, BufVec) -> MinimalOp + 'static,
D: Fn(&mut CoreIsolateState, bool, i32, &mut [ZeroCopyBuf]) -> MinimalOp, {
{ let base_op_fn = move |state: Rc<Self>, bufs: BufVec| {
move |isolate_state: &mut CoreIsolateState, zero_copy: &mut [ZeroCopyBuf]| { let mut bufs_iter = bufs.into_iter();
assert!(!zero_copy.is_empty(), "Expected record at position 0"); let record_buf = bufs_iter.next().expect("Expected record at position 0");
let mut record = match parse_min_record(&zero_copy[0]) { let zero_copy = bufs_iter.collect::<BufVec>();
Some(r) => r,
None => {
let error = ErrBox::type_error("Unparsable control buffer");
let error_class = get_error_class(&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 = d(isolate_state, is_sync, rid, &mut zero_copy[1..]);
match min_op { let mut record = match parse_min_record(&record_buf) {
MinimalOp::Sync(sync_result) => Op::Sync(match sync_result { Some(r) => r,
Ok(r) => { None => {
record.result = r; let error = ErrBox::type_error("Unparsable control buffer");
record.into() let error_class = state.get_error_class_name(&error);
}
Err(err) => {
let error_class = get_error_class(&err);
let error_record = ErrorRecord { let error_record = ErrorRecord {
promise_id: record.promise_id, promise_id: 0,
arg: -1, arg: -1,
error_len: error_class.len() as i32, error_len: error_class.len() as i32,
error_class: error_class.as_bytes(), error_class: error_class.as_bytes(),
error_message: err.to_string().as_bytes().to_owned(), error_message: error.to_string().as_bytes().to_owned(),
}; };
error_record.into() return Op::Sync(error_record.into());
} }
}), };
MinimalOp::Async(min_fut) => { let is_sync = record.promise_id == 0;
let fut = async move { let rid = record.arg;
match min_fut.await { let min_op = op_fn(state.clone(), is_sync, rid, zero_copy);
Ok(r) => {
record.result = r; match min_op {
record.into() MinimalOp::Sync(sync_result) => Op::Sync(match sync_result {
} Ok(r) => {
Err(err) => { record.result = r;
let error_class = get_error_class(&err); record.into()
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()
}
} }
}; Err(err) => {
Op::Async(fut.boxed_local()) 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()
}
}
};
Op::Async(fut.boxed_local())
}
} }
} };
self.register_op(name, base_op_fn)
} }
} }

View file

@ -1,27 +1,20 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::{Deserialize, Value};
use crate::diagnostics::Diagnostic; use crate::diagnostics::Diagnostic;
use crate::source_maps::get_orig_position; use crate::source_maps::get_orig_position;
use crate::source_maps::CachedMaps; use crate::source_maps::CachedMaps;
use crate::state::State; use crate::state::State;
use deno_core::CoreIsolate;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ResourceTable; use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use serde_derive::Deserialize;
use serde_json::Value;
use std::collections::HashMap; use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { pub fn init(s: &Rc<State>) {
let t = &CoreIsolate::state(i).borrow().resource_table.clone(); s.register_op_json_sync("op_apply_source_map", op_apply_source_map);
s.register_op_json_sync("op_format_diagnostic", op_format_diagnostic);
i.register_op(
"op_apply_source_map",
s.stateful_json_op_sync(t, op_apply_source_map),
);
i.register_op(
"op_format_diagnostic",
s.stateful_json_op_sync(t, op_format_diagnostic),
);
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -34,7 +27,6 @@ struct ApplySourceMap {
fn op_apply_source_map( fn op_apply_source_map(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -59,7 +51,6 @@ fn op_apply_source_map(
fn op_format_diagnostic( fn op_format_diagnostic(
_state: &State, _state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {

View file

@ -1,30 +1,25 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::{Deserialize, Value};
use super::io::{StreamResource, StreamResourceHolder}; use super::io::{StreamResource, StreamResourceHolder};
use crate::http_util::{create_http_client, HttpBody}; use crate::http_util::{create_http_client, HttpBody};
use crate::state::State; use crate::state::State;
use deno_core::BufVec; use deno_core::BufVec;
use deno_core::CoreIsolate;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ResourceTable; use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use http::header::HeaderName; use http::header::HeaderName;
use http::header::HeaderValue; use http::header::HeaderValue;
use http::Method; use http::Method;
use reqwest::Client; use reqwest::Client;
use std::cell::RefCell; use serde_derive::Deserialize;
use serde_json::Value;
use std::convert::From; use std::convert::From;
use std::path::PathBuf; use std::path::PathBuf;
use std::rc::Rc; use std::rc::Rc;
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { pub fn init(s: &Rc<State>) {
let t = &CoreIsolate::state(i).borrow().resource_table.clone(); s.register_op_json_async("op_fetch", op_fetch);
s.register_op_json_sync("op_create_http_client", op_create_http_client);
i.register_op("op_fetch", s.stateful_json_op_async(t, op_fetch));
i.register_op(
"op_create_http_client",
s.stateful_json_op_sync(t, op_create_http_client),
);
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -38,16 +33,14 @@ struct FetchArgs {
async fn op_fetch( async fn op_fetch(
state: Rc<State>, state: Rc<State>,
resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
data: BufVec, data: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
let args: FetchArgs = serde_json::from_value(args)?; let args: FetchArgs = serde_json::from_value(args)?;
let url = args.url; let url = args.url;
let resource_table2 = resource_table.clone();
let client = if let Some(rid) = args.client_rid { let client = if let Some(rid) = args.client_rid {
let resource_table_ = resource_table.borrow(); let resource_table_ = state.resource_table.borrow();
let r = resource_table_ let r = resource_table_
.get::<HttpClientResource>(rid) .get::<HttpClientResource>(rid)
.ok_or_else(ErrBox::bad_resource_id)?; .ok_or_else(ErrBox::bad_resource_id)?;
@ -100,8 +93,7 @@ async fn op_fetch(
} }
let body = HttpBody::from(res); let body = HttpBody::from(res);
let mut resource_table = resource_table2.borrow_mut(); let rid = state.resource_table.borrow_mut().add(
let rid = resource_table.add(
"httpBody", "httpBody",
Box::new(StreamResourceHolder::new(StreamResource::HttpBody( Box::new(StreamResourceHolder::new(StreamResource::HttpBody(
Box::new(body), Box::new(body),
@ -137,7 +129,6 @@ struct CreateHttpClientOptions {
fn op_create_http_client( fn op_create_http_client(
state: &State, state: &State,
resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -149,7 +140,9 @@ fn op_create_http_client(
let client = create_http_client(args.ca_file.as_deref()).unwrap(); let client = create_http_client(args.ca_file.as_deref()).unwrap();
let rid = let rid = state
resource_table.add("httpClient", Box::new(HttpClientResource::new(client))); .resource_table
.borrow_mut()
.add("httpClient", Box::new(HttpClientResource::new(client)));
Ok(json!(rid)) Ok(json!(rid))
} }

View file

@ -1,16 +1,16 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
// Some deserializer fields are only used on Unix and Windows build fails without it // Some deserializer fields are only used on Unix and Windows build fails without it
use super::dispatch_json::{Deserialize, Value};
use super::io::std_file_resource; use super::io::std_file_resource;
use super::io::{FileMetadata, StreamResource, StreamResourceHolder}; use super::io::{FileMetadata, StreamResource, StreamResourceHolder};
use crate::ops::dispatch_json::JsonResult;
use crate::state::State; use crate::state::State;
use deno_core::BufVec; use deno_core::BufVec;
use deno_core::CoreIsolate;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ResourceTable; use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use std::cell::RefCell; use rand::thread_rng;
use rand::Rng;
use serde_derive::Deserialize;
use serde_json::Value;
use std::convert::From; use std::convert::From;
use std::env::{current_dir, set_current_dir, temp_dir}; use std::env::{current_dir, set_current_dir, temp_dir};
use std::io; use std::io;
@ -20,171 +20,80 @@ use std::rc::Rc;
use std::time::SystemTime; use std::time::SystemTime;
use std::time::UNIX_EPOCH; use std::time::UNIX_EPOCH;
use rand::{thread_rng, Rng}; pub fn init(s: &Rc<State>) {
s.register_op_json_sync("op_open_sync", op_open_sync);
s.register_op_json_async("op_open_async", op_open_async);
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { s.register_op_json_sync("op_seek_sync", op_seek_sync);
let t = &CoreIsolate::state(i).borrow().resource_table.clone(); s.register_op_json_async("op_seek_async", op_seek_async);
i.register_op("op_open_sync", s.stateful_json_op_sync(t, op_open_sync)); s.register_op_json_sync("op_fdatasync_sync", op_fdatasync_sync);
i.register_op("op_open_async", s.stateful_json_op_async(t, op_open_async)); s.register_op_json_async("op_fdatasync_async", op_fdatasync_async);
i.register_op("op_seek_sync", s.stateful_json_op_sync(t, op_seek_sync)); s.register_op_json_sync("op_fsync_sync", op_fsync_sync);
i.register_op("op_seek_async", s.stateful_json_op_async(t, op_seek_async)); s.register_op_json_async("op_fsync_async", op_fsync_async);
i.register_op( s.register_op_json_sync("op_fstat_sync", op_fstat_sync);
"op_fdatasync_sync", s.register_op_json_async("op_fstat_async", op_fstat_async);
s.stateful_json_op_sync(t, op_fdatasync_sync),
);
i.register_op(
"op_fdatasync_async",
s.stateful_json_op_async(t, op_fdatasync_async),
);
i.register_op("op_fsync_sync", s.stateful_json_op_sync(t, op_fsync_sync)); s.register_op_json_sync("op_umask", op_umask);
i.register_op( s.register_op_json_sync("op_chdir", op_chdir);
"op_fsync_async",
s.stateful_json_op_async(t, op_fsync_async),
);
i.register_op("op_fstat_sync", s.stateful_json_op_sync(t, op_fstat_sync)); s.register_op_json_sync("op_mkdir_sync", op_mkdir_sync);
i.register_op( s.register_op_json_async("op_mkdir_async", op_mkdir_async);
"op_fstat_async",
s.stateful_json_op_async(t, op_fstat_async),
);
i.register_op("op_umask", s.stateful_json_op_sync(t, op_umask)); s.register_op_json_sync("op_chmod_sync", op_chmod_sync);
i.register_op("op_chdir", s.stateful_json_op_sync(t, op_chdir)); s.register_op_json_async("op_chmod_async", op_chmod_async);
i.register_op("op_mkdir_sync", s.stateful_json_op_sync(t, op_mkdir_sync)); s.register_op_json_sync("op_chown_sync", op_chown_sync);
i.register_op( s.register_op_json_async("op_chown_async", op_chown_async);
"op_mkdir_async",
s.stateful_json_op_async(t, op_mkdir_async),
);
i.register_op("op_chmod_sync", s.stateful_json_op_sync(t, op_chmod_sync)); s.register_op_json_sync("op_remove_sync", op_remove_sync);
i.register_op( s.register_op_json_async("op_remove_async", op_remove_async);
"op_chmod_async",
s.stateful_json_op_async(t, op_chmod_async),
);
i.register_op("op_chown_sync", s.stateful_json_op_sync(t, op_chown_sync)); s.register_op_json_sync("op_copy_file_sync", op_copy_file_sync);
i.register_op( s.register_op_json_async("op_copy_file_async", op_copy_file_async);
"op_chown_async",
s.stateful_json_op_async(t, op_chown_async),
);
i.register_op("op_remove_sync", s.stateful_json_op_sync(t, op_remove_sync)); s.register_op_json_sync("op_stat_sync", op_stat_sync);
i.register_op( s.register_op_json_async("op_stat_async", op_stat_async);
"op_remove_async",
s.stateful_json_op_async(t, op_remove_async),
);
i.register_op( s.register_op_json_sync("op_realpath_sync", op_realpath_sync);
"op_copy_file_sync", s.register_op_json_async("op_realpath_async", op_realpath_async);
s.stateful_json_op_sync(t, op_copy_file_sync),
);
i.register_op(
"op_copy_file_async",
s.stateful_json_op_async(t, op_copy_file_async),
);
i.register_op("op_stat_sync", s.stateful_json_op_sync(t, op_stat_sync)); s.register_op_json_sync("op_read_dir_sync", op_read_dir_sync);
i.register_op("op_stat_async", s.stateful_json_op_async(t, op_stat_async)); s.register_op_json_async("op_read_dir_async", op_read_dir_async);
i.register_op( s.register_op_json_sync("op_rename_sync", op_rename_sync);
"op_realpath_sync", s.register_op_json_async("op_rename_async", op_rename_async);
s.stateful_json_op_sync(t, op_realpath_sync),
);
i.register_op(
"op_realpath_async",
s.stateful_json_op_async(t, op_realpath_async),
);
i.register_op( s.register_op_json_sync("op_link_sync", op_link_sync);
"op_read_dir_sync", s.register_op_json_async("op_link_async", op_link_async);
s.stateful_json_op_sync(t, op_read_dir_sync),
);
i.register_op(
"op_read_dir_async",
s.stateful_json_op_async(t, op_read_dir_async),
);
i.register_op("op_rename_sync", s.stateful_json_op_sync(t, op_rename_sync)); s.register_op_json_sync("op_symlink_sync", op_symlink_sync);
i.register_op( s.register_op_json_async("op_symlink_async", op_symlink_async);
"op_rename_async",
s.stateful_json_op_async(t, op_rename_async),
);
i.register_op("op_link_sync", s.stateful_json_op_sync(t, op_link_sync)); s.register_op_json_sync("op_read_link_sync", op_read_link_sync);
i.register_op("op_link_async", s.stateful_json_op_async(t, op_link_async)); s.register_op_json_async("op_read_link_async", op_read_link_async);
i.register_op( s.register_op_json_sync("op_ftruncate_sync", op_ftruncate_sync);
"op_symlink_sync", s.register_op_json_async("op_ftruncate_async", op_ftruncate_async);
s.stateful_json_op_sync(t, op_symlink_sync),
);
i.register_op(
"op_symlink_async",
s.stateful_json_op_async(t, op_symlink_async),
);
i.register_op( s.register_op_json_sync("op_truncate_sync", op_truncate_sync);
"op_read_link_sync", s.register_op_json_async("op_truncate_async", op_truncate_async);
s.stateful_json_op_sync(t, op_read_link_sync),
);
i.register_op(
"op_read_link_async",
s.stateful_json_op_async(t, op_read_link_async),
);
i.register_op( s.register_op_json_sync("op_make_temp_dir_sync", op_make_temp_dir_sync);
"op_ftruncate_sync", s.register_op_json_async("op_make_temp_dir_async", op_make_temp_dir_async);
s.stateful_json_op_sync(t, op_ftruncate_sync),
);
i.register_op(
"op_ftruncate_async",
s.stateful_json_op_async(t, op_ftruncate_async),
);
i.register_op( s.register_op_json_sync("op_make_temp_file_sync", op_make_temp_file_sync);
"op_truncate_sync", s.register_op_json_async("op_make_temp_file_async", op_make_temp_file_async);
s.stateful_json_op_sync(t, op_truncate_sync),
);
i.register_op(
"op_truncate_async",
s.stateful_json_op_async(t, op_truncate_async),
);
i.register_op( s.register_op_json_sync("op_cwd", op_cwd);
"op_make_temp_dir_sync",
s.stateful_json_op_sync(t, op_make_temp_dir_sync),
);
i.register_op(
"op_make_temp_dir_async",
s.stateful_json_op_async(t, op_make_temp_dir_async),
);
i.register_op( s.register_op_json_sync("op_futime_sync", op_futime_sync);
"op_make_temp_file_sync", s.register_op_json_async("op_futime_async", op_futime_async);
s.stateful_json_op_sync(t, op_make_temp_file_sync),
);
i.register_op(
"op_make_temp_file_async",
s.stateful_json_op_async(t, op_make_temp_file_async),
);
i.register_op("op_cwd", s.stateful_json_op_sync(t, op_cwd)); s.register_op_json_sync("op_utime_sync", op_utime_sync);
s.register_op_json_async("op_utime_async", op_utime_async);
i.register_op("op_futime_sync", s.stateful_json_op_sync(t, op_futime_sync));
i.register_op(
"op_futime_async",
s.stateful_json_op_async(t, op_futime_async),
);
i.register_op("op_utime_sync", s.stateful_json_op_sync(t, op_utime_sync));
i.register_op(
"op_utime_async",
s.stateful_json_op_async(t, op_utime_async),
);
} }
fn into_string(s: std::ffi::OsString) -> Result<String, ErrBox> { fn into_string(s: std::ffi::OsString) -> Result<String, ErrBox> {
@ -257,14 +166,13 @@ fn open_helper(
fn op_open_sync( fn op_open_sync(
state: &State, state: &State,
resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
let (path, open_options) = open_helper(state, args)?; let (path, open_options) = open_helper(state, args)?;
let std_file = open_options.open(path)?; let std_file = open_options.open(path)?;
let tokio_file = tokio::fs::File::from_std(std_file); let tokio_file = tokio::fs::File::from_std(std_file);
let rid = resource_table.add( let rid = state.resource_table.borrow_mut().add(
"fsFile", "fsFile",
Box::new(StreamResourceHolder::new(StreamResource::FsFile(Some(( Box::new(StreamResourceHolder::new(StreamResource::FsFile(Some((
tokio_file, tokio_file,
@ -276,7 +184,6 @@ fn op_open_sync(
async fn op_open_async( async fn op_open_async(
state: Rc<State>, state: Rc<State>,
resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -284,7 +191,7 @@ async fn op_open_async(
let tokio_file = tokio::fs::OpenOptions::from(open_options) let tokio_file = tokio::fs::OpenOptions::from(open_options)
.open(path) .open(path)
.await?; .await?;
let rid = resource_table.borrow_mut().add( let rid = state.resource_table.borrow_mut().add(
"fsFile", "fsFile",
Box::new(StreamResourceHolder::new(StreamResource::FsFile(Some(( Box::new(StreamResourceHolder::new(StreamResource::FsFile(Some((
tokio_file, tokio_file,
@ -321,13 +228,12 @@ fn seek_helper(args: Value) -> Result<(u32, SeekFrom), ErrBox> {
} }
fn op_seek_sync( fn op_seek_sync(
_state: &State, state: &State,
resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
let (rid, seek_from) = seek_helper(args)?; let (rid, seek_from) = seek_helper(args)?;
let pos = std_file_resource(resource_table, rid, |r| match r { let pos = std_file_resource(state, rid, |r| match r {
Ok(std_file) => std_file.seek(seek_from).map_err(ErrBox::from), Ok(std_file) => std_file.seek(seek_from).map_err(ErrBox::from),
Err(_) => Err(ErrBox::type_error( Err(_) => Err(ErrBox::type_error(
"cannot seek on this type of resource".to_string(), "cannot seek on this type of resource".to_string(),
@ -337,16 +243,14 @@ fn op_seek_sync(
} }
async fn op_seek_async( async fn op_seek_async(
_state: Rc<State>, state: Rc<State>,
resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
let (rid, seek_from) = seek_helper(args)?; let (rid, seek_from) = seek_helper(args)?;
// TODO(ry) This is a fake async op. We need to use poll_fn, // TODO(ry) This is a fake async op. We need to use poll_fn,
// tokio::fs::File::start_seek and tokio::fs::File::poll_complete // tokio::fs::File::start_seek and tokio::fs::File::poll_complete
let mut resource_table = resource_table.borrow_mut(); let pos = std_file_resource(&state, rid, |r| match r {
let pos = std_file_resource(&mut resource_table, rid, |r| match r {
Ok(std_file) => std_file.seek(seek_from).map_err(ErrBox::from), Ok(std_file) => std_file.seek(seek_from).map_err(ErrBox::from),
Err(_) => Err(ErrBox::type_error( Err(_) => Err(ErrBox::type_error(
"cannot seek on this type of resource".to_string(), "cannot seek on this type of resource".to_string(),
@ -363,14 +267,13 @@ struct FdatasyncArgs {
fn op_fdatasync_sync( fn op_fdatasync_sync(
state: &State, state: &State,
resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
state.check_unstable("Deno.fdatasync"); state.check_unstable("Deno.fdatasync");
let args: FdatasyncArgs = serde_json::from_value(args)?; let args: FdatasyncArgs = serde_json::from_value(args)?;
let rid = args.rid as u32; let rid = args.rid as u32;
std_file_resource(resource_table, rid, |r| match r { std_file_resource(state, rid, |r| match r {
Ok(std_file) => std_file.sync_data().map_err(ErrBox::from), Ok(std_file) => std_file.sync_data().map_err(ErrBox::from),
Err(_) => Err(ErrBox::type_error( Err(_) => Err(ErrBox::type_error(
"cannot sync this type of resource".to_string(), "cannot sync this type of resource".to_string(),
@ -381,15 +284,13 @@ fn op_fdatasync_sync(
async fn op_fdatasync_async( async fn op_fdatasync_async(
state: Rc<State>, state: Rc<State>,
resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
state.check_unstable("Deno.fdatasync"); state.check_unstable("Deno.fdatasync");
let args: FdatasyncArgs = serde_json::from_value(args)?; let args: FdatasyncArgs = serde_json::from_value(args)?;
let rid = args.rid as u32; let rid = args.rid as u32;
let mut resource_table = resource_table.borrow_mut(); std_file_resource(&state, rid, |r| match r {
std_file_resource(&mut resource_table, rid, |r| match r {
Ok(std_file) => std_file.sync_data().map_err(ErrBox::from), Ok(std_file) => std_file.sync_data().map_err(ErrBox::from),
Err(_) => Err(ErrBox::type_error( Err(_) => Err(ErrBox::type_error(
"cannot sync this type of resource".to_string(), "cannot sync this type of resource".to_string(),
@ -406,14 +307,13 @@ struct FsyncArgs {
fn op_fsync_sync( fn op_fsync_sync(
state: &State, state: &State,
resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
state.check_unstable("Deno.fsync"); state.check_unstable("Deno.fsync");
let args: FsyncArgs = serde_json::from_value(args)?; let args: FsyncArgs = serde_json::from_value(args)?;
let rid = args.rid as u32; let rid = args.rid as u32;
std_file_resource(resource_table, rid, |r| match r { std_file_resource(state, rid, |r| match r {
Ok(std_file) => std_file.sync_all().map_err(ErrBox::from), Ok(std_file) => std_file.sync_all().map_err(ErrBox::from),
Err(_) => Err(ErrBox::type_error( Err(_) => Err(ErrBox::type_error(
"cannot sync this type of resource".to_string(), "cannot sync this type of resource".to_string(),
@ -424,15 +324,13 @@ fn op_fsync_sync(
async fn op_fsync_async( async fn op_fsync_async(
state: Rc<State>, state: Rc<State>,
resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
state.check_unstable("Deno.fsync"); state.check_unstable("Deno.fsync");
let args: FsyncArgs = serde_json::from_value(args)?; let args: FsyncArgs = serde_json::from_value(args)?;
let rid = args.rid as u32; let rid = args.rid as u32;
let mut resource_table = resource_table.borrow_mut(); std_file_resource(&state, rid, |r| match r {
std_file_resource(&mut resource_table, rid, |r| match r {
Ok(std_file) => std_file.sync_all().map_err(ErrBox::from), Ok(std_file) => std_file.sync_all().map_err(ErrBox::from),
Err(_) => Err(ErrBox::type_error( Err(_) => Err(ErrBox::type_error(
"cannot sync this type of resource".to_string(), "cannot sync this type of resource".to_string(),
@ -449,14 +347,13 @@ struct FstatArgs {
fn op_fstat_sync( fn op_fstat_sync(
state: &State, state: &State,
resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
state.check_unstable("Deno.fstat"); state.check_unstable("Deno.fstat");
let args: FstatArgs = serde_json::from_value(args)?; let args: FstatArgs = serde_json::from_value(args)?;
let rid = args.rid as u32; let rid = args.rid as u32;
let metadata = std_file_resource(resource_table, rid, |r| match r { let metadata = std_file_resource(state, rid, |r| match r {
Ok(std_file) => std_file.metadata().map_err(ErrBox::from), Ok(std_file) => std_file.metadata().map_err(ErrBox::from),
Err(_) => Err(ErrBox::type_error( Err(_) => Err(ErrBox::type_error(
"cannot stat this type of resource".to_string(), "cannot stat this type of resource".to_string(),
@ -467,15 +364,13 @@ fn op_fstat_sync(
async fn op_fstat_async( async fn op_fstat_async(
state: Rc<State>, state: Rc<State>,
resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
state.check_unstable("Deno.fstat"); state.check_unstable("Deno.fstat");
let args: FstatArgs = serde_json::from_value(args)?; let args: FstatArgs = serde_json::from_value(args)?;
let rid = args.rid as u32; let rid = args.rid as u32;
let mut resource_table = resource_table.borrow_mut(); let metadata = std_file_resource(&state, rid, |r| match r {
let metadata = std_file_resource(&mut resource_table, rid, |r| match r {
Ok(std_file) => std_file.metadata().map_err(ErrBox::from), Ok(std_file) => std_file.metadata().map_err(ErrBox::from),
Err(_) => Err(ErrBox::type_error( Err(_) => Err(ErrBox::type_error(
"cannot stat this type of resource".to_string(), "cannot stat this type of resource".to_string(),
@ -491,7 +386,6 @@ struct UmaskArgs {
fn op_umask( fn op_umask(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -530,7 +424,6 @@ struct ChdirArgs {
fn op_chdir( fn op_chdir(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -551,7 +444,6 @@ struct MkdirArgs {
fn op_mkdir_sync( fn op_mkdir_sync(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -573,7 +465,6 @@ fn op_mkdir_sync(
async fn op_mkdir_async( async fn op_mkdir_async(
state: Rc<State>, state: Rc<State>,
_resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -606,7 +497,6 @@ struct ChmodArgs {
fn op_chmod_sync( fn op_chmod_sync(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -634,7 +524,6 @@ fn op_chmod_sync(
async fn op_chmod_async( async fn op_chmod_async(
state: Rc<State>, state: Rc<State>,
_resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -673,7 +562,6 @@ struct ChownArgs {
fn op_chown_sync( fn op_chown_sync(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -703,7 +591,6 @@ fn op_chown_sync(
async fn op_chown_async( async fn op_chown_async(
state: Rc<State>, state: Rc<State>,
_resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -742,7 +629,6 @@ struct RemoveArgs {
fn op_remove_sync( fn op_remove_sync(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -786,7 +672,6 @@ fn op_remove_sync(
async fn op_remove_async( async fn op_remove_async(
state: Rc<State>, state: Rc<State>,
_resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -841,7 +726,6 @@ struct CopyFileArgs {
fn op_copy_file_sync( fn op_copy_file_sync(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -867,7 +751,6 @@ fn op_copy_file_sync(
async fn op_copy_file_async( async fn op_copy_file_async(
state: Rc<State>, state: Rc<State>,
_resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -895,7 +778,7 @@ async fn op_copy_file_async(
.unwrap() .unwrap()
} }
fn to_msec(maybe_time: Result<SystemTime, io::Error>) -> serde_json::Value { fn to_msec(maybe_time: Result<SystemTime, io::Error>) -> Value {
match maybe_time { match maybe_time {
Ok(time) => { Ok(time) => {
let msec = time let msec = time
@ -903,18 +786,18 @@ fn to_msec(maybe_time: Result<SystemTime, io::Error>) -> serde_json::Value {
.map(|t| t.as_secs_f64() * 1000f64) .map(|t| t.as_secs_f64() * 1000f64)
.unwrap_or_else(|err| err.duration().as_secs_f64() * -1000f64); .unwrap_or_else(|err| err.duration().as_secs_f64() * -1000f64);
serde_json::Number::from_f64(msec) serde_json::Number::from_f64(msec)
.map(serde_json::Value::Number) .map(Value::Number)
.unwrap_or(serde_json::Value::Null) .unwrap_or(Value::Null)
} }
Err(_) => serde_json::Value::Null, Err(_) => Value::Null,
} }
} }
#[inline(always)] #[inline(always)]
fn get_stat_json(metadata: std::fs::Metadata) -> JsonResult { fn get_stat_json(metadata: std::fs::Metadata) -> Result<Value, ErrBox> {
// Unix stat member (number types only). 0 if not on unix. // Unix stat member (number types only). 0 if not on unix.
macro_rules! usm { macro_rules! usm {
($member: ident) => {{ ($member:ident) => {{
#[cfg(unix)] #[cfg(unix)]
{ {
metadata.$member() metadata.$member()
@ -962,7 +845,6 @@ struct StatArgs {
fn op_stat_sync( fn op_stat_sync(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -981,7 +863,6 @@ fn op_stat_sync(
async fn op_stat_async( async fn op_stat_async(
state: Rc<State>, state: Rc<State>,
_resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1012,7 +893,6 @@ struct RealpathArgs {
fn op_realpath_sync( fn op_realpath_sync(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1038,7 +918,6 @@ fn op_realpath_sync(
async fn op_realpath_async( async fn op_realpath_async(
state: Rc<State>, state: Rc<State>,
_resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1074,7 +953,6 @@ struct ReadDirArgs {
fn op_read_dir_sync( fn op_read_dir_sync(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1107,7 +985,6 @@ fn op_read_dir_sync(
async fn op_read_dir_async( async fn op_read_dir_async(
state: Rc<State>, state: Rc<State>,
_resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1151,7 +1028,6 @@ struct RenameArgs {
fn op_rename_sync( fn op_rename_sync(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1169,7 +1045,6 @@ fn op_rename_sync(
async fn op_rename_async( async fn op_rename_async(
state: Rc<State>, state: Rc<State>,
_resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1203,7 +1078,6 @@ struct LinkArgs {
fn op_link_sync( fn op_link_sync(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1222,7 +1096,6 @@ fn op_link_sync(
async fn op_link_async( async fn op_link_async(
state: Rc<State>, state: Rc<State>,
_resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1261,7 +1134,6 @@ struct SymlinkOptions {
fn op_symlink_sync( fn op_symlink_sync(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1303,10 +1175,7 @@ fn op_symlink_sync(
symlink_dir(&oldpath, &newpath)? symlink_dir(&oldpath, &newpath)?
} }
} }
Err(_) => return Err(ErrBox::type_error( Err(_) => return Err(ErrBox::type_error("you must pass a `options` argument for non-existent target path in windows".to_string())),
"you must pass a `options` argument for non-existent target path in windows"
.to_string(),
)),
} }
} }
}; };
@ -1316,7 +1185,6 @@ fn op_symlink_sync(
async fn op_symlink_async( async fn op_symlink_async(
state: Rc<State>, state: Rc<State>,
_resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1355,10 +1223,7 @@ async fn op_symlink_async(
symlink_dir(&oldpath, &newpath)? symlink_dir(&oldpath, &newpath)?
} }
} }
Err(_) => return Err(ErrBox::type_error( Err(_) => return Err(ErrBox::type_error("you must pass a `options` argument for non-existent target path in windows".to_string())),
"you must pass a `options` argument for non-existent target path in windows"
.to_string(),
)),
} }
} }
}; };
@ -1377,7 +1242,6 @@ struct ReadLinkArgs {
fn op_read_link_sync( fn op_read_link_sync(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1394,7 +1258,6 @@ fn op_read_link_sync(
async fn op_read_link_async( async fn op_read_link_async(
state: Rc<State>, state: Rc<State>,
_resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1422,7 +1285,6 @@ struct FtruncateArgs {
fn op_ftruncate_sync( fn op_ftruncate_sync(
state: &State, state: &State,
resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1430,7 +1292,7 @@ fn op_ftruncate_sync(
let args: FtruncateArgs = serde_json::from_value(args)?; let args: FtruncateArgs = serde_json::from_value(args)?;
let rid = args.rid as u32; let rid = args.rid as u32;
let len = args.len as u64; let len = args.len as u64;
std_file_resource(resource_table, rid, |r| match r { std_file_resource(state, rid, |r| match r {
Ok(std_file) => std_file.set_len(len).map_err(ErrBox::from), Ok(std_file) => std_file.set_len(len).map_err(ErrBox::from),
Err(_) => Err(ErrBox::type_error("cannot truncate this type of resource")), Err(_) => Err(ErrBox::type_error("cannot truncate this type of resource")),
})?; })?;
@ -1439,7 +1301,6 @@ fn op_ftruncate_sync(
async fn op_ftruncate_async( async fn op_ftruncate_async(
state: Rc<State>, state: Rc<State>,
resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1447,8 +1308,7 @@ async fn op_ftruncate_async(
let args: FtruncateArgs = serde_json::from_value(args)?; let args: FtruncateArgs = serde_json::from_value(args)?;
let rid = args.rid as u32; let rid = args.rid as u32;
let len = args.len as u64; let len = args.len as u64;
let mut resource_table = resource_table.borrow_mut(); std_file_resource(&state, rid, |r| match r {
std_file_resource(&mut resource_table, rid, |r| match r {
Ok(std_file) => std_file.set_len(len).map_err(ErrBox::from), Ok(std_file) => std_file.set_len(len).map_err(ErrBox::from),
Err(_) => Err(ErrBox::type_error("cannot truncate this type of resource")), Err(_) => Err(ErrBox::type_error("cannot truncate this type of resource")),
})?; })?;
@ -1464,7 +1324,6 @@ struct TruncateArgs {
fn op_truncate_sync( fn op_truncate_sync(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1482,7 +1341,6 @@ fn op_truncate_sync(
async fn op_truncate_async( async fn op_truncate_async(
state: Rc<State>, state: Rc<State>,
_resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1557,7 +1415,6 @@ struct MakeTempArgs {
fn op_make_temp_dir_sync( fn op_make_temp_dir_sync(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1586,7 +1443,6 @@ fn op_make_temp_dir_sync(
async fn op_make_temp_dir_async( async fn op_make_temp_dir_async(
state: Rc<State>, state: Rc<State>,
_resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1619,7 +1475,6 @@ async fn op_make_temp_dir_async(
fn op_make_temp_file_sync( fn op_make_temp_file_sync(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1648,7 +1503,6 @@ fn op_make_temp_file_sync(
async fn op_make_temp_file_async( async fn op_make_temp_file_async(
state: Rc<State>, state: Rc<State>,
_resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1689,7 +1543,6 @@ struct FutimeArgs {
fn op_futime_sync( fn op_futime_sync(
state: &State, state: &State,
resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1699,7 +1552,7 @@ fn op_futime_sync(
let atime = filetime::FileTime::from_unix_time(args.atime.0, args.atime.1); let atime = filetime::FileTime::from_unix_time(args.atime.0, args.atime.1);
let mtime = filetime::FileTime::from_unix_time(args.mtime.0, args.mtime.1); let mtime = filetime::FileTime::from_unix_time(args.mtime.0, args.mtime.1);
std_file_resource(resource_table, rid, |r| match r { std_file_resource(state, rid, |r| match r {
Ok(std_file) => { Ok(std_file) => {
filetime::set_file_handle_times(std_file, Some(atime), Some(mtime)) filetime::set_file_handle_times(std_file, Some(atime), Some(mtime))
.map_err(ErrBox::from) .map_err(ErrBox::from)
@ -1714,7 +1567,6 @@ fn op_futime_sync(
async fn op_futime_async( async fn op_futime_async(
state: Rc<State>, state: Rc<State>,
resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1724,8 +1576,7 @@ async fn op_futime_async(
let atime = filetime::FileTime::from_unix_time(args.atime.0, args.atime.1); let atime = filetime::FileTime::from_unix_time(args.atime.0, args.atime.1);
let mtime = filetime::FileTime::from_unix_time(args.mtime.0, args.mtime.1); let mtime = filetime::FileTime::from_unix_time(args.mtime.0, args.mtime.1);
let mut resource_table = resource_table.borrow_mut(); std_file_resource(&state, rid, |r| match r {
std_file_resource(&mut resource_table, rid, |r| match r {
Ok(std_file) => { Ok(std_file) => {
filetime::set_file_handle_times(std_file, Some(atime), Some(mtime)) filetime::set_file_handle_times(std_file, Some(atime), Some(mtime))
.map_err(ErrBox::from) .map_err(ErrBox::from)
@ -1748,7 +1599,6 @@ struct UtimeArgs {
fn op_utime_sync( fn op_utime_sync(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1766,7 +1616,6 @@ fn op_utime_sync(
async fn op_utime_async( async fn op_utime_async(
state: Rc<State>, state: Rc<State>,
_resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -1789,7 +1638,6 @@ async fn op_utime_async(
fn op_cwd( fn op_cwd(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
_args: Value, _args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {

View file

@ -1,10 +1,9 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::{Deserialize, Value};
use crate::state::State; use crate::state::State;
use deno_core::BufVec; use deno_core::BufVec;
use deno_core::CoreIsolate;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ResourceTable; use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use futures::future::poll_fn; use futures::future::poll_fn;
use notify::event::Event as NotifyEvent; use notify::event::Event as NotifyEvent;
@ -14,23 +13,16 @@ use notify::RecommendedWatcher;
use notify::RecursiveMode; use notify::RecursiveMode;
use notify::Watcher; use notify::Watcher;
use serde::Serialize; use serde::Serialize;
use std::cell::RefCell; use serde_derive::Deserialize;
use serde_json::Value;
use std::convert::From; use std::convert::From;
use std::path::PathBuf; use std::path::PathBuf;
use std::rc::Rc; use std::rc::Rc;
use tokio::sync::mpsc; use tokio::sync::mpsc;
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { pub fn init(s: &Rc<State>) {
let t = &CoreIsolate::state(i).borrow().resource_table.clone(); 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);
i.register_op(
"op_fs_events_open",
s.stateful_json_op_sync(t, op_fs_events_open),
);
i.register_op(
"op_fs_events_poll",
s.stateful_json_op_async(t, op_fs_events_poll),
);
} }
struct FsEventsResource { struct FsEventsResource {
@ -73,7 +65,6 @@ impl From<NotifyEvent> for FsEvent {
fn op_fs_events_open( fn op_fs_events_open(
state: &State, state: &State,
resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -103,13 +94,15 @@ fn op_fs_events_open(
watcher.watch(path, recursive_mode)?; watcher.watch(path, recursive_mode)?;
} }
let resource = FsEventsResource { watcher, receiver }; let resource = FsEventsResource { watcher, receiver };
let rid = resource_table.add("fsEvents", Box::new(resource)); let rid = state
.resource_table
.borrow_mut()
.add("fsEvents", Box::new(resource));
Ok(json!(rid)) Ok(json!(rid))
} }
async fn op_fs_events_poll( async fn op_fs_events_poll(
_state: Rc<State>, state: Rc<State>,
resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -119,7 +112,7 @@ async fn op_fs_events_poll(
} }
let PollArgs { rid } = serde_json::from_value(args)?; let PollArgs { rid } = serde_json::from_value(args)?;
poll_fn(move |cx| { poll_fn(move |cx| {
let mut resource_table = resource_table.borrow_mut(); let mut resource_table = state.resource_table.borrow_mut();
let watcher = resource_table let watcher = resource_table
.get_mut::<FsEventsResource>(rid) .get_mut::<FsEventsResource>(rid)
.ok_or_else(ErrBox::bad_resource_id)?; .ok_or_else(ErrBox::bad_resource_id)?;

View file

@ -2,21 +2,18 @@
//! https://url.spec.whatwg.org/#idna //! https://url.spec.whatwg.org/#idna
use super::dispatch_json::{Deserialize, Value};
use crate::state::State; use crate::state::State;
use deno_core::CoreIsolate;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ResourceTable; use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use idna::{domain_to_ascii, domain_to_ascii_strict}; use idna::domain_to_ascii;
use idna::domain_to_ascii_strict;
use serde_derive::Deserialize;
use serde_json::Value;
use std::rc::Rc; use std::rc::Rc;
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { pub fn init(s: &Rc<State>) {
let t = &CoreIsolate::state(i).borrow().resource_table.clone(); s.register_op_json_sync("op_domain_to_ascii", op_domain_to_ascii);
i.register_op(
"op_domain_to_ascii",
s.stateful_json_op_sync(t, op_domain_to_ascii),
);
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -28,7 +25,6 @@ struct DomainToAscii {
fn op_domain_to_ascii( fn op_domain_to_ascii(
_state: &State, _state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {

View file

@ -1,11 +1,8 @@
use super::dispatch_minimal::MinimalOp; use super::dispatch_minimal::MinimalOp;
use crate::http_util::HttpBody; use crate::http_util::HttpBody;
use crate::state::State; use crate::state::State;
use deno_core::CoreIsolate; use deno_core::BufVec;
use deno_core::CoreIsolateState;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ResourceTable;
use deno_core::ZeroCopyBuf;
use futures::future::poll_fn; use futures::future::poll_fn;
use futures::future::FutureExt; use futures::future::FutureExt;
use futures::ready; use futures::ready;
@ -85,9 +82,9 @@ lazy_static! {
}; };
} }
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { pub fn init(s: &Rc<State>) {
i.register_op("op_read", s.stateful_minimal_op2(op_read)); s.register_op_minimal("op_read", op_read);
i.register_op("op_write", s.stateful_minimal_op2(op_write)); s.register_op_minimal("op_write", op_write);
} }
pub fn get_stdio() -> ( pub fn get_stdio() -> (
@ -236,11 +233,10 @@ impl DenoAsyncRead for StreamResource {
} }
pub fn op_read( pub fn op_read(
isolate_state: &mut CoreIsolateState, state: Rc<State>,
_state: &Rc<State>,
is_sync: bool, is_sync: bool,
rid: i32, rid: i32,
zero_copy: &mut [ZeroCopyBuf], mut zero_copy: BufVec,
) -> MinimalOp { ) -> MinimalOp {
debug!("read rid={}", rid); debug!("read rid={}", rid);
match zero_copy.len() { match zero_copy.len() {
@ -248,13 +244,11 @@ pub fn op_read(
1 => {} 1 => {}
_ => panic!("Invalid number of arguments"), _ => panic!("Invalid number of arguments"),
} }
let resource_table = isolate_state.resource_table.clone();
if is_sync { if is_sync {
MinimalOp::Sync({ MinimalOp::Sync({
// First we look up the rid in the resource table. // First we look up the rid in the resource table.
let mut resource_table = resource_table.borrow_mut(); std_file_resource(&state, rid as u32, move |r| match r {
std_file_resource(&mut resource_table, rid as u32, move |r| match r {
Ok(std_file) => { Ok(std_file) => {
use std::io::Read; use std::io::Read;
std_file std_file
@ -271,7 +265,7 @@ pub fn op_read(
let mut zero_copy = zero_copy[0].clone(); let mut zero_copy = zero_copy[0].clone();
MinimalOp::Async( MinimalOp::Async(
poll_fn(move |cx| { poll_fn(move |cx| {
let mut resource_table = resource_table.borrow_mut(); let mut resource_table = state.resource_table.borrow_mut();
let resource_holder = resource_table let resource_holder = resource_table
.get_mut::<StreamResourceHolder>(rid as u32) .get_mut::<StreamResourceHolder>(rid as u32)
.ok_or_else(ErrBox::bad_resource_id)?; .ok_or_else(ErrBox::bad_resource_id)?;
@ -358,11 +352,10 @@ impl DenoAsyncWrite for StreamResource {
} }
pub fn op_write( pub fn op_write(
isolate_state: &mut CoreIsolateState, state: Rc<State>,
_state: &Rc<State>,
is_sync: bool, is_sync: bool,
rid: i32, rid: i32,
zero_copy: &mut [ZeroCopyBuf], zero_copy: BufVec,
) -> MinimalOp { ) -> MinimalOp {
debug!("write rid={}", rid); debug!("write rid={}", rid);
match zero_copy.len() { match zero_copy.len() {
@ -374,8 +367,7 @@ pub fn op_write(
if is_sync { if is_sync {
MinimalOp::Sync({ MinimalOp::Sync({
// First we look up the rid in the resource table. // First we look up the rid in the resource table.
let mut resource_table = isolate_state.resource_table.borrow_mut(); std_file_resource(&state, rid as u32, move |r| match r {
std_file_resource(&mut resource_table, rid as u32, move |r| match r {
Ok(std_file) => { Ok(std_file) => {
use std::io::Write; use std::io::Write;
std_file std_file
@ -390,11 +382,10 @@ pub fn op_write(
}) })
} else { } else {
let zero_copy = zero_copy[0].clone(); let zero_copy = zero_copy[0].clone();
let resource_table = isolate_state.resource_table.clone();
MinimalOp::Async( MinimalOp::Async(
async move { async move {
let nwritten = poll_fn(|cx| { let nwritten = poll_fn(|cx| {
let mut resource_table = resource_table.borrow_mut(); let mut resource_table = state.resource_table.borrow_mut();
let resource_holder = resource_table let resource_holder = resource_table
.get_mut::<StreamResourceHolder>(rid as u32) .get_mut::<StreamResourceHolder>(rid as u32)
.ok_or_else(ErrBox::bad_resource_id)?; .ok_or_else(ErrBox::bad_resource_id)?;
@ -407,7 +398,7 @@ pub fn op_write(
// Figure out why it's needed and preferably remove it. // Figure out why it's needed and preferably remove it.
// https://github.com/denoland/deno/issues/3565 // https://github.com/denoland/deno/issues/3565
poll_fn(|cx| { poll_fn(|cx| {
let mut resource_table = resource_table.borrow_mut(); let mut resource_table = state.resource_table.borrow_mut();
let resource_holder = resource_table let resource_holder = resource_table
.get_mut::<StreamResourceHolder>(rid as u32) .get_mut::<StreamResourceHolder>(rid as u32)
.ok_or_else(ErrBox::bad_resource_id)?; .ok_or_else(ErrBox::bad_resource_id)?;
@ -430,7 +421,7 @@ pub fn op_write(
/// ///
/// Returns ErrorKind::Busy if the resource is being used by another op. /// Returns ErrorKind::Busy if the resource is being used by another op.
pub fn std_file_resource<F, T>( pub fn std_file_resource<F, T>(
resource_table: &mut ResourceTable, state: &State,
rid: u32, rid: u32,
mut f: F, mut f: F,
) -> Result<T, ErrBox> ) -> Result<T, ErrBox>
@ -439,6 +430,7 @@ where
FnMut(Result<&mut std::fs::File, &mut StreamResource>) -> Result<T, ErrBox>, FnMut(Result<&mut std::fs::File, &mut StreamResource>) -> Result<T, ErrBox>,
{ {
// First we look up the rid in the resource table. // 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 = resource_table.get_mut::<StreamResourceHolder>(rid);
if let Some(ref mut resource_holder) = r { if let Some(ref mut resource_holder) = r {
// Sync write only works for FsFile. It doesn't make sense to do this // Sync write only works for FsFile. It doesn't make sense to do this

View file

@ -1,12 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
mod dispatch_json;
mod dispatch_minimal;
pub use dispatch_json::json_op; mod dispatch_minimal;
pub use dispatch_json::serialize_result;
pub use dispatch_json::JsonOp;
pub use dispatch_json::JsonResult;
pub use dispatch_minimal::minimal_op;
pub use dispatch_minimal::MinimalOp; pub use dispatch_minimal::MinimalOp;
pub mod compiler; pub mod compiler;

View file

@ -1,15 +1,15 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::{Deserialize, Value};
use super::io::{StreamResource, StreamResourceHolder}; use crate::ops::io::{StreamResource, StreamResourceHolder};
use crate::resolve_addr::resolve_addr; use crate::resolve_addr::resolve_addr;
use crate::state::State; use crate::state::State;
use deno_core::BufVec; use deno_core::BufVec;
use deno_core::CoreIsolate;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ResourceTable; use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use futures::future::poll_fn; use futures::future::poll_fn;
use std::cell::RefCell; use serde_derive::Deserialize;
use serde_json::Value;
use std::net::Shutdown; use std::net::Shutdown;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::rc::Rc; use std::rc::Rc;
@ -22,38 +22,30 @@ use tokio::net::UdpSocket;
#[cfg(unix)] #[cfg(unix)]
use super::net_unix; use super::net_unix;
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { pub fn init(s: &Rc<State>) {
let t = &CoreIsolate::state(i).borrow().resource_table.clone(); s.register_op_json_async("op_accept", op_accept);
s.register_op_json_async("op_connect", op_connect);
i.register_op("op_accept", s.stateful_json_op_async(t, op_accept)); s.register_op_json_sync("op_shutdown", op_shutdown);
i.register_op("op_connect", s.stateful_json_op_async(t, op_connect)); s.register_op_json_sync("op_listen", op_listen);
i.register_op("op_shutdown", s.stateful_json_op_sync(t, op_shutdown)); s.register_op_json_async("op_datagram_receive", op_datagram_receive);
i.register_op("op_listen", s.stateful_json_op_sync(t, op_listen)); s.register_op_json_async("op_datagram_send", op_datagram_send);
i.register_op(
"op_datagram_receive",
s.stateful_json_op_async(t, op_datagram_receive),
);
i.register_op(
"op_datagram_send",
s.stateful_json_op_async(t, op_datagram_send),
);
} }
#[derive(Deserialize)] #[derive(Deserialize)]
struct AcceptArgs { pub(crate) struct AcceptArgs {
rid: i32, pub rid: i32,
transport: String, pub transport: String,
} }
async fn accept_tcp( async fn accept_tcp(
resource_table: Rc<RefCell<ResourceTable>>, state: Rc<State>,
args: AcceptArgs, args: AcceptArgs,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
let rid = args.rid as u32; let rid = args.rid as u32;
let accept_fut = poll_fn(|cx| { let accept_fut = poll_fn(|cx| {
let mut resource_table = resource_table.borrow_mut(); let mut resource_table = state.resource_table.borrow_mut();
let listener_resource = resource_table let listener_resource = resource_table
.get_mut::<TcpListenerResource>(rid) .get_mut::<TcpListenerResource>(rid)
.ok_or_else(|| ErrBox::bad_resource("Listener has been closed"))?; .ok_or_else(|| ErrBox::bad_resource("Listener has been closed"))?;
@ -76,8 +68,7 @@ async fn accept_tcp(
let (tcp_stream, _socket_addr) = accept_fut.await?; let (tcp_stream, _socket_addr) = accept_fut.await?;
let local_addr = tcp_stream.local_addr()?; let local_addr = tcp_stream.local_addr()?;
let remote_addr = tcp_stream.peer_addr()?; let remote_addr = tcp_stream.peer_addr()?;
let mut resource_table = resource_table.borrow_mut(); let rid = state.resource_table.borrow_mut().add(
let rid = resource_table.add(
"tcpStream", "tcpStream",
Box::new(StreamResourceHolder::new(StreamResource::TcpStream(Some( Box::new(StreamResourceHolder::new(StreamResource::TcpStream(Some(
tcp_stream, tcp_stream,
@ -99,18 +90,15 @@ async fn accept_tcp(
} }
async fn op_accept( async fn op_accept(
_state: Rc<State>, state: Rc<State>,
resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
zero_copy: BufVec, bufs: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
let args: AcceptArgs = serde_json::from_value(args)?; let args: AcceptArgs = serde_json::from_value(args)?;
match args.transport.as_str() { match args.transport.as_str() {
"tcp" => accept_tcp(resource_table, args, zero_copy).await, "tcp" => accept_tcp(state, args, bufs).await,
#[cfg(unix)] #[cfg(unix)]
"unix" => { "unix" => net_unix::accept_unix(state, args, bufs).await,
net_unix::accept_unix(resource_table, args.rid as u32, zero_copy).await
}
_ => Err(ErrBox::error(format!( _ => Err(ErrBox::error(format!(
"Unsupported transport protocol {}", "Unsupported transport protocol {}",
args.transport args.transport
@ -119,14 +107,13 @@ async fn op_accept(
} }
#[derive(Deserialize)] #[derive(Deserialize)]
struct ReceiveArgs { pub(crate) struct ReceiveArgs {
rid: i32, pub rid: i32,
transport: String, pub transport: String,
} }
async fn receive_udp( async fn receive_udp(
resource_table: Rc<RefCell<ResourceTable>>, state: Rc<State>,
_state: &Rc<State>,
args: ReceiveArgs, args: ReceiveArgs,
zero_copy: BufVec, zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -136,7 +123,7 @@ async fn receive_udp(
let rid = args.rid as u32; let rid = args.rid as u32;
let receive_fut = poll_fn(|cx| { let receive_fut = poll_fn(|cx| {
let mut resource_table = resource_table.borrow_mut(); let mut resource_table = state.resource_table.borrow_mut();
let resource = resource_table let resource = resource_table
.get_mut::<UdpSocketResource>(rid) .get_mut::<UdpSocketResource>(rid)
.ok_or_else(|| ErrBox::bad_resource("Socket has been closed"))?; .ok_or_else(|| ErrBox::bad_resource("Socket has been closed"))?;
@ -158,7 +145,6 @@ async fn receive_udp(
async fn op_datagram_receive( async fn op_datagram_receive(
state: Rc<State>, state: Rc<State>,
resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
zero_copy: BufVec, zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -166,12 +152,9 @@ async fn op_datagram_receive(
let args: ReceiveArgs = serde_json::from_value(args)?; let args: ReceiveArgs = serde_json::from_value(args)?;
match args.transport.as_str() { match args.transport.as_str() {
"udp" => receive_udp(resource_table, &state, args, zero_copy).await, "udp" => receive_udp(state, args, zero_copy).await,
#[cfg(unix)] #[cfg(unix)]
"unixpacket" => { "unixpacket" => net_unix::receive_unix_packet(state, args, zero_copy).await,
net_unix::receive_unix_packet(resource_table, args.rid as u32, zero_copy)
.await
}
_ => Err(ErrBox::error(format!( _ => Err(ErrBox::error(format!(
"Unsupported transport protocol {}", "Unsupported transport protocol {}",
args.transport args.transport
@ -189,7 +172,6 @@ struct SendArgs {
async fn op_datagram_send( async fn op_datagram_send(
state: Rc<State>, state: Rc<State>,
resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
zero_copy: BufVec, zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -205,7 +187,7 @@ async fn op_datagram_send(
state.check_net(&args.hostname, args.port)?; state.check_net(&args.hostname, args.port)?;
let addr = resolve_addr(&args.hostname, args.port)?; let addr = resolve_addr(&args.hostname, args.port)?;
poll_fn(move |cx| { poll_fn(move |cx| {
let mut resource_table = resource_table.borrow_mut(); let mut resource_table = state.resource_table.borrow_mut();
let resource = resource_table let resource = resource_table
.get_mut::<UdpSocketResource>(rid as u32) .get_mut::<UdpSocketResource>(rid as u32)
.ok_or_else(|| ErrBox::bad_resource("Socket has been closed"))?; .ok_or_else(|| ErrBox::bad_resource("Socket has been closed"))?;
@ -225,7 +207,7 @@ async fn op_datagram_send(
} if transport == "unixpacket" => { } if transport == "unixpacket" => {
let address_path = net_unix::Path::new(&args.path); let address_path = net_unix::Path::new(&args.path);
state.check_read(&address_path)?; state.check_read(&address_path)?;
let mut resource_table = resource_table.borrow_mut(); let mut resource_table = state.resource_table.borrow_mut();
let resource = resource_table let resource = resource_table
.get_mut::<net_unix::UnixDatagramResource>(rid as u32) .get_mut::<net_unix::UnixDatagramResource>(rid as u32)
.ok_or_else(|| ErrBox::new("NotConnected", "Socket has been closed"))?; .ok_or_else(|| ErrBox::new("NotConnected", "Socket has been closed"))?;
@ -249,7 +231,6 @@ struct ConnectArgs {
async fn op_connect( async fn op_connect(
state: Rc<State>, state: Rc<State>,
resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -263,8 +244,7 @@ async fn op_connect(
let tcp_stream = TcpStream::connect(&addr).await?; let tcp_stream = TcpStream::connect(&addr).await?;
let local_addr = tcp_stream.local_addr()?; let local_addr = tcp_stream.local_addr()?;
let remote_addr = tcp_stream.peer_addr()?; let remote_addr = tcp_stream.peer_addr()?;
let mut resource_table = resource_table.borrow_mut(); let rid = state.resource_table.borrow_mut().add(
let rid = resource_table.add(
"tcpStream", "tcpStream",
Box::new(StreamResourceHolder::new(StreamResource::TcpStream(Some( Box::new(StreamResourceHolder::new(StreamResource::TcpStream(Some(
tcp_stream, tcp_stream,
@ -297,8 +277,7 @@ async fn op_connect(
net_unix::UnixStream::connect(net_unix::Path::new(&path)).await?; net_unix::UnixStream::connect(net_unix::Path::new(&path)).await?;
let local_addr = unix_stream.local_addr()?; let local_addr = unix_stream.local_addr()?;
let remote_addr = unix_stream.peer_addr()?; let remote_addr = unix_stream.peer_addr()?;
let mut resource_table = resource_table.borrow_mut(); let rid = state.resource_table.borrow_mut().add(
let rid = resource_table.add(
"unixStream", "unixStream",
Box::new(StreamResourceHolder::new(StreamResource::UnixStream( Box::new(StreamResourceHolder::new(StreamResource::UnixStream(
unix_stream, unix_stream,
@ -328,7 +307,6 @@ struct ShutdownArgs {
fn op_shutdown( fn op_shutdown(
state: &State, state: &State,
resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -345,6 +323,7 @@ fn op_shutdown(
_ => unimplemented!(), _ => unimplemented!(),
}; };
let mut resource_table = state.resource_table.borrow_mut();
let resource_holder = resource_table let resource_holder = resource_table
.get_mut::<StreamResourceHolder>(rid) .get_mut::<StreamResourceHolder>(rid)
.ok_or_else(ErrBox::bad_resource_id)?; .ok_or_else(ErrBox::bad_resource_id)?;
@ -437,7 +416,7 @@ struct ListenArgs {
} }
fn listen_tcp( fn listen_tcp(
resource_table: &mut ResourceTable, state: &State,
addr: SocketAddr, addr: SocketAddr,
) -> Result<(u32, SocketAddr), ErrBox> { ) -> Result<(u32, SocketAddr), ErrBox> {
let std_listener = std::net::TcpListener::bind(&addr)?; let std_listener = std::net::TcpListener::bind(&addr)?;
@ -448,27 +427,32 @@ fn listen_tcp(
waker: None, waker: None,
local_addr, local_addr,
}; };
let rid = resource_table.add("tcpListener", Box::new(listener_resource)); let rid = state
.resource_table
.borrow_mut()
.add("tcpListener", Box::new(listener_resource));
Ok((rid, local_addr)) Ok((rid, local_addr))
} }
fn listen_udp( fn listen_udp(
resource_table: &mut ResourceTable, state: &State,
addr: SocketAddr, addr: SocketAddr,
) -> Result<(u32, SocketAddr), ErrBox> { ) -> Result<(u32, SocketAddr), ErrBox> {
let std_socket = std::net::UdpSocket::bind(&addr)?; let std_socket = std::net::UdpSocket::bind(&addr)?;
let socket = UdpSocket::from_std(std_socket)?; let socket = UdpSocket::from_std(std_socket)?;
let local_addr = socket.local_addr()?; let local_addr = socket.local_addr()?;
let socket_resource = UdpSocketResource { socket }; let socket_resource = UdpSocketResource { socket };
let rid = resource_table.add("udpSocket", Box::new(socket_resource)); let rid = state
.resource_table
.borrow_mut()
.add("udpSocket", Box::new(socket_resource));
Ok((rid, local_addr)) Ok((rid, local_addr))
} }
fn op_listen( fn op_listen(
state: &State, state: &State,
resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -483,9 +467,9 @@ fn op_listen(
state.check_net(&args.hostname, args.port)?; state.check_net(&args.hostname, args.port)?;
let addr = resolve_addr(&args.hostname, args.port)?; let addr = resolve_addr(&args.hostname, args.port)?;
let (rid, local_addr) = if transport == "tcp" { let (rid, local_addr) = if transport == "tcp" {
listen_tcp(resource_table, addr)? listen_tcp(state, addr)?
} else { } else {
listen_udp(resource_table, addr)? listen_udp(state, addr)?
}; };
debug!( debug!(
"New listener {} {}:{}", "New listener {} {}:{}",
@ -517,9 +501,9 @@ fn op_listen(
state.check_read(&address_path)?; state.check_read(&address_path)?;
state.check_write(&address_path)?; state.check_write(&address_path)?;
let (rid, local_addr) = if transport == "unix" { let (rid, local_addr) = if transport == "unix" {
net_unix::listen_unix(resource_table, &address_path)? net_unix::listen_unix(state, &address_path)?
} else { } else {
net_unix::listen_unix_packet(resource_table, &address_path)? net_unix::listen_unix_packet(state, &address_path)?
}; };
debug!( debug!(
"New listener {} {}", "New listener {} {}",

View file

@ -1,9 +1,12 @@
use super::dispatch_json::{Deserialize, Value}; use crate::ops::io::StreamResource;
use super::io::{StreamResource, StreamResourceHolder}; 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::BufVec;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ResourceTable; use serde_derive::Deserialize;
use std::cell::RefCell; use serde_json::Value;
use std::fs::remove_file; use std::fs::remove_file;
use std::os::unix; use std::os::unix;
pub use std::path::Path; pub use std::path::Path;
@ -26,24 +29,25 @@ pub struct UnixListenArgs {
pub path: String, pub path: String,
} }
pub async fn accept_unix( pub(crate) async fn accept_unix(
resource_table: Rc<RefCell<ResourceTable>>, state: Rc<State>,
rid: u32, args: AcceptArgs,
_zero_copy: BufVec, _bufs: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
let mut resource_table_ = resource_table.borrow_mut(); let rid = args.rid as u32;
let mut resource_table_ = state.resource_table.borrow_mut();
let listener_resource = { let listener_resource = {
resource_table_ resource_table_
.get_mut::<UnixListenerResource>(rid) .get_mut::<UnixListenerResource>(rid)
.ok_or_else(|| ErrBox::bad_resource("Listener has been closed"))? .ok_or_else(|| ErrBox::bad_resource("Listener has been closed"))?
}; };
let (unix_stream, _socket_addr) = listener_resource.listener.accept().await?; let (unix_stream, _socket_addr) = listener_resource.listener.accept().await?;
drop(resource_table_); drop(resource_table_);
let local_addr = unix_stream.local_addr()?; let local_addr = unix_stream.local_addr()?;
let remote_addr = unix_stream.peer_addr()?; let remote_addr = unix_stream.peer_addr()?;
let mut resource_table_ = resource_table.borrow_mut(); let mut resource_table_ = state.resource_table.borrow_mut();
let rid = resource_table_.add( let rid = resource_table_.add(
"unixStream", "unixStream",
Box::new(StreamResourceHolder::new(StreamResource::UnixStream( Box::new(StreamResourceHolder::new(StreamResource::UnixStream(
@ -63,19 +67,21 @@ pub async fn accept_unix(
})) }))
} }
pub async fn receive_unix_packet( pub(crate) async fn receive_unix_packet(
resource_table: Rc<RefCell<ResourceTable>>, state: Rc<State>,
rid: u32, args: ReceiveArgs,
zero_copy: BufVec, bufs: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
assert_eq!(zero_copy.len(), 1, "Invalid number of arguments"); assert_eq!(bufs.len(), 1, "Invalid number of arguments");
let mut zero_copy = zero_copy[0].clone();
let mut resource_table_ = resource_table.borrow_mut(); 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 resource = resource_table_
.get_mut::<UnixDatagramResource>(rid) .get_mut::<UnixDatagramResource>(rid)
.ok_or_else(|| ErrBox::bad_resource("Socket has been closed"))?; .ok_or_else(|| ErrBox::bad_resource("Socket has been closed"))?;
let (size, remote_addr) = resource.socket.recv_from(&mut zero_copy).await?; let (size, remote_addr) = resource.socket.recv_from(&mut buf).await?;
Ok(json!({ Ok(json!({
"size": size, "size": size,
"remoteAddr": { "remoteAddr": {
@ -86,7 +92,7 @@ pub async fn receive_unix_packet(
} }
pub fn listen_unix( pub fn listen_unix(
resource_table: &mut ResourceTable, state: &State,
addr: &Path, addr: &Path,
) -> Result<(u32, unix::net::SocketAddr), ErrBox> { ) -> Result<(u32, unix::net::SocketAddr), ErrBox> {
if addr.exists() { if addr.exists() {
@ -95,13 +101,16 @@ pub fn listen_unix(
let listener = UnixListener::bind(&addr)?; let listener = UnixListener::bind(&addr)?;
let local_addr = listener.local_addr()?; let local_addr = listener.local_addr()?;
let listener_resource = UnixListenerResource { listener }; let listener_resource = UnixListenerResource { listener };
let rid = resource_table.add("unixListener", Box::new(listener_resource)); let rid = state
.resource_table
.borrow_mut()
.add("unixListener", Box::new(listener_resource));
Ok((rid, local_addr)) Ok((rid, local_addr))
} }
pub fn listen_unix_packet( pub fn listen_unix_packet(
resource_table: &mut ResourceTable, state: &State,
addr: &Path, addr: &Path,
) -> Result<(u32, unix::net::SocketAddr), ErrBox> { ) -> Result<(u32, unix::net::SocketAddr), ErrBox> {
if addr.exists() { if addr.exists() {
@ -113,7 +122,10 @@ pub fn listen_unix_packet(
socket, socket,
local_addr: local_addr.clone(), local_addr: local_addr.clone(),
}; };
let rid = resource_table.add("unixDatagram", Box::new(datagram_resource)); let rid = state
.resource_table
.borrow_mut()
.add("unixDatagram", Box::new(datagram_resource));
Ok((rid, local_addr)) Ok((rid, local_addr))
} }

View file

@ -1,32 +1,30 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::{Deserialize, Value};
use crate::state::State; use crate::state::State;
use deno_core::CoreIsolate;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ResourceTable; use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use serde_derive::Deserialize;
use serde_json::Value;
use std::collections::HashMap; use std::collections::HashMap;
use std::env; use std::env;
use std::rc::Rc; use std::rc::Rc;
use url::Url; use url::Url;
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { pub fn init(s: &Rc<State>) {
let t = &CoreIsolate::state(i).borrow().resource_table.clone(); s.register_op_json_sync("op_exit", op_exit);
s.register_op_json_sync("op_env", op_env);
i.register_op("op_exit", s.stateful_json_op_sync(t, op_exit)); s.register_op_json_sync("op_exec_path", op_exec_path);
i.register_op("op_env", s.stateful_json_op_sync(t, op_env)); s.register_op_json_sync("op_set_env", op_set_env);
i.register_op("op_exec_path", s.stateful_json_op_sync(t, op_exec_path)); s.register_op_json_sync("op_get_env", op_get_env);
i.register_op("op_set_env", s.stateful_json_op_sync(t, op_set_env)); s.register_op_json_sync("op_delete_env", op_delete_env);
i.register_op("op_get_env", s.stateful_json_op_sync(t, op_get_env)); s.register_op_json_sync("op_hostname", op_hostname);
i.register_op("op_delete_env", s.stateful_json_op_sync(t, op_delete_env)); s.register_op_json_sync("op_loadavg", op_loadavg);
i.register_op("op_hostname", s.stateful_json_op_sync(t, op_hostname)); s.register_op_json_sync("op_os_release", op_os_release);
i.register_op("op_loadavg", s.stateful_json_op_sync(t, op_loadavg));
i.register_op("op_os_release", s.stateful_json_op_sync(t, op_os_release));
} }
fn op_exec_path( fn op_exec_path(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
_args: Value, _args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -47,7 +45,6 @@ struct SetEnv {
fn op_set_env( fn op_set_env(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -59,7 +56,6 @@ fn op_set_env(
fn op_env( fn op_env(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
_args: Value, _args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -75,7 +71,6 @@ struct GetEnv {
fn op_get_env( fn op_get_env(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -95,7 +90,6 @@ struct DeleteEnv {
fn op_delete_env( fn op_delete_env(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -112,7 +106,6 @@ struct Exit {
fn op_exit( fn op_exit(
_state: &State, _state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -122,7 +115,6 @@ fn op_exit(
fn op_loadavg( fn op_loadavg(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
_args: Value, _args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -136,7 +128,6 @@ fn op_loadavg(
fn op_hostname( fn op_hostname(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
_args: Value, _args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -148,7 +139,6 @@ fn op_hostname(
fn op_os_release( fn op_os_release(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
_args: Value, _args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {

View file

@ -1,28 +1,18 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::{Deserialize, Value};
use crate::state::State; use crate::state::State;
use deno_core::CoreIsolate;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ResourceTable; use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use serde_derive::Deserialize;
use serde_json::Value;
use std::path::Path; use std::path::Path;
use std::rc::Rc; use std::rc::Rc;
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { pub fn init(s: &Rc<State>) {
let t = &CoreIsolate::state(i).borrow().resource_table.clone(); s.register_op_json_sync("op_query_permission", op_query_permission);
s.register_op_json_sync("op_revoke_permission", op_revoke_permission);
i.register_op( s.register_op_json_sync("op_request_permission", op_request_permission);
"op_query_permission",
s.stateful_json_op_sync(t, op_query_permission),
);
i.register_op(
"op_revoke_permission",
s.stateful_json_op_sync(t, op_revoke_permission),
);
i.register_op(
"op_request_permission",
s.stateful_json_op_sync(t, op_request_permission),
);
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -34,7 +24,6 @@ struct PermissionArgs {
pub fn op_query_permission( pub fn op_query_permission(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -61,7 +50,6 @@ pub fn op_query_permission(
pub fn op_revoke_permission( pub fn op_revoke_permission(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -88,7 +76,6 @@ pub fn op_revoke_permission(
pub fn op_request_permission( pub fn op_request_permission(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {

View file

@ -1,26 +1,26 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::ops::dispatch_json::Deserialize;
use crate::ops::dispatch_json::JsonOp;
use crate::ops::dispatch_json::Value;
use crate::state::State; use crate::state::State;
use deno_core::plugin_api; use deno_core::plugin_api;
use deno_core::CoreIsolate; use deno_core::BufVec;
use deno_core::CoreIsolateState;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::Op; use deno_core::Op;
use deno_core::OpAsyncFuture; use deno_core::OpAsyncFuture;
use deno_core::OpId; use deno_core::OpId;
use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use dlopen::symbor::Library; use dlopen::symbor::Library;
use futures::prelude::*; use futures::prelude::*;
use serde_derive::Deserialize;
use serde_json::Value;
use std::path::PathBuf; use std::path::PathBuf;
use std::pin::Pin; use std::pin::Pin;
use std::rc::Rc; use std::rc::Rc;
use std::task::Context; use std::task::Context;
use std::task::Poll; use std::task::Poll;
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { pub fn init(s: &Rc<State>) {
i.register_op("op_open_plugin", s.stateful_json_op2(op_open_plugin)); s.register_op_json_sync("op_open_plugin", op_open_plugin);
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -30,12 +30,12 @@ struct OpenPluginArgs {
} }
pub fn op_open_plugin( pub fn op_open_plugin(
isolate_state: &mut CoreIsolateState, state: &State,
state: &Rc<State>,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<JsonOp, ErrBox> { ) -> Result<Value, ErrBox> {
state.check_unstable("Deno.openPlugin"); state.check_unstable("Deno.openPlugin");
let args: OpenPluginArgs = serde_json::from_value(args).unwrap(); let args: OpenPluginArgs = serde_json::from_value(args).unwrap();
let filename = PathBuf::from(&args.filename); let filename = PathBuf::from(&args.filename);
@ -45,22 +45,25 @@ pub fn op_open_plugin(
let plugin_lib = Library::open(filename).map(Rc::new)?; let plugin_lib = Library::open(filename).map(Rc::new)?;
let plugin_resource = PluginResource::new(&plugin_lib); let plugin_resource = PluginResource::new(&plugin_lib);
let mut resource_table = isolate_state.resource_table.borrow_mut(); let rid;
let rid = resource_table.add("plugin", Box::new(plugin_resource)); let deno_plugin_init;
let plugin_resource = resource_table.get::<PluginResource>(rid).unwrap(); {
let mut resource_table = state.resource_table.borrow_mut();
let deno_plugin_init = *unsafe { rid = resource_table.add("plugin", Box::new(plugin_resource));
plugin_resource deno_plugin_init = *unsafe {
.lib resource_table
.symbol::<plugin_api::InitFn>("deno_plugin_init") .get::<PluginResource>(rid)
.unwrap()
.lib
.symbol::<plugin_api::InitFn>("deno_plugin_init")
.unwrap()
};
} }
.unwrap();
drop(resource_table);
let mut interface = PluginInterface::new(isolate_state, &plugin_lib); let mut interface = PluginInterface::new(state, &plugin_lib);
deno_plugin_init(&mut interface); deno_plugin_init(&mut interface);
Ok(JsonOp::Sync(json!(rid))) Ok(json!(rid))
} }
struct PluginResource { struct PluginResource {
@ -74,19 +77,13 @@ impl PluginResource {
} }
struct PluginInterface<'a> { struct PluginInterface<'a> {
isolate_state: &'a mut CoreIsolateState, state: &'a State,
plugin_lib: &'a Rc<Library>, plugin_lib: &'a Rc<Library>,
} }
impl<'a> PluginInterface<'a> { impl<'a> PluginInterface<'a> {
fn new( fn new(state: &'a State, plugin_lib: &'a Rc<Library>) -> Self {
isolate_state: &'a mut CoreIsolateState, Self { state, plugin_lib }
plugin_lib: &'a Rc<Library>,
) -> Self {
Self {
isolate_state,
plugin_lib,
}
} }
} }
@ -102,11 +99,11 @@ impl<'a> plugin_api::Interface for PluginInterface<'a> {
dispatch_op_fn: plugin_api::DispatchOpFn, dispatch_op_fn: plugin_api::DispatchOpFn,
) -> OpId { ) -> OpId {
let plugin_lib = self.plugin_lib.clone(); let plugin_lib = self.plugin_lib.clone();
self.isolate_state.op_registry.register( self.state.register_op(
name, name,
move |isolate_state, zero_copy| { move |state: Rc<State>, mut zero_copy: BufVec| {
let mut interface = PluginInterface::new(isolate_state, &plugin_lib); let mut interface = PluginInterface::new(&state, &plugin_lib);
let op = dispatch_op_fn(&mut interface, zero_copy); let op = dispatch_op_fn(&mut interface, &mut zero_copy);
match op { match op {
sync_op @ Op::Sync(..) => sync_op, sync_op @ Op::Sync(..) => sync_op,
Op::Async(fut) => { Op::Async(fut) => {
@ -115,6 +112,7 @@ impl<'a> plugin_api::Interface for PluginInterface<'a> {
Op::AsyncUnref(fut) => { Op::AsyncUnref(fut) => {
Op::AsyncUnref(PluginOpAsyncFuture::new(&plugin_lib, fut)) Op::AsyncUnref(PluginOpAsyncFuture::new(&plugin_lib, fut))
} }
_ => unreachable!(),
} }
}, },
) )

View file

@ -1,35 +1,30 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::{Deserialize, Value};
use super::io::{std_file_resource, StreamResource, StreamResourceHolder}; use super::io::{std_file_resource, StreamResource, StreamResourceHolder};
use crate::signal::kill; use crate::signal::kill;
use crate::state::State; use crate::state::State;
use deno_core::BufVec; use deno_core::BufVec;
use deno_core::CoreIsolate;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ResourceTable; use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use futures::future::poll_fn; use futures::future::poll_fn;
use futures::future::FutureExt; use futures::future::FutureExt;
use std::cell::RefCell; use serde_derive::Deserialize;
use serde_json::Value;
use std::rc::Rc; use std::rc::Rc;
use tokio::process::Command; use tokio::process::Command;
#[cfg(unix)] #[cfg(unix)]
use std::os::unix::process::ExitStatusExt; use std::os::unix::process::ExitStatusExt;
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { pub fn init(s: &Rc<State>) {
let t = &CoreIsolate::state(i).borrow().resource_table.clone(); s.register_op_json_sync("op_run", op_run);
s.register_op_json_async("op_run_status", op_run_status);
i.register_op("op_run", s.stateful_json_op_sync(t, op_run)); s.register_op_json_sync("op_kill", op_kill);
i.register_op("op_run_status", s.stateful_json_op_async(t, op_run_status));
i.register_op("op_kill", s.stateful_json_op_sync(t, op_kill));
} }
fn clone_file( fn clone_file(state: &State, rid: u32) -> Result<std::fs::File, ErrBox> {
rid: u32, std_file_resource(state, rid, move |r| match r {
resource_table: &mut ResourceTable,
) -> Result<std::fs::File, ErrBox> {
std_file_resource(resource_table, rid, move |r| match r {
Ok(std_file) => std_file.try_clone().map_err(ErrBox::from), Ok(std_file) => std_file.try_clone().map_err(ErrBox::from),
Err(_) => Err(ErrBox::bad_resource_id()), Err(_) => Err(ErrBox::bad_resource_id()),
}) })
@ -64,7 +59,6 @@ struct ChildResource {
fn op_run( fn op_run(
state: &State, state: &State,
resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -90,21 +84,21 @@ fn op_run(
if run_args.stdin != "" { if run_args.stdin != "" {
c.stdin(subprocess_stdio_map(run_args.stdin.as_ref())?); c.stdin(subprocess_stdio_map(run_args.stdin.as_ref())?);
} else { } else {
let file = clone_file(run_args.stdin_rid, resource_table)?; let file = clone_file(state, run_args.stdin_rid)?;
c.stdin(file); c.stdin(file);
} }
if run_args.stdout != "" { if run_args.stdout != "" {
c.stdout(subprocess_stdio_map(run_args.stdout.as_ref())?); c.stdout(subprocess_stdio_map(run_args.stdout.as_ref())?);
} else { } else {
let file = clone_file(run_args.stdout_rid, resource_table)?; let file = clone_file(state, run_args.stdout_rid)?;
c.stdout(file); c.stdout(file);
} }
if run_args.stderr != "" { if run_args.stderr != "" {
c.stderr(subprocess_stdio_map(run_args.stderr.as_ref())?); c.stderr(subprocess_stdio_map(run_args.stderr.as_ref())?);
} else { } else {
let file = clone_file(run_args.stderr_rid, resource_table)?; let file = clone_file(state, run_args.stderr_rid)?;
c.stderr(file); c.stderr(file);
} }
@ -117,7 +111,7 @@ fn op_run(
let stdin_rid = match child.stdin.take() { let stdin_rid = match child.stdin.take() {
Some(child_stdin) => { Some(child_stdin) => {
let rid = resource_table.add( let rid = state.resource_table.borrow_mut().add(
"childStdin", "childStdin",
Box::new(StreamResourceHolder::new(StreamResource::ChildStdin( Box::new(StreamResourceHolder::new(StreamResource::ChildStdin(
child_stdin, child_stdin,
@ -130,7 +124,7 @@ fn op_run(
let stdout_rid = match child.stdout.take() { let stdout_rid = match child.stdout.take() {
Some(child_stdout) => { Some(child_stdout) => {
let rid = resource_table.add( let rid = state.resource_table.borrow_mut().add(
"childStdout", "childStdout",
Box::new(StreamResourceHolder::new(StreamResource::ChildStdout( Box::new(StreamResourceHolder::new(StreamResource::ChildStdout(
child_stdout, child_stdout,
@ -143,7 +137,7 @@ fn op_run(
let stderr_rid = match child.stderr.take() { let stderr_rid = match child.stderr.take() {
Some(child_stderr) => { Some(child_stderr) => {
let rid = resource_table.add( let rid = state.resource_table.borrow_mut().add(
"childStderr", "childStderr",
Box::new(StreamResourceHolder::new(StreamResource::ChildStderr( Box::new(StreamResourceHolder::new(StreamResource::ChildStderr(
child_stderr, child_stderr,
@ -155,7 +149,10 @@ fn op_run(
}; };
let child_resource = ChildResource { child }; let child_resource = ChildResource { child };
let child_rid = resource_table.add("child", Box::new(child_resource)); let child_rid = state
.resource_table
.borrow_mut()
.add("child", Box::new(child_resource));
Ok(json!({ Ok(json!({
"rid": child_rid, "rid": child_rid,
@ -174,7 +171,6 @@ struct RunStatusArgs {
async fn op_run_status( async fn op_run_status(
state: Rc<State>, state: Rc<State>,
resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -184,7 +180,7 @@ async fn op_run_status(
state.check_run()?; state.check_run()?;
let run_status = poll_fn(|cx| { let run_status = poll_fn(|cx| {
let mut resource_table = resource_table.borrow_mut(); let mut resource_table = state.resource_table.borrow_mut();
let child_resource = resource_table let child_resource = resource_table
.get_mut::<ChildResource>(rid) .get_mut::<ChildResource>(rid)
.ok_or_else(ErrBox::bad_resource_id)?; .ok_or_else(ErrBox::bad_resource_id)?;
@ -220,7 +216,6 @@ struct KillArgs {
fn op_kill( fn op_kill(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {

View file

@ -1,26 +1,20 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::Value;
use crate::state::State; use crate::state::State;
use deno_core::CoreIsolate;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ResourceTable; use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use rand::thread_rng; use rand::thread_rng;
use rand::Rng; use rand::Rng;
use serde_json::Value;
use std::rc::Rc; use std::rc::Rc;
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { pub fn init(s: &Rc<State>) {
let t = &CoreIsolate::state(i).borrow().resource_table.clone(); s.register_op_json_sync("op_get_random_values", op_get_random_values);
i.register_op(
"op_get_random_values",
s.stateful_json_op_sync(t, op_get_random_values),
);
} }
fn op_get_random_values( fn op_get_random_values(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
_args: Value, _args: Value,
zero_copy: &mut [ZeroCopyBuf], zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {

View file

@ -1,26 +1,21 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::{Deserialize, Value};
use crate::repl; use crate::repl;
use crate::repl::Repl; use crate::repl::Repl;
use crate::state::State; use crate::state::State;
use deno_core::BufVec; use deno_core::BufVec;
use deno_core::CoreIsolate;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ResourceTable; use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use std::cell::RefCell; use serde_derive::Deserialize;
use serde_json::Value;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex; use std::sync::Mutex;
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { pub fn init(s: &Rc<State>) {
let t = &CoreIsolate::state(i).borrow().resource_table.clone(); s.register_op_json_sync("op_repl_start", op_repl_start);
s.register_op_json_async("op_repl_readline", op_repl_readline);
i.register_op("op_repl_start", s.stateful_json_op_sync(t, op_repl_start));
i.register_op(
"op_repl_readline",
s.stateful_json_op_async(t, op_repl_readline),
);
} }
struct ReplResource(Arc<Mutex<Repl>>); struct ReplResource(Arc<Mutex<Repl>>);
@ -33,7 +28,6 @@ struct ReplStartArgs {
fn op_repl_start( fn op_repl_start(
state: &State, state: &State,
resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -43,7 +37,10 @@ fn op_repl_start(
repl::history_path(&state.global_state.dir, &args.history_file); repl::history_path(&state.global_state.dir, &args.history_file);
let repl = repl::Repl::new(history_path); let repl = repl::Repl::new(history_path);
let resource = ReplResource(Arc::new(Mutex::new(repl))); let resource = ReplResource(Arc::new(Mutex::new(repl)));
let rid = resource_table.add("repl", Box::new(resource)); let rid = state
.resource_table
.borrow_mut()
.add("repl", Box::new(resource));
Ok(json!(rid)) Ok(json!(rid))
} }
@ -54,8 +51,7 @@ struct ReplReadlineArgs {
} }
async fn op_repl_readline( async fn op_repl_readline(
_state: Rc<State>, state: Rc<State>,
resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -63,7 +59,7 @@ async fn op_repl_readline(
let rid = args.rid as u32; let rid = args.rid as u32;
let prompt = args.prompt; let prompt = args.prompt;
debug!("op_repl_readline {} {}", rid, prompt); debug!("op_repl_readline {} {}", rid, prompt);
let resource_table = resource_table.borrow(); let resource_table = state.resource_table.borrow();
let resource = resource_table let resource = resource_table
.get::<ReplResource>(rid) .get::<ReplResource>(rid)
.ok_or_else(ErrBox::bad_resource_id)?; .ok_or_else(ErrBox::bad_resource_id)?;

View file

@ -1,33 +1,31 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::{Deserialize, Value};
use crate::state::State; use crate::state::State;
use deno_core::CoreIsolate;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ResourceTable; use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use serde_derive::Deserialize;
use serde_json::Value;
use std::rc::Rc; use std::rc::Rc;
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { pub fn init(s: &Rc<State>) {
let t = &CoreIsolate::state(i).borrow().resource_table.clone(); s.register_op_json_sync("op_resources", op_resources);
s.register_op_json_sync("op_close", op_close);
i.register_op("op_resources", s.stateful_json_op_sync(t, op_resources));
i.register_op("op_close", s.stateful_json_op_sync(t, op_close));
} }
fn op_resources( fn op_resources(
_state: &State, state: &State,
resource_table: &mut ResourceTable,
_args: Value, _args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
let resource_table = state.resource_table.borrow();
let serialized_resources = resource_table.entries(); let serialized_resources = resource_table.entries();
Ok(json!(serialized_resources)) Ok(json!(serialized_resources))
} }
/// op_close removes a resource from the resource table. /// op_close removes a resource from the resource table.
fn op_close( fn op_close(
_state: &State, state: &State,
resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -36,7 +34,9 @@ fn op_close(
rid: i32, rid: i32,
} }
let args: CloseArgs = serde_json::from_value(args)?; let args: CloseArgs = serde_json::from_value(args)?;
resource_table state
.resource_table
.borrow_mut()
.close(args.rid as u32) .close(args.rid as u32)
.ok_or_else(ErrBox::bad_resource_id)?; .ok_or_else(ErrBox::bad_resource_id)?;
Ok(json!({})) Ok(json!({}))

View file

@ -1,28 +1,25 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::Value;
use crate::colors; use crate::colors;
use crate::state::State; use crate::state::State;
use crate::version; use crate::version;
use crate::DenoSubcommand; use crate::DenoSubcommand;
use deno_core::CoreIsolate;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ModuleSpecifier; use deno_core::ModuleSpecifier;
use deno_core::ResourceTable; use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use serde_json::Value;
use std::env; use std::env;
use std::rc::Rc; use std::rc::Rc;
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { pub fn init(s: &Rc<State>) {
let t = &CoreIsolate::state(i).borrow().resource_table.clone(); s.register_op_json_sync("op_start", op_start);
s.register_op_json_sync("op_main_module", op_main_module);
i.register_op("op_start", s.stateful_json_op_sync(t, op_start)); s.register_op_json_sync("op_metrics", op_metrics);
i.register_op("op_main_module", s.stateful_json_op_sync(t, op_main_module));
i.register_op("op_metrics", s.stateful_json_op_sync(t, op_metrics));
} }
fn op_start( fn op_start(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
_args: Value, _args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -48,7 +45,6 @@ fn op_start(
fn op_main_module( fn op_main_module(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
_args: Value, _args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -63,7 +59,6 @@ fn op_main_module(
fn op_metrics( fn op_metrics(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
_args: Value, _args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {

View file

@ -1,23 +1,21 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::{Deserialize, Value};
use crate::futures::FutureExt; use crate::futures::FutureExt;
use crate::state::State; use crate::state::State;
use crate::tsc::runtime_bundle; use crate::tsc::runtime_bundle;
use crate::tsc::runtime_compile; use crate::tsc::runtime_compile;
use crate::tsc::runtime_transpile; use crate::tsc::runtime_transpile;
use deno_core::BufVec; use deno_core::BufVec;
use deno_core::CoreIsolate;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ResourceTable; use deno_core::OpRegistry;
use std::cell::RefCell; use serde_derive::Deserialize;
use serde_json::Value;
use std::collections::HashMap; use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { pub fn init(s: &Rc<State>) {
let t = &CoreIsolate::state(i).borrow().resource_table.clone(); s.register_op_json_async("op_compile", op_compile);
s.register_op_json_async("op_transpile", op_transpile);
i.register_op("op_compile", s.stateful_json_op_async(t, op_compile));
i.register_op("op_transpile", s.stateful_json_op_async(t, op_transpile));
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
@ -31,7 +29,6 @@ struct CompileArgs {
async fn op_compile( async fn op_compile(
state: Rc<State>, state: Rc<State>,
_resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_data: BufVec, _data: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -70,7 +67,6 @@ struct TranspileArgs {
async fn op_transpile( async fn op_transpile(
state: Rc<State>, state: Rc<State>,
_resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_data: BufVec, _data: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {

View file

@ -1,35 +1,26 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::Value;
use crate::state::State; use crate::state::State;
use deno_core::BufVec; use deno_core::BufVec;
use deno_core::CoreIsolate;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ResourceTable; use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use std::cell::RefCell; use serde_json::Value;
use std::rc::Rc; use std::rc::Rc;
#[cfg(unix)]
use super::dispatch_json::Deserialize;
#[cfg(unix)] #[cfg(unix)]
use futures::future::poll_fn; use futures::future::poll_fn;
#[cfg(unix)] #[cfg(unix)]
use serde_derive::Deserialize;
#[cfg(unix)]
use std::task::Waker; use std::task::Waker;
#[cfg(unix)] #[cfg(unix)]
use tokio::signal::unix::{signal, Signal, SignalKind}; use tokio::signal::unix::{signal, Signal, SignalKind};
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { pub fn init(s: &Rc<State>) {
let t = &CoreIsolate::state(i).borrow().resource_table.clone(); s.register_op_json_sync("op_signal_bind", op_signal_bind);
s.register_op_json_sync("op_signal_unbind", op_signal_unbind);
i.register_op("op_signal_bind", s.stateful_json_op_sync(t, op_signal_bind)); s.register_op_json_async("op_signal_poll", op_signal_poll);
i.register_op(
"op_signal_unbind",
s.stateful_json_op_sync(t, op_signal_unbind),
);
i.register_op(
"op_signal_poll",
s.stateful_json_op_async(t, op_signal_poll),
);
} }
#[cfg(unix)] #[cfg(unix)]
@ -52,13 +43,12 @@ struct SignalArgs {
#[cfg(unix)] #[cfg(unix)]
fn op_signal_bind( fn op_signal_bind(
state: &State, state: &State,
resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
state.check_unstable("Deno.signal"); state.check_unstable("Deno.signal");
let args: BindSignalArgs = serde_json::from_value(args)?; let args: BindSignalArgs = serde_json::from_value(args)?;
let rid = resource_table.add( let rid = state.resource_table.borrow_mut().add(
"signal", "signal",
Box::new(SignalStreamResource( Box::new(SignalStreamResource(
signal(SignalKind::from_raw(args.signo)).expect(""), signal(SignalKind::from_raw(args.signo)).expect(""),
@ -73,7 +63,6 @@ fn op_signal_bind(
#[cfg(unix)] #[cfg(unix)]
async fn op_signal_poll( async fn op_signal_poll(
state: Rc<State>, state: Rc<State>,
resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -82,7 +71,7 @@ async fn op_signal_poll(
let rid = args.rid as u32; let rid = args.rid as u32;
let future = poll_fn(move |cx| { let future = poll_fn(move |cx| {
let mut resource_table = resource_table.borrow_mut(); let mut resource_table = state.resource_table.borrow_mut();
if let Some(mut signal) = if let Some(mut signal) =
resource_table.get_mut::<SignalStreamResource>(rid) resource_table.get_mut::<SignalStreamResource>(rid)
{ {
@ -98,14 +87,14 @@ async fn op_signal_poll(
#[cfg(unix)] #[cfg(unix)]
pub fn op_signal_unbind( pub fn op_signal_unbind(
state: &State, state: &State,
resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
state.check_unstable("Deno.signal"); state.check_unstable("Deno.signal");
let mut resource_table = state.resource_table.borrow_mut();
let args: SignalArgs = serde_json::from_value(args)?; let args: SignalArgs = serde_json::from_value(args)?;
let rid = args.rid as u32; let rid = args.rid as u32;
let resource = resource_table.get::<SignalStreamResource>(rid); let resource = resource_table.get_mut::<SignalStreamResource>(rid);
if let Some(signal) = resource { if let Some(signal) = resource {
if let Some(waker) = &signal.1 { if let Some(waker) = &signal.1 {
// Wakes up the pending poll if exists. // Wakes up the pending poll if exists.
@ -122,7 +111,6 @@ pub fn op_signal_unbind(
#[cfg(not(unix))] #[cfg(not(unix))]
pub fn op_signal_bind( pub fn op_signal_bind(
_state: &State, _state: &State,
_resource_table: &mut ResourceTable,
_args: Value, _args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -132,7 +120,6 @@ pub fn op_signal_bind(
#[cfg(not(unix))] #[cfg(not(unix))]
fn op_signal_unbind( fn op_signal_unbind(
_state: &State, _state: &State,
_resource_table: &mut ResourceTable,
_args: Value, _args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -142,7 +129,6 @@ fn op_signal_unbind(
#[cfg(not(unix))] #[cfg(not(unix))]
async fn op_signal_poll( async fn op_signal_poll(
_state: Rc<State>, _state: Rc<State>,
_resource_table: Rc<RefCell<ResourceTable>>,
_args: Value, _args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {

View file

@ -1,34 +1,25 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::{Deserialize, Value};
use crate::state::State; use crate::state::State;
use deno_core::BufVec; use deno_core::BufVec;
use deno_core::CoreIsolate;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ResourceTable; use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use futures::future::FutureExt; use futures::future::FutureExt;
use std::cell::RefCell; use serde_derive::Deserialize;
use serde_json::Value;
use std::rc::Rc; use std::rc::Rc;
use std::time::Duration; use std::time::Duration;
use std::time::Instant; use std::time::Instant;
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { pub fn init(s: &Rc<State>) {
let t = &CoreIsolate::state(i).borrow().resource_table.clone(); s.register_op_json_sync("op_global_timer_stop", op_global_timer_stop);
s.register_op_json_async("op_global_timer", op_global_timer);
i.register_op( s.register_op_json_sync("op_now", op_now);
"op_global_timer_stop",
s.stateful_json_op_sync(t, op_global_timer_stop),
);
i.register_op(
"op_global_timer",
s.stateful_json_op_async(t, op_global_timer),
);
i.register_op("op_now", s.stateful_json_op_sync(t, op_now));
} }
fn op_global_timer_stop( fn op_global_timer_stop(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
_args: Value, _args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -43,7 +34,6 @@ struct GlobalTimerArgs {
async fn op_global_timer( async fn op_global_timer(
state: Rc<State>, state: Rc<State>,
_resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -66,7 +56,6 @@ async fn op_global_timer(
// nanoseconds are rounded on 2ms. // nanoseconds are rounded on 2ms.
fn op_now( fn op_now(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
_args: Value, _args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {

View file

@ -1,15 +1,15 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::{Deserialize, Value};
use super::io::{StreamResource, StreamResourceHolder}; use super::io::{StreamResource, StreamResourceHolder};
use crate::resolve_addr::resolve_addr; use crate::resolve_addr::resolve_addr;
use crate::state::State; use crate::state::State;
use deno_core::BufVec; use deno_core::BufVec;
use deno_core::CoreIsolate;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ResourceTable; use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use futures::future::poll_fn; use futures::future::poll_fn;
use std::cell::RefCell; use serde_derive::Deserialize;
use serde_json::Value;
use std::convert::From; use std::convert::From;
use std::fs::File; use std::fs::File;
use std::io::BufReader; use std::io::BufReader;
@ -31,16 +31,11 @@ use tokio_rustls::{
}; };
use webpki::DNSNameRef; use webpki::DNSNameRef;
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { pub fn init(s: &Rc<State>) {
let t = &CoreIsolate::state(i).borrow().resource_table.clone(); s.register_op_json_async("op_start_tls", op_start_tls);
s.register_op_json_async("op_connect_tls", op_connect_tls);
i.register_op("op_start_tls", s.stateful_json_op_async(t, op_start_tls)); s.register_op_json_sync("op_listen_tls", op_listen_tls);
i.register_op( s.register_op_json_async("op_accept_tls", op_accept_tls);
"op_connect_tls",
s.stateful_json_op_async(t, op_connect_tls),
);
i.register_op("op_listen_tls", s.stateful_json_op_sync(t, op_listen_tls));
i.register_op("op_accept_tls", s.stateful_json_op_async(t, op_accept_tls));
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -62,7 +57,6 @@ struct StartTLSArgs {
async fn op_start_tls( async fn op_start_tls(
state: Rc<State>, state: Rc<State>,
resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -82,8 +76,8 @@ async fn op_start_tls(
} }
let mut resource_holder = { let mut resource_holder = {
let mut resource_table_ = resource_table.borrow_mut(); let mut resource_table = state.resource_table.borrow_mut();
match resource_table_.remove::<StreamResourceHolder>(rid) { match resource_table.remove::<StreamResourceHolder>(rid) {
Some(resource) => *resource, Some(resource) => *resource,
None => return Err(ErrBox::bad_resource_id()), None => return Err(ErrBox::bad_resource_id()),
} }
@ -110,8 +104,8 @@ async fn op_start_tls(
DNSNameRef::try_from_ascii_str(&domain).expect("Invalid DNS lookup"); DNSNameRef::try_from_ascii_str(&domain).expect("Invalid DNS lookup");
let tls_stream = tls_connector.connect(dnsname, tcp_stream).await?; let tls_stream = tls_connector.connect(dnsname, tcp_stream).await?;
let mut resource_table_ = resource_table.borrow_mut(); let mut resource_table = state.resource_table.borrow_mut();
let rid = resource_table_.add( let rid = resource_table.add(
"clientTlsStream", "clientTlsStream",
Box::new(StreamResourceHolder::new(StreamResource::ClientTlsStream( Box::new(StreamResourceHolder::new(StreamResource::ClientTlsStream(
Box::new(tls_stream), Box::new(tls_stream),
@ -137,7 +131,6 @@ async fn op_start_tls(
async fn op_connect_tls( async fn op_connect_tls(
state: Rc<State>, state: Rc<State>,
resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -170,8 +163,8 @@ async fn op_connect_tls(
let dnsname = let dnsname =
DNSNameRef::try_from_ascii_str(&domain).expect("Invalid DNS lookup"); DNSNameRef::try_from_ascii_str(&domain).expect("Invalid DNS lookup");
let tls_stream = tls_connector.connect(dnsname, tcp_stream).await?; let tls_stream = tls_connector.connect(dnsname, tcp_stream).await?;
let mut resource_table_ = resource_table.borrow_mut(); let mut resource_table = state.resource_table.borrow_mut();
let rid = resource_table_.add( let rid = resource_table.add(
"clientTlsStream", "clientTlsStream",
Box::new(StreamResourceHolder::new(StreamResource::ClientTlsStream( Box::new(StreamResourceHolder::new(StreamResource::ClientTlsStream(
Box::new(tls_stream), Box::new(tls_stream),
@ -306,7 +299,6 @@ struct ListenTlsArgs {
fn op_listen_tls( fn op_listen_tls(
state: &State, state: &State,
resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -336,7 +328,10 @@ fn op_listen_tls(
local_addr, local_addr,
}; };
let rid = resource_table.add("tlsListener", Box::new(tls_listener_resource)); let rid = state
.resource_table
.borrow_mut()
.add("tlsListener", Box::new(tls_listener_resource));
Ok(json!({ Ok(json!({
"rid": rid, "rid": rid,
@ -354,15 +349,14 @@ struct AcceptTlsArgs {
} }
async fn op_accept_tls( async fn op_accept_tls(
_state: Rc<State>, state: Rc<State>,
resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
let args: AcceptTlsArgs = serde_json::from_value(args)?; let args: AcceptTlsArgs = serde_json::from_value(args)?;
let rid = args.rid as u32; let rid = args.rid as u32;
let accept_fut = poll_fn(|cx| { let accept_fut = poll_fn(|cx| {
let mut resource_table = resource_table.borrow_mut(); let mut resource_table = state.resource_table.borrow_mut();
let listener_resource = resource_table let listener_resource = resource_table
.get_mut::<TlsListenerResource>(rid) .get_mut::<TlsListenerResource>(rid)
.ok_or_else(|| ErrBox::bad_resource("Listener has been closed"))?; .ok_or_else(|| ErrBox::bad_resource("Listener has been closed"))?;
@ -386,7 +380,7 @@ async fn op_accept_tls(
let local_addr = tcp_stream.local_addr()?; let local_addr = tcp_stream.local_addr()?;
let remote_addr = tcp_stream.peer_addr()?; let remote_addr = tcp_stream.peer_addr()?;
let tls_acceptor = { let tls_acceptor = {
let resource_table = resource_table.borrow(); let resource_table = state.resource_table.borrow();
let resource = resource_table let resource = resource_table
.get::<TlsListenerResource>(rid) .get::<TlsListenerResource>(rid)
.ok_or_else(ErrBox::bad_resource_id) .ok_or_else(ErrBox::bad_resource_id)
@ -395,7 +389,7 @@ async fn op_accept_tls(
}; };
let tls_stream = tls_acceptor.accept(tcp_stream).await?; let tls_stream = tls_acceptor.accept(tcp_stream).await?;
let rid = { let rid = {
let mut resource_table = resource_table.borrow_mut(); let mut resource_table = state.resource_table.borrow_mut();
resource_table.add( resource_table.add(
"serverTlsStream", "serverTlsStream",
Box::new(StreamResourceHolder::new(StreamResource::ServerTlsStream( Box::new(StreamResourceHolder::new(StreamResource::ServerTlsStream(

View file

@ -1,10 +1,10 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::io::std_file_resource; use super::io::std_file_resource;
use super::io::{StreamResource, StreamResourceHolder}; use super::io::{StreamResource, StreamResourceHolder};
use crate::state::State; use crate::state::State;
use deno_core::CoreIsolate;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ResourceTable; use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
#[cfg(unix)] #[cfg(unix)]
use nix::sys::termios; use nix::sys::termios;
@ -36,15 +36,10 @@ fn get_windows_handle(
Ok(handle) Ok(handle)
} }
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { pub fn init(s: &Rc<State>) {
let t = &CoreIsolate::state(i).borrow().resource_table.clone(); s.register_op_json_sync("op_set_raw", op_set_raw);
s.register_op_json_sync("op_isatty", op_isatty);
i.register_op("op_set_raw", s.stateful_json_op_sync(t, op_set_raw)); s.register_op_json_sync("op_console_size", op_console_size);
i.register_op("op_isatty", s.stateful_json_op_sync(t, op_isatty));
i.register_op(
"op_console_size",
s.stateful_json_op_sync(t, op_console_size),
);
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -55,7 +50,6 @@ struct SetRawArgs {
fn op_set_raw( fn op_set_raw(
state: &State, state: &State,
resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -75,6 +69,7 @@ fn op_set_raw(
use winapi::shared::minwindef::FALSE; use winapi::shared::minwindef::FALSE;
use winapi::um::{consoleapi, handleapi}; 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 = resource_table.get_mut::<StreamResourceHolder>(rid);
if resource_holder.is_none() { if resource_holder.is_none() {
return Err(ErrBox::bad_resource_id()); return Err(ErrBox::bad_resource_id());
@ -140,6 +135,7 @@ fn op_set_raw(
{ {
use std::os::unix::io::AsRawFd; 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 = resource_table.get_mut::<StreamResourceHolder>(rid);
if resource_holder.is_none() { if resource_holder.is_none() {
return Err(ErrBox::bad_resource_id()); return Err(ErrBox::bad_resource_id());
@ -221,37 +217,35 @@ struct IsattyArgs {
} }
fn op_isatty( fn op_isatty(
_state: &State, state: &State,
resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
let args: IsattyArgs = serde_json::from_value(args)?; let args: IsattyArgs = serde_json::from_value(args)?;
let rid = args.rid; let rid = args.rid;
let isatty: bool = let isatty: bool = std_file_resource(state, rid as u32, move |r| match r {
std_file_resource(resource_table, rid as u32, move |r| match r { Ok(std_file) => {
Ok(std_file) => { #[cfg(windows)]
#[cfg(windows)] {
{ use winapi::um::consoleapi;
use winapi::um::consoleapi;
let handle = get_windows_handle(&std_file)?; let handle = get_windows_handle(&std_file)?;
let mut test_mode: DWORD = 0; let mut test_mode: DWORD = 0;
// If I cannot get mode out of console, it is not a console. // If I cannot get mode out of console, it is not a console.
Ok(unsafe { consoleapi::GetConsoleMode(handle, &mut test_mode) != 0 }) Ok(unsafe { consoleapi::GetConsoleMode(handle, &mut test_mode) != 0 })
}
#[cfg(unix)]
{
use std::os::unix::io::AsRawFd;
let raw_fd = std_file.as_raw_fd();
Ok(unsafe { libc::isatty(raw_fd as libc::c_int) == 1 })
}
} }
Err(StreamResource::FsFile(_)) => unreachable!(), #[cfg(unix)]
Err(StreamResource::Stdin(..)) => Ok(atty::is(atty::Stream::Stdin)), {
_ => Ok(false), use std::os::unix::io::AsRawFd;
})?; let raw_fd = std_file.as_raw_fd();
Ok(unsafe { libc::isatty(raw_fd as libc::c_int) == 1 })
}
}
Err(StreamResource::FsFile(_)) => unreachable!(),
Err(StreamResource::Stdin(..)) => Ok(atty::is(atty::Stream::Stdin)),
_ => Ok(false),
})?;
Ok(json!(isatty)) Ok(json!(isatty))
} }
@ -268,7 +262,6 @@ struct ConsoleSize {
fn op_console_size( fn op_console_size(
state: &State, state: &State,
resource_table: &mut ResourceTable,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -276,7 +269,7 @@ fn op_console_size(
let args: ConsoleSizeArgs = serde_json::from_value(args)?; let args: ConsoleSizeArgs = serde_json::from_value(args)?;
let rid = args.rid; let rid = args.rid;
let size = std_file_resource(resource_table, rid as u32, move |r| match r { let size = std_file_resource(state, rid as u32, move |r| match r {
Ok(std_file) => { Ok(std_file) => {
#[cfg(windows)] #[cfg(windows)]
{ {

View file

@ -1,112 +1,39 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::{JsonOp, Value};
use crate::ops::json_op;
use crate::state::State; use crate::state::State;
use crate::web_worker::WebWorkerHandle; use crate::web_worker::WebWorkerHandle;
use crate::worker::WorkerEvent; use crate::worker::WorkerEvent;
use deno_core::CoreIsolate; use deno_core::OpRegistry;
use deno_core::CoreIsolateState;
use deno_core::ErrBox;
use deno_core::ZeroCopyBuf;
use futures::channel::mpsc; use futures::channel::mpsc;
use std::convert::From;
use std::rc::Rc; use std::rc::Rc;
pub fn web_worker_op<D>(
sender: mpsc::Sender<WorkerEvent>,
dispatcher: D,
) -> impl Fn(
&mut CoreIsolateState,
Value,
&mut [ZeroCopyBuf],
) -> Result<JsonOp, ErrBox>
where
D: Fn(
&mpsc::Sender<WorkerEvent>,
Value,
&mut [ZeroCopyBuf],
) -> Result<JsonOp, ErrBox>,
{
move |_isolate_state: &mut CoreIsolateState,
args: Value,
zero_copy: &mut [ZeroCopyBuf]|
-> Result<JsonOp, ErrBox> { dispatcher(&sender, args, zero_copy) }
}
pub fn web_worker_op2<D>(
handle: WebWorkerHandle,
sender: mpsc::Sender<WorkerEvent>,
dispatcher: D,
) -> impl Fn(
&mut CoreIsolateState,
Value,
&mut [ZeroCopyBuf],
) -> Result<JsonOp, ErrBox>
where
D: Fn(
WebWorkerHandle,
&mpsc::Sender<WorkerEvent>,
Value,
&mut [ZeroCopyBuf],
) -> Result<JsonOp, ErrBox>,
{
move |_isolate_state: &mut CoreIsolateState,
args: Value,
zero_copy: &mut [ZeroCopyBuf]|
-> Result<JsonOp, ErrBox> {
dispatcher(handle.clone(), &sender, args, zero_copy)
}
}
pub fn init( pub fn init(
i: &mut CoreIsolate,
s: &Rc<State>, s: &Rc<State>,
sender: &mpsc::Sender<WorkerEvent>, sender: &mpsc::Sender<WorkerEvent>,
handle: WebWorkerHandle, handle: WebWorkerHandle,
) { ) {
i.register_op( // Post message to host as guest worker.
let sender_ = sender.clone();
s.register_op_json_sync(
"op_worker_post_message", "op_worker_post_message",
s.core_op(json_op(web_worker_op( move |_state, _args, bufs| {
sender.clone(), assert_eq!(bufs.len(), 1, "Invalid number of arguments");
op_worker_post_message, let msg_buf: Box<[u8]> = (*bufs[0]).into();
))), sender_
.clone()
.try_send(WorkerEvent::Message(msg_buf))
.expect("Failed to post message to host");
Ok(json!({}))
},
); );
i.register_op(
"op_worker_close",
s.core_op(json_op(web_worker_op2(
handle,
sender.clone(),
op_worker_close,
))),
);
}
/// Post message to host as guest worker // Notify host that guest worker closes.
fn op_worker_post_message( let sender_ = sender.clone();
sender: &mpsc::Sender<WorkerEvent>, s.register_op_json_sync("op_worker_close", move |_state, _args, _bufs| {
_args: Value, // Notify parent that we're finished
data: &mut [ZeroCopyBuf], sender_.clone().close_channel();
) -> Result<JsonOp, ErrBox> { // Terminate execution of current worker
assert_eq!(data.len(), 1, "Invalid number of arguments"); handle.terminate();
let d = Vec::from(&*data[0]).into_boxed_slice(); Ok(json!({}))
let mut sender = sender.clone(); });
sender
.try_send(WorkerEvent::Message(d))
.expect("Failed to post message to host");
Ok(JsonOp::Sync(json!({})))
}
/// Notify host that guest worker closes
fn op_worker_close(
handle: WebWorkerHandle,
sender: &mpsc::Sender<WorkerEvent>,
_args: Value,
_data: &mut [ZeroCopyBuf],
) -> Result<JsonOp, ErrBox> {
let mut sender = sender.clone();
// Notify parent that we're finished
sender.close_channel();
// Terminate execution of current worker
handle.terminate();
Ok(JsonOp::Sync(json!({})))
} }

View file

@ -1,15 +1,16 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::{Deserialize, JsonOp, Value};
use crate::state::State; use crate::state::State;
use core::task::Poll; use core::task::Poll;
use deno_core::BufVec;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ZeroCopyBuf; use deno_core::OpRegistry;
use deno_core::{CoreIsolate, CoreIsolateState}; use futures::future::poll_fn;
use futures::future::{poll_fn, FutureExt};
use futures::StreamExt; use futures::StreamExt;
use futures::{ready, SinkExt}; use futures::{ready, SinkExt};
use http::{Method, Request, Uri}; use http::{Method, Request, Uri};
use serde_derive::Deserialize;
use serde_json::Value;
use std::borrow::Cow; use std::borrow::Cow;
use std::fs::File; use std::fs::File;
use std::io::BufReader; use std::io::BufReader;
@ -25,11 +26,11 @@ use tokio_tungstenite::tungstenite::{
use tokio_tungstenite::{client_async, WebSocketStream}; use tokio_tungstenite::{client_async, WebSocketStream};
use webpki::DNSNameRef; use webpki::DNSNameRef;
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { pub fn init(s: &Rc<State>) {
i.register_op("op_ws_create", s.stateful_json_op2(op_ws_create)); s.register_op_json_async("op_ws_create", op_ws_create);
i.register_op("op_ws_send", s.stateful_json_op2(op_ws_send)); s.register_op_json_async("op_ws_send", op_ws_send);
i.register_op("op_ws_close", s.stateful_json_op2(op_ws_close)); s.register_op_json_async("op_ws_close", op_ws_close);
i.register_op("op_ws_next_event", s.stateful_json_op2(op_ws_next_event)); s.register_op_json_async("op_ws_next_event", op_ws_next_event);
} }
type MaybeTlsStream = type MaybeTlsStream =
@ -44,86 +45,81 @@ struct CreateArgs {
protocols: String, protocols: String,
} }
pub fn op_ws_create( pub async fn op_ws_create(
isolate_state: &mut CoreIsolateState, state: Rc<State>,
state: &Rc<State>,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _bufs: BufVec,
) -> Result<JsonOp, ErrBox> { ) -> Result<Value, ErrBox> {
let args: CreateArgs = serde_json::from_value(args)?; let args: CreateArgs = serde_json::from_value(args)?;
state.check_net_url(&url::Url::parse(&args.url)?)?; state.check_net_url(&url::Url::parse(&args.url)?)?;
let resource_table = isolate_state.resource_table.clone();
let ca_file = state.global_state.flags.ca_file.clone(); let ca_file = state.global_state.flags.ca_file.clone();
let future = async move { let uri: Uri = args.url.parse().unwrap();
let uri: Uri = args.url.parse().unwrap(); let request = Request::builder()
let request = Request::builder() .method(Method::GET)
.method(Method::GET) .uri(&uri)
.uri(&uri) .header("Sec-WebSocket-Protocol", args.protocols)
.header("Sec-WebSocket-Protocol", args.protocols) .body(())
.body(()) .unwrap();
.unwrap(); let domain = &uri.host().unwrap().to_string();
let domain = &uri.host().unwrap().to_string(); let port = &uri.port_u16().unwrap_or(match uri.scheme_str() {
let port = &uri.port_u16().unwrap_or(match uri.scheme_str() { Some("wss") => 443,
Some("wss") => 443, Some("ws") => 80,
Some("ws") => 80, _ => unreachable!(),
_ => unreachable!(), });
}); let addr = format!("{}:{}", domain, port);
let addr = format!("{}:{}", domain, port); let try_socket = TcpStream::connect(addr).await;
let try_socket = TcpStream::connect(addr).await; let tcp_socket = match try_socket.map_err(Error::Io) {
let tcp_socket = match try_socket.map_err(Error::Io) { Ok(socket) => socket,
Ok(socket) => socket, Err(_) => return Ok(json!({"success": false})),
Err(_) => return Ok(json!({"success": false})), };
};
let socket: MaybeTlsStream = match uri.scheme_str() { let socket: MaybeTlsStream = match uri.scheme_str() {
Some("ws") => StreamSwitcher::Plain(tcp_socket), Some("ws") => StreamSwitcher::Plain(tcp_socket),
Some("wss") => { Some("wss") => {
let mut config = ClientConfig::new(); let mut config = ClientConfig::new();
config config
.root_store .root_store
.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS); .add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
if let Some(path) = ca_file { if let Some(path) = ca_file {
let key_file = File::open(path)?; let key_file = File::open(path)?;
let reader = &mut BufReader::new(key_file); let reader = &mut BufReader::new(key_file);
config.root_store.add_pem_file(reader).unwrap(); config.root_store.add_pem_file(reader).unwrap();
}
let tls_connector = TlsConnector::from(Arc::new(config));
let dnsname =
DNSNameRef::try_from_ascii_str(&domain).expect("Invalid DNS lookup");
let tls_socket = tls_connector.connect(dnsname, tcp_socket).await?;
StreamSwitcher::Tls(tls_socket)
} }
_ => unreachable!(),
};
let (stream, response): (WsStream, Response) = let tls_connector = TlsConnector::from(Arc::new(config));
client_async(request, socket).await.unwrap(); let dnsname =
DNSNameRef::try_from_ascii_str(&domain).expect("Invalid DNS lookup");
let tls_socket = tls_connector.connect(dnsname, tcp_socket).await?;
StreamSwitcher::Tls(tls_socket)
}
_ => unreachable!(),
};
let rid = { let (stream, response): (WsStream, Response) =
let mut resource_table = resource_table.borrow_mut(); client_async(request, socket).await.unwrap();
resource_table.add("webSocketStream", Box::new(stream))
};
let protocol = match response.headers().get("Sec-WebSocket-Protocol") { let rid = state
Some(header) => header.to_str().unwrap(), .resource_table
None => "", .borrow_mut()
}; .add("webSocketStream", Box::new(stream));
let extensions = response
.headers() let protocol = match response.headers().get("Sec-WebSocket-Protocol") {
.get_all("Sec-WebSocket-Extensions") Some(header) => header.to_str().unwrap(),
.iter() None => "",
.map(|header| header.to_str().unwrap()) };
.collect::<String>(); let extensions = response
Ok(json!({ .headers()
.get_all("Sec-WebSocket-Extensions")
.iter()
.map(|header| header.to_str().unwrap())
.collect::<String>();
Ok(json!({
"success": true, "success": true,
"rid": rid, "rid": rid,
"protocol": protocol, "protocol": protocol,
"extensions": extensions "extensions": extensions
})) }))
};
Ok(JsonOp::Async(future.boxed_local()))
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -133,23 +129,21 @@ struct SendArgs {
text: Option<String>, text: Option<String>,
} }
pub fn op_ws_send( pub async fn op_ws_send(
isolate_state: &mut CoreIsolateState, state: Rc<State>,
_state: &Rc<State>,
args: Value, args: Value,
zero_copy: &mut [ZeroCopyBuf], bufs: BufVec,
) -> Result<JsonOp, ErrBox> { ) -> Result<Value, ErrBox> {
let args: SendArgs = serde_json::from_value(args)?; let args: SendArgs = serde_json::from_value(args)?;
let mut maybe_msg = Some(match args.text { let mut maybe_msg = Some(match args.text {
Some(text) => Message::Text(text), Some(text) => Message::Text(text),
None => Message::Binary(zero_copy[0].to_owned().to_vec()), None => Message::Binary(bufs[0].to_vec()),
}); });
let resource_table = isolate_state.resource_table.clone();
let rid = args.rid; let rid = args.rid;
let future = poll_fn(move |cx| { poll_fn(move |cx| {
let mut resource_table = resource_table.borrow_mut(); let mut resource_table = state.resource_table.borrow_mut();
let stream = resource_table let stream = resource_table
.get_mut::<WsStream>(rid) .get_mut::<WsStream>(rid)
.ok_or_else(ErrBox::bad_resource_id)?; .ok_or_else(ErrBox::bad_resource_id)?;
@ -164,8 +158,8 @@ pub fn op_ws_send(
ready!(stream.poll_flush_unpin(cx)).unwrap(); ready!(stream.poll_flush_unpin(cx)).unwrap();
Poll::Ready(Ok(json!({}))) Poll::Ready(Ok(json!({})))
}); })
Ok(JsonOp::Async(future.boxed_local())) .await
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -176,14 +170,12 @@ struct CloseArgs {
reason: Option<String>, reason: Option<String>,
} }
pub fn op_ws_close( pub async fn op_ws_close(
isolate_state: &mut CoreIsolateState, state: Rc<State>,
_state: &Rc<State>,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _bufs: BufVec,
) -> Result<JsonOp, ErrBox> { ) -> Result<Value, ErrBox> {
let args: CloseArgs = serde_json::from_value(args)?; let args: CloseArgs = serde_json::from_value(args)?;
let resource_table = isolate_state.resource_table.clone();
let rid = args.rid; let rid = args.rid;
let mut maybe_msg = Some(Message::Close(args.code.map(|c| CloseFrame { let mut maybe_msg = Some(Message::Close(args.code.map(|c| CloseFrame {
code: CloseCode::from(c), code: CloseCode::from(c),
@ -193,8 +185,8 @@ pub fn op_ws_close(
}, },
}))); })));
let future = poll_fn(move |cx| { poll_fn(move |cx| {
let mut resource_table = resource_table.borrow_mut(); let mut resource_table = state.resource_table.borrow_mut();
let stream = resource_table let stream = resource_table
.get_mut::<WsStream>(rid) .get_mut::<WsStream>(rid)
.ok_or_else(ErrBox::bad_resource_id)?; .ok_or_else(ErrBox::bad_resource_id)?;
@ -210,9 +202,8 @@ pub fn op_ws_close(
ready!(stream.poll_close_unpin(cx)).unwrap(); ready!(stream.poll_close_unpin(cx)).unwrap();
Poll::Ready(Ok(json!({}))) Poll::Ready(Ok(json!({})))
}); })
.await
Ok(JsonOp::Async(future.boxed_local()))
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -221,68 +212,48 @@ struct NextEventArgs {
rid: u32, rid: u32,
} }
pub fn op_ws_next_event( pub async fn op_ws_next_event(
isolate_state: &mut CoreIsolateState, state: Rc<State>,
_state: &Rc<State>,
args: Value, args: Value,
_zero_copy: &mut [ZeroCopyBuf], _bufs: BufVec,
) -> Result<JsonOp, ErrBox> { ) -> Result<Value, ErrBox> {
let args: NextEventArgs = serde_json::from_value(args)?; let args: NextEventArgs = serde_json::from_value(args)?;
let resource_table = isolate_state.resource_table.clone(); poll_fn(move |cx| {
let future = poll_fn(move |cx| { let mut resource_table = state.resource_table.borrow_mut();
let mut resource_table = resource_table.borrow_mut();
let stream = resource_table let stream = resource_table
.get_mut::<WsStream>(args.rid) .get_mut::<WsStream>(args.rid)
.ok_or_else(ErrBox::bad_resource_id)?; .ok_or_else(ErrBox::bad_resource_id)?;
stream
stream.poll_next_unpin(cx).map(|val| { .poll_next_unpin(cx)
match val { .map(|val| {
Some(val) => { match val {
match val { Some(Ok(Message::Text(text))) => json!({
Ok(message) => { "type": "string",
match message { "data": text
Message::Text(text) => Ok(json!({ }),
"type": "string", Some(Ok(Message::Binary(data))) => {
"data": text // TODO(ry): don't use json to send binary data.
})), json!({
Message::Binary(data) => { "type": "binary",
Ok(json!({ //TODO: don't use json to send binary data "data": data
"type": "binary", })
"data": data }
})) Some(Ok(Message::Close(Some(frame)))) => json!({
} "type": "close",
Message::Close(frame) => { "code": u16::from(frame.code),
if let Some(frame) = frame { "reason": frame.reason.as_ref()
let code: u16 = frame.code.into(); }),
Ok(json!({ Some(Ok(Message::Close(None))) => json!({ "type": "close" }),
"type": "close", Some(Ok(Message::Ping(_))) => json!({"type": "ping"}),
"code": code, Some(Ok(Message::Pong(_))) => json!({"type": "pong"}),
"reason": frame.reason.as_ref() Some(Err(_)) => json!({"type": "error"}),
})) None => {
} else { resource_table.close(args.rid).unwrap();
Ok(json!({ "type": "close" })) json!({"type": "closed"})
}
}
Message::Ping(_) => Ok(json!({"type": "ping"})),
Message::Pong(_) => Ok(json!({"type": "pong"})),
}
}
Err(_) => Ok(json!({
"type": "error",
})),
} }
} }
None => { })
resource_table .map(Ok)
.close(args.rid) })
.ok_or_else(ErrBox::bad_resource_id)?; .await
Ok(json!({
"type": "closed",
}))
}
}
})
});
Ok(JsonOp::Async(future.boxed_local()))
} }

View file

@ -1,5 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::{Deserialize, Value};
use crate::fmt_errors::JSError; use crate::fmt_errors::JSError;
use crate::global_state::GlobalState; use crate::global_state::GlobalState;
use crate::ops::io::get_stdio; use crate::ops::io::get_stdio;
@ -11,37 +11,23 @@ use crate::web_worker::WebWorker;
use crate::web_worker::WebWorkerHandle; use crate::web_worker::WebWorkerHandle;
use crate::worker::WorkerEvent; use crate::worker::WorkerEvent;
use deno_core::BufVec; use deno_core::BufVec;
use deno_core::CoreIsolate;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ModuleSpecifier; use deno_core::ModuleSpecifier;
use deno_core::ResourceTable; use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use futures::future::FutureExt; use futures::future::FutureExt;
use std::cell::RefCell; use serde_derive::Deserialize;
use serde_json::Value;
use std::convert::From; use std::convert::From;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use std::thread::JoinHandle; use std::thread::JoinHandle;
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { pub fn init(s: &Rc<State>) {
let t = &CoreIsolate::state(i).borrow().resource_table.clone(); s.register_op_json_sync("op_create_worker", op_create_worker);
s.register_op_json_sync("op_host_terminate_worker", op_host_terminate_worker);
i.register_op( s.register_op_json_sync("op_host_post_message", op_host_post_message);
"op_create_worker", s.register_op_json_async("op_host_get_message", op_host_get_message);
s.stateful_json_op_sync(t, op_create_worker),
);
i.register_op(
"op_host_terminate_worker",
s.stateful_json_op_sync(t, op_host_terminate_worker),
);
i.register_op(
"op_host_post_message",
s.stateful_json_op_sync(t, op_host_post_message),
);
i.register_op(
"op_host_get_message",
s.stateful_json_op_async(t, op_host_get_message),
);
} }
fn create_web_worker( fn create_web_worker(
@ -63,8 +49,6 @@ fn create_web_worker(
); );
if has_deno_namespace { if has_deno_namespace {
let state_rc = CoreIsolate::state(&worker.isolate);
let state = state_rc.borrow();
let mut resource_table = state.resource_table.borrow_mut(); let mut resource_table = state.resource_table.borrow_mut();
let (stdin, stdout, stderr) = get_stdio(); let (stdin, stdout, stderr) = get_stdio();
if let Some(stream) = stdin { if let Some(stream) = stdin {
@ -189,7 +173,6 @@ struct CreateWorkerArgs {
/// Create worker as the host /// Create worker as the host
fn op_create_worker( fn op_create_worker(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_data: &mut [ZeroCopyBuf], _data: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -240,7 +223,6 @@ struct WorkerArgs {
fn op_host_terminate_worker( fn op_host_terminate_worker(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
_data: &mut [ZeroCopyBuf], _data: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -309,7 +291,6 @@ fn serialize_worker_event(event: WorkerEvent) -> Value {
/// Get message from guest worker as host /// Get message from guest worker as host
async fn op_host_get_message( async fn op_host_get_message(
state: Rc<State>, state: Rc<State>,
_resource_table: Rc<RefCell<ResourceTable>>,
args: Value, args: Value,
_zero_copy: BufVec, _zero_copy: BufVec,
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {
@ -358,7 +339,6 @@ async fn op_host_get_message(
/// Post message to guest worker as host /// Post message to guest worker as host
fn op_host_post_message( fn op_host_post_message(
state: &State, state: &State,
_resource_table: &mut ResourceTable,
args: Value, args: Value,
data: &mut [ZeroCopyBuf], data: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> { ) -> Result<Value, ErrBox> {

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::colors; use crate::colors;
use crate::flags::Flags; use crate::flags::Flags;
use crate::fs::resolve_from_cwd; use crate::fs::resolve_from_cwd;

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::deno_dir::DenoDir; use crate::deno_dir::DenoDir;
use deno_core::ErrBox; use deno_core::ErrBox;
use rustyline::Editor; use rustyline::Editor;

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use deno_core::ErrBox; use deno_core::ErrBox;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::net::ToSocketAddrs; use std::net::ToSocketAddrs;

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use deno_core::ErrBox; use deno_core::ErrBox;
#[cfg(not(unix))] #[cfg(not(unix))]

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::js::CLI_SNAPSHOT; use crate::js::CLI_SNAPSHOT;
use crate::js::COMPILER_SNAPSHOT; use crate::js::COMPILER_SNAPSHOT;
use deno_core::Snapshot; use deno_core::Snapshot;

View file

@ -1,31 +1,30 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // 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::file_fetcher::SourceFileFetcher;
use crate::global_state::GlobalState; use crate::global_state::GlobalState;
use crate::global_timer::GlobalTimer; use crate::global_timer::GlobalTimer;
use crate::http_util::create_http_client; use crate::http_util::create_http_client;
use crate::import_map::ImportMap; use crate::import_map::ImportMap;
use crate::metrics::Metrics; use crate::metrics::Metrics;
use crate::ops::serialize_result;
use crate::ops::JsonOp;
use crate::ops::MinimalOp;
use crate::permissions::Permissions; use crate::permissions::Permissions;
use crate::tsc::TargetLib; use crate::tsc::TargetLib;
use crate::web_worker::WebWorkerHandle; use crate::web_worker::WebWorkerHandle;
use deno_core::Buf;
use deno_core::BufVec; use deno_core::BufVec;
use deno_core::CoreIsolateState;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ModuleLoadId; use deno_core::ModuleLoadId;
use deno_core::ModuleLoader; use deno_core::ModuleLoader;
use deno_core::ModuleSpecifier; use deno_core::ModuleSpecifier;
use deno_core::Op; 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 deno_core::ResourceTable;
use deno_core::ZeroCopyBuf;
use futures::future::FutureExt; use futures::future::FutureExt;
use futures::Future; use futures::Future;
use rand::rngs::StdRng; use rand::rngs::StdRng;
use rand::SeedableRng; use rand::SeedableRng;
use serde_json::Value;
use std::cell::Cell; use std::cell::Cell;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
@ -55,266 +54,11 @@ pub struct State {
pub is_main: bool, pub is_main: bool,
pub is_internal: bool, pub is_internal: bool,
pub http_client: RefCell<reqwest::Client>, pub http_client: RefCell<reqwest::Client>,
pub resource_table: RefCell<ResourceTable>,
pub op_table: RefCell<OpTable<Self>>,
} }
impl State { impl State {
pub fn stateful_json_op_sync<D>(
self: &Rc<Self>,
resource_table: &Rc<RefCell<ResourceTable>>,
dispatcher: D,
) -> impl Fn(&mut deno_core::CoreIsolateState, &mut [ZeroCopyBuf]) -> Op
where
D: Fn(
&State,
&mut ResourceTable,
Value,
&mut [ZeroCopyBuf],
) -> Result<Value, ErrBox>,
{
let state = self.clone();
let resource_table = resource_table.clone();
let f = move |isolate_state: &mut CoreIsolateState,
bufs: &mut [ZeroCopyBuf]| {
let get_error_class_fn = isolate_state.get_error_class_fn;
// The first buffer should contain JSON encoded op arguments; parse them.
let args: Value = match serde_json::from_slice(&bufs[0]) {
Ok(v) => v,
Err(e) => {
return Op::Sync(serialize_result(
None,
Err(e.into()),
get_error_class_fn,
));
}
};
// Make a slice containing all buffers except for the first one.
let zero_copy = &mut bufs[1..];
let result =
dispatcher(&state, &mut *resource_table.borrow_mut(), args, zero_copy);
// Convert to Op.
Op::Sync(serialize_result(None, result, get_error_class_fn))
};
self.core_op(f)
}
pub fn stateful_json_op_async<D, F>(
self: &Rc<Self>,
resource_table: &Rc<RefCell<ResourceTable>>,
dispatcher: D,
) -> impl Fn(&mut CoreIsolateState, &mut [ZeroCopyBuf]) -> Op
where
D:
FnOnce(Rc<State>, Rc<RefCell<ResourceTable>>, Value, BufVec) -> F + Clone,
F: Future<Output = Result<Value, ErrBox>> + 'static,
{
let state = self.clone();
let resource_table = resource_table.clone();
let f = move |isolate_state: &mut CoreIsolateState,
bufs: &mut [ZeroCopyBuf]| {
let get_error_class_fn = isolate_state.get_error_class_fn;
// The first buffer should contain JSON encoded op arguments; parse them.
let args: Value = match serde_json::from_slice(&bufs[0]) {
Ok(v) => v,
Err(e) => {
let e = e.into();
return Op::Sync(serialize_result(None, Err(e), get_error_class_fn));
}
};
// `args` should have a `promiseId` property with positive integer value.
let promise_id = match args.get("promiseId").and_then(|v| v.as_u64()) {
Some(i) => i,
None => {
let e = ErrBox::new("TypeError", "`promiseId` invalid/missing");
return Op::Sync(serialize_result(None, Err(e), get_error_class_fn));
}
};
// Take ownership of all buffers after the first one.
let zero_copy: BufVec = bufs[1..].into();
// Call dispatcher to obtain op future.
let fut = (dispatcher.clone())(
state.clone(),
resource_table.clone(),
args,
zero_copy,
);
// Convert to Op.
Op::Async(
async move {
serialize_result(Some(promise_id), fut.await, get_error_class_fn)
}
.boxed_local(),
)
};
self.core_op(f)
}
// TODO(bartlomieju): remove me - still used by `op_open_plugin` which
// needs access to isolate_state
pub fn stateful_json_op2<D>(
self: &Rc<Self>,
dispatcher: D,
) -> impl Fn(&mut deno_core::CoreIsolateState, &mut [ZeroCopyBuf]) -> Op
where
D: Fn(
&mut deno_core::CoreIsolateState,
&Rc<State>,
Value,
&mut [ZeroCopyBuf],
) -> Result<JsonOp, ErrBox>,
{
use crate::ops::json_op;
self.core_op(json_op(self.stateful_op2(dispatcher)))
}
/// Wrap core `OpDispatcher` to collect metrics.
// TODO(ry) this should be private. Is called by stateful_json_op or
// stateful_minimal_op
pub(crate) fn core_op<D>(
self: &Rc<Self>,
dispatcher: D,
) -> impl Fn(&mut deno_core::CoreIsolateState, &mut [ZeroCopyBuf]) -> Op
where
D: Fn(&mut deno_core::CoreIsolateState, &mut [ZeroCopyBuf]) -> Op,
{
let state = self.clone();
move |isolate_state: &mut deno_core::CoreIsolateState,
zero_copy: &mut [ZeroCopyBuf]|
-> Op {
let bytes_sent_control =
zero_copy.get(0).map(|s| s.len()).unwrap_or(0) as u64;
let bytes_sent_zero_copy =
zero_copy[1..].iter().map(|b| b.len()).sum::<usize>() as u64;
let op = dispatcher(isolate_state, zero_copy);
match op {
Op::Sync(buf) => {
state.metrics.borrow_mut().op_sync(
bytes_sent_control,
bytes_sent_zero_copy,
buf.len() as u64,
);
Op::Sync(buf)
}
Op::Async(fut) => {
state
.metrics
.borrow_mut()
.op_dispatched_async(bytes_sent_control, bytes_sent_zero_copy);
let state = state.clone();
let result_fut = fut.map(move |buf: Buf| {
state
.metrics
.borrow_mut()
.op_completed_async(buf.len() as u64);
buf
});
Op::Async(result_fut.boxed_local())
}
Op::AsyncUnref(fut) => {
state.metrics.borrow_mut().op_dispatched_async_unref(
bytes_sent_control,
bytes_sent_zero_copy,
);
let state = state.clone();
let result_fut = fut.map(move |buf: Buf| {
state
.metrics
.borrow_mut()
.op_completed_async_unref(buf.len() as u64);
buf
});
Op::AsyncUnref(result_fut.boxed_local())
}
}
}
}
pub fn stateful_minimal_op2<D>(
self: &Rc<Self>,
dispatcher: D,
) -> impl Fn(&mut deno_core::CoreIsolateState, &mut [ZeroCopyBuf]) -> Op
where
D: Fn(
&mut deno_core::CoreIsolateState,
&Rc<State>,
bool,
i32,
&mut [ZeroCopyBuf],
) -> MinimalOp,
{
let state = self.clone();
self.core_op(crate::ops::minimal_op(
move |isolate_state: &mut deno_core::CoreIsolateState,
is_sync: bool,
rid: i32,
zero_copy: &mut [ZeroCopyBuf]|
-> MinimalOp {
dispatcher(isolate_state, &state, is_sync, rid, zero_copy)
},
))
}
/// This is a special function that provides `state` argument to dispatcher.
///
/// NOTE: This only works with JSON dispatcher.
/// This is a band-aid for transition to `CoreIsolate.register_op` API as most of our
/// ops require `state` argument.
pub fn stateful_op<D>(
self: &Rc<Self>,
dispatcher: D,
) -> impl Fn(
&mut deno_core::CoreIsolateState,
Value,
&mut [ZeroCopyBuf],
) -> Result<JsonOp, ErrBox>
where
D: Fn(&Rc<State>, Value, &mut [ZeroCopyBuf]) -> Result<JsonOp, ErrBox>,
{
let state = self.clone();
move |_isolate_state: &mut deno_core::CoreIsolateState,
args: Value,
zero_copy: &mut [ZeroCopyBuf]|
-> Result<JsonOp, ErrBox> { dispatcher(&state, args, zero_copy) }
}
pub fn stateful_op2<D>(
self: &Rc<Self>,
dispatcher: D,
) -> impl Fn(
&mut deno_core::CoreIsolateState,
Value,
&mut [ZeroCopyBuf],
) -> Result<JsonOp, ErrBox>
where
D: Fn(
&mut deno_core::CoreIsolateState,
&Rc<State>,
Value,
&mut [ZeroCopyBuf],
) -> Result<JsonOp, ErrBox>,
{
let state = self.clone();
move |isolate_state: &mut deno_core::CoreIsolateState,
args: Value,
zero_copy: &mut [ZeroCopyBuf]|
-> Result<JsonOp, ErrBox> {
dispatcher(isolate_state, &state, args, zero_copy)
}
}
/// Quits the process if the --unstable flag was not provided. /// Quits the process if the --unstable flag was not provided.
/// ///
/// This is intentionally a non-recoverable check so that people cannot probe /// This is intentionally a non-recoverable check so that people cannot probe
@ -458,6 +202,8 @@ impl State {
is_main: true, is_main: true,
is_internal, is_internal,
http_client: create_http_client(fl.ca_file.as_deref())?.into(), http_client: create_http_client(fl.ca_file.as_deref())?.into(),
resource_table: Default::default(),
op_table: Default::default(),
}; };
Ok(Rc::new(state)) Ok(Rc::new(state))
} }
@ -486,6 +232,8 @@ impl State {
is_main: false, is_main: false,
is_internal: false, is_internal: false,
http_client: create_http_client(fl.ca_file.as_deref())?.into(), http_client: create_http_client(fl.ca_file.as_deref())?.into(),
resource_table: Default::default(),
op_table: Default::default(),
}; };
Ok(Rc::new(state)) Ok(Rc::new(state))
} }
@ -570,7 +318,7 @@ impl State {
} }
#[cfg(test)] #[cfg(test)]
pub fn mock(main_module: &str) -> Rc<State> { pub fn mock(main_module: &str) -> Rc<Self> {
let module_specifier = ModuleSpecifier::resolve_url_or_path(main_module) let module_specifier = ModuleSpecifier::resolve_url_or_path(main_module)
.expect("Invalid entry module"); .expect("Invalid entry module");
State::new( State::new(
@ -583,3 +331,78 @@ impl State {
.unwrap() .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)
}
}

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::msg::MediaType; use crate::msg::MediaType;
use deno_core::ErrBox; use deno_core::ErrBox;
use serde::Serialize; use serde::Serialize;
@ -304,7 +305,7 @@ pub fn transpile(
Optional::new(jsx_pass, options.transform_jsx), Optional::new(jsx_pass, options.transform_jsx),
decorators::decorators(decorators::Config { decorators::decorators(decorators::Config {
legacy: true, legacy: true,
emit_metadata: options.emit_metadata, emit_metadata: options.emit_metadata
}), }),
typescript::strip(), typescript::strip(),
fixer(Some(&ast_parser.comments)), fixer(Some(&ast_parser.comments)),

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use encoding_rs::*; use encoding_rs::*;
use std::{ use std::{
borrow::Cow, borrow::Cow,

View file

@ -139,14 +139,13 @@ impl CompilerWorker {
startup_data: StartupData, startup_data: StartupData,
state: &Rc<State>, state: &Rc<State>,
) -> Self { ) -> Self {
let mut worker = Worker::new(name, startup_data, state); let worker = Worker::new(name, startup_data, state);
let response = Arc::new(Mutex::new(None)); let response = Arc::new(Mutex::new(None));
{ {
let isolate = &mut worker.isolate; ops::runtime::init(&state);
ops::runtime::init(isolate, &state); ops::errors::init(&state);
ops::errors::init(isolate, &state); ops::timers::init(&state);
ops::timers::init(isolate, &state); ops::compiler::init(&state, response.clone());
ops::compiler::init(isolate, &state, response.clone());
} }
Self { worker, response } Self { worker, response }
@ -1437,7 +1436,7 @@ pub async fn runtime_transpile(
let json_str = execute_in_same_thread(global_state, permissions, req_msg) let json_str = execute_in_same_thread(global_state, permissions, req_msg)
.await .await
.map_err(js_error_to_errbox)?; .map_err(js_error_to_errbox)?;
let v = serde_json::from_str::<serde_json::Value>(&json_str) let v = serde_json::from_str::<Value>(&json_str)
.expect("Error decoding JSON string."); .expect("Error decoding JSON string.");
Ok(v) Ok(v)
} }

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
pub const DENO: &str = env!("CARGO_PKG_VERSION"); pub const DENO: &str = env!("CARGO_PKG_VERSION");
pub const TYPESCRIPT: &str = crate::js::TS_VERSION; pub const TYPESCRIPT: &str = crate::js::TS_VERSION;

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::ops; use crate::ops;
use crate::state::State; use crate::state::State;
use crate::worker::Worker; use crate::worker::Worker;
@ -101,7 +102,7 @@ impl WebWorker {
terminate_tx, terminate_tx,
}; };
let mut web_worker = Self { let web_worker = Self {
worker, worker,
event_loop_idle: false, event_loop_idle: false,
terminate_rx, terminate_rx,
@ -112,36 +113,34 @@ impl WebWorker {
let handle = web_worker.thread_safe_handle(); let handle = web_worker.thread_safe_handle();
{ {
let isolate = &mut web_worker.worker.isolate; ops::runtime::init(&state);
ops::runtime::init(isolate, &state);
ops::web_worker::init( ops::web_worker::init(
isolate,
&state, &state,
&web_worker.worker.internal_channels.sender, &web_worker.worker.internal_channels.sender,
handle, handle,
); );
ops::worker_host::init(isolate, &state); ops::worker_host::init(&state);
ops::idna::init(isolate, &state); ops::idna::init(&state);
ops::io::init(isolate, &state); ops::io::init(&state);
ops::resources::init(isolate, &state); ops::resources::init(&state);
ops::errors::init(isolate, &state); ops::errors::init(&state);
ops::timers::init(isolate, &state); ops::timers::init(&state);
ops::fetch::init(isolate, &state); ops::fetch::init(&state);
ops::websocket::init(isolate, &state); ops::websocket::init(&state);
if has_deno_namespace { if has_deno_namespace {
ops::runtime_compiler::init(isolate, &state); ops::runtime_compiler::init(&state);
ops::fs::init(isolate, &state); ops::fs::init(&state);
ops::fs_events::init(isolate, &state); ops::fs_events::init(&state);
ops::plugin::init(isolate, &state); ops::plugin::init(&state);
ops::net::init(isolate, &state); ops::net::init(&state);
ops::tls::init(isolate, &state); ops::tls::init(&state);
ops::os::init(isolate, &state); ops::os::init(&state);
ops::permissions::init(isolate, &state); ops::permissions::init(&state);
ops::process::init(isolate, &state); ops::process::init(&state);
ops::random::init(isolate, &state); ops::random::init(&state);
ops::signal::init(isolate, &state); ops::signal::init(&state);
ops::tty::init(isolate, &state); ops::tty::init(&state);
} }
} }

View file

@ -1,5 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::errors::get_error_class;
use crate::fmt_errors::JSError; use crate::fmt_errors::JSError;
use crate::global_state::GlobalState; use crate::global_state::GlobalState;
use crate::inspector::DenoInspector; use crate::inspector::DenoInspector;
@ -7,7 +7,6 @@ use crate::ops;
use crate::ops::io::get_stdio; use crate::ops::io::get_stdio;
use crate::startup_data; use crate::startup_data;
use crate::state::State; use crate::state::State;
use deno_core::Buf;
use deno_core::CoreIsolate; use deno_core::CoreIsolate;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::ModuleId; use deno_core::ModuleId;
@ -32,25 +31,25 @@ use url::Url;
/// Events that are sent to host from child /// Events that are sent to host from child
/// worker. /// worker.
pub enum WorkerEvent { pub enum WorkerEvent {
Message(Buf), Message(Box<[u8]>),
Error(ErrBox), Error(ErrBox),
TerminalError(ErrBox), TerminalError(ErrBox),
} }
pub struct WorkerChannelsInternal { pub struct WorkerChannelsInternal {
pub sender: mpsc::Sender<WorkerEvent>, pub sender: mpsc::Sender<WorkerEvent>,
pub receiver: mpsc::Receiver<Buf>, pub receiver: mpsc::Receiver<Box<[u8]>>,
} }
#[derive(Clone)] #[derive(Clone)]
pub struct WorkerHandle { pub struct WorkerHandle {
pub sender: mpsc::Sender<Buf>, pub sender: mpsc::Sender<Box<[u8]>>,
pub receiver: Arc<AsyncMutex<mpsc::Receiver<WorkerEvent>>>, pub receiver: Arc<AsyncMutex<mpsc::Receiver<WorkerEvent>>>,
} }
impl WorkerHandle { impl WorkerHandle {
/// Post message to worker as a host. /// Post message to worker as a host.
pub fn post_message(&self, buf: Buf) -> Result<(), ErrBox> { pub fn post_message(&self, buf: Box<[u8]>) -> Result<(), ErrBox> {
let mut sender = self.sender.clone(); let mut sender = self.sender.clone();
sender.try_send(buf)?; sender.try_send(buf)?;
Ok(()) Ok(())
@ -65,7 +64,7 @@ impl WorkerHandle {
} }
fn create_channels() -> (WorkerChannelsInternal, WorkerHandle) { fn create_channels() -> (WorkerChannelsInternal, WorkerHandle) {
let (in_tx, in_rx) = mpsc::channel::<Buf>(1); let (in_tx, in_rx) = mpsc::channel::<Box<[u8]>>(1);
let (out_tx, out_rx) = mpsc::channel::<WorkerEvent>(1); let (out_tx, out_rx) = mpsc::channel::<WorkerEvent>(1);
let internal_channels = WorkerChannelsInternal { let internal_channels = WorkerChannelsInternal {
sender: out_tx, sender: out_tx,
@ -106,8 +105,12 @@ impl Worker {
startup_data: StartupData, startup_data: StartupData,
state: &Rc<State>, state: &Rc<State>,
) -> Self { ) -> Self {
let mut isolate = let mut isolate = deno_core::EsIsolate::new(
deno_core::EsIsolate::new(state.clone(), startup_data, false); state.clone(),
state.clone(),
startup_data,
false,
);
{ {
let global_state = state.global_state.clone(); let global_state = state.global_state.clone();
@ -116,7 +119,6 @@ impl Worker {
core_state.set_js_error_create_fn(move |core_js_error| { core_state.set_js_error_create_fn(move |core_js_error| {
JSError::create(core_js_error, &global_state.ts_compiler) JSError::create(core_js_error, &global_state.ts_compiler)
}); });
core_state.set_get_error_class_fn(&get_error_class);
} }
let inspector = { let inspector = {
@ -256,31 +258,30 @@ pub struct MainWorker(Worker);
impl MainWorker { impl MainWorker {
// TODO(ry) combine MainWorker::new and MainWorker::create. // TODO(ry) combine MainWorker::new and MainWorker::create.
fn new(name: String, startup_data: StartupData, state: &Rc<State>) -> Self { fn new(name: String, startup_data: StartupData, state: &Rc<State>) -> Self {
let mut worker = Worker::new(name, startup_data, state); let worker = Worker::new(name, startup_data, state);
{ {
let isolate = &mut worker.isolate; ops::runtime::init(&state);
ops::runtime::init(isolate, &state); ops::runtime_compiler::init(&state);
ops::runtime_compiler::init(isolate, &state); ops::errors::init(&state);
ops::errors::init(isolate, &state); ops::fetch::init(&state);
ops::fetch::init(isolate, &state); ops::websocket::init(&state);
ops::websocket::init(isolate, &state); ops::fs::init(&state);
ops::fs::init(isolate, &state); ops::fs_events::init(&state);
ops::fs_events::init(isolate, &state); ops::idna::init(&state);
ops::idna::init(isolate, &state); ops::io::init(&state);
ops::io::init(isolate, &state); ops::plugin::init(&state);
ops::plugin::init(isolate, &state); ops::net::init(&state);
ops::net::init(isolate, &state); ops::tls::init(&state);
ops::tls::init(isolate, &state); ops::os::init(&state);
ops::os::init(isolate, &state); ops::permissions::init(&state);
ops::permissions::init(isolate, &state); ops::process::init(&state);
ops::process::init(isolate, &state); ops::random::init(&state);
ops::random::init(isolate, &state); ops::repl::init(&state);
ops::repl::init(isolate, &state); ops::resources::init(&state);
ops::resources::init(isolate, &state); ops::signal::init(&state);
ops::signal::init(isolate, &state); ops::timers::init(&state);
ops::timers::init(isolate, &state); ops::tty::init(&state);
ops::tty::init(isolate, &state); ops::worker_host::init(&state);
ops::worker_host::init(isolate, &state);
} }
Self(worker) Self(worker)
} }
@ -302,10 +303,8 @@ impl MainWorker {
&state, &state,
); );
{ {
let (stdin, stdout, stderr) = get_stdio();
let state_rc = CoreIsolate::state(&worker.isolate);
let state = state_rc.borrow();
let mut t = state.resource_table.borrow_mut(); let mut t = state.resource_table.borrow_mut();
let (stdin, stdout, stderr) = get_stdio();
if let Some(stream) = stdin { if let Some(stream) = stdin {
t.add("stdin", Box::new(stream)); t.add("stdin", Box::new(stream));
} }

View file

@ -22,6 +22,7 @@ rusty_v8 = "0.9.1"
serde_json = { version = "1.0.57", features = ["preserve_order"] } serde_json = { version = "1.0.57", features = ["preserve_order"] }
smallvec = "1.4.2" smallvec = "1.4.2"
url = "2.1.1" url = "2.1.1"
indexmap = "1.5.2"
[[example]] [[example]]
name = "http_bench_bin_ops" name = "http_bench_bin_ops"

91
core/basic_state.rs Normal file
View file

@ -0,0 +1,91 @@
// 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)
]
)
}

View file

@ -2,18 +2,19 @@
use crate::CoreIsolate; use crate::CoreIsolate;
use crate::CoreIsolateState; use crate::CoreIsolateState;
use crate::ErrBox;
use crate::EsIsolate; use crate::EsIsolate;
use crate::JSError; use crate::JSError;
use crate::Op;
use crate::OpId;
use crate::ZeroCopyBuf; use crate::ZeroCopyBuf;
use futures::future::FutureExt;
use rusty_v8 as v8; use rusty_v8 as v8;
use v8::MapFnTo;
use smallvec::SmallVec;
use std::cell::Cell; use std::cell::Cell;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::option::Option; use std::option::Option;
use url::Url; use url::Url;
use v8::MapFnTo;
lazy_static! { lazy_static! {
pub static ref EXTERNAL_REFERENCES: v8::ExternalReferences = pub static ref EXTERNAL_REFERENCES: v8::ExternalReferences =
@ -49,7 +50,7 @@ lazy_static! {
function: decode.map_fn_to() function: decode.map_fn_to()
}, },
v8::ExternalReference { v8::ExternalReference {
function: get_promise_details.map_fn_to(), function: get_promise_details.map_fn_to()
} }
]); ]);
} }
@ -371,13 +372,19 @@ fn recv(
slot.replace(v8::Global::new(scope, cb)); slot.replace(v8::Global::new(scope, cb));
} }
fn send( fn send<'s>(
scope: &mut v8::HandleScope, scope: &mut v8::HandleScope<'s>,
args: v8::FunctionCallbackArguments, args: v8::FunctionCallbackArguments,
mut rv: v8::ReturnValue, mut rv: v8::ReturnValue,
) { ) {
let op_id = match v8::Local::<v8::Uint32>::try_from(args.get(0)) { let state_rc = CoreIsolate::state(scope);
Ok(op_id) => op_id.value() as u32, let state = state_rc.borrow_mut();
let op_id = match v8::Local::<v8::Integer>::try_from(args.get(0))
.map_err(ErrBox::from)
.and_then(|l| OpId::try_from(l.value()).map_err(ErrBox::from))
{
Ok(op_id) => op_id,
Err(err) => { Err(err) => {
let msg = format!("invalid op id: {}", err); let msg = format!("invalid op id: {}", err);
let msg = v8::String::new(scope, &msg).unwrap(); let msg = v8::String::new(scope, &msg).unwrap();
@ -387,9 +394,6 @@ fn send(
} }
}; };
let state_rc = CoreIsolate::state(scope);
let mut state = state_rc.borrow_mut();
let buf_iter = (1..args.length()).map(|idx| { let buf_iter = (1..args.length()).map(|idx| {
v8::Local::<v8::ArrayBufferView>::try_from(args.get(idx)) v8::Local::<v8::ArrayBufferView>::try_from(args.get(idx))
.map(|view| ZeroCopyBuf::new(scope, view)) .map(|view| ZeroCopyBuf::new(scope, view))
@ -400,24 +404,37 @@ fn send(
}) })
}); });
// If response is empty then it's either async op or exception was thrown. let bufs = match buf_iter.collect::<Result<_, _>>() {
let maybe_response = Ok(bufs) => bufs,
match buf_iter.collect::<Result<SmallVec<[ZeroCopyBuf; 2]>, _>>() { Err(exc) => {
Ok(mut bufs) => state.dispatch_op(scope, op_id, &mut bufs), scope.throw_exception(exc);
Err(exc) => { return;
scope.throw_exception(exc); }
return; };
}
};
if let Some(response) = maybe_response { let op_router = state.op_router.clone();
// Synchronous response. let op = op_router.route_op(op_id, bufs);
// Note op_id is not passed back in the case of synchronous response. assert_eq!(state.shared.size(), 0);
let (_op_id, buf) = response; match op {
Op::Sync(buf) if !buf.is_empty() => {
if !buf.is_empty() { rv.set(boxed_slice_to_uint8array(scope, buf).into());
let ui8 = boxed_slice_to_uint8array(scope, buf); }
rv.set(ui8.into()); Op::Sync(_) => {}
Op::Async(fut) => {
let fut2 = fut.map(move |buf| (op_id, buf));
state.pending_ops.push(fut2.boxed_local());
state.have_unpolled_ops.set(true);
}
Op::AsyncUnref(fut) => {
let fut2 = fut.map(move |buf| (op_id, buf));
state.pending_unref_ops.push(fut2.boxed_local());
state.have_unpolled_ops.set(true);
}
Op::NotFound => {
let msg = format!("Unknown op id: {}", op_id);
let msg = v8::String::new(scope, &msg).unwrap();
let exc = v8::Exception::type_error(scope, msg);
scope.throw_exception(exc);
} }
} }
} }

View file

@ -13,16 +13,12 @@ use crate::shared_queue::SharedQueue;
use crate::shared_queue::RECOMMENDED_SIZE; use crate::shared_queue::RECOMMENDED_SIZE;
use crate::ErrBox; use crate::ErrBox;
use crate::JSError; use crate::JSError;
use crate::ResourceTable;
use crate::ZeroCopyBuf;
use futures::future::FutureExt;
use futures::stream::FuturesUnordered; use futures::stream::FuturesUnordered;
use futures::stream::StreamExt; use futures::stream::StreamExt;
use futures::task::AtomicWaker; use futures::task::AtomicWaker;
use futures::Future; use futures::Future;
use serde_json::json;
use serde_json::Value;
use std::any::Any; use std::any::Any;
use std::cell::Cell;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::From; use std::convert::From;
@ -37,7 +33,7 @@ use std::sync::Once;
use std::task::Context; use std::task::Context;
use std::task::Poll; use std::task::Poll;
type PendingOpFuture = Pin<Box<dyn Future<Output = (OpId, Buf)>>>; type PendingOpFuture = Pin<Box<dyn Future<Output = (OpId, Box<[u8]>)>>>;
/// Stores a script used to initialize a Isolate /// Stores a script used to initialize a Isolate
pub struct Script<'a> { pub struct Script<'a> {
@ -87,7 +83,7 @@ impl StartupData<'_> {
type JSErrorCreateFn = dyn Fn(JSError) -> ErrBox; type JSErrorCreateFn = dyn Fn(JSError) -> ErrBox;
pub type GetErrorClassFn = &'static dyn for<'e> Fn(&'e ErrBox) -> &'static str; pub type GetErrorClassFn = dyn for<'e> Fn(&'e ErrBox) -> &'static str;
/// Objects that need to live as long as the isolate /// Objects that need to live as long as the isolate
#[derive(Default)] #[derive(Default)]
@ -118,19 +114,17 @@ pub struct CoreIsolate {
/// Internal state for CoreIsolate which is stored in one of v8::Isolate's /// Internal state for CoreIsolate which is stored in one of v8::Isolate's
/// embedder slots. /// embedder slots.
pub struct CoreIsolateState { pub struct CoreIsolateState {
pub resource_table: Rc<RefCell<ResourceTable>>,
pub global_context: Option<v8::Global<v8::Context>>, pub global_context: Option<v8::Global<v8::Context>>,
pub(crate) shared_ab: Option<v8::Global<v8::SharedArrayBuffer>>, pub(crate) shared_ab: Option<v8::Global<v8::SharedArrayBuffer>>,
pub(crate) js_recv_cb: Option<v8::Global<v8::Function>>, pub(crate) js_recv_cb: Option<v8::Global<v8::Function>>,
pub(crate) js_macrotask_cb: Option<v8::Global<v8::Function>>, pub(crate) js_macrotask_cb: Option<v8::Global<v8::Function>>,
pub(crate) pending_promise_exceptions: HashMap<i32, v8::Global<v8::Value>>, pub(crate) pending_promise_exceptions: HashMap<i32, v8::Global<v8::Value>>,
pub(crate) js_error_create_fn: Box<JSErrorCreateFn>, pub(crate) js_error_create_fn: Box<JSErrorCreateFn>,
pub get_error_class_fn: GetErrorClassFn,
pub(crate) shared: SharedQueue, pub(crate) shared: SharedQueue,
pending_ops: FuturesUnordered<PendingOpFuture>, pub(crate) pending_ops: FuturesUnordered<PendingOpFuture>,
pending_unref_ops: FuturesUnordered<PendingOpFuture>, pub(crate) pending_unref_ops: FuturesUnordered<PendingOpFuture>,
have_unpolled_ops: bool, pub(crate) have_unpolled_ops: Cell<bool>,
pub op_registry: OpRegistry, pub(crate) op_router: Rc<dyn OpRouter>,
waker: AtomicWaker, waker: AtomicWaker,
} }
@ -205,21 +199,27 @@ pub struct HeapLimits {
} }
pub(crate) struct IsolateOptions { pub(crate) struct IsolateOptions {
will_snapshot: bool, op_router: Rc<dyn OpRouter>,
startup_script: Option<OwnedScript>, startup_script: Option<OwnedScript>,
startup_snapshot: Option<Snapshot>, startup_snapshot: Option<Snapshot>,
will_snapshot: bool,
heap_limits: Option<HeapLimits>, heap_limits: Option<HeapLimits>,
} }
impl CoreIsolate { impl CoreIsolate {
/// startup_data defines the snapshot or script used at startup to initialize /// startup_data defines the snapshot or script used at startup to initialize
/// the isolate. /// the isolate.
pub fn new(startup_data: StartupData, will_snapshot: bool) -> Self { pub fn new(
op_router: Rc<dyn OpRouter>,
startup_data: StartupData,
will_snapshot: bool,
) -> Self {
let (startup_script, startup_snapshot) = startup_data.into_options(); let (startup_script, startup_snapshot) = startup_data.into_options();
let options = IsolateOptions { let options = IsolateOptions {
will_snapshot, op_router,
startup_script, startup_script,
startup_snapshot, startup_snapshot,
will_snapshot,
heap_limits: None, heap_limits: None,
}; };
@ -233,14 +233,16 @@ impl CoreIsolate {
/// Make sure to use [`add_near_heap_limit_callback`](#method.add_near_heap_limit_callback) /// 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. /// to prevent v8 from crashing when reaching the upper limit.
pub fn with_heap_limits( pub fn with_heap_limits(
op_router: Rc<dyn OpRouter>,
startup_data: StartupData, startup_data: StartupData,
heap_limits: HeapLimits, heap_limits: HeapLimits,
) -> Self { ) -> Self {
let (startup_script, startup_snapshot) = startup_data.into_options(); let (startup_script, startup_snapshot) = startup_data.into_options();
let options = IsolateOptions { let options = IsolateOptions {
will_snapshot: false, op_router,
startup_script, startup_script,
startup_snapshot, startup_snapshot,
will_snapshot: false,
heap_limits: Some(heap_limits), heap_limits: Some(heap_limits),
}; };
@ -304,18 +306,16 @@ impl CoreIsolate {
isolate.set_slot(Rc::new(RefCell::new(CoreIsolateState { isolate.set_slot(Rc::new(RefCell::new(CoreIsolateState {
global_context: Some(global_context), global_context: Some(global_context),
resource_table: Rc::new(RefCell::new(ResourceTable::default())),
pending_promise_exceptions: HashMap::new(), pending_promise_exceptions: HashMap::new(),
shared_ab: None, shared_ab: None,
js_recv_cb: None, js_recv_cb: None,
js_macrotask_cb: None, js_macrotask_cb: None,
js_error_create_fn: Box::new(JSError::create), js_error_create_fn: Box::new(JSError::create),
get_error_class_fn: &|_| "Error",
shared: SharedQueue::new(RECOMMENDED_SIZE), shared: SharedQueue::new(RECOMMENDED_SIZE),
pending_ops: FuturesUnordered::new(), pending_ops: FuturesUnordered::new(),
pending_unref_ops: FuturesUnordered::new(), pending_unref_ops: FuturesUnordered::new(),
have_unpolled_ops: false, have_unpolled_ops: Cell::new(false),
op_registry: OpRegistry::new(), op_router: options.op_router,
waker: AtomicWaker::new(), waker: AtomicWaker::new(),
}))); })));
@ -421,66 +421,6 @@ impl CoreIsolate {
snapshot snapshot
} }
/// Defines the how Deno.core.dispatch() acts.
/// Called whenever Deno.core.dispatch() is called in JavaScript. zero_copy_buf
/// corresponds to the second argument of Deno.core.dispatch().
///
/// Requires runtime to explicitly ask for op ids before using any of the ops.
pub fn register_op<F>(&mut self, name: &str, op: F) -> OpId
where
F: Fn(&mut CoreIsolateState, &mut [ZeroCopyBuf]) -> Op + 'static,
{
let state_rc = Self::state(self);
let mut state = state_rc.borrow_mut();
state.op_registry.register(name, op)
}
pub fn register_op_json_sync<F>(&mut self, name: &str, op: F) -> OpId
where
F: 'static
+ Fn(
&mut CoreIsolateState,
serde_json::Value,
&mut [ZeroCopyBuf],
) -> Result<serde_json::Value, ErrBox>,
{
let core_op =
move |state: &mut CoreIsolateState, bufs: &mut [ZeroCopyBuf]| -> Op {
let value = serde_json::from_slice(&bufs[0]).unwrap();
let result = op(state, value, &mut bufs[1..]);
let buf = serialize_result(None, result, state.get_error_class_fn);
Op::Sync(buf)
};
let state_rc = Self::state(self);
let mut state = state_rc.borrow_mut();
state.op_registry.register(name, core_op)
}
pub fn register_op_json_async<F, Fut>(&mut self, name: &str, op: F) -> OpId
where
Fut: 'static + Future<Output = Result<serde_json::Value, ErrBox>>,
F: 'static
+ Fn(&mut CoreIsolateState, serde_json::Value, &mut [ZeroCopyBuf]) -> Fut,
{
let core_op = move |state: &mut CoreIsolateState,
bufs: &mut [ZeroCopyBuf]|
-> Op {
let get_error_class_fn = state.get_error_class_fn;
let value: serde_json::Value = serde_json::from_slice(&bufs[0]).unwrap();
let promise_id = value.get("promiseId").unwrap().as_u64().unwrap();
let fut = op(state, value, &mut bufs[1..]);
let fut2 = fut.map(move |result| {
serialize_result(Some(promise_id), result, get_error_class_fn)
});
Op::Async(Box::pin(fut2))
};
let state_rc = Self::state(self);
let mut state = state_rc.borrow_mut();
state.op_registry.register(name, core_op)
}
/// Registers a callback on the isolate when the memory limits are approached. /// 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. /// Use this to prevent V8 from crashing the process when reaching the limit.
/// ///
@ -536,24 +476,6 @@ where
callback(current_heap_limit, initial_heap_limit) callback(current_heap_limit, initial_heap_limit)
} }
fn serialize_result(
promise_id: Option<u64>,
result: Result<Value, ErrBox>,
get_error_class_fn: GetErrorClassFn,
) -> Buf {
let value = match result {
Ok(v) => json!({ "ok": v, "promiseId": promise_id }),
Err(err) => json!({
"promiseId": promise_id ,
"err": {
"className": (get_error_class_fn)(&err),
"message": err.to_string(),
}
}),
};
serde_json::to_vec(&value).unwrap().into_boxed_slice()
}
impl Future for CoreIsolate { impl Future for CoreIsolate {
type Output = Result<(), ErrBox>; type Output = Result<(), ErrBox>;
@ -574,12 +496,12 @@ impl Future for CoreIsolate {
check_promise_exceptions(scope)?; check_promise_exceptions(scope)?;
let mut overflow_response: Option<(OpId, Buf)> = None; let mut overflow_response: Option<(OpId, Box<[u8]>)> = None;
loop { loop {
let mut state = state_rc.borrow_mut(); let mut state = state_rc.borrow_mut();
// Now handle actual ops. // Now handle actual ops.
state.have_unpolled_ops = false; state.have_unpolled_ops.set(false);
let pending_r = state.pending_ops.poll_next_unpin(cx); let pending_r = state.pending_ops.poll_next_unpin(cx);
match pending_r { match pending_r {
@ -644,7 +566,7 @@ impl Future for CoreIsolate {
if state.pending_ops.is_empty() { if state.pending_ops.is_empty() {
Poll::Ready(Ok(())) Poll::Ready(Ok(()))
} else { } else {
if state.have_unpolled_ops { if state.have_unpolled_ops.get() {
state.waker.wake(); state.waker.wake();
} }
Poll::Pending Poll::Pending
@ -653,18 +575,6 @@ impl Future for CoreIsolate {
} }
impl CoreIsolateState { impl CoreIsolateState {
/// Defines the how Deno.core.dispatch() acts.
/// Called whenever Deno.core.dispatch() is called in JavaScript. zero_copy_buf
/// corresponds to the second argument of Deno.core.dispatch().
///
/// Requires runtime to explicitly ask for op ids before using any of the ops.
pub fn register_op<F>(&mut self, name: &str, op: F) -> OpId
where
F: Fn(&mut CoreIsolateState, &mut [ZeroCopyBuf]) -> Op + 'static,
{
self.op_registry.register(name, op)
}
/// Allows a callback to be set whenever a V8 exception is made. This allows /// Allows a callback to be set whenever a V8 exception is made. This allows
/// the caller to wrap the JSError into an error. By default this callback /// the caller to wrap the JSError into an error. By default this callback
/// is set to JSError::create. /// is set to JSError::create.
@ -674,49 +584,6 @@ impl CoreIsolateState {
) { ) {
self.js_error_create_fn = Box::new(f); self.js_error_create_fn = Box::new(f);
} }
pub fn set_get_error_class_fn(&mut self, f: GetErrorClassFn) {
self.get_error_class_fn = f;
}
pub fn dispatch_op<'s>(
&mut self,
scope: &mut v8::HandleScope<'s>,
op_id: OpId,
zero_copy_bufs: &mut [ZeroCopyBuf],
) -> Option<(OpId, Box<[u8]>)> {
let op = if let Some(dispatcher) = self.op_registry.get(op_id) {
dispatcher(self, zero_copy_bufs)
} else {
let message =
v8::String::new(scope, &format!("Unknown op id: {}", op_id)).unwrap();
let exception = v8::Exception::type_error(scope, message);
scope.throw_exception(exception);
return None;
};
debug_assert_eq!(self.shared.size(), 0);
match op {
Op::Sync(buf) => {
// For sync messages, we always return the response via Deno.core.send's
// return value. Sync messages ignore the op_id.
let op_id = 0;
Some((op_id, buf))
}
Op::Async(fut) => {
let fut2 = fut.map(move |buf| (op_id, buf));
self.pending_ops.push(fut2.boxed_local());
self.have_unpolled_ops = true;
None
}
Op::AsyncUnref(fut) => {
let fut2 = fut.map(move |buf| (op_id, buf));
self.pending_unref_ops.push(fut2.boxed_local());
self.have_unpolled_ops = true;
None
}
}
}
} }
fn async_op_response<'s>( fn async_op_response<'s>(
@ -739,7 +606,7 @@ fn async_op_response<'s>(
let op_id: v8::Local<v8::Value> = let op_id: v8::Local<v8::Value> =
v8::Integer::new(tc_scope, op_id as i32).into(); v8::Integer::new(tc_scope, op_id as i32).into();
let ui8: v8::Local<v8::Value> = let ui8: v8::Local<v8::Value> =
bindings::boxed_slice_to_uint8array(tc_scope, buf).into(); boxed_slice_to_uint8array(tc_scope, buf).into();
js_recv_cb.call(tc_scope, global, &[op_id, ui8]) js_recv_cb.call(tc_scope, global, &[op_id, ui8])
} }
None => js_recv_cb.call(tc_scope, global, &[]), None => js_recv_cb.call(tc_scope, global, &[]),
@ -848,11 +715,28 @@ pub fn js_check<T>(r: Result<T, ErrBox>) -> T {
r.unwrap() r.unwrap()
} }
fn boxed_slice_to_uint8array<'sc>(
scope: &mut v8::HandleScope<'sc>,
buf: Box<[u8]>,
) -> v8::Local<'sc, v8::Uint8Array> {
assert!(!buf.is_empty());
let buf_len = buf.len();
let backing_store = v8::ArrayBuffer::new_backing_store_from_boxed_slice(buf);
let backing_store_shared = backing_store.make_shared();
let ab = v8::ArrayBuffer::with_backing_store(scope, &backing_store_shared);
v8::Uint8Array::new(scope, ab, 0, buf_len)
.expect("Failed to create UintArray8")
}
#[cfg(test)] #[cfg(test)]
pub mod tests { pub mod tests {
use super::*; use super::*;
use crate::BasicState;
use crate::BufVec;
use futures::future::lazy; use futures::future::lazy;
use futures::FutureExt;
use std::ops::FnOnce; use std::ops::FnOnce;
use std::rc::Rc;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc; use std::sync::Arc;
@ -880,7 +764,7 @@ pub mod tests {
) )
} }
pub enum Mode { enum Mode {
Async, Async,
AsyncUnref, AsyncUnref,
AsyncZeroCopy(u8), AsyncZeroCopy(u8),
@ -890,28 +774,29 @@ pub mod tests {
OverflowResAsync, OverflowResAsync,
} }
pub fn setup(mode: Mode) -> (CoreIsolate, Arc<AtomicUsize>) { struct TestOpRouter {
let dispatch_count = Arc::new(AtomicUsize::new(0)); mode: Mode,
let dispatch_count_ = dispatch_count.clone(); dispatch_count: Arc<AtomicUsize>,
}
let mut isolate = CoreIsolate::new(StartupData::None, false); impl OpRouter for TestOpRouter {
fn route_op(self: Rc<Self>, op_id: OpId, bufs: BufVec) -> Op {
let dispatcher = move |_state: &mut CoreIsolateState, if op_id != 1 {
zero_copy: &mut [ZeroCopyBuf]| return Op::NotFound;
-> Op { }
dispatch_count_.fetch_add(1, Ordering::Relaxed); self.dispatch_count.fetch_add(1, Ordering::Relaxed);
match mode { match self.mode {
Mode::Async => { Mode::Async => {
assert_eq!(zero_copy.len(), 1); assert_eq!(bufs.len(), 1);
assert_eq!(zero_copy[0].len(), 1); assert_eq!(bufs[0].len(), 1);
assert_eq!(zero_copy[0][0], 42); assert_eq!(bufs[0][0], 42);
let buf = vec![43u8].into_boxed_slice(); let buf = vec![43u8].into_boxed_slice();
Op::Async(futures::future::ready(buf).boxed()) Op::Async(futures::future::ready(buf).boxed())
} }
Mode::AsyncUnref => { Mode::AsyncUnref => {
assert_eq!(zero_copy.len(), 1); assert_eq!(bufs.len(), 1);
assert_eq!(zero_copy[0].len(), 1); assert_eq!(bufs[0].len(), 1);
assert_eq!(zero_copy[0][0], 42); assert_eq!(bufs[0][0], 42);
let fut = async { let fut = async {
// This future never finish. // This future never finish.
futures::future::pending::<()>().await; futures::future::pending::<()>().await;
@ -920,8 +805,8 @@ pub mod tests {
Op::AsyncUnref(fut.boxed()) Op::AsyncUnref(fut.boxed())
} }
Mode::AsyncZeroCopy(count) => { Mode::AsyncZeroCopy(count) => {
assert_eq!(zero_copy.len(), count as usize); assert_eq!(bufs.len(), count as usize);
zero_copy.iter().enumerate().for_each(|(idx, buf)| { bufs.iter().enumerate().for_each(|(idx, buf)| {
assert_eq!(buf.len(), 1); assert_eq!(buf.len(), 1);
assert_eq!(idx, buf[0] as usize); assert_eq!(idx, buf[0] as usize);
}); });
@ -930,15 +815,15 @@ pub mod tests {
Op::Async(futures::future::ready(buf).boxed()) Op::Async(futures::future::ready(buf).boxed())
} }
Mode::OverflowReqSync => { Mode::OverflowReqSync => {
assert_eq!(zero_copy.len(), 1); assert_eq!(bufs.len(), 1);
assert_eq!(zero_copy[0].len(), 100 * 1024 * 1024); assert_eq!(bufs[0].len(), 100 * 1024 * 1024);
let buf = vec![43u8].into_boxed_slice(); let buf = vec![43u8].into_boxed_slice();
Op::Sync(buf) Op::Sync(buf)
} }
Mode::OverflowResSync => { Mode::OverflowResSync => {
assert_eq!(zero_copy.len(), 1); assert_eq!(bufs.len(), 1);
assert_eq!(zero_copy[0].len(), 1); assert_eq!(bufs[0].len(), 1);
assert_eq!(zero_copy[0][0], 42); assert_eq!(bufs[0][0], 42);
let mut vec = Vec::<u8>::new(); let mut vec = Vec::<u8>::new();
vec.resize(100 * 1024 * 1024, 0); vec.resize(100 * 1024 * 1024, 0);
vec[0] = 99; vec[0] = 99;
@ -946,15 +831,15 @@ pub mod tests {
Op::Sync(buf) Op::Sync(buf)
} }
Mode::OverflowReqAsync => { Mode::OverflowReqAsync => {
assert_eq!(zero_copy.len(), 1); assert_eq!(bufs.len(), 1);
assert_eq!(zero_copy[0].len(), 100 * 1024 * 1024); assert_eq!(bufs[0].len(), 100 * 1024 * 1024);
let buf = vec![43u8].into_boxed_slice(); let buf = vec![43u8].into_boxed_slice();
Op::Async(futures::future::ready(buf).boxed()) Op::Async(futures::future::ready(buf).boxed())
} }
Mode::OverflowResAsync => { Mode::OverflowResAsync => {
assert_eq!(zero_copy.len(), 1); assert_eq!(bufs.len(), 1);
assert_eq!(zero_copy[0].len(), 1); assert_eq!(bufs[0].len(), 1);
assert_eq!(zero_copy[0][0], 42); assert_eq!(bufs[0][0], 42);
let mut vec = Vec::<u8>::new(); let mut vec = Vec::<u8>::new();
vec.resize(100 * 1024 * 1024, 0); vec.resize(100 * 1024 * 1024, 0);
vec[0] = 4; vec[0] = 4;
@ -962,9 +847,16 @@ pub mod tests {
Op::Async(futures::future::ready(buf).boxed()) Op::Async(futures::future::ready(buf).boxed())
} }
} }
}; }
}
isolate.register_op("test", dispatcher); fn setup(mode: Mode) -> (CoreIsolate, Arc<AtomicUsize>) {
let dispatch_count = Arc::new(AtomicUsize::new(0));
let test_state = Rc::new(TestOpRouter {
mode,
dispatch_count: dispatch_count.clone(),
});
let mut isolate = CoreIsolate::new(test_state, StartupData::None, false);
js_check(isolate.execute( js_check(isolate.execute(
"setup.js", "setup.js",
@ -1328,7 +1220,8 @@ pub mod tests {
#[test] #[test]
fn syntax_error() { fn syntax_error() {
let mut isolate = CoreIsolate::new(StartupData::None, false); let mut isolate =
CoreIsolate::new(BasicState::new(), StartupData::None, false);
let src = "hocuspocus("; let src = "hocuspocus(";
let r = isolate.execute("i.js", src); let r = isolate.execute("i.js", src);
let e = r.unwrap_err(); let e = r.unwrap_err();
@ -1353,27 +1246,29 @@ pub mod tests {
#[test] #[test]
fn will_snapshot() { fn will_snapshot() {
let snapshot = { let snapshot = {
let mut isolate = CoreIsolate::new(StartupData::None, true); let mut isolate =
CoreIsolate::new(BasicState::new(), StartupData::None, true);
js_check(isolate.execute("a.js", "a = 1 + 2")); js_check(isolate.execute("a.js", "a = 1 + 2"));
isolate.snapshot() isolate.snapshot()
}; };
let startup_data = StartupData::Snapshot(Snapshot::JustCreated(snapshot)); let startup_data = StartupData::Snapshot(Snapshot::JustCreated(snapshot));
let mut isolate2 = CoreIsolate::new(startup_data, false); let mut isolate2 = CoreIsolate::new(BasicState::new(), startup_data, false);
js_check(isolate2.execute("check.js", "if (a != 3) throw Error('x')")); js_check(isolate2.execute("check.js", "if (a != 3) throw Error('x')"));
} }
#[test] #[test]
fn test_from_boxed_snapshot() { fn test_from_boxed_snapshot() {
let snapshot = { let snapshot = {
let mut isolate = CoreIsolate::new(StartupData::None, true); let mut isolate =
CoreIsolate::new(BasicState::new(), StartupData::None, true);
js_check(isolate.execute("a.js", "a = 1 + 2")); js_check(isolate.execute("a.js", "a = 1 + 2"));
let snap: &[u8] = &*isolate.snapshot(); let snap: &[u8] = &*isolate.snapshot();
Vec::from(snap).into_boxed_slice() Vec::from(snap).into_boxed_slice()
}; };
let startup_data = StartupData::Snapshot(Snapshot::Boxed(snapshot)); let startup_data = StartupData::Snapshot(Snapshot::Boxed(snapshot));
let mut isolate2 = CoreIsolate::new(startup_data, false); let mut isolate2 = CoreIsolate::new(BasicState::new(), startup_data, false);
js_check(isolate2.execute("check.js", "if (a != 3) throw Error('x')")); js_check(isolate2.execute("check.js", "if (a != 3) throw Error('x')"));
} }
@ -1383,8 +1278,11 @@ pub mod tests {
initial: 0, initial: 0,
max: 20 * 1024, // 20 kB max: 20 * 1024, // 20 kB
}; };
let mut isolate = let mut isolate = CoreIsolate::with_heap_limits(
CoreIsolate::with_heap_limits(StartupData::None, heap_limits); BasicState::new(),
StartupData::None,
heap_limits,
);
let cb_handle = isolate.thread_safe_handle(); let cb_handle = isolate.thread_safe_handle();
let callback_invoke_count = Rc::new(AtomicUsize::default()); let callback_invoke_count = Rc::new(AtomicUsize::default());
@ -1412,7 +1310,8 @@ pub mod tests {
#[test] #[test]
fn test_heap_limit_cb_remove() { fn test_heap_limit_cb_remove() {
let mut isolate = CoreIsolate::new(StartupData::None, false); let mut isolate =
CoreIsolate::new(BasicState::new(), StartupData::None, false);
isolate.add_near_heap_limit_callback(|current_limit, _initial_limit| { isolate.add_near_heap_limit_callback(|current_limit, _initial_limit| {
current_limit * 2 current_limit * 2
@ -1427,8 +1326,11 @@ pub mod tests {
initial: 0, initial: 0,
max: 20 * 1024, // 20 kB max: 20 * 1024, // 20 kB
}; };
let mut isolate = let mut isolate = CoreIsolate::with_heap_limits(
CoreIsolate::with_heap_limits(StartupData::None, heap_limits); BasicState::new(),
StartupData::None,
heap_limits,
);
let cb_handle = isolate.thread_safe_handle(); let cb_handle = isolate.thread_safe_handle();
let callback_invoke_count_first = Rc::new(AtomicUsize::default()); let callback_invoke_count_first = Rc::new(AtomicUsize::default());

View file

@ -446,19 +446,21 @@ impl fmt::Debug for ErrWithV8Handle {
} }
} }
#[cfg(tests)] #[cfg(test)]
mod tests { mod tests {
use super::*;
#[test] #[test]
fn test_bad_resource() { fn test_bad_resource() {
let err = ErrBox::bad_resource("Resource has been closed"); let err = ErrBox::bad_resource("Resource has been closed");
assert_eq!(err.1, "BadResource"); assert!(matches!(err, ErrBox::Simple { class: "BadResource", .. }));
assert_eq!(err.to_string(), "Resource has been closed"); assert_eq!(err.to_string(), "Resource has been closed");
} }
#[test] #[test]
fn test_bad_resource_id() { fn test_bad_resource_id() {
let err = ErrBox::bad_resource_id(); let err = ErrBox::bad_resource_id();
assert_eq!(err.1, "BadResource"); assert!(matches!(err, ErrBox::Simple { class: "BadResource", .. }));
assert_eq!(err.to_string(), "Bad resource ID"); assert_eq!(err.to_string(), "Bad resource ID");
} }
} }

View file

@ -10,6 +10,7 @@ use crate::bindings;
use crate::errors::ErrBox; use crate::errors::ErrBox;
use crate::errors::ErrWithV8Handle; use crate::errors::ErrWithV8Handle;
use crate::futures::FutureExt; use crate::futures::FutureExt;
use crate::OpRouter;
use futures::ready; use futures::ready;
use futures::stream::FuturesUnordered; use futures::stream::FuturesUnordered;
use futures::stream::StreamExt; use futures::stream::StreamExt;
@ -76,10 +77,12 @@ impl DerefMut for EsIsolate {
impl EsIsolate { impl EsIsolate {
pub fn new( pub fn new(
loader: Rc<dyn ModuleLoader>, loader: Rc<dyn ModuleLoader>,
op_router: Rc<dyn OpRouter>,
startup_data: StartupData, startup_data: StartupData,
will_snapshot: bool, will_snapshot: bool,
) -> Self { ) -> Self {
let mut core_isolate = CoreIsolate::new(startup_data, will_snapshot); let mut core_isolate =
CoreIsolate::new(op_router, startup_data, will_snapshot);
{ {
core_isolate.set_host_initialize_import_meta_object_callback( core_isolate.set_host_initialize_import_meta_object_callback(
bindings::host_initialize_import_meta_object_callback, bindings::host_initialize_import_meta_object_callback,
@ -640,11 +643,11 @@ impl EsIsolateState {
pub mod tests { pub mod tests {
use super::*; use super::*;
use crate::core_isolate::tests::run_in_task; use crate::core_isolate::tests::run_in_task;
use crate::core_isolate::CoreIsolateState;
use crate::js_check; use crate::js_check;
use crate::modules::ModuleSourceFuture; use crate::modules::ModuleSourceFuture;
use crate::ops::*; use crate::ops::*;
use crate::ZeroCopyBuf; use crate::BasicState;
use crate::BufVec;
use std::io; use std::io;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc; use std::sync::Arc;
@ -681,24 +684,23 @@ pub mod tests {
} }
let loader = Rc::new(ModsLoader::default()); let loader = Rc::new(ModsLoader::default());
let state = BasicState::new();
let resolve_count = loader.count.clone(); let resolve_count = loader.count.clone();
let dispatch_count = Arc::new(AtomicUsize::new(0)); let dispatch_count = Arc::new(AtomicUsize::new(0));
let dispatch_count_ = dispatch_count.clone(); let dispatch_count_ = dispatch_count.clone();
let mut isolate = EsIsolate::new(loader, StartupData::None, false); let dispatcher = move |_state: Rc<BasicState>, bufs: BufVec| -> Op {
let dispatcher = move |_state: &mut CoreIsolateState,
zero_copy: &mut [ZeroCopyBuf]|
-> Op {
dispatch_count_.fetch_add(1, Ordering::Relaxed); dispatch_count_.fetch_add(1, Ordering::Relaxed);
assert_eq!(zero_copy.len(), 1); assert_eq!(bufs.len(), 1);
assert_eq!(zero_copy[0].len(), 1); assert_eq!(bufs[0].len(), 1);
assert_eq!(zero_copy[0][0], 42); assert_eq!(bufs[0][0], 42);
let buf = vec![43u8, 0, 0, 0].into_boxed_slice(); let buf = [43u8, 0, 0, 0][..].into();
Op::Async(futures::future::ready(buf).boxed()) Op::Async(futures::future::ready(buf).boxed())
}; };
state.register_op("test", dispatcher);
isolate.register_op("test", dispatcher); let mut isolate = EsIsolate::new(loader, state, StartupData::None, false);
js_check(isolate.execute( js_check(isolate.execute(
"setup.js", "setup.js",
@ -792,7 +794,8 @@ pub mod tests {
run_in_task(|cx| { run_in_task(|cx| {
let loader = Rc::new(DynImportErrLoader::default()); let loader = Rc::new(DynImportErrLoader::default());
let count = loader.count.clone(); let count = loader.count.clone();
let mut isolate = EsIsolate::new(loader, StartupData::None, false); let mut isolate =
EsIsolate::new(loader, BasicState::new(), StartupData::None, false);
js_check(isolate.execute( js_check(isolate.execute(
"file:///dyn_import2.js", "file:///dyn_import2.js",
@ -869,7 +872,8 @@ pub mod tests {
let prepare_load_count = loader.prepare_load_count.clone(); let prepare_load_count = loader.prepare_load_count.clone();
let resolve_count = loader.resolve_count.clone(); let resolve_count = loader.resolve_count.clone();
let load_count = loader.load_count.clone(); let load_count = loader.load_count.clone();
let mut isolate = EsIsolate::new(loader, StartupData::None, false); let mut isolate =
EsIsolate::new(loader, BasicState::new(), StartupData::None, false);
// Dynamically import mod_b // Dynamically import mod_b
js_check(isolate.execute( js_check(isolate.execute(
@ -909,7 +913,8 @@ pub mod tests {
run_in_task(|cx| { run_in_task(|cx| {
let loader = Rc::new(DynImportOkLoader::default()); let loader = Rc::new(DynImportOkLoader::default());
let prepare_load_count = loader.prepare_load_count.clone(); let prepare_load_count = loader.prepare_load_count.clone();
let mut isolate = EsIsolate::new(loader, StartupData::None, false); let mut isolate =
EsIsolate::new(loader, BasicState::new(), StartupData::None, false);
js_check(isolate.execute( js_check(isolate.execute(
"file:///dyn_import3.js", "file:///dyn_import3.js",
r#" r#"
@ -960,7 +965,8 @@ pub mod tests {
} }
let loader = std::rc::Rc::new(ModsLoader::default()); let loader = std::rc::Rc::new(ModsLoader::default());
let mut runtime_isolate = EsIsolate::new(loader, StartupData::None, true); let mut runtime_isolate =
EsIsolate::new(loader, BasicState::new(), StartupData::None, true);
let specifier = ModuleSpecifier::resolve_url("file:///main.js").unwrap(); let specifier = ModuleSpecifier::resolve_url("file:///main.js").unwrap();
let source_code = "Deno.core.print('hello\\n')".to_string(); let source_code = "Deno.core.print('hello\\n')".to_string();

View file

@ -1,10 +1,12 @@
#[macro_use] #[macro_use]
extern crate log; extern crate log;
use deno_core::js_check;
use deno_core::BasicState;
use deno_core::BufVec;
use deno_core::CoreIsolate; use deno_core::CoreIsolate;
use deno_core::CoreIsolateState;
use deno_core::Op; use deno_core::Op;
use deno_core::ResourceTable; use deno_core::OpRegistry;
use deno_core::Script; use deno_core::Script;
use deno_core::StartupData; use deno_core::StartupData;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
@ -12,7 +14,6 @@ use futures::future::poll_fn;
use futures::future::FutureExt; use futures::future::FutureExt;
use futures::future::TryFuture; use futures::future::TryFuture;
use futures::future::TryFutureExt; use futures::future::TryFutureExt;
use std::cell::RefCell;
use std::convert::TryInto; use std::convert::TryInto;
use std::env; use std::env;
use std::fmt::Debug; use std::fmt::Debug;
@ -27,6 +28,7 @@ use tokio::io::AsyncRead;
use tokio::io::AsyncWrite; use tokio::io::AsyncWrite;
use tokio::net::TcpListener; use tokio::net::TcpListener;
use tokio::net::TcpStream; use tokio::net::TcpStream;
use tokio::runtime;
struct Logger; struct Logger;
@ -46,9 +48,9 @@ impl log::Log for Logger {
#[derive(Copy, Clone, Debug, PartialEq)] #[derive(Copy, Clone, Debug, PartialEq)]
struct Record { struct Record {
pub promise_id: u32, promise_id: u32,
pub rid: u32, rid: u32,
pub result: i32, result: i32,
} }
type RecordBuf = [u8; size_of::<Record>()]; type RecordBuf = [u8; size_of::<Record>()];
@ -75,131 +77,64 @@ impl From<Record> for RecordBuf {
} }
} }
pub fn isolate_new() -> CoreIsolate { fn create_isolate() -> CoreIsolate {
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 { let startup_data = StartupData::Script(Script {
source: include_str!("http_bench_bin_ops.js"), source: include_str!("http_bench_bin_ops.js"),
filename: "http_bench_bin_ops.js", filename: "http_bench_bin_ops.js",
}); });
let mut isolate = CoreIsolate::new(startup_data, false); CoreIsolate::new(state, startup_data, false)
fn register_sync_op<F>(
isolate: &mut CoreIsolate,
name: &'static str,
handler: F,
) where
F: 'static
+ Fn(
Rc<RefCell<ResourceTable>>,
u32,
&mut [ZeroCopyBuf],
) -> Result<u32, Error>,
{
let core_handler = move |state: &mut CoreIsolateState,
zero_copy_bufs: &mut [ZeroCopyBuf]|
-> Op {
assert!(!zero_copy_bufs.is_empty());
let record = Record::from(zero_copy_bufs[0].as_ref());
let is_sync = record.promise_id == 0;
assert!(is_sync);
let resource_table = state.resource_table.clone();
let result: i32 =
match handler(resource_table, record.rid, &mut zero_copy_bufs[1..]) {
Ok(r) => r as i32,
Err(_) => -1,
};
let buf = RecordBuf::from(Record { result, ..record })[..].into();
Op::Sync(buf)
};
isolate.register_op(name, core_handler);
}
fn register_async_op<F>(
isolate: &mut CoreIsolate,
name: &'static str,
handler: impl Fn(Rc<RefCell<ResourceTable>>, u32, &mut [ZeroCopyBuf]) -> F
+ Copy
+ 'static,
) where
F: TryFuture,
F::Ok: TryInto<i32>,
<F::Ok as TryInto<i32>>::Error: Debug,
{
let core_handler = move |state: &mut CoreIsolateState,
zero_copy_bufs: &mut [ZeroCopyBuf]|
-> Op {
assert!(!zero_copy_bufs.is_empty());
let record = Record::from(zero_copy_bufs[0].as_ref());
let is_sync = record.promise_id == 0;
assert!(!is_sync);
let mut zero_copy = zero_copy_bufs[1..].to_vec();
let resource_table = state.resource_table.clone();
let fut = async move {
let op = handler(resource_table, record.rid, &mut zero_copy);
let result = op
.map_ok(|r| r.try_into().expect("op result does not fit in i32"))
.unwrap_or_else(|_| -1)
.await;
RecordBuf::from(Record { result, ..record })[..].into()
};
Op::Async(fut.boxed_local())
};
isolate.register_op(name, core_handler);
}
register_sync_op(&mut isolate, "listen", op_listen);
register_async_op(&mut isolate, "accept", op_accept);
register_async_op(&mut isolate, "read", op_read);
register_async_op(&mut isolate, "write", op_write);
register_sync_op(&mut isolate, "close", op_close);
isolate
}
fn op_close(
resource_table: Rc<RefCell<ResourceTable>>,
rid: u32,
_buf: &mut [ZeroCopyBuf],
) -> Result<u32, Error> {
debug!("close rid={}", rid);
let resource_table = &mut resource_table.borrow_mut();
resource_table
.close(rid)
.map(|_| 0)
.ok_or_else(bad_resource)
} }
fn op_listen( fn op_listen(
resource_table: Rc<RefCell<ResourceTable>>, state: &BasicState,
_rid: u32, _rid: u32,
_buf: &mut [ZeroCopyBuf], _bufs: &mut [ZeroCopyBuf],
) -> Result<u32, Error> { ) -> Result<u32, Error> {
debug!("listen"); debug!("listen");
let addr = "127.0.0.1:4544".parse::<SocketAddr>().unwrap(); let addr = "127.0.0.1:4544".parse::<SocketAddr>().unwrap();
let std_listener = std::net::TcpListener::bind(&addr)?; let std_listener = std::net::TcpListener::bind(&addr)?;
let listener = TcpListener::from_std(std_listener)?; let listener = TcpListener::from_std(std_listener)?;
let resource_table = &mut resource_table.borrow_mut(); let rid = state
let rid = resource_table.add("tcpListener", Box::new(listener)); .resource_table
.borrow_mut()
.add("tcpListener", Box::new(listener));
Ok(rid) Ok(rid)
} }
fn op_accept( fn op_close(
resource_table: Rc<RefCell<ResourceTable>>, state: &BasicState,
rid: u32, rid: u32,
_buf: &mut [ZeroCopyBuf], _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>,
rid: u32,
_bufs: BufVec,
) -> impl TryFuture<Ok = u32, Error = Error> { ) -> impl TryFuture<Ok = u32, Error = Error> {
debug!("accept rid={}", rid); debug!("accept rid={}", rid);
poll_fn(move |cx| { poll_fn(move |cx| {
let resource_table = &mut resource_table.borrow_mut(); let resource_table = &mut state.resource_table.borrow_mut();
let listener = resource_table let listener = resource_table
.get_mut::<TcpListener>(rid) .get_mut::<TcpListener>(rid)
.ok_or_else(bad_resource)?; .ok_or_else(bad_resource_id)?;
listener.poll_accept(cx).map_ok(|(stream, _addr)| { listener.poll_accept(cx).map_ok(|(stream, _addr)| {
resource_table.add("tcpStream", Box::new(stream)) resource_table.add("tcpStream", Box::new(stream))
}) })
@ -207,9 +142,9 @@ fn op_accept(
} }
fn op_read( fn op_read(
resource_table: Rc<RefCell<ResourceTable>>, state: Rc<BasicState>,
rid: u32, rid: u32,
bufs: &mut [ZeroCopyBuf], bufs: BufVec,
) -> impl TryFuture<Ok = usize, Error = Error> { ) -> impl TryFuture<Ok = usize, Error = Error> {
assert_eq!(bufs.len(), 1, "Invalid number of arguments"); assert_eq!(bufs.len(), 1, "Invalid number of arguments");
let mut buf = bufs[0].clone(); let mut buf = bufs[0].clone();
@ -217,33 +152,85 @@ fn op_read(
debug!("read rid={}", rid); debug!("read rid={}", rid);
poll_fn(move |cx| { poll_fn(move |cx| {
let resource_table = &mut resource_table.borrow_mut(); let resource_table = &mut state.resource_table.borrow_mut();
let stream = resource_table let stream = resource_table
.get_mut::<TcpStream>(rid) .get_mut::<TcpStream>(rid)
.ok_or_else(bad_resource)?; .ok_or_else(bad_resource_id)?;
Pin::new(stream).poll_read(cx, &mut buf) Pin::new(stream).poll_read(cx, &mut buf)
}) })
} }
fn op_write( fn op_write(
resource_table: Rc<RefCell<ResourceTable>>, state: Rc<BasicState>,
rid: u32, rid: u32,
bufs: &mut [ZeroCopyBuf], bufs: BufVec,
) -> impl TryFuture<Ok = usize, Error = Error> { ) -> impl TryFuture<Ok = usize, Error = Error> {
assert_eq!(bufs.len(), 1, "Invalid number of arguments"); assert_eq!(bufs.len(), 1, "Invalid number of arguments");
let buf = bufs[0].clone(); let buf = bufs[0].clone();
debug!("write rid={}", rid); debug!("write rid={}", rid);
poll_fn(move |cx| { poll_fn(move |cx| {
let resource_table = &mut resource_table.borrow_mut(); let resource_table = &mut state.resource_table.borrow_mut();
let stream = resource_table let stream = resource_table
.get_mut::<TcpStream>(rid) .get_mut::<TcpStream>(rid)
.ok_or_else(bad_resource)?; .ok_or_else(bad_resource_id)?;
Pin::new(stream).poll_write(cx, &buf) Pin::new(stream).poll_write(cx, &buf)
}) })
} }
fn bad_resource() -> Error { 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,
{
let base_op_fn = move |state: Rc<BasicState>, 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 buf = RecordBuf::from(Record { result, ..record })[..].into();
Op::Sync(buf)
};
state.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,
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 mut bufs_iter = bufs.into_iter();
let record_buf = bufs_iter.next().unwrap();
let zero_copy_bufs = bufs_iter.collect::<BufVec>();
let record = Record::from(record_buf.as_ref());
let is_sync = record.promise_id == 0;
assert!(!is_sync);
let fut = async move {
let op = op_fn(state, record.rid, zero_copy_bufs);
let result = op
.map_ok(|r| r.try_into().expect("op result does not fit in i32"))
.unwrap_or_else(|_| -1)
.await;
RecordBuf::from(Record { result, ..record })[..].into()
};
Op::Async(fut.boxed_local())
};
state.register_op(name, base_op_fn);
}
fn bad_resource_id() -> Error {
Error::new(ErrorKind::NotFound, "bad resource id") Error::new(ErrorKind::NotFound, "bad resource id")
} }
@ -259,13 +246,13 @@ fn main() {
// NOTE: `--help` arg will display V8 help and exit // NOTE: `--help` arg will display V8 help and exit
deno_core::v8_set_flags(env::args().collect()); deno_core::v8_set_flags(env::args().collect());
let isolate = isolate_new(); let isolate = create_isolate();
let mut runtime = tokio::runtime::Builder::new() let mut runtime = runtime::Builder::new()
.basic_scheduler() .basic_scheduler()
.enable_all() .enable_all()
.build() .build()
.unwrap(); .unwrap();
runtime.block_on(isolate).expect("unexpected isolate error"); js_check(runtime.block_on(isolate));
} }
#[test] #[test]

View file

@ -1,25 +1,29 @@
#[macro_use] #[macro_use]
extern crate log; extern crate log;
use deno_core::serde_json; use deno_core::js_check;
use deno_core::BasicState;
use deno_core::BufVec;
use deno_core::CoreIsolate; use deno_core::CoreIsolate;
use deno_core::CoreIsolateState;
use deno_core::ErrBox; use deno_core::ErrBox;
use deno_core::OpRegistry;
use deno_core::Script; use deno_core::Script;
use deno_core::StartupData; use deno_core::StartupData;
use deno_core::ZeroCopyBuf; use deno_core::ZeroCopyBuf;
use futures::future::poll_fn; use futures::future::poll_fn;
use futures::future::Future; use futures::future::Future;
use serde_json::Value;
use std::convert::TryInto;
use std::env; use std::env;
use std::io::Error;
use std::io::ErrorKind;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::pin::Pin; use std::pin::Pin;
use std::rc::Rc;
use std::task::Poll; use std::task::Poll;
use tokio::io::AsyncRead; use tokio::io::AsyncRead;
use tokio::io::AsyncWrite; use tokio::io::AsyncWrite;
use tokio::net::TcpListener; use tokio::net::TcpListener;
use tokio::net::TcpStream; use tokio::net::TcpStream;
use tokio::runtime;
struct Logger; struct Logger;
@ -37,66 +41,79 @@ impl log::Log for Logger {
fn flush(&self) {} fn flush(&self) {}
} }
pub fn isolate_new() -> CoreIsolate { fn create_isolate() -> CoreIsolate {
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 { let startup_data = StartupData::Script(Script {
source: include_str!("http_bench_json_ops.js"), source: include_str!("http_bench_json_ops.js"),
filename: "http_bench_json_ops.js", filename: "http_bench_json_ops.js",
}); });
let mut isolate = CoreIsolate::new(startup_data, false); CoreIsolate::new(state, startup_data, false)
isolate.register_op_json_sync("listen", op_listen);
isolate.register_op_json_async("accept", op_accept);
isolate.register_op_json_async("read", op_read);
isolate.register_op_json_async("write", op_write);
isolate.register_op_json_sync("close", op_close);
isolate
}
fn op_close(
state: &mut CoreIsolateState,
args: serde_json::Value,
_buf: &mut [ZeroCopyBuf],
) -> Result<serde_json::Value, ErrBox> {
let rid = args.get("rid").unwrap().as_u64().unwrap() as u32;
debug!("close rid={}", rid);
let resource_table = &mut state.resource_table.borrow_mut();
resource_table
.close(rid)
.map(|_| serde_json::json!(()))
.ok_or_else(bad_resource)
} }
fn op_listen( fn op_listen(
state: &mut CoreIsolateState, state: &BasicState,
_args: serde_json::Value, _args: Value,
_buf: &mut [ZeroCopyBuf], _bufs: &mut [ZeroCopyBuf],
) -> Result<serde_json::Value, ErrBox> { ) -> Result<Value, ErrBox> {
debug!("listen"); debug!("listen");
let addr = "127.0.0.1:4544".parse::<SocketAddr>().unwrap(); let addr = "127.0.0.1:4544".parse::<SocketAddr>().unwrap();
let std_listener = std::net::TcpListener::bind(&addr)?; let std_listener = std::net::TcpListener::bind(&addr)?;
let listener = TcpListener::from_std(std_listener)?; let listener = TcpListener::from_std(std_listener)?;
let resource_table = &mut state.resource_table.borrow_mut(); let rid = state
let rid = resource_table.add("tcpListener", Box::new(listener)); .resource_table
.borrow_mut()
.add("tcpListener", Box::new(listener));
Ok(serde_json::json!({ "rid": rid })) Ok(serde_json::json!({ "rid": rid }))
} }
fn op_accept( fn op_close(
state: &mut CoreIsolateState, state: &BasicState,
args: serde_json::Value, args: Value,
_buf: &mut [ZeroCopyBuf], _buf: &mut [ZeroCopyBuf],
) -> impl Future<Output = Result<serde_json::Value, ErrBox>> { ) -> Result<Value, ErrBox> {
let rid = args.get("rid").unwrap().as_u64().unwrap() as u32; let rid: u32 = args
.get("rid")
.unwrap()
.as_u64()
.unwrap()
.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>,
args: Value,
_bufs: BufVec,
) -> impl Future<Output = Result<Value, ErrBox>> {
let rid: u32 = args
.get("rid")
.unwrap()
.as_u64()
.unwrap()
.try_into()
.unwrap();
debug!("accept rid={}", rid); debug!("accept rid={}", rid);
let resource_table = state.resource_table.clone();
poll_fn(move |cx| { poll_fn(move |cx| {
let resource_table = &mut resource_table.borrow_mut(); let resource_table = &mut state.resource_table.borrow_mut();
let listener = resource_table let listener = resource_table
.get_mut::<TcpListener>(rid) .get_mut::<TcpListener>(rid)
.ok_or_else(bad_resource)?; .ok_or_else(ErrBox::bad_resource_id)?;
listener.poll_accept(cx)?.map(|(stream, _addr)| { listener.poll_accept(cx)?.map(|(stream, _addr)| {
let rid = resource_table.add("tcpStream", Box::new(stream)); let rid = resource_table.add("tcpStream", Box::new(stream));
Ok(serde_json::json!({ "rid": rid })) Ok(serde_json::json!({ "rid": rid }))
@ -105,57 +122,59 @@ fn op_accept(
} }
fn op_read( fn op_read(
state: &mut CoreIsolateState, state: Rc<BasicState>,
args: serde_json::Value, args: Value,
bufs: &mut [ZeroCopyBuf], mut bufs: BufVec,
) -> impl Future<Output = Result<serde_json::Value, ErrBox>> { ) -> impl Future<Output = Result<Value, ErrBox>> {
assert_eq!(bufs.len(), 1, "Invalid number of arguments"); assert_eq!(bufs.len(), 1, "Invalid number of arguments");
let rid = args.get("rid").unwrap().as_u64().unwrap() as u32; let rid: u32 = args
.get("rid")
.unwrap()
.as_u64()
.unwrap()
.try_into()
.unwrap();
debug!("read rid={}", rid); debug!("read rid={}", rid);
let mut buf = bufs[0].clone(); poll_fn(move |cx| -> Poll<Result<Value, ErrBox>> {
let resource_table = state.resource_table.clone(); let resource_table = &mut state.resource_table.borrow_mut();
poll_fn(move |cx| -> Poll<Result<serde_json::Value, ErrBox>> {
let resource_table = &mut resource_table.borrow_mut();
let stream = resource_table let stream = resource_table
.get_mut::<TcpStream>(rid) .get_mut::<TcpStream>(rid)
.ok_or_else(bad_resource)?; .ok_or_else(ErrBox::bad_resource_id)?;
Pin::new(stream) Pin::new(stream)
.poll_read(cx, &mut buf)? .poll_read(cx, &mut bufs[0])?
.map(|nread| Ok(serde_json::json!({ "nread": nread }))) .map(|nread| Ok(serde_json::json!({ "nread": nread })))
}) })
} }
fn op_write( fn op_write(
state: &mut CoreIsolateState, state: Rc<BasicState>,
args: serde_json::Value, args: Value,
bufs: &mut [ZeroCopyBuf], bufs: BufVec,
) -> impl Future<Output = Result<serde_json::Value, ErrBox>> { ) -> impl Future<Output = Result<Value, ErrBox>> {
assert_eq!(bufs.len(), 1, "Invalid number of arguments"); assert_eq!(bufs.len(), 1, "Invalid number of arguments");
let rid = args.get("rid").unwrap().as_u64().unwrap() as u32; let rid: u32 = args
.get("rid")
.unwrap()
.as_u64()
.unwrap()
.try_into()
.unwrap();
debug!("write rid={}", rid); debug!("write rid={}", rid);
let buf = bufs[0].clone();
let resource_table = state.resource_table.clone();
poll_fn(move |cx| { poll_fn(move |cx| {
let resource_table = &mut resource_table.borrow_mut(); let resource_table = &mut state.resource_table.borrow_mut();
let stream = resource_table let stream = resource_table
.get_mut::<TcpStream>(rid) .get_mut::<TcpStream>(rid)
.ok_or_else(bad_resource)?; .ok_or_else(ErrBox::bad_resource_id)?;
Pin::new(stream) Pin::new(stream)
.poll_write(cx, &buf)? .poll_write(cx, &bufs[0])?
.map(|nwritten| Ok(serde_json::json!({ "nwritten": nwritten }))) .map(|nwritten| Ok(serde_json::json!({ "nwritten": nwritten })))
}) })
} }
fn bad_resource() -> ErrBox {
Error::new(ErrorKind::NotFound, "bad resource id").into()
}
fn main() { fn main() {
log::set_logger(&Logger).unwrap(); log::set_logger(&Logger).unwrap();
log::set_max_level( log::set_max_level(
@ -168,11 +187,11 @@ fn main() {
// NOTE: `--help` arg will display V8 help and exit // NOTE: `--help` arg will display V8 help and exit
deno_core::v8_set_flags(env::args().collect()); deno_core::v8_set_flags(env::args().collect());
let isolate = isolate_new(); let isolate = create_isolate();
let mut runtime = tokio::runtime::Builder::new() let mut runtime = runtime::Builder::new()
.basic_scheduler() .basic_scheduler()
.enable_all() .enable_all()
.build() .build()
.unwrap(); .unwrap();
deno_core::js_check(runtime.block_on(isolate)); js_check(runtime.block_on(isolate));
} }

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use rusty_v8 as v8; use rusty_v8 as v8;
/// Pass the command line arguments to v8. /// Pass the command line arguments to v8.
/// Returns a vector of command line arguments that V8 did not understand. /// Returns a vector of command line arguments that V8 did not understand.

View file

@ -8,6 +8,7 @@ extern crate lazy_static;
#[macro_use] #[macro_use]
extern crate log; extern crate log;
mod basic_state;
mod bindings; mod bindings;
mod core_isolate; mod core_isolate;
mod errors; mod errors;
@ -24,6 +25,7 @@ mod zero_copy_buf;
pub use rusty_v8 as v8; pub use rusty_v8 as v8;
pub use crate::basic_state::BasicState;
pub use crate::core_isolate::js_check; pub use crate::core_isolate::js_check;
pub use crate::core_isolate::CoreIsolate; pub use crate::core_isolate::CoreIsolate;
pub use crate::core_isolate::CoreIsolateState; pub use crate::core_isolate::CoreIsolateState;
@ -32,6 +34,7 @@ pub use crate::core_isolate::HeapLimits;
pub use crate::core_isolate::Script; pub use crate::core_isolate::Script;
pub use crate::core_isolate::Snapshot; pub use crate::core_isolate::Snapshot;
pub use crate::core_isolate::StartupData; pub use crate::core_isolate::StartupData;
pub use crate::errors::AnyError;
pub use crate::errors::ErrBox; pub use crate::errors::ErrBox;
pub use crate::errors::JSError; pub use crate::errors::JSError;
pub use crate::es_isolate::EsIsolate; pub use crate::es_isolate::EsIsolate;
@ -47,10 +50,13 @@ pub use crate::modules::ModuleSource;
pub use crate::modules::ModuleSourceFuture; pub use crate::modules::ModuleSourceFuture;
pub use crate::modules::RecursiveModuleLoad; pub use crate::modules::RecursiveModuleLoad;
pub use crate::normalize_path::normalize_path; pub use crate::normalize_path::normalize_path;
pub use crate::ops::Buf;
pub use crate::ops::Op; pub use crate::ops::Op;
pub use crate::ops::OpAsyncFuture; pub use crate::ops::OpAsyncFuture;
pub use crate::ops::OpFn;
pub use crate::ops::OpId; pub use crate::ops::OpId;
pub use crate::ops::OpRegistry;
pub use crate::ops::OpRouter;
pub use crate::ops::OpTable;
pub use crate::resources::ResourceTable; pub use crate::resources::ResourceTable;
pub use crate::zero_copy_buf::BufVec; pub use crate::zero_copy_buf::BufVec;
pub use crate::zero_copy_buf::ZeroCopyBuf; pub use crate::zero_copy_buf::ZeroCopyBuf;

View file

@ -8,6 +8,7 @@ use futures::future::FutureExt;
use futures::stream::FuturesUnordered; use futures::stream::FuturesUnordered;
use futures::stream::Stream; use futures::stream::Stream;
use futures::stream::TryStreamExt; use futures::stream::TryStreamExt;
use serde_json::Value;
use std::collections::HashMap; use std::collections::HashMap;
use std::collections::HashSet; use std::collections::HashSet;
use std::fmt; use std::fmt;
@ -481,7 +482,7 @@ impl Deps {
} }
} }
pub fn to_json(&self) -> serde_json::Value { pub fn to_json(&self) -> Value {
let children; let children;
if let Some(deps) = &self.deps { if let Some(deps) = &self.deps {
children = deps.iter().map(|c| c.to_json()).collect(); children = deps.iter().map(|c| c.to_json()).collect();
@ -521,6 +522,7 @@ mod tests {
use super::*; use super::*;
use crate::es_isolate::EsIsolate; use crate::es_isolate::EsIsolate;
use crate::js_check; use crate::js_check;
use crate::BasicState;
use crate::StartupData; use crate::StartupData;
use futures::future::FutureExt; use futures::future::FutureExt;
use std::error::Error; use std::error::Error;
@ -535,15 +537,14 @@ mod tests {
// removed in the future. // removed in the future.
use crate::core_isolate::tests::run_in_task; use crate::core_isolate::tests::run_in_task;
#[derive(Default)]
struct MockLoader { struct MockLoader {
pub loads: Arc<Mutex<Vec<String>>>, pub loads: Arc<Mutex<Vec<String>>>,
} }
impl MockLoader { impl MockLoader {
fn new() -> Self { fn new() -> Rc<Self> {
Self { Default::default()
loads: Arc::new(Mutex::new(Vec::new())),
}
} }
} }
@ -699,7 +700,8 @@ mod tests {
fn test_recursive_load() { fn test_recursive_load() {
let loader = MockLoader::new(); let loader = MockLoader::new();
let loads = loader.loads.clone(); let loads = loader.loads.clone();
let mut isolate = EsIsolate::new(Rc::new(loader), StartupData::None, false); let mut isolate =
EsIsolate::new(loader, BasicState::new(), StartupData::None, false);
let spec = ModuleSpecifier::resolve_url("file:///a.js").unwrap(); let spec = ModuleSpecifier::resolve_url("file:///a.js").unwrap();
let a_id_fut = isolate.load_module(&spec, None); let a_id_fut = isolate.load_module(&spec, None);
let a_id = futures::executor::block_on(a_id_fut).expect("Failed to load"); let a_id = futures::executor::block_on(a_id_fut).expect("Failed to load");
@ -761,7 +763,8 @@ mod tests {
fn test_circular_load() { fn test_circular_load() {
let loader = MockLoader::new(); let loader = MockLoader::new();
let loads = loader.loads.clone(); let loads = loader.loads.clone();
let mut isolate = EsIsolate::new(Rc::new(loader), StartupData::None, false); let mut isolate =
EsIsolate::new(loader, BasicState::new(), StartupData::None, false);
let fut = async move { let fut = async move {
let spec = ModuleSpecifier::resolve_url("file:///circular1.js").unwrap(); let spec = ModuleSpecifier::resolve_url("file:///circular1.js").unwrap();
@ -834,7 +837,8 @@ mod tests {
fn test_redirect_load() { fn test_redirect_load() {
let loader = MockLoader::new(); let loader = MockLoader::new();
let loads = loader.loads.clone(); let loads = loader.loads.clone();
let mut isolate = EsIsolate::new(Rc::new(loader), StartupData::None, false); let mut isolate =
EsIsolate::new(loader, BasicState::new(), StartupData::None, false);
let fut = async move { let fut = async move {
let spec = ModuleSpecifier::resolve_url("file:///redirect1.js").unwrap(); let spec = ModuleSpecifier::resolve_url("file:///redirect1.js").unwrap();
@ -899,7 +903,7 @@ mod tests {
let loader = MockLoader::new(); let loader = MockLoader::new();
let loads = loader.loads.clone(); let loads = loader.loads.clone();
let mut isolate = let mut isolate =
EsIsolate::new(Rc::new(loader), StartupData::None, false); EsIsolate::new(loader, BasicState::new(), StartupData::None, false);
let spec = ModuleSpecifier::resolve_url("file:///main.js").unwrap(); let spec = ModuleSpecifier::resolve_url("file:///main.js").unwrap();
let mut recursive_load = isolate.load_module(&spec, None).boxed_local(); let mut recursive_load = isolate.load_module(&spec, None).boxed_local();
@ -945,7 +949,7 @@ mod tests {
run_in_task(|mut cx| { run_in_task(|mut cx| {
let loader = MockLoader::new(); let loader = MockLoader::new();
let mut isolate = let mut isolate =
EsIsolate::new(Rc::new(loader), StartupData::None, false); EsIsolate::new(loader, BasicState::new(), StartupData::None, false);
let spec = ModuleSpecifier::resolve_url("file:///bad_import.js").unwrap(); let spec = ModuleSpecifier::resolve_url("file:///bad_import.js").unwrap();
let mut load_fut = isolate.load_module(&spec, None).boxed_local(); let mut load_fut = isolate.load_module(&spec, None).boxed_local();
let result = load_fut.poll_unpin(&mut cx); let result = load_fut.poll_unpin(&mut cx);
@ -973,7 +977,8 @@ mod tests {
fn recursive_load_main_with_code() { fn recursive_load_main_with_code() {
let loader = MockLoader::new(); let loader = MockLoader::new();
let loads = loader.loads.clone(); let loads = loader.loads.clone();
let mut isolate = EsIsolate::new(Rc::new(loader), StartupData::None, false); let mut isolate =
EsIsolate::new(loader, BasicState::new(), StartupData::None, false);
// In default resolution code should be empty. // In default resolution code should be empty.
// Instead we explicitly pass in our own code. // Instead we explicitly pass in our own code.
// The behavior should be very similar to /a.js. // The behavior should be very similar to /a.js.

View file

@ -1,179 +1,146 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::core_isolate::CoreIsolateState;
use crate::BufVec;
use crate::ErrBox;
use crate::ZeroCopyBuf; use crate::ZeroCopyBuf;
use futures::Future; use futures::Future;
use futures::FutureExt;
use indexmap::IndexMap;
use serde_json::json;
use serde_json::Value;
use std::collections::HashMap; use std::collections::HashMap;
use std::iter::once;
use std::ops::Deref;
use std::ops::DerefMut;
use std::pin::Pin; use std::pin::Pin;
use std::rc::Rc; use std::rc::Rc;
pub type OpId = u32; pub type OpAsyncFuture = Pin<Box<dyn Future<Output = Box<[u8]>>>>;
pub type OpFn<S> = dyn Fn(Rc<S>, BufVec) -> Op + 'static;
pub type Buf = Box<[u8]>; pub type OpId = usize;
pub type OpAsyncFuture = Pin<Box<dyn Future<Output = Buf>>>;
pub enum Op { pub enum Op {
Sync(Buf), Sync(Box<[u8]>),
Async(OpAsyncFuture), Async(OpAsyncFuture),
/// AsyncUnref is the variation of Async, which doesn't block the program /// AsyncUnref is the variation of Async, which doesn't block the program
/// exiting. /// exiting.
AsyncUnref(OpAsyncFuture), AsyncUnref(OpAsyncFuture),
NotFound,
} }
/// Main type describing op pub trait OpRouter {
pub type OpDispatcher = fn route_op(self: Rc<Self>, op_id: OpId, bufs: BufVec) -> Op;
dyn Fn(&mut CoreIsolateState, &mut [ZeroCopyBuf]) -> Op + 'static;
#[derive(Default)]
pub struct OpRegistry {
dispatchers: Vec<Rc<OpDispatcher>>,
name_to_id: HashMap<String, OpId>,
} }
impl OpRegistry { pub trait OpRegistry: OpRouter + 'static {
pub fn new() -> Self { fn get_op_catalog(self: Rc<Self>) -> HashMap<String, OpId>;
let mut registry = Self::default();
let op_id = registry.register("ops", |state, _| {
let buf = state.op_registry.json_map();
Op::Sync(buf)
});
assert_eq!(op_id, 0);
registry
}
pub fn register<F>(&mut self, name: &str, op: F) -> OpId fn register_op<F>(&self, name: &str, op_fn: F) -> OpId
where where
F: Fn(&mut CoreIsolateState, &mut [ZeroCopyBuf]) -> Op + 'static, F: Fn(Rc<Self>, BufVec) -> Op + 'static;
fn register_op_json_sync<F>(self: &Rc<Self>, name: &str, op_fn: F) -> OpId
where
F: Fn(&Self, Value, &mut [ZeroCopyBuf]) -> Result<Value, ErrBox> + 'static,
{ {
let op_id = self.dispatchers.len() as u32; 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)
};
let existing = self.name_to_id.insert(name.to_string(), op_id); self.register_op(name, base_op_fn)
assert!(
existing.is_none(),
format!("Op already registered: {}", name)
);
self.dispatchers.push(Rc::new(op));
op_id
} }
fn json_map(&self) -> Buf { fn register_op_json_async<F, R>(self: &Rc<Self>, name: &str, op_fn: F) -> OpId
let op_map_json = serde_json::to_string(&self.name_to_id).unwrap(); where
op_map_json.as_bytes().to_owned().into_boxed_slice() F: Fn(Rc<Self>, Value, BufVec) -> R + 'static,
} R: Future<Output = Result<Value, ErrBox>> + 'static,
{
pub fn get(&self, op_id: OpId) -> Option<Rc<OpDispatcher>> { let try_dispatch_op = move |state: Rc<Self>,
self.dispatchers.get(op_id as usize).map(Rc::clone) bufs: BufVec|
} -> Result<Op, ErrBox> {
let args: Value = serde_json::from_slice(&bufs[0])?;
pub fn unregister_op(&mut self, name: &str) { let promise_id = args
let id = self.name_to_id.remove(name).unwrap(); .get("promiseId")
drop(self.dispatchers.remove(id as usize)); .and_then(Value::as_u64)
} .ok_or_else(|| ErrBox::type_error("missing or invalid `promiseId`"))?;
} let bufs = bufs[1..].into();
let fut = op_fn(state.clone(), args, bufs).map(move |result| {
#[test] state.json_serialize_op_result(Some(promise_id), result)
fn test_op_registry() {
use crate::CoreIsolate;
use std::sync::atomic;
use std::sync::Arc;
let mut op_registry = OpRegistry::new();
let c = Arc::new(atomic::AtomicUsize::new(0));
let c_ = c.clone();
let test_id = op_registry.register("test", move |_, _| {
c_.fetch_add(1, atomic::Ordering::SeqCst);
Op::Sync(Box::new([]))
});
assert!(test_id != 0);
let mut expected = HashMap::new();
expected.insert("ops".to_string(), 0);
expected.insert("test".to_string(), 1);
assert_eq!(op_registry.name_to_id, expected);
let isolate = CoreIsolate::new(crate::StartupData::None, false);
let dispatch = op_registry.get(test_id).unwrap();
let state_rc = CoreIsolate::state(&isolate);
let mut state = state_rc.borrow_mut();
let res = dispatch(&mut state, &mut []);
if let Op::Sync(buf) = res {
assert_eq!(buf.len(), 0);
} else {
unreachable!();
}
assert_eq!(c.load(atomic::Ordering::SeqCst), 1);
assert!(op_registry.get(100).is_none());
op_registry.unregister_op("test");
expected.remove("test");
assert_eq!(op_registry.name_to_id, expected);
assert!(op_registry.get(1).is_none());
}
#[test]
fn register_op_during_call() {
use crate::CoreIsolate;
use std::sync::atomic;
use std::sync::Arc;
use std::sync::Mutex;
let op_registry = Arc::new(Mutex::new(OpRegistry::new()));
let c = Arc::new(atomic::AtomicUsize::new(0));
let c_ = c.clone();
let op_registry_ = op_registry.clone();
let test_id = {
let mut g = op_registry.lock().unwrap();
g.register("dynamic_register_op", move |_, _| {
let c__ = c_.clone();
let mut g = op_registry_.lock().unwrap();
g.register("test", move |_, _| {
c__.fetch_add(1, atomic::Ordering::SeqCst);
Op::Sync(Box::new([]))
}); });
Op::Sync(Box::new([])) Ok(Op::Async(Box::pin(fut)))
}) };
};
assert!(test_id != 0);
let isolate = CoreIsolate::new(crate::StartupData::None, false); 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))),
}
};
let dispatcher1 = { self.register_op(name, base_op_fn)
let g = op_registry.lock().unwrap();
g.get(test_id).unwrap()
};
{
let state_rc = CoreIsolate::state(&isolate);
let mut state = state_rc.borrow_mut();
dispatcher1(&mut state, &mut []);
} }
let mut expected = HashMap::new(); fn json_serialize_op_result(
expected.insert("ops".to_string(), 0); &self,
expected.insert("dynamic_register_op".to_string(), 1); promise_id: Option<u64>,
expected.insert("test".to_string(), 2); result: Result<Value, ErrBox>,
{ ) -> Box<[u8]> {
let g = op_registry.lock().unwrap(); let value = match result {
assert_eq!(g.name_to_id, expected); 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()
} }
let dispatcher2 = { fn get_error_class_name(&self, _err: &ErrBox) -> &'static str {
let g = op_registry.lock().unwrap(); "Error"
g.get(2).unwrap() }
}; }
let state_rc = CoreIsolate::state(&isolate);
let mut state = state_rc.borrow_mut(); /// Collection for storing registered ops. The special 'get_op_catalog'
let res = dispatcher2(&mut state, &mut []); /// op with OpId `0` is automatically added when the OpTable is created.
if let Op::Sync(buf) = res { pub struct OpTable<S>(IndexMap<String, Rc<OpFn<S>>>);
assert_eq!(buf.len(), 0);
} else { impl<S: OpRegistry> OpTable<S> {
unreachable!(); 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
} }
assert_eq!(c.load(atomic::Ordering::SeqCst), 1);
let g = op_registry.lock().unwrap();
assert!(g.get(100).is_none());
} }

View file

@ -8,7 +8,6 @@
// shared library itself, which would cause segfaults when the plugin is // shared library itself, which would cause segfaults when the plugin is
// unloaded and all functions in the plugin library are unmapped from memory. // unloaded and all functions in the plugin library are unmapped from memory.
pub use crate::Buf;
pub use crate::Op; pub use crate::Op;
pub use crate::OpId; pub use crate::OpId;
pub use crate::ZeroCopyBuf; pub use crate::ZeroCopyBuf;

View file

@ -19,6 +19,7 @@ SharedQueue Binary Layout
use crate::bindings; use crate::bindings;
use crate::ops::OpId; use crate::ops::OpId;
use rusty_v8 as v8; use rusty_v8 as v8;
use std::convert::TryInto;
const MAX_RECORDS: usize = 100; const MAX_RECORDS: usize = 100;
/// Total number of records added. /// Total number of records added.
@ -121,7 +122,7 @@ impl SharedQueue {
fn set_meta(&mut self, index: usize, end: usize, op_id: OpId) { fn set_meta(&mut self, index: usize, end: usize, op_id: OpId) {
let s = self.as_u32_slice_mut(); let s = self.as_u32_slice_mut();
s[INDEX_OFFSETS + 2 * index] = end as u32; s[INDEX_OFFSETS + 2 * index] = end as u32;
s[INDEX_OFFSETS + 2 * index + 1] = op_id; s[INDEX_OFFSETS + 2 * index + 1] = op_id.try_into().unwrap();
} }
#[cfg(test)] #[cfg(test)]
@ -129,7 +130,7 @@ impl SharedQueue {
if index < self.num_records() { if index < self.num_records() {
let s = self.as_u32_slice(); let s = self.as_u32_slice();
let end = s[INDEX_OFFSETS + 2 * index] as usize; let end = s[INDEX_OFFSETS + 2 * index] as usize;
let op_id = s[INDEX_OFFSETS + 2 * index + 1]; let op_id = s[INDEX_OFFSETS + 2 * index + 1] as OpId;
Some((op_id, end)) Some((op_id, end))
} else { } else {
None None
@ -218,7 +219,6 @@ impl SharedQueue {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::ops::Buf;
#[test] #[test]
fn basic() { fn basic() {
@ -262,7 +262,7 @@ mod tests {
assert_eq!(q.size(), 0); assert_eq!(q.size(), 0);
} }
fn alloc_buf(byte_length: usize) -> Buf { fn alloc_buf(byte_length: usize) -> Box<[u8]> {
let mut v = Vec::new(); let mut v = Vec::new();
v.resize(byte_length, 0); v.resize(byte_length, 0);
v.into_boxed_slice() v.into_boxed_slice()

View file

@ -31,6 +31,7 @@ fn get_path(file_name: &str) -> PathBuf {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use deno_core::js_check; use deno_core::js_check;
use deno_core::BasicState;
use deno_core::CoreIsolate; use deno_core::CoreIsolate;
use deno_core::StartupData; use deno_core::StartupData;
use futures::future::lazy; use futures::future::lazy;
@ -46,7 +47,8 @@ mod tests {
} }
fn setup() -> CoreIsolate { fn setup() -> CoreIsolate {
let mut isolate = CoreIsolate::new(StartupData::None, false); let mut isolate =
CoreIsolate::new(BasicState::new(), StartupData::None, false);
crate::init(&mut isolate); crate::init(&mut isolate);
isolate isolate
} }

View file

@ -1,4 +1,3 @@
use deno_core::plugin_api::Buf;
use deno_core::plugin_api::Interface; use deno_core::plugin_api::Interface;
use deno_core::plugin_api::Op; use deno_core::plugin_api::Op;
use deno_core::plugin_api::ZeroCopyBuf; use deno_core::plugin_api::ZeroCopyBuf;
@ -23,7 +22,7 @@ fn op_test_sync(
println!("zero_copy[{}]: {}", idx, buf_str); println!("zero_copy[{}]: {}", idx, buf_str);
} }
let result = b"test"; let result = b"test";
let result_box: Buf = Box::new(*result); let result_box: Box<[u8]> = Box::new(*result);
Op::Sync(result_box) Op::Sync(result_box)
} }
@ -47,7 +46,7 @@ fn op_test_async(
}); });
assert!(rx.await.is_ok()); assert!(rx.await.is_ok());
let result = b"test"; let result = b"test";
let result_box: Buf = Box::new(*result); let result_box: Box<[u8]> = Box::new(*result);
result_box result_box
}; };

View file

@ -65,11 +65,11 @@ function runTestOpCount() {
const end = Deno.metrics(); const end = Deno.metrics();
if (end.opsCompleted - start.opsCompleted !== 1) { if (end.opsCompleted - start.opsCompleted !== 2) {
// one op for the plugin and one for Deno.metrics // one op for the plugin and one for Deno.metrics
throw new Error("The opsCompleted metric is not correct!"); throw new Error("The opsCompleted metric is not correct!");
} }
if (end.opsDispatched - start.opsDispatched !== 1) { if (end.opsDispatched - start.opsDispatched !== 2) {
// one op for the plugin and one for Deno.metrics // one op for the plugin and one for Deno.metrics
throw new Error("The opsDispatched metric is not correct!"); throw new Error("The opsDispatched metric is not correct!");
} }