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 = [
"downcast-rs",
"futures",
"indexmap",
"lazy_static",
"libc",
"log",

View file

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

View file

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

View file

@ -1,8 +1,11 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
mod op_fetch_asset;
use deno_core::js_check;
use deno_core::BasicState;
use deno_core::CoreIsolate;
use deno_core::OpRegistry;
use deno_core::StartupData;
use std::collections::HashMap;
use std::env;
@ -28,8 +31,9 @@ fn create_snapshot(
}
fn create_runtime_snapshot(snapshot_path: &Path, files: Vec<String>) {
let runtime_isolate = CoreIsolate::new(StartupData::None, true);
create_snapshot(runtime_isolate, snapshot_path, files);
let state = BasicState::new();
let isolate = CoreIsolate::new(state, StartupData::None, true);
create_snapshot(isolate, snapshot_path, files);
}
fn create_compiler_snapshot(
@ -37,7 +41,6 @@ fn create_compiler_snapshot(
files: Vec<String>,
cwd: &Path,
) {
let mut runtime_isolate = CoreIsolate::new(StartupData::None, true);
let mut custom_libs: HashMap<String, PathBuf> = HashMap::new();
custom_libs
.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(),
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(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 {

View file

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

View file

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

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::colors;
use dissimilar::{diff as difference, Chunk};
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::*;
match e {
Simple { class, .. } => Some(*class),

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::flags::Flags;
use crate::global_state::GlobalState;
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]
fn cli_snapshot() {
let mut isolate = deno_core::CoreIsolate::new(
deno_core::BasicState::new(),
deno_core::StartupData::Snapshot(deno_core::Snapshot::Static(CLI_SNAPSHOT)),
false,
);
@ -31,6 +32,7 @@ fn cli_snapshot() {
#[test]
fn compiler_snapshot() {
let mut isolate = deno_core::CoreIsolate::new(
deno_core::BasicState::new(),
deno_core::StartupData::Snapshot(deno_core::Snapshot::Static(
COMPILER_SNAPSHOT,
)),

View file

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

View file

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

View file

@ -16,22 +16,26 @@ pub struct 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.bytes_sent_control += bytes_sent_control;
self.bytes_sent_data += bytes_sent_data;
self.bytes_sent_control += bytes_sent_control as u64;
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.bytes_received += bytes_received;
self.bytes_received += bytes_received as u64;
}
pub fn op_sync(
&mut self,
bytes_sent_control: u64,
bytes_sent_data: u64,
bytes_received: u64,
bytes_sent_control: usize,
bytes_sent_data: usize,
bytes_received: usize,
) {
self.ops_dispatched_sync += 1;
self.op_dispatched(bytes_sent_control, bytes_sent_data);
@ -41,8 +45,8 @@ impl Metrics {
pub fn op_dispatched_async(
&mut self,
bytes_sent_control: u64,
bytes_sent_data: u64,
bytes_sent_control: usize,
bytes_sent_data: usize,
) {
self.ops_dispatched_async += 1;
self.op_dispatched(bytes_sent_control, bytes_sent_data)
@ -50,19 +54,19 @@ impl Metrics {
pub fn op_dispatched_async_unref(
&mut self,
bytes_sent_control: u64,
bytes_sent_data: u64,
bytes_sent_control: usize,
bytes_sent_data: usize,
) {
self.ops_dispatched_async_unref += 1;
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.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.op_completed(bytes_received);
}

View file

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

View file

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

View file

@ -1,67 +1,27 @@
// 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 deno_core::CoreIsolate;
use deno_core::CoreIsolateState;
use deno_core::ErrBox;
use deno_core::ZeroCopyBuf;
use deno_core::OpRegistry;
use std::rc::Rc;
use std::sync::Arc;
use std::sync::Mutex;
pub fn init(
i: &mut CoreIsolate,
_s: &Rc<State>,
response: Arc<Mutex<Option<String>>>,
) {
pub fn init(s: &Rc<State>, response: Arc<Mutex<Option<String>>>) {
let custom_assets = std::collections::HashMap::new();
// TODO(ry) use None.
// TODO(bartlomieju): is this op even required?
i.register_op(
s.register_op(
"op_fetch_asset",
crate::op_fetch_asset::op_fetch_asset(custom_assets),
);
i.register_op(
"op_compiler_respond",
json_op(compiler_op(response, op_compiler_respond)),
);
}
pub fn compiler_op<D>(
response: Arc<Mutex<Option<String>>>,
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!({})))
s.register_op_json_sync("op_compiler_respond", move |_state, args, _bufs| {
let mut response_slot = response.lock().unwrap();
let replaced_value = response_slot.replace(args.to_string());
assert!(
replaced_value.is_none(),
"op_compiler_respond found unexpected existing compiler output",
);
Ok(json!({}))
});
}

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.
// Do not add flatbuffer dependencies to this module.
//! Connects to js/dispatch_minimal.ts sendAsyncMinimal This acts as a faster
//! alternative to flatbuffers using a very simple list of int32s to lay out
//! messages. The first i32 is used to determine if a message a flatbuffer
//! message or a "minimal" message.
use crate::errors::get_error_class;
use deno_core::Buf;
use deno_core::CoreIsolateState;
use crate::state::State;
use deno_core::BufVec;
use deno_core::ErrBox;
use deno_core::Op;
use deno_core::ZeroCopyBuf;
use deno_core::OpId;
use deno_core::OpRegistry;
use futures::future::FutureExt;
use std::future::Future;
use std::iter::repeat;
use std::mem::size_of_val;
use std::pin::Pin;
use std::rc::Rc;
use std::slice;
pub enum MinimalOp {
@ -30,8 +27,8 @@ pub struct Record {
pub result: i32,
}
impl Into<Buf> for Record {
fn into(self) -> Buf {
impl Into<Box<[u8]>> for Record {
fn into(self) -> Box<[u8]> {
let vec = vec![self.promise_id, self.arg, self.result];
let buf32 = vec.into_boxed_slice();
let ptr = Box::into_raw(buf32) as *mut [u8; 3 * 4];
@ -47,8 +44,8 @@ pub struct ErrorRecord {
pub error_message: Vec<u8>,
}
impl Into<Buf> for ErrorRecord {
fn into(self) -> Buf {
impl Into<Box<[u8]>> for ErrorRecord {
fn into(self) -> Box<[u8]> {
let Self {
promise_id,
arg,
@ -91,7 +88,7 @@ fn test_error_record() {
error_class: b"BadResource",
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());
}
@ -124,7 +121,7 @@ fn test_parse_min_record() {
Some(Record {
promise_id: 1,
arg: 3,
result: 4,
result: 4
})
);
@ -135,73 +132,78 @@ fn test_parse_min_record() {
assert_eq!(parse_min_record(&buf), None);
}
pub fn minimal_op<D>(
d: D,
) -> impl Fn(&mut CoreIsolateState, &mut [ZeroCopyBuf]) -> Op
where
D: Fn(&mut CoreIsolateState, bool, i32, &mut [ZeroCopyBuf]) -> MinimalOp,
{
move |isolate_state: &mut CoreIsolateState, zero_copy: &mut [ZeroCopyBuf]| {
assert!(!zero_copy.is_empty(), "Expected record at position 0");
let mut record = match parse_min_record(&zero_copy[0]) {
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..]);
impl State {
pub fn register_op_minimal<F>(self: &Rc<Self>, name: &str, op_fn: F) -> OpId
where
F: Fn(Rc<Self>, bool, i32, BufVec) -> MinimalOp + 'static,
{
let base_op_fn = move |state: Rc<Self>, bufs: BufVec| {
let mut bufs_iter = bufs.into_iter();
let record_buf = bufs_iter.next().expect("Expected record at position 0");
let zero_copy = bufs_iter.collect::<BufVec>();
match min_op {
MinimalOp::Sync(sync_result) => Op::Sync(match sync_result {
Ok(r) => {
record.result = r;
record.into()
}
Err(err) => {
let error_class = get_error_class(&err);
let mut record = match parse_min_record(&record_buf) {
Some(r) => r,
None => {
let error = ErrBox::type_error("Unparsable control buffer");
let error_class = state.get_error_class_name(&error);
let error_record = ErrorRecord {
promise_id: record.promise_id,
promise_id: 0,
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_message: error.to_string().as_bytes().to_owned(),
};
error_record.into()
return Op::Sync(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 = get_error_class(&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()
}
};
let is_sync = record.promise_id == 0;
let rid = record.arg;
let min_op = op_fn(state.clone(), is_sync, rid, zero_copy);
match min_op {
MinimalOp::Sync(sync_result) => Op::Sync(match sync_result {
Ok(r) => {
record.result = r;
record.into()
}
};
Op::Async(fut.boxed_local())
Err(err) => {
let error_class = state.get_error_class_name(&err);
let error_record = ErrorRecord {
promise_id: record.promise_id,
arg: -1,
error_len: error_class.len() as i32,
error_class: error_class.as_bytes(),
error_message: err.to_string().as_bytes().to_owned(),
};
error_record.into()
}
}),
MinimalOp::Async(min_fut) => {
let fut = async move {
match min_fut.await {
Ok(r) => {
record.result = r;
record.into()
}
Err(err) => {
let error_class = state.get_error_class_name(&err);
let error_record = ErrorRecord {
promise_id: record.promise_id,
arg: -1,
error_len: error_class.len() as i32,
error_class: error_class.as_bytes(),
error_message: err.to_string().as_bytes().to_owned(),
};
error_record.into()
}
}
};
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.
use super::dispatch_json::{Deserialize, Value};
use crate::diagnostics::Diagnostic;
use crate::source_maps::get_orig_position;
use crate::source_maps::CachedMaps;
use crate::state::State;
use deno_core::CoreIsolate;
use deno_core::ErrBox;
use deno_core::ResourceTable;
use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf;
use serde_derive::Deserialize;
use serde_json::Value;
use std::collections::HashMap;
use std::rc::Rc;
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) {
let t = &CoreIsolate::state(i).borrow().resource_table.clone();
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),
);
pub fn init(s: &Rc<State>) {
s.register_op_json_sync("op_apply_source_map", op_apply_source_map);
s.register_op_json_sync("op_format_diagnostic", op_format_diagnostic);
}
#[derive(Deserialize)]
@ -34,7 +27,6 @@ struct ApplySourceMap {
fn op_apply_source_map(
state: &State,
_resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> {
@ -59,7 +51,6 @@ fn op_apply_source_map(
fn op_format_diagnostic(
_state: &State,
_resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> {

View file

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

View file

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

View file

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

View file

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

View file

@ -1,11 +1,8 @@
use super::dispatch_minimal::MinimalOp;
use crate::http_util::HttpBody;
use crate::state::State;
use deno_core::CoreIsolate;
use deno_core::CoreIsolateState;
use deno_core::BufVec;
use deno_core::ErrBox;
use deno_core::ResourceTable;
use deno_core::ZeroCopyBuf;
use futures::future::poll_fn;
use futures::future::FutureExt;
use futures::ready;
@ -85,9 +82,9 @@ lazy_static! {
};
}
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) {
i.register_op("op_read", s.stateful_minimal_op2(op_read));
i.register_op("op_write", s.stateful_minimal_op2(op_write));
pub fn init(s: &Rc<State>) {
s.register_op_minimal("op_read", op_read);
s.register_op_minimal("op_write", op_write);
}
pub fn get_stdio() -> (
@ -236,11 +233,10 @@ impl DenoAsyncRead for StreamResource {
}
pub fn op_read(
isolate_state: &mut CoreIsolateState,
_state: &Rc<State>,
state: Rc<State>,
is_sync: bool,
rid: i32,
zero_copy: &mut [ZeroCopyBuf],
mut zero_copy: BufVec,
) -> MinimalOp {
debug!("read rid={}", rid);
match zero_copy.len() {
@ -248,13 +244,11 @@ pub fn op_read(
1 => {}
_ => panic!("Invalid number of arguments"),
}
let resource_table = isolate_state.resource_table.clone();
if is_sync {
MinimalOp::Sync({
// First we look up the rid in the resource table.
let mut resource_table = resource_table.borrow_mut();
std_file_resource(&mut resource_table, rid as u32, move |r| match r {
std_file_resource(&state, rid as u32, move |r| match r {
Ok(std_file) => {
use std::io::Read;
std_file
@ -271,7 +265,7 @@ pub fn op_read(
let mut zero_copy = zero_copy[0].clone();
MinimalOp::Async(
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
.get_mut::<StreamResourceHolder>(rid as u32)
.ok_or_else(ErrBox::bad_resource_id)?;
@ -358,11 +352,10 @@ impl DenoAsyncWrite for StreamResource {
}
pub fn op_write(
isolate_state: &mut CoreIsolateState,
_state: &Rc<State>,
state: Rc<State>,
is_sync: bool,
rid: i32,
zero_copy: &mut [ZeroCopyBuf],
zero_copy: BufVec,
) -> MinimalOp {
debug!("write rid={}", rid);
match zero_copy.len() {
@ -374,8 +367,7 @@ pub fn op_write(
if is_sync {
MinimalOp::Sync({
// First we look up the rid in the resource table.
let mut resource_table = isolate_state.resource_table.borrow_mut();
std_file_resource(&mut resource_table, rid as u32, move |r| match r {
std_file_resource(&state, rid as u32, move |r| match r {
Ok(std_file) => {
use std::io::Write;
std_file
@ -390,11 +382,10 @@ pub fn op_write(
})
} else {
let zero_copy = zero_copy[0].clone();
let resource_table = isolate_state.resource_table.clone();
MinimalOp::Async(
async move {
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
.get_mut::<StreamResourceHolder>(rid as u32)
.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.
// https://github.com/denoland/deno/issues/3565
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
.get_mut::<StreamResourceHolder>(rid as u32)
.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.
pub fn std_file_resource<F, T>(
resource_table: &mut ResourceTable,
state: &State,
rid: u32,
mut f: F,
) -> Result<T, ErrBox>
@ -439,6 +430,7 @@ where
FnMut(Result<&mut std::fs::File, &mut StreamResource>) -> Result<T, ErrBox>,
{
// First we look up the rid in the resource table.
let mut resource_table = state.resource_table.borrow_mut();
let mut r = resource_table.get_mut::<StreamResourceHolder>(rid);
if let Some(ref mut resource_holder) = r {
// 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.
mod dispatch_json;
mod dispatch_minimal;
pub use dispatch_json::json_op;
pub use dispatch_json::serialize_result;
pub use dispatch_json::JsonOp;
pub use dispatch_json::JsonResult;
pub use dispatch_minimal::minimal_op;
mod dispatch_minimal;
pub use dispatch_minimal::MinimalOp;
pub mod compiler;

View file

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

View file

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

View file

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

View file

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

View file

@ -1,26 +1,26 @@
// 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 deno_core::plugin_api;
use deno_core::CoreIsolate;
use deno_core::CoreIsolateState;
use deno_core::BufVec;
use deno_core::ErrBox;
use deno_core::Op;
use deno_core::OpAsyncFuture;
use deno_core::OpId;
use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf;
use dlopen::symbor::Library;
use futures::prelude::*;
use serde_derive::Deserialize;
use serde_json::Value;
use std::path::PathBuf;
use std::pin::Pin;
use std::rc::Rc;
use std::task::Context;
use std::task::Poll;
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) {
i.register_op("op_open_plugin", s.stateful_json_op2(op_open_plugin));
pub fn init(s: &Rc<State>) {
s.register_op_json_sync("op_open_plugin", op_open_plugin);
}
#[derive(Deserialize)]
@ -30,12 +30,12 @@ struct OpenPluginArgs {
}
pub fn op_open_plugin(
isolate_state: &mut CoreIsolateState,
state: &Rc<State>,
state: &State,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<JsonOp, ErrBox> {
) -> Result<Value, ErrBox> {
state.check_unstable("Deno.openPlugin");
let args: OpenPluginArgs = serde_json::from_value(args).unwrap();
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_resource = PluginResource::new(&plugin_lib);
let mut resource_table = isolate_state.resource_table.borrow_mut();
let rid = resource_table.add("plugin", Box::new(plugin_resource));
let plugin_resource = resource_table.get::<PluginResource>(rid).unwrap();
let deno_plugin_init = *unsafe {
plugin_resource
.lib
.symbol::<plugin_api::InitFn>("deno_plugin_init")
let rid;
let deno_plugin_init;
{
let mut resource_table = state.resource_table.borrow_mut();
rid = resource_table.add("plugin", Box::new(plugin_resource));
deno_plugin_init = *unsafe {
resource_table
.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);
Ok(JsonOp::Sync(json!(rid)))
Ok(json!(rid))
}
struct PluginResource {
@ -74,19 +77,13 @@ impl PluginResource {
}
struct PluginInterface<'a> {
isolate_state: &'a mut CoreIsolateState,
state: &'a State,
plugin_lib: &'a Rc<Library>,
}
impl<'a> PluginInterface<'a> {
fn new(
isolate_state: &'a mut CoreIsolateState,
plugin_lib: &'a Rc<Library>,
) -> Self {
Self {
isolate_state,
plugin_lib,
}
fn new(state: &'a State, plugin_lib: &'a Rc<Library>) -> Self {
Self { state, plugin_lib }
}
}
@ -102,11 +99,11 @@ impl<'a> plugin_api::Interface for PluginInterface<'a> {
dispatch_op_fn: plugin_api::DispatchOpFn,
) -> OpId {
let plugin_lib = self.plugin_lib.clone();
self.isolate_state.op_registry.register(
self.state.register_op(
name,
move |isolate_state, zero_copy| {
let mut interface = PluginInterface::new(isolate_state, &plugin_lib);
let op = dispatch_op_fn(&mut interface, zero_copy);
move |state: Rc<State>, mut zero_copy: BufVec| {
let mut interface = PluginInterface::new(&state, &plugin_lib);
let op = dispatch_op_fn(&mut interface, &mut zero_copy);
match op {
sync_op @ Op::Sync(..) => sync_op,
Op::Async(fut) => {
@ -115,6 +112,7 @@ impl<'a> plugin_api::Interface for PluginInterface<'a> {
Op::AsyncUnref(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.
use super::dispatch_json::{Deserialize, Value};
use super::io::{std_file_resource, StreamResource, StreamResourceHolder};
use crate::signal::kill;
use crate::state::State;
use deno_core::BufVec;
use deno_core::CoreIsolate;
use deno_core::ErrBox;
use deno_core::ResourceTable;
use deno_core::OpRegistry;
use deno_core::ZeroCopyBuf;
use futures::future::poll_fn;
use futures::future::FutureExt;
use std::cell::RefCell;
use serde_derive::Deserialize;
use serde_json::Value;
use std::rc::Rc;
use tokio::process::Command;
#[cfg(unix)]
use std::os::unix::process::ExitStatusExt;
pub fn init(i: &mut CoreIsolate, s: &Rc<State>) {
let t = &CoreIsolate::state(i).borrow().resource_table.clone();
i.register_op("op_run", s.stateful_json_op_sync(t, op_run));
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));
pub fn init(s: &Rc<State>) {
s.register_op_json_sync("op_run", op_run);
s.register_op_json_async("op_run_status", op_run_status);
s.register_op_json_sync("op_kill", op_kill);
}
fn clone_file(
rid: u32,
resource_table: &mut ResourceTable,
) -> Result<std::fs::File, ErrBox> {
std_file_resource(resource_table, rid, move |r| match r {
fn clone_file(state: &State, rid: u32) -> Result<std::fs::File, ErrBox> {
std_file_resource(state, rid, move |r| match r {
Ok(std_file) => std_file.try_clone().map_err(ErrBox::from),
Err(_) => Err(ErrBox::bad_resource_id()),
})
@ -64,7 +59,6 @@ struct ChildResource {
fn op_run(
state: &State,
resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> {
@ -90,21 +84,21 @@ fn op_run(
if run_args.stdin != "" {
c.stdin(subprocess_stdio_map(run_args.stdin.as_ref())?);
} else {
let file = clone_file(run_args.stdin_rid, resource_table)?;
let file = clone_file(state, run_args.stdin_rid)?;
c.stdin(file);
}
if run_args.stdout != "" {
c.stdout(subprocess_stdio_map(run_args.stdout.as_ref())?);
} else {
let file = clone_file(run_args.stdout_rid, resource_table)?;
let file = clone_file(state, run_args.stdout_rid)?;
c.stdout(file);
}
if run_args.stderr != "" {
c.stderr(subprocess_stdio_map(run_args.stderr.as_ref())?);
} else {
let file = clone_file(run_args.stderr_rid, resource_table)?;
let file = clone_file(state, run_args.stderr_rid)?;
c.stderr(file);
}
@ -117,7 +111,7 @@ fn op_run(
let stdin_rid = match child.stdin.take() {
Some(child_stdin) => {
let rid = resource_table.add(
let rid = state.resource_table.borrow_mut().add(
"childStdin",
Box::new(StreamResourceHolder::new(StreamResource::ChildStdin(
child_stdin,
@ -130,7 +124,7 @@ fn op_run(
let stdout_rid = match child.stdout.take() {
Some(child_stdout) => {
let rid = resource_table.add(
let rid = state.resource_table.borrow_mut().add(
"childStdout",
Box::new(StreamResourceHolder::new(StreamResource::ChildStdout(
child_stdout,
@ -143,7 +137,7 @@ fn op_run(
let stderr_rid = match child.stderr.take() {
Some(child_stderr) => {
let rid = resource_table.add(
let rid = state.resource_table.borrow_mut().add(
"childStderr",
Box::new(StreamResourceHolder::new(StreamResource::ChildStderr(
child_stderr,
@ -155,7 +149,10 @@ fn op_run(
};
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!({
"rid": child_rid,
@ -174,7 +171,6 @@ struct RunStatusArgs {
async fn op_run_status(
state: Rc<State>,
resource_table: Rc<RefCell<ResourceTable>>,
args: Value,
_zero_copy: BufVec,
) -> Result<Value, ErrBox> {
@ -184,7 +180,7 @@ async fn op_run_status(
state.check_run()?;
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
.get_mut::<ChildResource>(rid)
.ok_or_else(ErrBox::bad_resource_id)?;
@ -220,7 +216,6 @@ struct KillArgs {
fn op_kill(
state: &State,
_resource_table: &mut ResourceTable,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, ErrBox> {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,112 +1,39 @@
// 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::web_worker::WebWorkerHandle;
use crate::worker::WorkerEvent;
use deno_core::CoreIsolate;
use deno_core::CoreIsolateState;
use deno_core::ErrBox;
use deno_core::ZeroCopyBuf;
use deno_core::OpRegistry;
use futures::channel::mpsc;
use std::convert::From;
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(
i: &mut CoreIsolate,
s: &Rc<State>,
sender: &mpsc::Sender<WorkerEvent>,
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",
s.core_op(json_op(web_worker_op(
sender.clone(),
op_worker_post_message,
))),
move |_state, _args, bufs| {
assert_eq!(bufs.len(), 1, "Invalid number of arguments");
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
fn op_worker_post_message(
sender: &mpsc::Sender<WorkerEvent>,
_args: Value,
data: &mut [ZeroCopyBuf],
) -> Result<JsonOp, ErrBox> {
assert_eq!(data.len(), 1, "Invalid number of arguments");
let d = Vec::from(&*data[0]).into_boxed_slice();
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!({})))
// Notify host that guest worker closes.
let sender_ = sender.clone();
s.register_op_json_sync("op_worker_close", move |_state, _args, _bufs| {
// Notify parent that we're finished
sender_.clone().close_channel();
// Terminate execution of current worker
handle.terminate();
Ok(json!({}))
});
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,31 +1,30 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::errors::get_error_class_name;
use crate::file_fetcher::SourceFileFetcher;
use crate::global_state::GlobalState;
use crate::global_timer::GlobalTimer;
use crate::http_util::create_http_client;
use crate::import_map::ImportMap;
use crate::metrics::Metrics;
use crate::ops::serialize_result;
use crate::ops::JsonOp;
use crate::ops::MinimalOp;
use crate::permissions::Permissions;
use crate::tsc::TargetLib;
use crate::web_worker::WebWorkerHandle;
use deno_core::Buf;
use deno_core::BufVec;
use deno_core::CoreIsolateState;
use deno_core::ErrBox;
use deno_core::ModuleLoadId;
use deno_core::ModuleLoader;
use deno_core::ModuleSpecifier;
use deno_core::Op;
use deno_core::OpId;
use deno_core::OpRegistry;
use deno_core::OpRouter;
use deno_core::OpTable;
use deno_core::ResourceTable;
use deno_core::ZeroCopyBuf;
use futures::future::FutureExt;
use futures::Future;
use rand::rngs::StdRng;
use rand::SeedableRng;
use serde_json::Value;
use std::cell::Cell;
use std::cell::RefCell;
use std::collections::HashMap;
@ -55,266 +54,11 @@ pub struct State {
pub is_main: bool,
pub is_internal: bool,
pub http_client: RefCell<reqwest::Client>,
pub resource_table: RefCell<ResourceTable>,
pub op_table: RefCell<OpTable<Self>>,
}
impl State {
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.
///
/// This is intentionally a non-recoverable check so that people cannot probe
@ -458,6 +202,8 @@ impl State {
is_main: true,
is_internal,
http_client: create_http_client(fl.ca_file.as_deref())?.into(),
resource_table: Default::default(),
op_table: Default::default(),
};
Ok(Rc::new(state))
}
@ -486,6 +232,8 @@ impl State {
is_main: false,
is_internal: false,
http_client: create_http_client(fl.ca_file.as_deref())?.into(),
resource_table: Default::default(),
op_table: Default::default(),
};
Ok(Rc::new(state))
}
@ -570,7 +318,7 @@ impl State {
}
#[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)
.expect("Invalid entry module");
State::new(
@ -583,3 +331,78 @@ impl State {
.unwrap()
}
}
impl OpRouter for State {
fn route_op(self: Rc<Self>, op_id: OpId, bufs: BufVec) -> Op {
// TODOs:
// * The 'bytes' metrics seem pretty useless, especially now that the
// distinction between 'control' and 'data' buffers has become blurry.
// * Tracking completion of async ops currently makes us put the boxed
// future into _another_ box. Keeping some counters may not be expensive
// in itself, but adding a heap allocation for every metric seems bad.
let mut buf_len_iter = bufs.iter().map(|buf| buf.len());
let bytes_sent_control = buf_len_iter.next().unwrap_or(0);
let bytes_sent_data = buf_len_iter.sum();
let op_fn = self
.op_table
.borrow()
.get_index(op_id)
.map(|(_, op_fn)| op_fn.clone())
.unwrap();
let self_ = self.clone();
let op = (op_fn)(self_, bufs);
let self_ = self.clone();
let mut metrics = self_.metrics.borrow_mut();
match op {
Op::Sync(buf) => {
metrics.op_sync(bytes_sent_control, bytes_sent_data, buf.len());
Op::Sync(buf)
}
Op::Async(fut) => {
metrics.op_dispatched_async(bytes_sent_control, bytes_sent_data);
let fut = fut
.inspect(move |buf| {
self.metrics.borrow_mut().op_completed_async(buf.len());
})
.boxed_local();
Op::Async(fut)
}
Op::AsyncUnref(fut) => {
metrics.op_dispatched_async_unref(bytes_sent_control, bytes_sent_data);
let fut = fut
.inspect(move |buf| {
self
.metrics
.borrow_mut()
.op_completed_async_unref(buf.len());
})
.boxed_local();
Op::AsyncUnref(fut)
}
other => other,
}
}
}
impl OpRegistry for State {
fn get_op_catalog(self: Rc<Self>) -> HashMap<String, OpId> {
self.op_table.borrow().get_op_catalog()
}
fn register_op<F>(&self, name: &str, op_fn: F) -> OpId
where
F: Fn(Rc<Self>, BufVec) -> Op + 'static,
{
let mut op_table = self.op_table.borrow_mut();
let (op_id, prev) = op_table.insert_full(name.to_owned(), Rc::new(op_fn));
assert!(prev.is_none());
op_id
}
fn get_error_class_name(&self, err: &ErrBox) -> &'static str {
get_error_class_name(err)
}
}

View file

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

View file

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

View file

@ -139,14 +139,13 @@ impl CompilerWorker {
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 response = Arc::new(Mutex::new(None));
{
let isolate = &mut worker.isolate;
ops::runtime::init(isolate, &state);
ops::errors::init(isolate, &state);
ops::timers::init(isolate, &state);
ops::compiler::init(isolate, &state, response.clone());
ops::runtime::init(&state);
ops::errors::init(&state);
ops::timers::init(&state);
ops::compiler::init(&state, response.clone());
}
Self { worker, response }
@ -1437,7 +1436,7 @@ pub async fn runtime_transpile(
let json_str = execute_in_same_thread(global_state, permissions, req_msg)
.await
.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.");
Ok(v)
}

View file

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

View file

@ -1,5 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::errors::get_error_class;
use crate::fmt_errors::JSError;
use crate::global_state::GlobalState;
use crate::inspector::DenoInspector;
@ -7,7 +7,6 @@ use crate::ops;
use crate::ops::io::get_stdio;
use crate::startup_data;
use crate::state::State;
use deno_core::Buf;
use deno_core::CoreIsolate;
use deno_core::ErrBox;
use deno_core::ModuleId;
@ -32,25 +31,25 @@ use url::Url;
/// Events that are sent to host from child
/// worker.
pub enum WorkerEvent {
Message(Buf),
Message(Box<[u8]>),
Error(ErrBox),
TerminalError(ErrBox),
}
pub struct WorkerChannelsInternal {
pub sender: mpsc::Sender<WorkerEvent>,
pub receiver: mpsc::Receiver<Buf>,
pub receiver: mpsc::Receiver<Box<[u8]>>,
}
#[derive(Clone)]
pub struct WorkerHandle {
pub sender: mpsc::Sender<Buf>,
pub sender: mpsc::Sender<Box<[u8]>>,
pub receiver: Arc<AsyncMutex<mpsc::Receiver<WorkerEvent>>>,
}
impl WorkerHandle {
/// 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();
sender.try_send(buf)?;
Ok(())
@ -65,7 +64,7 @@ impl 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 internal_channels = WorkerChannelsInternal {
sender: out_tx,
@ -106,8 +105,12 @@ impl Worker {
startup_data: StartupData,
state: &Rc<State>,
) -> Self {
let mut isolate =
deno_core::EsIsolate::new(state.clone(), startup_data, false);
let mut isolate = deno_core::EsIsolate::new(
state.clone(),
state.clone(),
startup_data,
false,
);
{
let global_state = state.global_state.clone();
@ -116,7 +119,6 @@ impl Worker {
core_state.set_js_error_create_fn(move |core_js_error| {
JSError::create(core_js_error, &global_state.ts_compiler)
});
core_state.set_get_error_class_fn(&get_error_class);
}
let inspector = {
@ -256,31 +258,30 @@ pub struct MainWorker(Worker);
impl MainWorker {
// TODO(ry) combine MainWorker::new and MainWorker::create.
fn new(name: String, startup_data: StartupData, state: &Rc<State>) -> Self {
let mut worker = Worker::new(name, startup_data, state);
let worker = Worker::new(name, startup_data, state);
{
let isolate = &mut worker.isolate;
ops::runtime::init(isolate, &state);
ops::runtime_compiler::init(isolate, &state);
ops::errors::init(isolate, &state);
ops::fetch::init(isolate, &state);
ops::websocket::init(isolate, &state);
ops::fs::init(isolate, &state);
ops::fs_events::init(isolate, &state);
ops::idna::init(isolate, &state);
ops::io::init(isolate, &state);
ops::plugin::init(isolate, &state);
ops::net::init(isolate, &state);
ops::tls::init(isolate, &state);
ops::os::init(isolate, &state);
ops::permissions::init(isolate, &state);
ops::process::init(isolate, &state);
ops::random::init(isolate, &state);
ops::repl::init(isolate, &state);
ops::resources::init(isolate, &state);
ops::signal::init(isolate, &state);
ops::timers::init(isolate, &state);
ops::tty::init(isolate, &state);
ops::worker_host::init(isolate, &state);
ops::runtime::init(&state);
ops::runtime_compiler::init(&state);
ops::errors::init(&state);
ops::fetch::init(&state);
ops::websocket::init(&state);
ops::fs::init(&state);
ops::fs_events::init(&state);
ops::idna::init(&state);
ops::io::init(&state);
ops::plugin::init(&state);
ops::net::init(&state);
ops::tls::init(&state);
ops::os::init(&state);
ops::permissions::init(&state);
ops::process::init(&state);
ops::random::init(&state);
ops::repl::init(&state);
ops::resources::init(&state);
ops::signal::init(&state);
ops::timers::init(&state);
ops::tty::init(&state);
ops::worker_host::init(&state);
}
Self(worker)
}
@ -302,10 +303,8 @@ impl MainWorker {
&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 (stdin, stdout, stderr) = get_stdio();
if let Some(stream) = stdin {
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"] }
smallvec = "1.4.2"
url = "2.1.1"
indexmap = "1.5.2"
[[example]]
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::CoreIsolateState;
use crate::ErrBox;
use crate::EsIsolate;
use crate::JSError;
use crate::Op;
use crate::OpId;
use crate::ZeroCopyBuf;
use futures::future::FutureExt;
use rusty_v8 as v8;
use v8::MapFnTo;
use smallvec::SmallVec;
use std::cell::Cell;
use std::convert::TryFrom;
use std::option::Option;
use url::Url;
use v8::MapFnTo;
lazy_static! {
pub static ref EXTERNAL_REFERENCES: v8::ExternalReferences =
@ -49,7 +50,7 @@ lazy_static! {
function: decode.map_fn_to()
},
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));
}
fn send(
scope: &mut v8::HandleScope,
fn send<'s>(
scope: &mut v8::HandleScope<'s>,
args: v8::FunctionCallbackArguments,
mut rv: v8::ReturnValue,
) {
let op_id = match v8::Local::<v8::Uint32>::try_from(args.get(0)) {
Ok(op_id) => op_id.value() as u32,
let state_rc = CoreIsolate::state(scope);
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) => {
let msg = format!("invalid op id: {}", err);
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| {
v8::Local::<v8::ArrayBufferView>::try_from(args.get(idx))
.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 maybe_response =
match buf_iter.collect::<Result<SmallVec<[ZeroCopyBuf; 2]>, _>>() {
Ok(mut bufs) => state.dispatch_op(scope, op_id, &mut bufs),
Err(exc) => {
scope.throw_exception(exc);
return;
}
};
let bufs = match buf_iter.collect::<Result<_, _>>() {
Ok(bufs) => bufs,
Err(exc) => {
scope.throw_exception(exc);
return;
}
};
if let Some(response) = maybe_response {
// Synchronous response.
// Note op_id is not passed back in the case of synchronous response.
let (_op_id, buf) = response;
if !buf.is_empty() {
let ui8 = boxed_slice_to_uint8array(scope, buf);
rv.set(ui8.into());
let op_router = state.op_router.clone();
let op = op_router.route_op(op_id, bufs);
assert_eq!(state.shared.size(), 0);
match op {
Op::Sync(buf) if !buf.is_empty() => {
rv.set(boxed_slice_to_uint8array(scope, buf).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::ErrBox;
use crate::JSError;
use crate::ResourceTable;
use crate::ZeroCopyBuf;
use futures::future::FutureExt;
use futures::stream::FuturesUnordered;
use futures::stream::StreamExt;
use futures::task::AtomicWaker;
use futures::Future;
use serde_json::json;
use serde_json::Value;
use std::any::Any;
use std::cell::Cell;
use std::cell::RefCell;
use std::collections::HashMap;
use std::convert::From;
@ -37,7 +33,7 @@ use std::sync::Once;
use std::task::Context;
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
pub struct Script<'a> {
@ -87,7 +83,7 @@ impl StartupData<'_> {
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
#[derive(Default)]
@ -118,19 +114,17 @@ pub struct CoreIsolate {
/// Internal state for CoreIsolate which is stored in one of v8::Isolate's
/// embedder slots.
pub struct CoreIsolateState {
pub resource_table: Rc<RefCell<ResourceTable>>,
pub global_context: Option<v8::Global<v8::Context>>,
pub(crate) shared_ab: Option<v8::Global<v8::SharedArrayBuffer>>,
pub(crate) js_recv_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) js_error_create_fn: Box<JSErrorCreateFn>,
pub get_error_class_fn: GetErrorClassFn,
pub(crate) shared: SharedQueue,
pending_ops: FuturesUnordered<PendingOpFuture>,
pending_unref_ops: FuturesUnordered<PendingOpFuture>,
have_unpolled_ops: bool,
pub op_registry: OpRegistry,
pub(crate) pending_ops: FuturesUnordered<PendingOpFuture>,
pub(crate) pending_unref_ops: FuturesUnordered<PendingOpFuture>,
pub(crate) have_unpolled_ops: Cell<bool>,
pub(crate) op_router: Rc<dyn OpRouter>,
waker: AtomicWaker,
}
@ -205,21 +199,27 @@ pub struct HeapLimits {
}
pub(crate) struct IsolateOptions {
will_snapshot: bool,
op_router: Rc<dyn OpRouter>,
startup_script: Option<OwnedScript>,
startup_snapshot: Option<Snapshot>,
will_snapshot: bool,
heap_limits: Option<HeapLimits>,
}
impl CoreIsolate {
/// startup_data defines the snapshot or script used at startup to initialize
/// the isolate.
pub fn new(startup_data: StartupData, will_snapshot: bool) -> 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 options = IsolateOptions {
will_snapshot,
op_router,
startup_script,
startup_snapshot,
will_snapshot,
heap_limits: None,
};
@ -233,14 +233,16 @@ impl CoreIsolate {
/// Make sure to use [`add_near_heap_limit_callback`](#method.add_near_heap_limit_callback)
/// to prevent v8 from crashing when reaching the upper limit.
pub fn with_heap_limits(
op_router: Rc<dyn OpRouter>,
startup_data: StartupData,
heap_limits: HeapLimits,
) -> Self {
let (startup_script, startup_snapshot) = startup_data.into_options();
let options = IsolateOptions {
will_snapshot: false,
op_router,
startup_script,
startup_snapshot,
will_snapshot: false,
heap_limits: Some(heap_limits),
};
@ -304,18 +306,16 @@ impl CoreIsolate {
isolate.set_slot(Rc::new(RefCell::new(CoreIsolateState {
global_context: Some(global_context),
resource_table: Rc::new(RefCell::new(ResourceTable::default())),
pending_promise_exceptions: HashMap::new(),
shared_ab: None,
js_recv_cb: None,
js_macrotask_cb: None,
js_error_create_fn: Box::new(JSError::create),
get_error_class_fn: &|_| "Error",
shared: SharedQueue::new(RECOMMENDED_SIZE),
pending_ops: FuturesUnordered::new(),
pending_unref_ops: FuturesUnordered::new(),
have_unpolled_ops: false,
op_registry: OpRegistry::new(),
have_unpolled_ops: Cell::new(false),
op_router: options.op_router,
waker: AtomicWaker::new(),
})));
@ -421,66 +421,6 @@ impl CoreIsolate {
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.
/// 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)
}
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 {
type Output = Result<(), ErrBox>;
@ -574,12 +496,12 @@ impl Future for CoreIsolate {
check_promise_exceptions(scope)?;
let mut overflow_response: Option<(OpId, Buf)> = None;
let mut overflow_response: Option<(OpId, Box<[u8]>)> = None;
loop {
let mut state = state_rc.borrow_mut();
// 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);
match pending_r {
@ -644,7 +566,7 @@ impl Future for CoreIsolate {
if state.pending_ops.is_empty() {
Poll::Ready(Ok(()))
} else {
if state.have_unpolled_ops {
if state.have_unpolled_ops.get() {
state.waker.wake();
}
Poll::Pending
@ -653,18 +575,6 @@ impl Future for CoreIsolate {
}
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
/// the caller to wrap the JSError into an error. By default this callback
/// is set to JSError::create.
@ -674,49 +584,6 @@ impl CoreIsolateState {
) {
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>(
@ -739,7 +606,7 @@ fn async_op_response<'s>(
let op_id: v8::Local<v8::Value> =
v8::Integer::new(tc_scope, op_id as i32).into();
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])
}
None => js_recv_cb.call(tc_scope, global, &[]),
@ -848,11 +715,28 @@ pub fn js_check<T>(r: Result<T, ErrBox>) -> T {
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)]
pub mod tests {
use super::*;
use crate::BasicState;
use crate::BufVec;
use futures::future::lazy;
use futures::FutureExt;
use std::ops::FnOnce;
use std::rc::Rc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
@ -880,7 +764,7 @@ pub mod tests {
)
}
pub enum Mode {
enum Mode {
Async,
AsyncUnref,
AsyncZeroCopy(u8),
@ -890,28 +774,29 @@ pub mod tests {
OverflowResAsync,
}
pub fn setup(mode: Mode) -> (CoreIsolate, Arc<AtomicUsize>) {
let dispatch_count = Arc::new(AtomicUsize::new(0));
let dispatch_count_ = dispatch_count.clone();
struct TestOpRouter {
mode: Mode,
dispatch_count: Arc<AtomicUsize>,
}
let mut isolate = CoreIsolate::new(StartupData::None, false);
let dispatcher = move |_state: &mut CoreIsolateState,
zero_copy: &mut [ZeroCopyBuf]|
-> Op {
dispatch_count_.fetch_add(1, Ordering::Relaxed);
match mode {
impl OpRouter for TestOpRouter {
fn route_op(self: Rc<Self>, op_id: OpId, bufs: BufVec) -> Op {
if op_id != 1 {
return Op::NotFound;
}
self.dispatch_count.fetch_add(1, Ordering::Relaxed);
match self.mode {
Mode::Async => {
assert_eq!(zero_copy.len(), 1);
assert_eq!(zero_copy[0].len(), 1);
assert_eq!(zero_copy[0][0], 42);
assert_eq!(bufs.len(), 1);
assert_eq!(bufs[0].len(), 1);
assert_eq!(bufs[0][0], 42);
let buf = vec![43u8].into_boxed_slice();
Op::Async(futures::future::ready(buf).boxed())
}
Mode::AsyncUnref => {
assert_eq!(zero_copy.len(), 1);
assert_eq!(zero_copy[0].len(), 1);
assert_eq!(zero_copy[0][0], 42);
assert_eq!(bufs.len(), 1);
assert_eq!(bufs[0].len(), 1);
assert_eq!(bufs[0][0], 42);
let fut = async {
// This future never finish.
futures::future::pending::<()>().await;
@ -920,8 +805,8 @@ pub mod tests {
Op::AsyncUnref(fut.boxed())
}
Mode::AsyncZeroCopy(count) => {
assert_eq!(zero_copy.len(), count as usize);
zero_copy.iter().enumerate().for_each(|(idx, buf)| {
assert_eq!(bufs.len(), count as usize);
bufs.iter().enumerate().for_each(|(idx, buf)| {
assert_eq!(buf.len(), 1);
assert_eq!(idx, buf[0] as usize);
});
@ -930,15 +815,15 @@ pub mod tests {
Op::Async(futures::future::ready(buf).boxed())
}
Mode::OverflowReqSync => {
assert_eq!(zero_copy.len(), 1);
assert_eq!(zero_copy[0].len(), 100 * 1024 * 1024);
assert_eq!(bufs.len(), 1);
assert_eq!(bufs[0].len(), 100 * 1024 * 1024);
let buf = vec![43u8].into_boxed_slice();
Op::Sync(buf)
}
Mode::OverflowResSync => {
assert_eq!(zero_copy.len(), 1);
assert_eq!(zero_copy[0].len(), 1);
assert_eq!(zero_copy[0][0], 42);
assert_eq!(bufs.len(), 1);
assert_eq!(bufs[0].len(), 1);
assert_eq!(bufs[0][0], 42);
let mut vec = Vec::<u8>::new();
vec.resize(100 * 1024 * 1024, 0);
vec[0] = 99;
@ -946,15 +831,15 @@ pub mod tests {
Op::Sync(buf)
}
Mode::OverflowReqAsync => {
assert_eq!(zero_copy.len(), 1);
assert_eq!(zero_copy[0].len(), 100 * 1024 * 1024);
assert_eq!(bufs.len(), 1);
assert_eq!(bufs[0].len(), 100 * 1024 * 1024);
let buf = vec![43u8].into_boxed_slice();
Op::Async(futures::future::ready(buf).boxed())
}
Mode::OverflowResAsync => {
assert_eq!(zero_copy.len(), 1);
assert_eq!(zero_copy[0].len(), 1);
assert_eq!(zero_copy[0][0], 42);
assert_eq!(bufs.len(), 1);
assert_eq!(bufs[0].len(), 1);
assert_eq!(bufs[0][0], 42);
let mut vec = Vec::<u8>::new();
vec.resize(100 * 1024 * 1024, 0);
vec[0] = 4;
@ -962,9 +847,16 @@ pub mod tests {
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(
"setup.js",
@ -1328,7 +1220,8 @@ pub mod tests {
#[test]
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 r = isolate.execute("i.js", src);
let e = r.unwrap_err();
@ -1353,27 +1246,29 @@ pub mod tests {
#[test]
fn will_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"));
isolate.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')"));
}
#[test]
fn test_from_boxed_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"));
let snap: &[u8] = &*isolate.snapshot();
Vec::from(snap).into_boxed_slice()
};
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')"));
}
@ -1383,8 +1278,11 @@ pub mod tests {
initial: 0,
max: 20 * 1024, // 20 kB
};
let mut isolate =
CoreIsolate::with_heap_limits(StartupData::None, heap_limits);
let mut isolate = CoreIsolate::with_heap_limits(
BasicState::new(),
StartupData::None,
heap_limits,
);
let cb_handle = isolate.thread_safe_handle();
let callback_invoke_count = Rc::new(AtomicUsize::default());
@ -1412,7 +1310,8 @@ pub mod tests {
#[test]
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| {
current_limit * 2
@ -1427,8 +1326,11 @@ pub mod tests {
initial: 0,
max: 20 * 1024, // 20 kB
};
let mut isolate =
CoreIsolate::with_heap_limits(StartupData::None, heap_limits);
let mut isolate = CoreIsolate::with_heap_limits(
BasicState::new(),
StartupData::None,
heap_limits,
);
let cb_handle = isolate.thread_safe_handle();
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 {
use super::*;
#[test]
fn test_bad_resource() {
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");
}
#[test]
fn test_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");
}
}

View file

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

View file

@ -1,10 +1,12 @@
#[macro_use]
extern crate log;
use deno_core::js_check;
use deno_core::BasicState;
use deno_core::BufVec;
use deno_core::CoreIsolate;
use deno_core::CoreIsolateState;
use deno_core::Op;
use deno_core::ResourceTable;
use deno_core::OpRegistry;
use deno_core::Script;
use deno_core::StartupData;
use deno_core::ZeroCopyBuf;
@ -12,7 +14,6 @@ use futures::future::poll_fn;
use futures::future::FutureExt;
use futures::future::TryFuture;
use futures::future::TryFutureExt;
use std::cell::RefCell;
use std::convert::TryInto;
use std::env;
use std::fmt::Debug;
@ -27,6 +28,7 @@ use tokio::io::AsyncRead;
use tokio::io::AsyncWrite;
use tokio::net::TcpListener;
use tokio::net::TcpStream;
use tokio::runtime;
struct Logger;
@ -46,9 +48,9 @@ impl log::Log for Logger {
#[derive(Copy, Clone, Debug, PartialEq)]
struct Record {
pub promise_id: u32,
pub rid: u32,
pub result: i32,
promise_id: u32,
rid: u32,
result: i32,
}
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 {
source: include_str!("http_bench_bin_ops.js"),
filename: "http_bench_bin_ops.js",
});
let mut isolate = CoreIsolate::new(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)
CoreIsolate::new(state, startup_data, false)
}
fn op_listen(
resource_table: Rc<RefCell<ResourceTable>>,
state: &BasicState,
_rid: u32,
_buf: &mut [ZeroCopyBuf],
_bufs: &mut [ZeroCopyBuf],
) -> Result<u32, Error> {
debug!("listen");
let addr = "127.0.0.1:4544".parse::<SocketAddr>().unwrap();
let std_listener = std::net::TcpListener::bind(&addr)?;
let listener = TcpListener::from_std(std_listener)?;
let resource_table = &mut resource_table.borrow_mut();
let rid = resource_table.add("tcpListener", Box::new(listener));
let rid = state
.resource_table
.borrow_mut()
.add("tcpListener", Box::new(listener));
Ok(rid)
}
fn op_accept(
resource_table: Rc<RefCell<ResourceTable>>,
fn op_close(
state: &BasicState,
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> {
debug!("accept rid={}", rid);
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
.get_mut::<TcpListener>(rid)
.ok_or_else(bad_resource)?;
.ok_or_else(bad_resource_id)?;
listener.poll_accept(cx).map_ok(|(stream, _addr)| {
resource_table.add("tcpStream", Box::new(stream))
})
@ -207,9 +142,9 @@ fn op_accept(
}
fn op_read(
resource_table: Rc<RefCell<ResourceTable>>,
state: Rc<BasicState>,
rid: u32,
bufs: &mut [ZeroCopyBuf],
bufs: BufVec,
) -> impl TryFuture<Ok = usize, Error = Error> {
assert_eq!(bufs.len(), 1, "Invalid number of arguments");
let mut buf = bufs[0].clone();
@ -217,33 +152,85 @@ fn op_read(
debug!("read rid={}", rid);
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
.get_mut::<TcpStream>(rid)
.ok_or_else(bad_resource)?;
.ok_or_else(bad_resource_id)?;
Pin::new(stream).poll_read(cx, &mut buf)
})
}
fn op_write(
resource_table: Rc<RefCell<ResourceTable>>,
state: Rc<BasicState>,
rid: u32,
bufs: &mut [ZeroCopyBuf],
bufs: BufVec,
) -> impl TryFuture<Ok = usize, Error = Error> {
assert_eq!(bufs.len(), 1, "Invalid number of arguments");
let buf = bufs[0].clone();
debug!("write rid={}", rid);
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
.get_mut::<TcpStream>(rid)
.ok_or_else(bad_resource)?;
.ok_or_else(bad_resource_id)?;
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")
}
@ -259,13 +246,13 @@ fn main() {
// NOTE: `--help` arg will display V8 help and exit
deno_core::v8_set_flags(env::args().collect());
let isolate = isolate_new();
let mut runtime = tokio::runtime::Builder::new()
let isolate = create_isolate();
let mut runtime = runtime::Builder::new()
.basic_scheduler()
.enable_all()
.build()
.unwrap();
runtime.block_on(isolate).expect("unexpected isolate error");
js_check(runtime.block_on(isolate));
}
#[test]

View file

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

View file

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

View file

@ -8,6 +8,7 @@ use futures::future::FutureExt;
use futures::stream::FuturesUnordered;
use futures::stream::Stream;
use futures::stream::TryStreamExt;
use serde_json::Value;
use std::collections::HashMap;
use std::collections::HashSet;
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;
if let Some(deps) = &self.deps {
children = deps.iter().map(|c| c.to_json()).collect();
@ -521,6 +522,7 @@ mod tests {
use super::*;
use crate::es_isolate::EsIsolate;
use crate::js_check;
use crate::BasicState;
use crate::StartupData;
use futures::future::FutureExt;
use std::error::Error;
@ -535,15 +537,14 @@ mod tests {
// removed in the future.
use crate::core_isolate::tests::run_in_task;
#[derive(Default)]
struct MockLoader {
pub loads: Arc<Mutex<Vec<String>>>,
}
impl MockLoader {
fn new() -> Self {
Self {
loads: Arc::new(Mutex::new(Vec::new())),
}
fn new() -> Rc<Self> {
Default::default()
}
}
@ -699,7 +700,8 @@ mod tests {
fn test_recursive_load() {
let loader = MockLoader::new();
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 a_id_fut = isolate.load_module(&spec, None);
let a_id = futures::executor::block_on(a_id_fut).expect("Failed to load");
@ -761,7 +763,8 @@ mod tests {
fn test_circular_load() {
let loader = MockLoader::new();
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 spec = ModuleSpecifier::resolve_url("file:///circular1.js").unwrap();
@ -834,7 +837,8 @@ mod tests {
fn test_redirect_load() {
let loader = MockLoader::new();
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 spec = ModuleSpecifier::resolve_url("file:///redirect1.js").unwrap();
@ -899,7 +903,7 @@ mod tests {
let loader = MockLoader::new();
let loads = loader.loads.clone();
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 mut recursive_load = isolate.load_module(&spec, None).boxed_local();
@ -945,7 +949,7 @@ mod tests {
run_in_task(|mut cx| {
let loader = MockLoader::new();
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 mut load_fut = isolate.load_module(&spec, None).boxed_local();
let result = load_fut.poll_unpin(&mut cx);
@ -973,7 +977,8 @@ mod tests {
fn recursive_load_main_with_code() {
let loader = MockLoader::new();
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.
// Instead we explicitly pass in our own code.
// 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.
use crate::core_isolate::CoreIsolateState;
use crate::BufVec;
use crate::ErrBox;
use crate::ZeroCopyBuf;
use futures::Future;
use futures::FutureExt;
use indexmap::IndexMap;
use serde_json::json;
use serde_json::Value;
use std::collections::HashMap;
use std::iter::once;
use std::ops::Deref;
use std::ops::DerefMut;
use std::pin::Pin;
use std::rc::Rc;
pub type OpId = u32;
pub type Buf = Box<[u8]>;
pub type OpAsyncFuture = Pin<Box<dyn Future<Output = Buf>>>;
pub type OpAsyncFuture = Pin<Box<dyn Future<Output = Box<[u8]>>>>;
pub type OpFn<S> = dyn Fn(Rc<S>, BufVec) -> Op + 'static;
pub type OpId = usize;
pub enum Op {
Sync(Buf),
Sync(Box<[u8]>),
Async(OpAsyncFuture),
/// AsyncUnref is the variation of Async, which doesn't block the program
/// exiting.
AsyncUnref(OpAsyncFuture),
NotFound,
}
/// Main type describing op
pub type OpDispatcher =
dyn Fn(&mut CoreIsolateState, &mut [ZeroCopyBuf]) -> Op + 'static;
#[derive(Default)]
pub struct OpRegistry {
dispatchers: Vec<Rc<OpDispatcher>>,
name_to_id: HashMap<String, OpId>,
pub trait OpRouter {
fn route_op(self: Rc<Self>, op_id: OpId, bufs: BufVec) -> Op;
}
impl OpRegistry {
pub fn new() -> Self {
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 trait OpRegistry: OpRouter + 'static {
fn get_op_catalog(self: Rc<Self>) -> HashMap<String, OpId>;
pub fn register<F>(&mut self, name: &str, op: F) -> OpId
fn register_op<F>(&self, name: &str, op_fn: F) -> OpId
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);
assert!(
existing.is_none(),
format!("Op already registered: {}", name)
);
self.dispatchers.push(Rc::new(op));
op_id
self.register_op(name, base_op_fn)
}
fn json_map(&self) -> Buf {
let op_map_json = serde_json::to_string(&self.name_to_id).unwrap();
op_map_json.as_bytes().to_owned().into_boxed_slice()
}
pub fn get(&self, op_id: OpId) -> Option<Rc<OpDispatcher>> {
self.dispatchers.get(op_id as usize).map(Rc::clone)
}
pub fn unregister_op(&mut self, name: &str) {
let id = self.name_to_id.remove(name).unwrap();
drop(self.dispatchers.remove(id as usize));
}
}
#[test]
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([]))
fn register_op_json_async<F, R>(self: &Rc<Self>, name: &str, op_fn: F) -> OpId
where
F: Fn(Rc<Self>, Value, BufVec) -> R + 'static,
R: Future<Output = Result<Value, ErrBox>> + 'static,
{
let try_dispatch_op = move |state: Rc<Self>,
bufs: BufVec|
-> Result<Op, ErrBox> {
let args: Value = serde_json::from_slice(&bufs[0])?;
let promise_id = args
.get("promiseId")
.and_then(Value::as_u64)
.ok_or_else(|| ErrBox::type_error("missing or invalid `promiseId`"))?;
let bufs = bufs[1..].into();
let fut = op_fn(state.clone(), args, bufs).map(move |result| {
state.json_serialize_op_result(Some(promise_id), result)
});
Op::Sync(Box::new([]))
})
};
assert!(test_id != 0);
Ok(Op::Async(Box::pin(fut)))
};
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 = {
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 []);
self.register_op(name, base_op_fn)
}
let mut expected = HashMap::new();
expected.insert("ops".to_string(), 0);
expected.insert("dynamic_register_op".to_string(), 1);
expected.insert("test".to_string(), 2);
{
let g = op_registry.lock().unwrap();
assert_eq!(g.name_to_id, expected);
fn json_serialize_op_result(
&self,
promise_id: Option<u64>,
result: Result<Value, ErrBox>,
) -> Box<[u8]> {
let value = match result {
Ok(v) => json!({ "ok": v, "promiseId": promise_id }),
Err(err) => json!({
"promiseId": promise_id ,
"err": {
"className": self.get_error_class_name(&err),
"message": err.to_string(),
}
}),
};
serde_json::to_vec(&value).unwrap().into_boxed_slice()
}
let dispatcher2 = {
let g = op_registry.lock().unwrap();
g.get(2).unwrap()
};
let state_rc = CoreIsolate::state(&isolate);
let mut state = state_rc.borrow_mut();
let res = dispatcher2(&mut state, &mut []);
if let Op::Sync(buf) = res {
assert_eq!(buf.len(), 0);
} else {
unreachable!();
fn get_error_class_name(&self, _err: &ErrBox) -> &'static str {
"Error"
}
}
/// Collection for storing registered ops. The special 'get_op_catalog'
/// op with OpId `0` is automatically added when the OpTable is created.
pub struct OpTable<S>(IndexMap<String, Rc<OpFn<S>>>);
impl<S: OpRegistry> OpTable<S> {
pub fn get_op_catalog(&self) -> HashMap<String, OpId> {
self.keys().cloned().zip(0..).collect()
}
fn op_get_op_catalog(state: Rc<S>, _bufs: BufVec) -> Op {
let ops = state.get_op_catalog();
let buf = serde_json::to_vec(&ops).map(Into::into).unwrap();
Op::Sync(buf)
}
}
impl<S: OpRegistry> Default for OpTable<S> {
fn default() -> Self {
Self(
once(("ops".to_owned(), Rc::new(Self::op_get_op_catalog) as _)).collect(),
)
}
}
impl<S> Deref for OpTable<S> {
type Target = IndexMap<String, Rc<OpFn<S>>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<S> DerefMut for OpTable<S> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
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
// unloaded and all functions in the plugin library are unmapped from memory.
pub use crate::Buf;
pub use crate::Op;
pub use crate::OpId;
pub use crate::ZeroCopyBuf;

View file

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

View file

@ -31,6 +31,7 @@ fn get_path(file_name: &str) -> PathBuf {
#[cfg(test)]
mod tests {
use deno_core::js_check;
use deno_core::BasicState;
use deno_core::CoreIsolate;
use deno_core::StartupData;
use futures::future::lazy;
@ -46,7 +47,8 @@ mod tests {
}
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);
isolate
}

View file

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

View file

@ -65,11 +65,11 @@ function runTestOpCount() {
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
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
throw new Error("The opsDispatched metric is not correct!");
}