mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -05:00
Move JSON ops to deno_core (#7336)
This commit is contained in:
parent
849431eb1d
commit
c821e8f2f1
78 changed files with 1492 additions and 2204 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -453,6 +453,7 @@ version = "0.56.0"
|
|||
dependencies = [
|
||||
"downcast-rs",
|
||||
"futures",
|
||||
"indexmap",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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(())
|
||||
|
|
17
cli/build.rs
17
cli/build.rs
|
@ -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 {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use regex::Regex;
|
||||
use std::env;
|
||||
use std::fmt;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::disk_cache::DiskCache;
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use clap::App;
|
||||
use clap::AppSettings;
|
||||
use clap::Arg;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
)),
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use serde_json::json;
|
||||
pub use serde_json::Value;
|
||||
use std::collections::BTreeMap;
|
||||
use std::io::Result;
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate dissimilar;
|
||||
#[macro_use]
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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!({}))
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
310
cli/ops/fs.rs
310
cli/ops/fs.rs
|
@ -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> {
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
112
cli/ops/net.rs
112
cli/ops/net.rs
|
@ -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 {} {}",
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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!(),
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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!({}))
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)]
|
||||
{
|
||||
|
|
|
@ -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!({}))
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use deno_core::ErrBox;
|
||||
|
||||
#[cfg(not(unix))]
|
||||
|
|
|
@ -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;
|
||||
|
|
353
cli/state.rs
353
cli/state.rs
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)),
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use encoding_rs::*;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
|
|
13
cli/tsc.rs
13
cli/tsc.rs
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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
91
core/basic_state.rs
Normal 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)
|
||||
]
|
||||
)
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
261
core/ops.rs
261
core/ops.rs
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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!");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue