From 7c2e7c660804afca823d60e6496aa853f75db16c Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Thu, 10 Sep 2020 09:57:45 -0400 Subject: [PATCH] Use gotham-like state for ops (#7385) Provides a concrete state type that can be dynamically added. This is necessary for op crates. * renames BasicState to OpState * async ops take `Rc>` * sync ops take `&mut OpState` * removes `OpRegistry`, `OpRouter` traits * `get_error_class_fn` moved to OpState * ResourceTable moved to OpState --- cli/build.rs | 11 +- cli/js.rs | 2 - cli/metrics.rs | 57 ++++ cli/ops/compiler.rs | 32 +- cli/ops/dispatch_minimal.rs | 132 ++++---- cli/ops/errors.rs | 16 +- cli/ops/fetch.rs | 29 +- cli/ops/fs.rs | 440 +++++++++++++++------------ cli/ops/fs_events.rs | 26 +- cli/ops/idna.rs | 9 +- cli/ops/io.rs | 40 +-- cli/ops/mod.rs | 40 +++ cli/ops/net.rs | 117 +++---- cli/ops/net_unix.rs | 52 ++-- cli/ops/os.rs | 81 ++--- cli/ops/permissions.rs | 27 +- cli/ops/plugin.rs | 65 ++-- cli/ops/process.rs | 46 ++- cli/ops/random.rs | 14 +- cli/ops/repl.rs | 39 +-- cli/ops/resources.rs | 18 +- cli/ops/runtime.rs | 28 +- cli/ops/runtime_compiler.rs | 28 +- cli/ops/signal.rs | 42 +-- cli/ops/timers.rs | 40 +-- cli/ops/tls.rs | 107 ++++--- cli/ops/tty.rs | 33 +- cli/ops/web_worker.rs | 15 +- cli/ops/websocket.rs | 48 +-- cli/ops/worker_host.rs | 89 +++--- cli/state.rs | 90 +----- cli/tsc.rs | 13 +- cli/web_worker.rs | 54 ++-- cli/worker.rs | 76 ++--- core/basic_state.rs | 91 ------ core/bindings.rs | 4 +- core/examples/http_bench_bin_ops.rs | 84 ++--- core/examples/http_bench_json_ops.rs | 46 ++- core/gotham_state.rs | 167 ++++++++++ core/lib.rs | 8 +- core/modules.rs | 49 +-- core/ops.rs | 266 ++++++++++------ core/runtime.rs | 249 +++++++-------- op_crates/web/lib.rs | 4 +- 44 files changed, 1576 insertions(+), 1348 deletions(-) delete mode 100644 core/basic_state.rs create mode 100644 core/gotham_state.rs diff --git a/cli/build.rs b/cli/build.rs index 422bc1759f..f2abb95298 100644 --- a/cli/build.rs +++ b/cli/build.rs @@ -3,9 +3,7 @@ mod op_fetch_asset; use deno_core::js_check; -use deno_core::BasicState; use deno_core::JsRuntime; -use deno_core::OpRegistry; use deno_core::StartupData; use std::collections::HashMap; use std::env; @@ -39,8 +37,7 @@ fn create_snapshot( } fn create_runtime_snapshot(snapshot_path: &Path, files: Vec) { - let state = BasicState::new(); - let isolate = JsRuntime::new(state, StartupData::None, true); + let isolate = JsRuntime::new(StartupData::None, true); create_snapshot(isolate, snapshot_path, files); } @@ -73,13 +70,11 @@ fn create_compiler_snapshot( cwd.join("dts/lib.deno.unstable.d.ts"), ); - let state = BasicState::new(); - state.register_op( + let mut isolate = JsRuntime::new(StartupData::None, true); + isolate.register_op( "op_fetch_asset", op_fetch_asset::op_fetch_asset(custom_libs), ); - - let isolate = JsRuntime::new(state, StartupData::None, true); create_snapshot(isolate, snapshot_path, files); } diff --git a/cli/js.rs b/cli/js.rs index 6e67678735..2dc56710d0 100644 --- a/cli/js.rs +++ b/cli/js.rs @@ -14,7 +14,6 @@ pub static UNSTABLE_NS_LIB: &str = include_str!("dts/lib.deno.unstable.d.ts"); #[test] fn cli_snapshot() { let mut isolate = deno_core::JsRuntime::new( - deno_core::BasicState::new(), deno_core::StartupData::Snapshot(deno_core::Snapshot::Static(CLI_SNAPSHOT)), false, ); @@ -32,7 +31,6 @@ fn cli_snapshot() { #[test] fn compiler_snapshot() { let mut isolate = deno_core::JsRuntime::new( - deno_core::BasicState::new(), deno_core::StartupData::Snapshot(deno_core::Snapshot::Static( COMPILER_SNAPSHOT, )), diff --git a/cli/metrics.rs b/cli/metrics.rs index 43f11cd368..227c10f607 100644 --- a/cli/metrics.rs +++ b/cli/metrics.rs @@ -71,3 +71,60 @@ impl Metrics { self.op_completed(bytes_received); } } + +use deno_core::BufVec; +use deno_core::Op; +use deno_core::OpFn; +use deno_core::OpState; +use std::cell::RefCell; +use std::rc::Rc; + +pub fn metrics_op(op_fn: Box) -> Box { + Box::new(move |op_state: Rc>, bufs: BufVec| -> Op { + // TODOs: + // * The 'bytes' metrics seem pretty useless, especially now that the + // distinction between 'control' and 'data' buffers has become blurry. + // * Tracking completion of async ops currently makes us put the boxed + // future into _another_ box. Keeping some counters may not be expensive + // in itself, but adding a heap allocation for every metric seems bad. + let mut buf_len_iter = bufs.iter().map(|buf| buf.len()); + let bytes_sent_control = buf_len_iter.next().unwrap_or(0); + let bytes_sent_data = buf_len_iter.sum(); + + let op = (op_fn)(op_state.clone(), bufs); + + let cli_state = crate::ops::cli_state2(&op_state); + let cli_state_ = cli_state.clone(); + let mut metrics = cli_state.metrics.borrow_mut(); + + use futures::future::FutureExt; + + match op { + Op::Sync(buf) => { + metrics.op_sync(bytes_sent_control, bytes_sent_data, buf.len()); + Op::Sync(buf) + } + Op::Async(fut) => { + metrics.op_dispatched_async(bytes_sent_control, bytes_sent_data); + let fut = fut + .inspect(move |buf| { + let mut metrics = cli_state_.metrics.borrow_mut(); + metrics.op_completed_async(buf.len()); + }) + .boxed_local(); + Op::Async(fut) + } + Op::AsyncUnref(fut) => { + metrics.op_dispatched_async_unref(bytes_sent_control, bytes_sent_data); + let fut = fut + .inspect(move |buf| { + let mut metrics = cli_state_.metrics.borrow_mut(); + metrics.op_completed_async_unref(buf.len()); + }) + .boxed_local(); + Op::AsyncUnref(fut) + } + other => other, + } + }) +} diff --git a/cli/ops/compiler.rs b/cli/ops/compiler.rs index 0b8379fa35..618851daa8 100644 --- a/cli/ops/compiler.rs +++ b/cli/ops/compiler.rs @@ -1,27 +1,31 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use crate::state::State; -use deno_core::OpRegistry; -use std::rc::Rc; use std::sync::Arc; use std::sync::Mutex; -pub fn init(s: &Rc, response: Arc>>) { +pub fn init( + rt: &mut deno_core::JsRuntime, + response: Arc>>, +) { let custom_assets = std::collections::HashMap::new(); // TODO(ry) use None. // TODO(bartlomieju): is this op even required? - s.register_op( + rt.register_op( "op_fetch_asset", crate::op_fetch_asset::op_fetch_asset(custom_assets), ); - s.register_op_json_sync("op_compiler_respond", move |_state, args, _bufs| { - let mut response_slot = response.lock().unwrap(); - let replaced_value = response_slot.replace(args.to_string()); - assert!( - replaced_value.is_none(), - "op_compiler_respond found unexpected existing compiler output", - ); - Ok(json!({})) - }); + super::reg_json_sync( + rt, + "op_compiler_respond", + move |_state, args, _bufs| { + let mut response_slot = response.lock().unwrap(); + let replaced_value = response_slot.replace(args.to_string()); + assert!( + replaced_value.is_none(), + "op_compiler_respond found unexpected existing compiler output", + ); + Ok(json!({})) + }, + ); } diff --git a/cli/ops/dispatch_minimal.rs b/cli/ops/dispatch_minimal.rs index 9d941682d8..0429e7f7be 100644 --- a/cli/ops/dispatch_minimal.rs +++ b/cli/ops/dispatch_minimal.rs @@ -1,12 +1,12 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use crate::state::State; use deno_core::BufVec; use deno_core::ErrBox; use deno_core::Op; -use deno_core::OpId; -use deno_core::OpRegistry; +use deno_core::OpFn; +use deno_core::OpState; use futures::future::FutureExt; +use std::cell::RefCell; use std::future::Future; use std::iter::repeat; use std::mem::size_of_val; @@ -132,78 +132,74 @@ fn test_parse_min_record() { assert_eq!(parse_min_record(&buf), None); } -impl State { - pub fn register_op_minimal(self: &Rc, name: &str, op_fn: F) -> OpId - where - F: Fn(Rc, bool, i32, BufVec) -> MinimalOp + 'static, - { - let base_op_fn = move |state: Rc, 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::(); +pub fn minimal_op(op_fn: F) -> Box +where + F: Fn(Rc>, bool, i32, BufVec) -> MinimalOp + 'static, +{ + Box::new(move |state: Rc>, 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::(); - let mut record = match parse_min_record(&record_buf) { - Some(r) => r, - None => { - let error = ErrBox::type_error("Unparsable control buffer"); - let error_class = state.get_error_class_name(&error); + let mut record = match parse_min_record(&record_buf) { + Some(r) => r, + None => { + let error = ErrBox::type_error("Unparsable control buffer"); + let error_class = (state.borrow().get_error_class_fn)(&error); + let error_record = ErrorRecord { + promise_id: 0, + arg: -1, + error_len: error_class.len() as i32, + error_class: error_class.as_bytes(), + error_message: error.to_string().as_bytes().to_owned(), + }; + return Op::Sync(error_record.into()); + } + }; + let is_sync = record.promise_id == 0; + let rid = record.arg; + let min_op = op_fn(state.clone(), is_sync, rid, zero_copy); + + match min_op { + MinimalOp::Sync(sync_result) => Op::Sync(match sync_result { + Ok(r) => { + record.result = r; + record.into() + } + Err(err) => { + let error_class = (state.borrow().get_error_class_fn)(&err); let error_record = ErrorRecord { - promise_id: 0, + promise_id: record.promise_id, arg: -1, error_len: error_class.len() as i32, error_class: error_class.as_bytes(), - error_message: error.to_string().as_bytes().to_owned(), + error_message: err.to_string().as_bytes().to_owned(), }; - return Op::Sync(error_record.into()); + error_record.into() } - }; - let is_sync = record.promise_id == 0; - let rid = record.arg; - let min_op = op_fn(state.clone(), is_sync, rid, zero_copy); - - match min_op { - MinimalOp::Sync(sync_result) => Op::Sync(match sync_result { - Ok(r) => { - record.result = r; - record.into() - } - Err(err) => { - let error_class = state.get_error_class_name(&err); - let error_record = ErrorRecord { - promise_id: record.promise_id, - arg: -1, - error_len: error_class.len() as i32, - error_class: error_class.as_bytes(), - error_message: err.to_string().as_bytes().to_owned(), - }; - error_record.into() - } - }), - MinimalOp::Async(min_fut) => { - let fut = async move { - match min_fut.await { - Ok(r) => { - record.result = r; - record.into() - } - Err(err) => { - let error_class = state.get_error_class_name(&err); - let error_record = ErrorRecord { - promise_id: record.promise_id, - arg: -1, - error_len: error_class.len() as i32, - error_class: error_class.as_bytes(), - error_message: err.to_string().as_bytes().to_owned(), - }; - error_record.into() - } + }), + MinimalOp::Async(min_fut) => { + let fut = async move { + match min_fut.await { + Ok(r) => { + record.result = r; + record.into() } - }; - Op::Async(fut.boxed_local()) - } + Err(err) => { + let error_class = (state.borrow().get_error_class_fn)(&err); + let error_record = ErrorRecord { + promise_id: record.promise_id, + arg: -1, + error_len: error_class.len() as i32, + error_class: error_class.as_bytes(), + error_message: err.to_string().as_bytes().to_owned(), + }; + error_record.into() + } + } + }; + Op::Async(fut.boxed_local()) } - }; - - self.register_op(name, base_op_fn) - } + } + }) } diff --git a/cli/ops/errors.rs b/cli/ops/errors.rs index a4f4665e20..40ec1da30c 100644 --- a/cli/ops/errors.rs +++ b/cli/ops/errors.rs @@ -3,18 +3,16 @@ use crate::diagnostics::Diagnostic; use crate::source_maps::get_orig_position; use crate::source_maps::CachedMaps; -use crate::state::State; use deno_core::ErrBox; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::ZeroCopyBuf; use serde_derive::Deserialize; use serde_json::Value; use std::collections::HashMap; -use std::rc::Rc; -pub fn init(s: &Rc) { - s.register_op_json_sync("op_apply_source_map", op_apply_source_map); - s.register_op_json_sync("op_format_diagnostic", op_format_diagnostic); +pub fn init(rt: &mut deno_core::JsRuntime) { + super::reg_json_sync(rt, "op_apply_source_map", op_apply_source_map); + super::reg_json_sync(rt, "op_format_diagnostic", op_format_diagnostic); } #[derive(Deserialize)] @@ -26,7 +24,7 @@ struct ApplySourceMap { } fn op_apply_source_map( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -39,7 +37,7 @@ fn op_apply_source_map( args.line_number.into(), args.column_number.into(), &mut mappings_map, - &state.global_state.ts_compiler, + &super::cli_state(state).global_state.ts_compiler, ); Ok(json!({ @@ -50,7 +48,7 @@ fn op_apply_source_map( } fn op_format_diagnostic( - _state: &State, + _state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { diff --git a/cli/ops/fetch.rs b/cli/ops/fetch.rs index 690cbc592b..44031e2aca 100644 --- a/cli/ops/fetch.rs +++ b/cli/ops/fetch.rs @@ -2,10 +2,9 @@ use super::io::{StreamResource, StreamResourceHolder}; use crate::http_util::{create_http_client, HttpBody}; -use crate::state::State; use deno_core::BufVec; use deno_core::ErrBox; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::ZeroCopyBuf; use http::header::HeaderName; use http::header::HeaderValue; @@ -13,13 +12,14 @@ use http::Method; use reqwest::Client; use serde_derive::Deserialize; use serde_json::Value; +use std::cell::RefCell; use std::convert::From; use std::path::PathBuf; use std::rc::Rc; -pub fn init(s: &Rc) { - s.register_op_json_async("op_fetch", op_fetch); - s.register_op_json_sync("op_create_http_client", op_create_http_client); +pub fn init(rt: &mut deno_core::JsRuntime) { + super::reg_json_async(rt, "op_fetch", op_fetch); + super::reg_json_sync(rt, "op_create_http_client", op_create_http_client); } #[derive(Deserialize)] @@ -32,7 +32,7 @@ struct FetchArgs { } async fn op_fetch( - state: Rc, + state: Rc>, args: Value, data: BufVec, ) -> Result { @@ -40,13 +40,15 @@ async fn op_fetch( let url = args.url; let client = if let Some(rid) = args.client_rid { - let resource_table_ = state.resource_table.borrow(); - let r = resource_table_ + let state = state.borrow(); + let r = state + .resource_table .get::(rid) .ok_or_else(ErrBox::bad_resource_id)?; r.client.clone() } else { - let client_ref = state.http_client.borrow_mut(); + let cli_state = super::cli_state2(&state); + let client_ref = cli_state.http_client.borrow(); client_ref.clone() }; @@ -66,7 +68,7 @@ async fn op_fetch( ))); } - state.check_net_url(&url_)?; + super::cli_state2(&state).check_net_url(&url_)?; let mut request = client.request(method, url_); @@ -93,7 +95,7 @@ async fn op_fetch( } let body = HttpBody::from(res); - let rid = state.resource_table.borrow_mut().add( + let rid = state.borrow_mut().resource_table.add( "httpBody", Box::new(StreamResourceHolder::new(StreamResource::HttpBody( Box::new(body), @@ -128,21 +130,20 @@ struct CreateHttpClientOptions { } fn op_create_http_client( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let args: CreateHttpClientOptions = serde_json::from_value(args)?; if let Some(ca_file) = args.ca_file.clone() { - state.check_read(&PathBuf::from(ca_file))?; + super::cli_state(state).check_read(&PathBuf::from(ca_file))?; } let client = create_http_client(args.ca_file.as_deref()).unwrap(); let rid = state .resource_table - .borrow_mut() .add("httpClient", Box::new(HttpClientResource::new(client))); Ok(json!(rid)) } diff --git a/cli/ops/fs.rs b/cli/ops/fs.rs index e281f947ef..7f9443efb9 100644 --- a/cli/ops/fs.rs +++ b/cli/ops/fs.rs @@ -2,15 +2,15 @@ // Some deserializer fields are only used on Unix and Windows build fails without it use super::io::std_file_resource; use super::io::{FileMetadata, StreamResource, StreamResourceHolder}; -use crate::state::State; use deno_core::BufVec; use deno_core::ErrBox; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::ZeroCopyBuf; use rand::thread_rng; use rand::Rng; use serde_derive::Deserialize; use serde_json::Value; +use std::cell::RefCell; use std::convert::From; use std::env::{current_dir, set_current_dir, temp_dir}; use std::io; @@ -20,80 +20,80 @@ use std::rc::Rc; use std::time::SystemTime; use std::time::UNIX_EPOCH; -pub fn init(s: &Rc) { - 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(rt: &mut deno_core::JsRuntime) { + super::reg_json_sync(rt, "op_open_sync", op_open_sync); + super::reg_json_async(rt, "op_open_async", op_open_async); - s.register_op_json_sync("op_seek_sync", op_seek_sync); - s.register_op_json_async("op_seek_async", op_seek_async); + super::reg_json_sync(rt, "op_seek_sync", op_seek_sync); + super::reg_json_async(rt, "op_seek_async", op_seek_async); - s.register_op_json_sync("op_fdatasync_sync", op_fdatasync_sync); - s.register_op_json_async("op_fdatasync_async", op_fdatasync_async); + super::reg_json_sync(rt, "op_fdatasync_sync", op_fdatasync_sync); + super::reg_json_async(rt, "op_fdatasync_async", op_fdatasync_async); - s.register_op_json_sync("op_fsync_sync", op_fsync_sync); - s.register_op_json_async("op_fsync_async", op_fsync_async); + super::reg_json_sync(rt, "op_fsync_sync", op_fsync_sync); + super::reg_json_async(rt, "op_fsync_async", op_fsync_async); - s.register_op_json_sync("op_fstat_sync", op_fstat_sync); - s.register_op_json_async("op_fstat_async", op_fstat_async); + super::reg_json_sync(rt, "op_fstat_sync", op_fstat_sync); + super::reg_json_async(rt, "op_fstat_async", op_fstat_async); - s.register_op_json_sync("op_umask", op_umask); - s.register_op_json_sync("op_chdir", op_chdir); + super::reg_json_sync(rt, "op_umask", op_umask); + super::reg_json_sync(rt, "op_chdir", op_chdir); - s.register_op_json_sync("op_mkdir_sync", op_mkdir_sync); - s.register_op_json_async("op_mkdir_async", op_mkdir_async); + super::reg_json_sync(rt, "op_mkdir_sync", op_mkdir_sync); + super::reg_json_async(rt, "op_mkdir_async", op_mkdir_async); - s.register_op_json_sync("op_chmod_sync", op_chmod_sync); - s.register_op_json_async("op_chmod_async", op_chmod_async); + super::reg_json_sync(rt, "op_chmod_sync", op_chmod_sync); + super::reg_json_async(rt, "op_chmod_async", op_chmod_async); - s.register_op_json_sync("op_chown_sync", op_chown_sync); - s.register_op_json_async("op_chown_async", op_chown_async); + super::reg_json_sync(rt, "op_chown_sync", op_chown_sync); + super::reg_json_async(rt, "op_chown_async", op_chown_async); - s.register_op_json_sync("op_remove_sync", op_remove_sync); - s.register_op_json_async("op_remove_async", op_remove_async); + super::reg_json_sync(rt, "op_remove_sync", op_remove_sync); + super::reg_json_async(rt, "op_remove_async", op_remove_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); + super::reg_json_sync(rt, "op_copy_file_sync", op_copy_file_sync); + super::reg_json_async(rt, "op_copy_file_async", op_copy_file_async); - s.register_op_json_sync("op_stat_sync", op_stat_sync); - s.register_op_json_async("op_stat_async", op_stat_async); + super::reg_json_sync(rt, "op_stat_sync", op_stat_sync); + super::reg_json_async(rt, "op_stat_async", op_stat_async); - s.register_op_json_sync("op_realpath_sync", op_realpath_sync); - s.register_op_json_async("op_realpath_async", op_realpath_async); + super::reg_json_sync(rt, "op_realpath_sync", op_realpath_sync); + super::reg_json_async(rt, "op_realpath_async", op_realpath_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); + super::reg_json_sync(rt, "op_read_dir_sync", op_read_dir_sync); + super::reg_json_async(rt, "op_read_dir_async", op_read_dir_async); - s.register_op_json_sync("op_rename_sync", op_rename_sync); - s.register_op_json_async("op_rename_async", op_rename_async); + super::reg_json_sync(rt, "op_rename_sync", op_rename_sync); + super::reg_json_async(rt, "op_rename_async", op_rename_async); - s.register_op_json_sync("op_link_sync", op_link_sync); - s.register_op_json_async("op_link_async", op_link_async); + super::reg_json_sync(rt, "op_link_sync", op_link_sync); + super::reg_json_async(rt, "op_link_async", op_link_async); - s.register_op_json_sync("op_symlink_sync", op_symlink_sync); - s.register_op_json_async("op_symlink_async", op_symlink_async); + super::reg_json_sync(rt, "op_symlink_sync", op_symlink_sync); + super::reg_json_async(rt, "op_symlink_async", op_symlink_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); + super::reg_json_sync(rt, "op_read_link_sync", op_read_link_sync); + super::reg_json_async(rt, "op_read_link_async", op_read_link_async); - s.register_op_json_sync("op_ftruncate_sync", op_ftruncate_sync); - s.register_op_json_async("op_ftruncate_async", op_ftruncate_async); + super::reg_json_sync(rt, "op_ftruncate_sync", op_ftruncate_sync); + super::reg_json_async(rt, "op_ftruncate_async", op_ftruncate_async); - s.register_op_json_sync("op_truncate_sync", op_truncate_sync); - s.register_op_json_async("op_truncate_async", op_truncate_async); + super::reg_json_sync(rt, "op_truncate_sync", op_truncate_sync); + super::reg_json_async(rt, "op_truncate_async", op_truncate_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); + super::reg_json_sync(rt, "op_make_temp_dir_sync", op_make_temp_dir_sync); + super::reg_json_async(rt, "op_make_temp_dir_async", op_make_temp_dir_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); + super::reg_json_sync(rt, "op_make_temp_file_sync", op_make_temp_file_sync); + super::reg_json_async(rt, "op_make_temp_file_async", op_make_temp_file_async); - s.register_op_json_sync("op_cwd", op_cwd); + super::reg_json_sync(rt, "op_cwd", op_cwd); - s.register_op_json_sync("op_futime_sync", op_futime_sync); - s.register_op_json_async("op_futime_async", op_futime_async); + super::reg_json_sync(rt, "op_futime_sync", op_futime_sync); + super::reg_json_async(rt, "op_futime_async", op_futime_async); - s.register_op_json_sync("op_utime_sync", op_utime_sync); - s.register_op_json_async("op_utime_async", op_utime_async); + super::reg_json_sync(rt, "op_utime_sync", op_utime_sync); + super::reg_json_async(rt, "op_utime_async", op_utime_async); } fn into_string(s: std::ffi::OsString) -> Result { @@ -124,7 +124,7 @@ struct OpenOptions { } fn open_helper( - state: &State, + state: &mut OpState, args: Value, ) -> Result<(PathBuf, std::fs::OpenOptions), ErrBox> { let args: OpenArgs = serde_json::from_value(args)?; @@ -146,11 +146,13 @@ fn open_helper( let options = args.options; if options.read { - state.check_read(&path)?; + let cli_state = super::cli_state(state); + cli_state.check_read(&path)?; } if options.write || options.append { - state.check_write(&path)?; + let cli_state = super::cli_state(state); + cli_state.check_write(&path)?; } open_options @@ -165,14 +167,14 @@ fn open_helper( } fn op_open_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { 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 = state.resource_table.borrow_mut().add( + let rid = state.resource_table.add( "fsFile", Box::new(StreamResourceHolder::new(StreamResource::FsFile(Some(( tokio_file, @@ -183,15 +185,15 @@ fn op_open_sync( } async fn op_open_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { - let (path, open_options) = open_helper(&state, args)?; + let (path, open_options) = open_helper(&mut state.borrow_mut(), args)?; let tokio_file = tokio::fs::OpenOptions::from(open_options) .open(path) .await?; - let rid = state.resource_table.borrow_mut().add( + let rid = state.borrow_mut().resource_table.add( "fsFile", Box::new(StreamResourceHolder::new(StreamResource::FsFile(Some(( tokio_file, @@ -228,7 +230,7 @@ fn seek_helper(args: Value) -> Result<(u32, SeekFrom), ErrBox> { } fn op_seek_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -243,14 +245,14 @@ fn op_seek_sync( } async fn op_seek_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { 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 pos = std_file_resource(&state, rid, |r| match r { + let pos = std_file_resource(&mut state.borrow_mut(), 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(), @@ -266,11 +268,14 @@ struct FdatasyncArgs { } fn op_fdatasync_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.check_unstable("Deno.fdatasync"); + { + let cli_state = super::cli_state(state); + cli_state.check_unstable("Deno.fdatasync"); + } let args: FdatasyncArgs = serde_json::from_value(args)?; let rid = args.rid as u32; std_file_resource(state, rid, |r| match r { @@ -283,14 +288,15 @@ fn op_fdatasync_sync( } async fn op_fdatasync_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { - state.check_unstable("Deno.fdatasync"); + super::cli_state2(&state).check_unstable("Deno.fdatasync"); + let args: FdatasyncArgs = serde_json::from_value(args)?; let rid = args.rid as u32; - std_file_resource(&state, rid, |r| match r { + std_file_resource(&mut state.borrow_mut(), 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(), @@ -306,11 +312,14 @@ struct FsyncArgs { } fn op_fsync_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.check_unstable("Deno.fsync"); + { + let cli_state = super::cli_state(state); + cli_state.check_unstable("Deno.fsync"); + } let args: FsyncArgs = serde_json::from_value(args)?; let rid = args.rid as u32; std_file_resource(state, rid, |r| match r { @@ -323,14 +332,15 @@ fn op_fsync_sync( } async fn op_fsync_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { - state.check_unstable("Deno.fsync"); + super::cli_state2(&state).check_unstable("Deno.fsync"); + let args: FsyncArgs = serde_json::from_value(args)?; let rid = args.rid as u32; - std_file_resource(&state, rid, |r| match r { + std_file_resource(&mut state.borrow_mut(), 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(), @@ -346,11 +356,14 @@ struct FstatArgs { } fn op_fstat_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.check_unstable("Deno.fstat"); + { + let cli_state = super::cli_state(state); + cli_state.check_unstable("Deno.fstat"); + } let args: FstatArgs = serde_json::from_value(args)?; let rid = args.rid as u32; let metadata = std_file_resource(state, rid, |r| match r { @@ -363,19 +376,21 @@ fn op_fstat_sync( } async fn op_fstat_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { - state.check_unstable("Deno.fstat"); + super::cli_state2(&state).check_unstable("Deno.fstat"); + let args: FstatArgs = serde_json::from_value(args)?; let rid = args.rid as u32; - 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(), - )), - })?; + let metadata = + std_file_resource(&mut state.borrow_mut(), 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(), + )), + })?; Ok(get_stat_json(metadata).unwrap()) } @@ -385,11 +400,14 @@ struct UmaskArgs { } fn op_umask( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.check_unstable("Deno.umask"); + { + let cli_state = super::cli_state(state); + cli_state.check_unstable("Deno.umask"); + } let args: UmaskArgs = serde_json::from_value(args)?; // TODO implement umask for Windows // see https://github.com/nodejs/node/blob/master/src/node_process_methods.cc @@ -423,13 +441,14 @@ struct ChdirArgs { } fn op_chdir( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let args: ChdirArgs = serde_json::from_value(args)?; let d = PathBuf::from(&args.directory); - state.check_read(&d)?; + let cli_state = super::cli_state(state); + cli_state.check_read(&d)?; set_current_dir(&d)?; Ok(json!({})) } @@ -443,14 +462,15 @@ struct MkdirArgs { } fn op_mkdir_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let args: MkdirArgs = serde_json::from_value(args)?; let path = Path::new(&args.path).to_path_buf(); let mode = args.mode.unwrap_or(0o777) & 0o777; - state.check_write(&path)?; + let cli_state = super::cli_state(state); + cli_state.check_write(&path)?; debug!("op_mkdir {} {:o} {}", path.display(), mode, args.recursive); let mut builder = std::fs::DirBuilder::new(); builder.recursive(args.recursive); @@ -464,14 +484,16 @@ fn op_mkdir_sync( } async fn op_mkdir_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { let args: MkdirArgs = serde_json::from_value(args)?; let path = Path::new(&args.path).to_path_buf(); let mode = args.mode.unwrap_or(0o777) & 0o777; - state.check_write(&path)?; + + super::cli_state2(&state).check_write(&path)?; + tokio::task::spawn_blocking(move || { debug!("op_mkdir {} {:o} {}", path.display(), mode, args.recursive); let mut builder = std::fs::DirBuilder::new(); @@ -496,7 +518,7 @@ struct ChmodArgs { } fn op_chmod_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -504,7 +526,8 @@ fn op_chmod_sync( let path = Path::new(&args.path).to_path_buf(); let mode = args.mode & 0o777; - state.check_write(&path)?; + let cli_state = super::cli_state(state); + cli_state.check_write(&path)?; debug!("op_chmod_sync {} {:o}", path.display(), mode); #[cfg(unix)] { @@ -523,14 +546,16 @@ fn op_chmod_sync( } async fn op_chmod_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { let args: ChmodArgs = serde_json::from_value(args)?; let path = Path::new(&args.path).to_path_buf(); let mode = args.mode & 0o777; - state.check_write(&path)?; + + super::cli_state2(&state).check_write(&path)?; + tokio::task::spawn_blocking(move || { debug!("op_chmod_async {} {:o}", path.display(), mode); #[cfg(unix)] @@ -561,13 +586,14 @@ struct ChownArgs { } fn op_chown_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let args: ChownArgs = serde_json::from_value(args)?; let path = Path::new(&args.path).to_path_buf(); - state.check_write(&path)?; + let cli_state = super::cli_state(state); + cli_state.check_write(&path)?; debug!( "op_chown_sync {} {:?} {:?}", path.display(), @@ -590,13 +616,15 @@ fn op_chown_sync( } async fn op_chown_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { let args: ChownArgs = serde_json::from_value(args)?; let path = Path::new(&args.path).to_path_buf(); - state.check_write(&path)?; + + super::cli_state2(&state).check_write(&path)?; + tokio::task::spawn_blocking(move || { debug!( "op_chown_async {} {:?} {:?}", @@ -628,7 +656,7 @@ struct RemoveArgs { } fn op_remove_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -636,7 +664,8 @@ fn op_remove_sync( let path = PathBuf::from(&args.path); let recursive = args.recursive; - state.check_write(&path)?; + let cli_state = super::cli_state(state); + cli_state.check_write(&path)?; #[cfg(not(unix))] use std::os::windows::prelude::MetadataExt; @@ -671,7 +700,7 @@ fn op_remove_sync( } async fn op_remove_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { @@ -679,7 +708,7 @@ async fn op_remove_async( let path = PathBuf::from(&args.path); let recursive = args.recursive; - state.check_write(&path)?; + super::cli_state2(&state).check_write(&path)?; tokio::task::spawn_blocking(move || { #[cfg(not(unix))] @@ -725,7 +754,7 @@ struct CopyFileArgs { } fn op_copy_file_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -733,8 +762,9 @@ fn op_copy_file_sync( let from = PathBuf::from(&args.from); let to = PathBuf::from(&args.to); - state.check_read(&from)?; - state.check_write(&to)?; + let cli_state = super::cli_state(state); + cli_state.check_read(&from)?; + cli_state.check_write(&to)?; debug!("op_copy_file_sync {} {}", from.display(), to.display()); // On *nix, Rust reports non-existent `from` as ErrorKind::InvalidInput @@ -750,7 +780,7 @@ fn op_copy_file_sync( } async fn op_copy_file_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { @@ -758,8 +788,9 @@ async fn op_copy_file_async( let from = PathBuf::from(&args.from); let to = PathBuf::from(&args.to); - state.check_read(&from)?; - state.check_write(&to)?; + let cli_state = super::cli_state2(&state); + cli_state.check_read(&from)?; + cli_state.check_write(&to)?; debug!("op_copy_file_async {} {}", from.display(), to.display()); tokio::task::spawn_blocking(move || { @@ -844,14 +875,15 @@ struct StatArgs { } fn op_stat_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let args: StatArgs = serde_json::from_value(args)?; let path = PathBuf::from(&args.path); let lstat = args.lstat; - state.check_read(&path)?; + let cli_state = super::cli_state(state); + cli_state.check_read(&path)?; debug!("op_stat_sync {} {}", path.display(), lstat); let metadata = if lstat { std::fs::symlink_metadata(&path)? @@ -862,7 +894,7 @@ fn op_stat_sync( } async fn op_stat_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { @@ -870,7 +902,7 @@ async fn op_stat_async( let path = PathBuf::from(&args.path); let lstat = args.lstat; - state.check_read(&path)?; + super::cli_state2(&state).check_read(&path)?; tokio::task::spawn_blocking(move || { debug!("op_stat_async {} {}", path.display(), lstat); @@ -892,16 +924,17 @@ struct RealpathArgs { } fn op_realpath_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let args: RealpathArgs = serde_json::from_value(args)?; let path = PathBuf::from(&args.path); - state.check_read(&path)?; + let cli_state = super::cli_state(state); + cli_state.check_read(&path)?; if path.is_relative() { - state.check_read_blind(¤t_dir()?, "CWD")?; + cli_state.check_read_blind(¤t_dir()?, "CWD")?; } debug!("op_realpath_sync {}", path.display()); @@ -917,16 +950,17 @@ fn op_realpath_sync( } async fn op_realpath_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { let args: RealpathArgs = serde_json::from_value(args)?; let path = PathBuf::from(&args.path); - state.check_read(&path)?; + let cli_state = super::cli_state2(&state); + cli_state.check_read(&path)?; if path.is_relative() { - state.check_read_blind(¤t_dir()?, "CWD")?; + cli_state.check_read_blind(¤t_dir()?, "CWD")?; } tokio::task::spawn_blocking(move || { @@ -952,14 +986,15 @@ struct ReadDirArgs { } fn op_read_dir_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let args: ReadDirArgs = serde_json::from_value(args)?; let path = PathBuf::from(&args.path); - state.check_read(&path)?; + let cli_state = super::cli_state(state); + cli_state.check_read(&path)?; debug!("op_read_dir_sync {}", path.display()); let entries: Vec<_> = std::fs::read_dir(path)? @@ -984,15 +1019,13 @@ fn op_read_dir_sync( } async fn op_read_dir_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { let args: ReadDirArgs = serde_json::from_value(args)?; let path = PathBuf::from(&args.path); - - state.check_read(&path)?; - + super::cli_state2(&state).check_read(&path)?; tokio::task::spawn_blocking(move || { debug!("op_read_dir_async {}", path.display()); let entries: Vec<_> = std::fs::read_dir(path)? @@ -1027,7 +1060,7 @@ struct RenameArgs { } fn op_rename_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -1035,27 +1068,29 @@ fn op_rename_sync( let oldpath = PathBuf::from(&args.oldpath); let newpath = PathBuf::from(&args.newpath); - state.check_read(&oldpath)?; - state.check_write(&oldpath)?; - state.check_write(&newpath)?; + let cli_state = super::cli_state(state); + cli_state.check_read(&oldpath)?; + cli_state.check_write(&oldpath)?; + cli_state.check_write(&newpath)?; debug!("op_rename_sync {} {}", oldpath.display(), newpath.display()); std::fs::rename(&oldpath, &newpath)?; Ok(json!({})) } async fn op_rename_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { let args: RenameArgs = serde_json::from_value(args)?; let oldpath = PathBuf::from(&args.oldpath); let newpath = PathBuf::from(&args.newpath); - - state.check_read(&oldpath)?; - state.check_write(&oldpath)?; - state.check_write(&newpath)?; - + { + let cli_state = super::cli_state2(&state); + cli_state.check_read(&oldpath)?; + cli_state.check_write(&oldpath)?; + cli_state.check_write(&newpath)?; + } tokio::task::spawn_blocking(move || { debug!( "op_rename_async {} {}", @@ -1077,17 +1112,18 @@ struct LinkArgs { } fn op_link_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.check_unstable("Deno.link"); + let cli_state = super::cli_state(state); + cli_state.check_unstable("Deno.link"); let args: LinkArgs = serde_json::from_value(args)?; let oldpath = PathBuf::from(&args.oldpath); let newpath = PathBuf::from(&args.newpath); - state.check_read(&oldpath)?; - state.check_write(&newpath)?; + cli_state.check_read(&oldpath)?; + cli_state.check_write(&newpath)?; debug!("op_link_sync {} {}", oldpath.display(), newpath.display()); std::fs::hard_link(&oldpath, &newpath)?; @@ -1095,17 +1131,19 @@ fn op_link_sync( } async fn op_link_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { - state.check_unstable("Deno.link"); + let cli_state = super::cli_state2(&state); + cli_state.check_unstable("Deno.link"); + let args: LinkArgs = serde_json::from_value(args)?; let oldpath = PathBuf::from(&args.oldpath); let newpath = PathBuf::from(&args.newpath); - state.check_read(&oldpath)?; - state.check_write(&newpath)?; + cli_state.check_read(&oldpath)?; + cli_state.check_write(&newpath)?; tokio::task::spawn_blocking(move || { debug!("op_link_async {} {}", oldpath.display(), newpath.display()); @@ -1133,16 +1171,17 @@ struct SymlinkOptions { } fn op_symlink_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.check_unstable("Deno.symlink"); + let cli_state = super::cli_state(state); + cli_state.check_unstable("Deno.symlink"); let args: SymlinkArgs = serde_json::from_value(args)?; let oldpath = PathBuf::from(&args.oldpath); let newpath = PathBuf::from(&args.newpath); - state.check_write(&newpath)?; + cli_state.check_write(&newpath)?; debug!( "op_symlink_sync {} {}", @@ -1184,16 +1223,18 @@ fn op_symlink_sync( } async fn op_symlink_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { - state.check_unstable("Deno.symlink"); + let cli_state = super::cli_state2(&state); + cli_state.check_unstable("Deno.symlink"); + let args: SymlinkArgs = serde_json::from_value(args)?; let oldpath = PathBuf::from(&args.oldpath); let newpath = PathBuf::from(&args.newpath); - state.check_write(&newpath)?; + cli_state.check_write(&newpath)?; tokio::task::spawn_blocking(move || { debug!("op_symlink_async {} {}", oldpath.display(), newpath.display()); @@ -1241,14 +1282,15 @@ struct ReadLinkArgs { } fn op_read_link_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let args: ReadLinkArgs = serde_json::from_value(args)?; let path = PathBuf::from(&args.path); - state.check_read(&path)?; + let cli_state = super::cli_state(state); + cli_state.check_read(&path)?; debug!("op_read_link_value {}", path.display()); let target = std::fs::read_link(&path)?.into_os_string(); @@ -1257,15 +1299,13 @@ fn op_read_link_sync( } async fn op_read_link_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { let args: ReadLinkArgs = serde_json::from_value(args)?; let path = PathBuf::from(&args.path); - - state.check_read(&path)?; - + super::cli_state2(&state).check_read(&path)?; tokio::task::spawn_blocking(move || { debug!("op_read_link_async {}", path.display()); let target = std::fs::read_link(&path)?.into_os_string(); @@ -1284,11 +1324,14 @@ struct FtruncateArgs { } fn op_ftruncate_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.check_unstable("Deno.ftruncate"); + { + let cli_state = super::cli_state(state); + cli_state.check_unstable("Deno.ftruncate"); + } let args: FtruncateArgs = serde_json::from_value(args)?; let rid = args.rid as u32; let len = args.len as u64; @@ -1300,15 +1343,15 @@ fn op_ftruncate_sync( } async fn op_ftruncate_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { - state.check_unstable("Deno.ftruncate"); + super::cli_state2(&state).check_unstable("Deno.ftruncate"); let args: FtruncateArgs = serde_json::from_value(args)?; let rid = args.rid as u32; let len = args.len as u64; - std_file_resource(&state, rid, |r| match r { + std_file_resource(&mut state.borrow_mut(), 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")), })?; @@ -1323,7 +1366,7 @@ struct TruncateArgs { } fn op_truncate_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -1331,7 +1374,8 @@ fn op_truncate_sync( let path = PathBuf::from(&args.path); let len = args.len; - state.check_write(&path)?; + let cli_state = super::cli_state(state); + cli_state.check_write(&path)?; debug!("op_truncate_sync {} {}", path.display(), len); let f = std::fs::OpenOptions::new().write(true).open(&path)?; @@ -1340,16 +1384,14 @@ fn op_truncate_sync( } async fn op_truncate_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { let args: TruncateArgs = serde_json::from_value(args)?; let path = PathBuf::from(&args.path); let len = args.len; - - state.check_write(&path)?; - + super::cli_state2(&state).check_write(&path)?; tokio::task::spawn_blocking(move || { debug!("op_truncate_async {} {}", path.display(), len); let f = std::fs::OpenOptions::new().write(true).open(&path)?; @@ -1414,7 +1456,7 @@ struct MakeTempArgs { } fn op_make_temp_dir_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -1424,7 +1466,8 @@ fn op_make_temp_dir_sync( let prefix = args.prefix.map(String::from); let suffix = args.suffix.map(String::from); - state.check_write(dir.clone().unwrap_or_else(temp_dir).as_path())?; + let cli_state = super::cli_state(state); + cli_state.check_write(dir.clone().unwrap_or_else(temp_dir).as_path())?; // TODO(piscisaureus): use byte vector for paths, not a string. // See https://github.com/denoland/deno/issues/627. @@ -1442,7 +1485,7 @@ fn op_make_temp_dir_sync( } async fn op_make_temp_dir_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { @@ -1451,9 +1494,10 @@ async fn op_make_temp_dir_async( let dir = args.dir.map(|s| PathBuf::from(&s)); let prefix = args.prefix.map(String::from); let suffix = args.suffix.map(String::from); - - state.check_write(dir.clone().unwrap_or_else(temp_dir).as_path())?; - + { + let cli_state = super::cli_state2(&state); + cli_state.check_write(dir.clone().unwrap_or_else(temp_dir).as_path())?; + } tokio::task::spawn_blocking(move || { // TODO(piscisaureus): use byte vector for paths, not a string. // See https://github.com/denoland/deno/issues/627. @@ -1474,7 +1518,7 @@ async fn op_make_temp_dir_async( } fn op_make_temp_file_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -1484,7 +1528,8 @@ fn op_make_temp_file_sync( let prefix = args.prefix.map(String::from); let suffix = args.suffix.map(String::from); - state.check_write(dir.clone().unwrap_or_else(temp_dir).as_path())?; + let cli_state = super::cli_state(state); + cli_state.check_write(dir.clone().unwrap_or_else(temp_dir).as_path())?; // TODO(piscisaureus): use byte vector for paths, not a string. // See https://github.com/denoland/deno/issues/627. @@ -1502,7 +1547,7 @@ fn op_make_temp_file_sync( } async fn op_make_temp_file_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { @@ -1511,9 +1556,11 @@ async fn op_make_temp_file_async( let dir = args.dir.map(|s| PathBuf::from(&s)); let prefix = args.prefix.map(String::from); let suffix = args.suffix.map(String::from); - - state.check_write(dir.clone().unwrap_or_else(temp_dir).as_path())?; - + { + let state = state.borrow(); + let cli_state = super::cli_state(&state); + cli_state.check_write(dir.clone().unwrap_or_else(temp_dir).as_path())?; + } tokio::task::spawn_blocking(move || { // TODO(piscisaureus): use byte vector for paths, not a string. // See https://github.com/denoland/deno/issues/627. @@ -1542,11 +1589,14 @@ struct FutimeArgs { } fn op_futime_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.check_unstable("Deno.futimeSync"); + { + let cli_state = super::cli_state(state); + cli_state.check_unstable("Deno.futimeSync"); + } let args: FutimeArgs = serde_json::from_value(args)?; let rid = args.rid as u32; let atime = filetime::FileTime::from_unix_time(args.atime.0, args.atime.1); @@ -1566,17 +1616,19 @@ fn op_futime_sync( } async fn op_futime_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { - state.check_unstable("Deno.futime"); + let mut state = state.borrow_mut(); + let cli_state = super::cli_state(&state); + cli_state.check_unstable("Deno.futime"); let args: FutimeArgs = serde_json::from_value(args)?; let rid = args.rid as u32; 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(&state, rid, |r| match r { + // TODO Not actually async! https://github.com/denoland/deno/issues/7400 + std_file_resource(&mut state, rid, |r| match r { Ok(std_file) => { filetime::set_file_handle_times(std_file, Some(atime), Some(mtime)) .map_err(ErrBox::from) @@ -1598,35 +1650,38 @@ struct UtimeArgs { } fn op_utime_sync( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.check_unstable("Deno.utime"); + let cli_state = super::cli_state(state); + cli_state.check_unstable("Deno.utime"); let args: UtimeArgs = serde_json::from_value(args)?; let path = PathBuf::from(&args.path); 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); - state.check_write(&path)?; + cli_state.check_write(&path)?; filetime::set_file_times(path, atime, mtime)?; Ok(json!({})) } async fn op_utime_async( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { - state.check_unstable("Deno.utime"); + let state = state.borrow(); + let cli_state = super::cli_state(&state); + cli_state.check_unstable("Deno.utime"); let args: UtimeArgs = serde_json::from_value(args)?; let path = PathBuf::from(&args.path); 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); - state.check_write(&path)?; + cli_state.check_write(&path)?; tokio::task::spawn_blocking(move || { filetime::set_file_times(path, atime, mtime)?; @@ -1637,12 +1692,13 @@ async fn op_utime_async( } fn op_cwd( - state: &State, + state: &mut OpState, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let path = current_dir()?; - state.check_read_blind(&path, "CWD")?; + let cli_state = super::cli_state(state); + cli_state.check_read_blind(&path, "CWD")?; let path_str = into_string(path.into_os_string())?; Ok(json!(path_str)) } diff --git a/cli/ops/fs_events.rs b/cli/ops/fs_events.rs index 142aa3ccfc..3468169b0f 100644 --- a/cli/ops/fs_events.rs +++ b/cli/ops/fs_events.rs @@ -1,9 +1,8 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use crate::state::State; use deno_core::BufVec; use deno_core::ErrBox; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::ZeroCopyBuf; use futures::future::poll_fn; use notify::event::Event as NotifyEvent; @@ -15,14 +14,15 @@ use notify::Watcher; use serde::Serialize; use serde_derive::Deserialize; use serde_json::Value; +use std::cell::RefCell; use std::convert::From; use std::path::PathBuf; use std::rc::Rc; use tokio::sync::mpsc; -pub fn init(s: &Rc) { - s.register_op_json_sync("op_fs_events_open", op_fs_events_open); - s.register_op_json_async("op_fs_events_poll", op_fs_events_poll); +pub fn init(rt: &mut deno_core::JsRuntime) { + super::reg_json_sync(rt, "op_fs_events_open", op_fs_events_open); + super::reg_json_async(rt, "op_fs_events_poll", op_fs_events_poll); } struct FsEventsResource { @@ -64,7 +64,7 @@ impl From for FsEvent { } fn op_fs_events_open( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -90,19 +90,16 @@ fn op_fs_events_open( RecursiveMode::NonRecursive }; for path in &args.paths { - state.check_read(&PathBuf::from(path))?; + super::cli_state(state).check_read(&PathBuf::from(path))?; watcher.watch(path, recursive_mode)?; } let resource = FsEventsResource { watcher, receiver }; - let rid = state - .resource_table - .borrow_mut() - .add("fsEvents", Box::new(resource)); + let rid = state.resource_table.add("fsEvents", Box::new(resource)); Ok(json!(rid)) } async fn op_fs_events_poll( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { @@ -112,8 +109,9 @@ async fn op_fs_events_poll( } let PollArgs { rid } = serde_json::from_value(args)?; poll_fn(move |cx| { - let mut resource_table = state.resource_table.borrow_mut(); - let watcher = resource_table + let mut state = state.borrow_mut(); + let watcher = state + .resource_table .get_mut::(rid) .ok_or_else(ErrBox::bad_resource_id)?; watcher diff --git a/cli/ops/idna.rs b/cli/ops/idna.rs index 8e83a03ba8..7a83f169d5 100644 --- a/cli/ops/idna.rs +++ b/cli/ops/idna.rs @@ -2,18 +2,15 @@ //! https://url.spec.whatwg.org/#idna -use crate::state::State; use deno_core::ErrBox; -use deno_core::OpRegistry; use deno_core::ZeroCopyBuf; use idna::domain_to_ascii; use idna::domain_to_ascii_strict; use serde_derive::Deserialize; use serde_json::Value; -use std::rc::Rc; -pub fn init(s: &Rc) { - s.register_op_json_sync("op_domain_to_ascii", op_domain_to_ascii); +pub fn init(rt: &mut deno_core::JsRuntime) { + super::reg_json_sync(rt, "op_domain_to_ascii", op_domain_to_ascii); } #[derive(Deserialize)] @@ -24,7 +21,7 @@ struct DomainToAscii { } fn op_domain_to_ascii( - _state: &State, + _state: &mut deno_core::OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { diff --git a/cli/ops/io.rs b/cli/ops/io.rs index 4a8f6d96dd..be59ac8634 100644 --- a/cli/ops/io.rs +++ b/cli/ops/io.rs @@ -1,11 +1,15 @@ +use super::dispatch_minimal::minimal_op; use super::dispatch_minimal::MinimalOp; use crate::http_util::HttpBody; -use crate::state::State; +use crate::metrics::metrics_op; use deno_core::BufVec; use deno_core::ErrBox; +use deno_core::JsRuntime; +use deno_core::OpState; use futures::future::poll_fn; use futures::future::FutureExt; use futures::ready; +use std::cell::RefCell; use std::collections::HashMap; use std::pin::Pin; use std::rc::Rc; @@ -82,9 +86,9 @@ lazy_static! { }; } -pub fn init(s: &Rc) { - s.register_op_minimal("op_read", op_read); - s.register_op_minimal("op_write", op_write); +pub fn init(rt: &mut JsRuntime) { + rt.register_op("op_read", metrics_op(minimal_op(op_read))); + rt.register_op("op_write", metrics_op(minimal_op(op_write))); } pub fn get_stdio() -> ( @@ -233,7 +237,7 @@ impl DenoAsyncRead for StreamResource { } pub fn op_read( - state: Rc, + state: Rc>, is_sync: bool, rid: i32, mut zero_copy: BufVec, @@ -248,7 +252,7 @@ pub fn op_read( if is_sync { MinimalOp::Sync({ // First we look up the rid in the resource table. - std_file_resource(&state, rid as u32, move |r| match r { + std_file_resource(&mut state.borrow_mut(), rid as u32, move |r| match r { Ok(std_file) => { use std::io::Read; std_file @@ -265,8 +269,9 @@ pub fn op_read( let mut zero_copy = zero_copy[0].clone(); MinimalOp::Async( poll_fn(move |cx| { - let mut resource_table = state.resource_table.borrow_mut(); - let resource_holder = resource_table + let mut state = state.borrow_mut(); + let resource_holder = state + .resource_table .get_mut::(rid as u32) .ok_or_else(ErrBox::bad_resource_id)?; @@ -352,7 +357,7 @@ impl DenoAsyncWrite for StreamResource { } pub fn op_write( - state: Rc, + state: Rc>, is_sync: bool, rid: i32, zero_copy: BufVec, @@ -367,7 +372,7 @@ pub fn op_write( if is_sync { MinimalOp::Sync({ // First we look up the rid in the resource table. - std_file_resource(&state, rid as u32, move |r| match r { + std_file_resource(&mut state.borrow_mut(), rid as u32, move |r| match r { Ok(std_file) => { use std::io::Write; std_file @@ -385,8 +390,9 @@ pub fn op_write( MinimalOp::Async( async move { let nwritten = poll_fn(|cx| { - let mut resource_table = state.resource_table.borrow_mut(); - let resource_holder = resource_table + let mut state = state.borrow_mut(); + let resource_holder = state + .resource_table .get_mut::(rid as u32) .ok_or_else(ErrBox::bad_resource_id)?; resource_holder.resource.poll_write(cx, &zero_copy) @@ -398,8 +404,9 @@ pub fn op_write( // Figure out why it's needed and preferably remove it. // https://github.com/denoland/deno/issues/3565 poll_fn(|cx| { - let mut resource_table = state.resource_table.borrow_mut(); - let resource_holder = resource_table + let mut state = state.borrow_mut(); + let resource_holder = state + .resource_table .get_mut::(rid as u32) .ok_or_else(ErrBox::bad_resource_id)?; resource_holder.resource.poll_flush(cx) @@ -421,7 +428,7 @@ pub fn op_write( /// /// Returns ErrorKind::Busy if the resource is being used by another op. pub fn std_file_resource( - state: &State, + state: &mut OpState, rid: u32, mut f: F, ) -> Result @@ -430,8 +437,7 @@ where FnMut(Result<&mut std::fs::File, &mut StreamResource>) -> Result, { // 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::(rid); + let mut r = state.resource_table.get_mut::(rid); if let Some(ref mut resource_holder) = r { // Sync write only works for FsFile. It doesn't make sense to do this // for non-blocking sockets. So we error out if not FsFile. diff --git a/cli/ops/mod.rs b/cli/ops/mod.rs index 06a55bade9..3858400a30 100644 --- a/cli/ops/mod.rs +++ b/cli/ops/mod.rs @@ -29,3 +29,43 @@ pub mod tty; pub mod web_worker; pub mod websocket; pub mod worker_host; + +use crate::metrics::metrics_op; +use deno_core::json_op_async; +use deno_core::json_op_sync; +use deno_core::BufVec; +use deno_core::ErrBox; +use deno_core::JsRuntime; +use deno_core::OpState; +use deno_core::ZeroCopyBuf; +use serde_json::Value; +use std::cell::RefCell; +use std::future::Future; +use std::rc::Rc; + +pub fn reg_json_async(rt: &mut JsRuntime, name: &'static str, op_fn: F) +where + F: Fn(Rc>, Value, BufVec) -> R + 'static, + R: Future> + 'static, +{ + rt.register_op(name, metrics_op(json_op_async(op_fn))); +} + +pub fn reg_json_sync(rt: &mut JsRuntime, name: &'static str, op_fn: F) +where + F: Fn(&mut OpState, Value, &mut [ZeroCopyBuf]) -> Result + + 'static, +{ + rt.register_op(name, metrics_op(json_op_sync(op_fn))); +} + +/// Helper for extracting the commonly used state. Used for sync ops. +pub fn cli_state(state: &OpState) -> Rc { + state.borrow::>().clone() +} + +/// Helper for extracting the commonly used state. Used for async ops. +pub fn cli_state2(state: &Rc>) -> Rc { + let state = state.borrow(); + state.borrow::>().clone() +} diff --git a/cli/ops/net.rs b/cli/ops/net.rs index 91a9079d40..67a2014609 100644 --- a/cli/ops/net.rs +++ b/cli/ops/net.rs @@ -2,14 +2,14 @@ use crate::ops::io::{StreamResource, StreamResourceHolder}; use crate::resolve_addr::resolve_addr; -use crate::state::State; use deno_core::BufVec; use deno_core::ErrBox; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::ZeroCopyBuf; use futures::future::poll_fn; use serde_derive::Deserialize; use serde_json::Value; +use std::cell::RefCell; use std::net::Shutdown; use std::net::SocketAddr; use std::rc::Rc; @@ -22,13 +22,13 @@ use tokio::net::UdpSocket; #[cfg(unix)] use super::net_unix; -pub fn init(s: &Rc) { - s.register_op_json_async("op_accept", op_accept); - s.register_op_json_async("op_connect", op_connect); - s.register_op_json_sync("op_shutdown", op_shutdown); - s.register_op_json_sync("op_listen", op_listen); - s.register_op_json_async("op_datagram_receive", op_datagram_receive); - s.register_op_json_async("op_datagram_send", op_datagram_send); +pub fn init(rt: &mut deno_core::JsRuntime) { + super::reg_json_async(rt, "op_accept", op_accept); + super::reg_json_async(rt, "op_connect", op_connect); + super::reg_json_sync(rt, "op_shutdown", op_shutdown); + super::reg_json_sync(rt, "op_listen", op_listen); + super::reg_json_async(rt, "op_datagram_receive", op_datagram_receive); + super::reg_json_async(rt, "op_datagram_send", op_datagram_send); } #[derive(Deserialize)] @@ -38,15 +38,16 @@ pub(crate) struct AcceptArgs { } async fn accept_tcp( - state: Rc, + state: Rc>, args: AcceptArgs, _zero_copy: BufVec, ) -> Result { let rid = args.rid as u32; let accept_fut = poll_fn(|cx| { - let mut resource_table = state.resource_table.borrow_mut(); - let listener_resource = resource_table + let mut state = state.borrow_mut(); + let listener_resource = state + .resource_table .get_mut::(rid) .ok_or_else(|| ErrBox::bad_resource("Listener has been closed"))?; let listener = &mut listener_resource.listener; @@ -68,7 +69,9 @@ async fn accept_tcp( let (tcp_stream, _socket_addr) = accept_fut.await?; let local_addr = tcp_stream.local_addr()?; let remote_addr = tcp_stream.peer_addr()?; - let rid = state.resource_table.borrow_mut().add( + + let mut state = state.borrow_mut(); + let rid = state.resource_table.add( "tcpStream", Box::new(StreamResourceHolder::new(StreamResource::TcpStream(Some( tcp_stream, @@ -90,7 +93,7 @@ async fn accept_tcp( } async fn op_accept( - state: Rc, + state: Rc>, args: Value, bufs: BufVec, ) -> Result { @@ -113,7 +116,7 @@ pub(crate) struct ReceiveArgs { } async fn receive_udp( - state: Rc, + state: Rc>, args: ReceiveArgs, zero_copy: BufVec, ) -> Result { @@ -123,8 +126,9 @@ async fn receive_udp( let rid = args.rid as u32; let receive_fut = poll_fn(|cx| { - let mut resource_table = state.resource_table.borrow_mut(); - let resource = resource_table + let mut state = state.borrow_mut(); + let resource = state + .resource_table .get_mut::(rid) .ok_or_else(|| ErrBox::bad_resource("Socket has been closed"))?; let socket = &mut resource.socket; @@ -144,7 +148,7 @@ async fn receive_udp( } async fn op_datagram_receive( - state: Rc, + state: Rc>, args: Value, zero_copy: BufVec, ) -> Result { @@ -171,12 +175,13 @@ struct SendArgs { } async fn op_datagram_send( - state: Rc, + state: Rc>, args: Value, zero_copy: BufVec, ) -> Result { assert_eq!(zero_copy.len(), 1, "Invalid number of arguments"); let zero_copy = zero_copy[0].clone(); + let cli_state = super::cli_state2(&state); match serde_json::from_value(args)? { SendArgs { @@ -184,11 +189,12 @@ async fn op_datagram_send( transport, transport_args: ArgsEnum::Ip(args), } if transport == "udp" => { - state.check_net(&args.hostname, args.port)?; + cli_state.check_net(&args.hostname, args.port)?; let addr = resolve_addr(&args.hostname, args.port)?; poll_fn(move |cx| { - let mut resource_table = state.resource_table.borrow_mut(); - let resource = resource_table + let mut state = state.borrow_mut(); + let resource = state + .resource_table .get_mut::(rid as u32) .ok_or_else(|| ErrBox::bad_resource("Socket has been closed"))?; resource @@ -206,9 +212,10 @@ async fn op_datagram_send( transport_args: ArgsEnum::Unix(args), } if transport == "unixpacket" => { let address_path = net_unix::Path::new(&args.path); - state.check_read(&address_path)?; - let mut resource_table = state.resource_table.borrow_mut(); - let resource = resource_table + cli_state.check_read(&address_path)?; + let mut state = state.borrow_mut(); + let resource = state + .resource_table .get_mut::(rid as u32) .ok_or_else(|| ErrBox::new("NotConnected", "Socket has been closed"))?; let socket = &mut resource.socket; @@ -230,21 +237,24 @@ struct ConnectArgs { } async fn op_connect( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { + let cli_state = super::cli_state2(&state); match serde_json::from_value(args)? { ConnectArgs { transport, transport_args: ArgsEnum::Ip(args), } if transport == "tcp" => { - state.check_net(&args.hostname, args.port)?; + cli_state.check_net(&args.hostname, args.port)?; let addr = resolve_addr(&args.hostname, args.port)?; let tcp_stream = TcpStream::connect(&addr).await?; let local_addr = tcp_stream.local_addr()?; let remote_addr = tcp_stream.peer_addr()?; - let rid = state.resource_table.borrow_mut().add( + + let mut state_ = state.borrow_mut(); + let rid = state_.resource_table.add( "tcpStream", Box::new(StreamResourceHolder::new(StreamResource::TcpStream(Some( tcp_stream, @@ -270,14 +280,16 @@ async fn op_connect( transport_args: ArgsEnum::Unix(args), } if transport == "unix" => { let address_path = net_unix::Path::new(&args.path); - state.check_unstable("Deno.connect"); - state.check_read(&address_path)?; + cli_state.check_unstable("Deno.connect"); + cli_state.check_read(&address_path)?; let path = args.path; let unix_stream = net_unix::UnixStream::connect(net_unix::Path::new(&path)).await?; let local_addr = unix_stream.local_addr()?; let remote_addr = unix_stream.peer_addr()?; - let rid = state.resource_table.borrow_mut().add( + + let mut state_ = state.borrow_mut(); + let rid = state_.resource_table.add( "unixStream", Box::new(StreamResourceHolder::new(StreamResource::UnixStream( unix_stream, @@ -306,11 +318,11 @@ struct ShutdownArgs { } fn op_shutdown( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.check_unstable("Deno.shutdown"); + super::cli_state(state).check_unstable("Deno.shutdown"); let args: ShutdownArgs = serde_json::from_value(args)?; @@ -323,8 +335,8 @@ fn op_shutdown( _ => unimplemented!(), }; - let mut resource_table = state.resource_table.borrow_mut(); - let resource_holder = resource_table + let resource_holder = state + .resource_table .get_mut::(rid) .ok_or_else(ErrBox::bad_resource_id)?; match resource_holder.resource { @@ -416,7 +428,7 @@ struct ListenArgs { } fn listen_tcp( - state: &State, + state: &mut OpState, addr: SocketAddr, ) -> Result<(u32, SocketAddr), ErrBox> { let std_listener = std::net::TcpListener::bind(&addr)?; @@ -429,14 +441,13 @@ fn listen_tcp( }; let rid = state .resource_table - .borrow_mut() .add("tcpListener", Box::new(listener_resource)); Ok((rid, local_addr)) } fn listen_udp( - state: &State, + state: &mut OpState, addr: SocketAddr, ) -> Result<(u32, SocketAddr), ErrBox> { let std_socket = std::net::UdpSocket::bind(&addr)?; @@ -445,26 +456,28 @@ fn listen_udp( let socket_resource = UdpSocketResource { socket }; let rid = state .resource_table - .borrow_mut() .add("udpSocket", Box::new(socket_resource)); Ok((rid, local_addr)) } fn op_listen( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { + let cli_state = super::cli_state(state); match serde_json::from_value(args)? { ListenArgs { transport, transport_args: ArgsEnum::Ip(args), } => { - if transport == "udp" { - state.check_unstable("Deno.listenDatagram"); + { + if transport == "udp" { + cli_state.check_unstable("Deno.listenDatagram"); + } + cli_state.check_net(&args.hostname, args.port)?; } - state.check_net(&args.hostname, args.port)?; let addr = resolve_addr(&args.hostname, args.port)?; let (rid, local_addr) = if transport == "tcp" { listen_tcp(state, addr)? @@ -491,15 +504,17 @@ fn op_listen( transport, transport_args: ArgsEnum::Unix(args), } if transport == "unix" || transport == "unixpacket" => { - if transport == "unix" { - state.check_unstable("Deno.listen"); - } - if transport == "unixpacket" { - state.check_unstable("Deno.listenDatagram"); - } let address_path = net_unix::Path::new(&args.path); - state.check_read(&address_path)?; - state.check_write(&address_path)?; + { + if transport == "unix" { + cli_state.check_unstable("Deno.listen"); + } + if transport == "unixpacket" { + cli_state.check_unstable("Deno.listenDatagram"); + } + cli_state.check_read(&address_path)?; + cli_state.check_write(&address_path)?; + } let (rid, local_addr) = if transport == "unix" { net_unix::listen_unix(state, &address_path)? } else { diff --git a/cli/ops/net_unix.rs b/cli/ops/net_unix.rs index a73db89b29..5cdb451dc7 100644 --- a/cli/ops/net_unix.rs +++ b/cli/ops/net_unix.rs @@ -2,15 +2,18 @@ use crate::ops::io::StreamResource; use crate::ops::io::StreamResourceHolder; use crate::ops::net::AcceptArgs; use crate::ops::net::ReceiveArgs; -use crate::state::State; use deno_core::BufVec; use deno_core::ErrBox; +use deno_core::OpState; +use futures::future::poll_fn; use serde_derive::Deserialize; use serde_json::Value; +use std::cell::RefCell; use std::fs::remove_file; use std::os::unix; pub use std::path::Path; use std::rc::Rc; +use std::task::Poll; use tokio::net::UnixDatagram; use tokio::net::UnixListener; pub use tokio::net::UnixStream; @@ -30,25 +33,39 @@ pub struct UnixListenArgs { } pub(crate) async fn accept_unix( - state: Rc, + state: Rc>, args: AcceptArgs, _bufs: BufVec, ) -> Result { let rid = args.rid as u32; - let mut resource_table_ = state.resource_table.borrow_mut(); - let listener_resource = { - resource_table_ + let accept_fut = poll_fn(|cx| { + let mut state = state.borrow_mut(); + let listener_resource = state + .resource_table .get_mut::(rid) - .ok_or_else(|| ErrBox::bad_resource("Listener has been closed"))? - }; - let (unix_stream, _socket_addr) = listener_resource.listener.accept().await?; - drop(resource_table_); + .ok_or_else(|| ErrBox::bad_resource("Listener has been closed"))?; + let listener = &mut listener_resource.listener; + use futures::StreamExt; + match listener.poll_next_unpin(cx) { + Poll::Ready(Some(stream)) => { + //listener_resource.untrack_task(); + Poll::Ready(stream) + } + Poll::Ready(None) => todo!(), + Poll::Pending => { + //listener_resource.track_task(cx)?; + Poll::Pending + } + } + .map_err(ErrBox::from) + }); + let unix_stream = accept_fut.await?; let local_addr = unix_stream.local_addr()?; let remote_addr = unix_stream.peer_addr()?; - let mut resource_table_ = state.resource_table.borrow_mut(); - let rid = resource_table_.add( + let mut state = state.borrow_mut(); + let rid = state.resource_table.add( "unixStream", Box::new(StreamResourceHolder::new(StreamResource::UnixStream( unix_stream, @@ -68,7 +85,7 @@ pub(crate) async fn accept_unix( } pub(crate) async fn receive_unix_packet( - state: Rc, + state: Rc>, args: ReceiveArgs, bufs: BufVec, ) -> Result { @@ -77,8 +94,9 @@ pub(crate) async fn receive_unix_packet( let rid = args.rid as u32; let mut buf = bufs.into_iter().next().unwrap(); - let mut resource_table_ = state.resource_table.borrow_mut(); - let resource = resource_table_ + let mut state = state.borrow_mut(); + let resource = state + .resource_table .get_mut::(rid) .ok_or_else(|| ErrBox::bad_resource("Socket has been closed"))?; let (size, remote_addr) = resource.socket.recv_from(&mut buf).await?; @@ -92,7 +110,7 @@ pub(crate) async fn receive_unix_packet( } pub fn listen_unix( - state: &State, + state: &mut OpState, addr: &Path, ) -> Result<(u32, unix::net::SocketAddr), ErrBox> { if addr.exists() { @@ -103,14 +121,13 @@ pub fn listen_unix( let listener_resource = UnixListenerResource { listener }; let rid = state .resource_table - .borrow_mut() .add("unixListener", Box::new(listener_resource)); Ok((rid, local_addr)) } pub fn listen_unix_packet( - state: &State, + state: &mut OpState, addr: &Path, ) -> Result<(u32, unix::net::SocketAddr), ErrBox> { if addr.exists() { @@ -124,7 +141,6 @@ pub fn listen_unix_packet( }; let rid = state .resource_table - .borrow_mut() .add("unixDatagram", Box::new(datagram_resource)); Ok((rid, local_addr)) diff --git a/cli/ops/os.rs b/cli/ops/os.rs index a38b5b08a9..9860018a0b 100644 --- a/cli/ops/os.rs +++ b/cli/ops/os.rs @@ -1,36 +1,35 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use crate::state::State; use deno_core::ErrBox; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::ZeroCopyBuf; use serde_derive::Deserialize; use serde_json::Value; use std::collections::HashMap; use std::env; -use std::rc::Rc; use url::Url; -pub fn init(s: &Rc) { - s.register_op_json_sync("op_exit", op_exit); - s.register_op_json_sync("op_env", op_env); - s.register_op_json_sync("op_exec_path", op_exec_path); - s.register_op_json_sync("op_set_env", op_set_env); - s.register_op_json_sync("op_get_env", op_get_env); - s.register_op_json_sync("op_delete_env", op_delete_env); - s.register_op_json_sync("op_hostname", op_hostname); - s.register_op_json_sync("op_loadavg", op_loadavg); - s.register_op_json_sync("op_os_release", op_os_release); - s.register_op_json_sync("op_system_memory_info", op_system_memory_info); +pub fn init(rt: &mut deno_core::JsRuntime) { + super::reg_json_sync(rt, "op_exit", op_exit); + super::reg_json_sync(rt, "op_env", op_env); + super::reg_json_sync(rt, "op_exec_path", op_exec_path); + super::reg_json_sync(rt, "op_set_env", op_set_env); + super::reg_json_sync(rt, "op_get_env", op_get_env); + super::reg_json_sync(rt, "op_delete_env", op_delete_env); + super::reg_json_sync(rt, "op_hostname", op_hostname); + super::reg_json_sync(rt, "op_loadavg", op_loadavg); + super::reg_json_sync(rt, "op_os_release", op_os_release); + super::reg_json_sync(rt, "op_system_memory_info", op_system_memory_info); } fn op_exec_path( - state: &State, + state: &mut OpState, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let current_exe = env::current_exe().unwrap(); - state.check_read_blind(¤t_exe, "exec_path")?; + let cli_state = super::cli_state(state); + cli_state.check_read_blind(¤t_exe, "exec_path")?; // Now apply URL parser to current exe to get fully resolved path, otherwise // we might get `./` and `../` bits in `exec_path` let exe_url = Url::from_file_path(current_exe).unwrap(); @@ -45,22 +44,24 @@ struct SetEnv { } fn op_set_env( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let args: SetEnv = serde_json::from_value(args)?; - state.check_env()?; + let cli_state = super::cli_state(state); + cli_state.check_env()?; env::set_var(args.key, args.value); Ok(json!({})) } fn op_env( - state: &State, + state: &mut OpState, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.check_env()?; + let cli_state = super::cli_state(state); + cli_state.check_env()?; let v = env::vars().collect::>(); Ok(json!(v)) } @@ -71,12 +72,13 @@ struct GetEnv { } fn op_get_env( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let args: GetEnv = serde_json::from_value(args)?; - state.check_env()?; + let cli_state = super::cli_state(state); + cli_state.check_env()?; let r = match env::var(args.key) { Err(env::VarError::NotPresent) => json!([]), v => json!([v?]), @@ -90,12 +92,13 @@ struct DeleteEnv { } fn op_delete_env( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let args: DeleteEnv = serde_json::from_value(args)?; - state.check_env()?; + let cli_state = super::cli_state(state); + cli_state.check_env()?; env::remove_var(args.key); Ok(json!({})) } @@ -106,7 +109,7 @@ struct Exit { } fn op_exit( - _state: &State, + _state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -115,12 +118,13 @@ fn op_exit( } fn op_loadavg( - state: &State, + state: &mut OpState, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.check_unstable("Deno.loadavg"); - state.check_env()?; + let cli_state = super::cli_state(state); + cli_state.check_unstable("Deno.loadavg"); + cli_state.check_env()?; match sys_info::loadavg() { Ok(loadavg) => Ok(json!([loadavg.one, loadavg.five, loadavg.fifteen])), Err(_) => Ok(json!([0f64, 0f64, 0f64])), @@ -128,34 +132,37 @@ fn op_loadavg( } fn op_hostname( - state: &State, + state: &mut OpState, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.check_unstable("Deno.hostname"); - state.check_env()?; + let cli_state = super::cli_state(state); + cli_state.check_unstable("Deno.hostname"); + cli_state.check_env()?; let hostname = sys_info::hostname().unwrap_or_else(|_| "".to_string()); Ok(json!(hostname)) } fn op_os_release( - state: &State, + state: &mut OpState, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.check_unstable("Deno.osRelease"); - state.check_env()?; + let cli_state = super::cli_state(state); + cli_state.check_unstable("Deno.osRelease"); + cli_state.check_env()?; let release = sys_info::os_release().unwrap_or_else(|_| "".to_string()); Ok(json!(release)) } fn op_system_memory_info( - state: &State, + state: &mut OpState, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.check_unstable("Deno.systemMemoryInfo"); - state.check_env()?; + let cli_state = super::cli_state(state); + cli_state.check_unstable("Deno.systemMemoryInfo"); + cli_state.check_env()?; match sys_info::mem_info() { Ok(info) => Ok(json!({ "total": info.total, diff --git a/cli/ops/permissions.rs b/cli/ops/permissions.rs index 90d21a726b..76d105ba73 100644 --- a/cli/ops/permissions.rs +++ b/cli/ops/permissions.rs @@ -1,18 +1,16 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use crate::state::State; use deno_core::ErrBox; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::ZeroCopyBuf; use serde_derive::Deserialize; use serde_json::Value; use std::path::Path; -use std::rc::Rc; -pub fn init(s: &Rc) { - s.register_op_json_sync("op_query_permission", op_query_permission); - s.register_op_json_sync("op_revoke_permission", op_revoke_permission); - s.register_op_json_sync("op_request_permission", op_request_permission); +pub fn init(rt: &mut deno_core::JsRuntime) { + super::reg_json_sync(rt, "op_query_permission", op_query_permission); + super::reg_json_sync(rt, "op_revoke_permission", op_revoke_permission); + super::reg_json_sync(rt, "op_request_permission", op_request_permission); } #[derive(Deserialize)] @@ -23,12 +21,13 @@ struct PermissionArgs { } pub fn op_query_permission( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let args: PermissionArgs = serde_json::from_value(args)?; - let permissions = state.permissions.borrow(); + let cli_state = super::cli_state(state); + let permissions = cli_state.permissions.borrow(); let path = args.path.as_deref(); let perm = match args.name.as_ref() { "read" => permissions.query_read(&path.as_deref().map(Path::new)), @@ -49,12 +48,13 @@ pub fn op_query_permission( } pub fn op_revoke_permission( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let args: PermissionArgs = serde_json::from_value(args)?; - let mut permissions = state.permissions.borrow_mut(); + let cli_state = super::cli_state(state); + let mut permissions = cli_state.permissions.borrow_mut(); let path = args.path.as_deref(); let perm = match args.name.as_ref() { "read" => permissions.revoke_read(&path.as_deref().map(Path::new)), @@ -75,12 +75,13 @@ pub fn op_revoke_permission( } pub fn op_request_permission( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let args: PermissionArgs = serde_json::from_value(args)?; - let permissions = &mut state.permissions.borrow_mut(); + let cli_state = super::cli_state(state); + let permissions = &mut cli_state.permissions.borrow_mut(); let path = args.path.as_deref(); let perm = match args.name.as_ref() { "read" => permissions.request_read(&path.as_deref().map(Path::new)), diff --git a/cli/ops/plugin.rs b/cli/ops/plugin.rs index 9cab05011b..fc3d5201db 100644 --- a/cli/ops/plugin.rs +++ b/cli/ops/plugin.rs @@ -1,26 +1,28 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use crate::state::State; +use crate::metrics::metrics_op; use deno_core::plugin_api; use deno_core::BufVec; use deno_core::ErrBox; +use deno_core::JsRuntime; use deno_core::Op; use deno_core::OpAsyncFuture; use deno_core::OpId; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::ZeroCopyBuf; use dlopen::symbor::Library; use futures::prelude::*; use serde_derive::Deserialize; use serde_json::Value; +use std::cell::RefCell; use std::path::PathBuf; use std::pin::Pin; use std::rc::Rc; use std::task::Context; use std::task::Poll; -pub fn init(s: &Rc) { - s.register_op_json_sync("op_open_plugin", op_open_plugin); +pub fn init(rt: &mut JsRuntime) { + super::reg_json_sync(rt, "op_open_plugin", op_open_plugin); } #[derive(Deserialize)] @@ -30,16 +32,16 @@ struct OpenPluginArgs { } pub fn op_open_plugin( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.check_unstable("Deno.openPlugin"); - - let args: OpenPluginArgs = serde_json::from_value(args).unwrap(); + let args: OpenPluginArgs = serde_json::from_value(args)?; let filename = PathBuf::from(&args.filename); - state.check_plugin(&filename)?; + let cli_state = super::cli_state(state); + cli_state.check_unstable("Deno.openPlugin"); + cli_state.check_plugin(&filename)?; debug!("Loading Plugin: {:#?}", filename); let plugin_lib = Library::open(filename).map(Rc::new)?; @@ -48,10 +50,12 @@ pub fn op_open_plugin( let rid; let deno_plugin_init; { - let mut resource_table = state.resource_table.borrow_mut(); - rid = resource_table.add("plugin", Box::new(plugin_resource)); + rid = state + .resource_table + .add("plugin", Box::new(plugin_resource)); deno_plugin_init = *unsafe { - resource_table + state + .resource_table .get::(rid) .unwrap() .lib @@ -77,12 +81,12 @@ impl PluginResource { } struct PluginInterface<'a> { - state: &'a State, + state: &'a mut OpState, plugin_lib: &'a Rc, } impl<'a> PluginInterface<'a> { - fn new(state: &'a State, plugin_lib: &'a Rc) -> Self { + fn new(state: &'a mut OpState, plugin_lib: &'a Rc) -> Self { Self { state, plugin_lib } } } @@ -99,23 +103,24 @@ impl<'a> plugin_api::Interface for PluginInterface<'a> { dispatch_op_fn: plugin_api::DispatchOpFn, ) -> OpId { let plugin_lib = self.plugin_lib.clone(); - self.state.register_op( - name, - move |state: Rc, mut zero_copy: BufVec| { - let mut interface = PluginInterface::new(&state, &plugin_lib); - let op = dispatch_op_fn(&mut interface, &mut zero_copy); - match op { - sync_op @ Op::Sync(..) => sync_op, - Op::Async(fut) => { - Op::Async(PluginOpAsyncFuture::new(&plugin_lib, fut)) - } - Op::AsyncUnref(fut) => { - Op::AsyncUnref(PluginOpAsyncFuture::new(&plugin_lib, fut)) - } - _ => unreachable!(), + let plugin_op_fn = move |state_rc: Rc>, + mut zero_copy: BufVec| { + let mut state = state_rc.borrow_mut(); + let mut interface = PluginInterface::new(&mut state, &plugin_lib); + let op = dispatch_op_fn(&mut interface, &mut zero_copy); + match op { + sync_op @ Op::Sync(..) => sync_op, + Op::Async(fut) => Op::Async(PluginOpAsyncFuture::new(&plugin_lib, fut)), + Op::AsyncUnref(fut) => { + Op::AsyncUnref(PluginOpAsyncFuture::new(&plugin_lib, fut)) } - }, - ) + _ => unreachable!(), + } + }; + self + .state + .op_table + .register_op(name, metrics_op(Box::new(plugin_op_fn))) } } diff --git a/cli/ops/process.rs b/cli/ops/process.rs index fb8675db93..6a7e05ebf4 100644 --- a/cli/ops/process.rs +++ b/cli/ops/process.rs @@ -2,28 +2,28 @@ use super::io::{std_file_resource, StreamResource, StreamResourceHolder}; use crate::signal::kill; -use crate::state::State; use deno_core::BufVec; use deno_core::ErrBox; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::ZeroCopyBuf; use futures::future::poll_fn; use futures::future::FutureExt; use serde_derive::Deserialize; use serde_json::Value; +use std::cell::RefCell; use std::rc::Rc; use tokio::process::Command; #[cfg(unix)] use std::os::unix::process::ExitStatusExt; -pub fn init(s: &Rc) { - s.register_op_json_sync("op_run", op_run); - s.register_op_json_async("op_run_status", op_run_status); - s.register_op_json_sync("op_kill", op_kill); +pub fn init(rt: &mut deno_core::JsRuntime) { + super::reg_json_sync(rt, "op_run", op_run); + super::reg_json_async(rt, "op_run_status", op_run_status); + super::reg_json_sync(rt, "op_kill", op_kill); } -fn clone_file(state: &State, rid: u32) -> Result { +fn clone_file(state: &mut OpState, rid: u32) -> Result { std_file_resource(state, rid, move |r| match r { Ok(std_file) => std_file.try_clone().map_err(ErrBox::from), Err(_) => Err(ErrBox::bad_resource_id()), @@ -58,13 +58,12 @@ struct ChildResource { } fn op_run( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let run_args: RunArgs = serde_json::from_value(args)?; - - state.check_run()?; + super::cli_state(state).check_run()?; let args = run_args.cmd; let env = run_args.env; @@ -111,7 +110,7 @@ fn op_run( let stdin_rid = match child.stdin.take() { Some(child_stdin) => { - let rid = state.resource_table.borrow_mut().add( + let rid = state.resource_table.add( "childStdin", Box::new(StreamResourceHolder::new(StreamResource::ChildStdin( child_stdin, @@ -124,7 +123,7 @@ fn op_run( let stdout_rid = match child.stdout.take() { Some(child_stdout) => { - let rid = state.resource_table.borrow_mut().add( + let rid = state.resource_table.add( "childStdout", Box::new(StreamResourceHolder::new(StreamResource::ChildStdout( child_stdout, @@ -137,7 +136,7 @@ fn op_run( let stderr_rid = match child.stderr.take() { Some(child_stderr) => { - let rid = state.resource_table.borrow_mut().add( + let rid = state.resource_table.add( "childStderr", Box::new(StreamResourceHolder::new(StreamResource::ChildStderr( child_stderr, @@ -149,10 +148,7 @@ fn op_run( }; let child_resource = ChildResource { child }; - let child_rid = state - .resource_table - .borrow_mut() - .add("child", Box::new(child_resource)); + let child_rid = state.resource_table.add("child", Box::new(child_resource)); Ok(json!({ "rid": child_rid, @@ -170,18 +166,19 @@ struct RunStatusArgs { } async fn op_run_status( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { let args: RunStatusArgs = serde_json::from_value(args)?; let rid = args.rid as u32; - state.check_run()?; + super::cli_state2(&state).check_run()?; let run_status = poll_fn(|cx| { - let mut resource_table = state.resource_table.borrow_mut(); - let child_resource = resource_table + let mut state = state.borrow_mut(); + let child_resource = state + .resource_table .get_mut::(rid) .ok_or_else(ErrBox::bad_resource_id)?; let child = &mut child_resource.child; @@ -215,12 +212,13 @@ struct KillArgs { } fn op_kill( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.check_unstable("Deno.kill"); - state.check_run()?; + let cli_state = super::cli_state(state); + cli_state.check_unstable("Deno.kill"); + cli_state.check_run()?; let args: KillArgs = serde_json::from_value(args)?; kill(args.pid, args.signo)?; diff --git a/cli/ops/random.rs b/cli/ops/random.rs index 4ce1411b89..1ef0c26456 100644 --- a/cli/ops/random.rs +++ b/cli/ops/random.rs @@ -1,26 +1,24 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use crate::state::State; use deno_core::ErrBox; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::ZeroCopyBuf; use rand::thread_rng; use rand::Rng; use serde_json::Value; -use std::rc::Rc; -pub fn init(s: &Rc) { - s.register_op_json_sync("op_get_random_values", op_get_random_values); +pub fn init(rt: &mut deno_core::JsRuntime) { + super::reg_json_sync(rt, "op_get_random_values", op_get_random_values); } fn op_get_random_values( - state: &State, + state: &mut OpState, _args: Value, zero_copy: &mut [ZeroCopyBuf], ) -> Result { assert_eq!(zero_copy.len(), 1); - - if let Some(seeded_rng) = &state.seeded_rng { + let cli_state = super::cli_state(state); + if let Some(seeded_rng) = &cli_state.seeded_rng { seeded_rng.borrow_mut().fill(&mut *zero_copy[0]); } else { let mut rng = thread_rng(); diff --git a/cli/ops/repl.rs b/cli/ops/repl.rs index 300432832e..e2cfe21cd7 100644 --- a/cli/ops/repl.rs +++ b/cli/ops/repl.rs @@ -2,20 +2,20 @@ use crate::repl; use crate::repl::Repl; -use crate::state::State; use deno_core::BufVec; use deno_core::ErrBox; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::ZeroCopyBuf; use serde_derive::Deserialize; use serde_json::Value; +use std::cell::RefCell; use std::rc::Rc; use std::sync::Arc; use std::sync::Mutex; -pub fn init(s: &Rc) { - s.register_op_json_sync("op_repl_start", op_repl_start); - s.register_op_json_async("op_repl_readline", op_repl_readline); +pub fn init(rt: &mut deno_core::JsRuntime) { + super::reg_json_sync(rt, "op_repl_start", op_repl_start); + super::reg_json_async(rt, "op_repl_readline", op_repl_readline); } struct ReplResource(Arc>); @@ -27,20 +27,19 @@ struct ReplStartArgs { } fn op_repl_start( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let args: ReplStartArgs = serde_json::from_value(args)?; debug!("op_repl_start {}", args.history_file); - let history_path = - repl::history_path(&state.global_state.dir, &args.history_file); + let history_path = { + let cli_state = super::cli_state(state); + repl::history_path(&cli_state.global_state.dir, &args.history_file) + }; let repl = repl::Repl::new(history_path); let resource = ReplResource(Arc::new(Mutex::new(repl))); - let rid = state - .resource_table - .borrow_mut() - .add("repl", Box::new(resource)); + let rid = state.resource_table.add("repl", Box::new(resource)); Ok(json!(rid)) } @@ -51,7 +50,7 @@ struct ReplReadlineArgs { } async fn op_repl_readline( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { @@ -59,12 +58,14 @@ async fn op_repl_readline( let rid = args.rid as u32; let prompt = args.prompt; debug!("op_repl_readline {} {}", rid, prompt); - let resource_table = state.resource_table.borrow(); - let resource = resource_table - .get::(rid) - .ok_or_else(ErrBox::bad_resource_id)?; - let repl = resource.0.clone(); - drop(resource_table); + let repl = { + let state = state.borrow(); + let resource = state + .resource_table + .get::(rid) + .ok_or_else(ErrBox::bad_resource_id)?; + resource.0.clone() + }; tokio::task::spawn_blocking(move || { let line = repl.lock().unwrap().readline(&prompt)?; Ok(json!(line)) diff --git a/cli/ops/resources.rs b/cli/ops/resources.rs index d7c2fd1426..78e35828e6 100644 --- a/cli/ops/resources.rs +++ b/cli/ops/resources.rs @@ -1,31 +1,28 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use crate::state::State; use deno_core::ErrBox; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::ZeroCopyBuf; use serde_derive::Deserialize; use serde_json::Value; -use std::rc::Rc; -pub fn init(s: &Rc) { - s.register_op_json_sync("op_resources", op_resources); - s.register_op_json_sync("op_close", op_close); +pub fn init(rt: &mut deno_core::JsRuntime) { + super::reg_json_sync(rt, "op_resources", op_resources); + super::reg_json_sync(rt, "op_close", op_close); } fn op_resources( - state: &State, + state: &mut OpState, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - let resource_table = state.resource_table.borrow(); - let serialized_resources = resource_table.entries(); + let serialized_resources = state.resource_table.entries(); Ok(json!(serialized_resources)) } /// op_close removes a resource from the resource table. fn op_close( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -36,7 +33,6 @@ fn op_close( let args: CloseArgs = serde_json::from_value(args)?; state .resource_table - .borrow_mut() .close(args.rid as u32) .ok_or_else(ErrBox::bad_resource_id)?; Ok(json!({})) diff --git a/cli/ops/runtime.rs b/cli/ops/runtime.rs index 10aac11fa6..396a6951ce 100644 --- a/cli/ops/runtime.rs +++ b/cli/ops/runtime.rs @@ -1,29 +1,27 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. use crate::colors; -use crate::state::State; use crate::version; use crate::DenoSubcommand; use deno_core::ErrBox; use deno_core::ModuleSpecifier; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::ZeroCopyBuf; use serde_json::Value; use std::env; -use std::rc::Rc; -pub fn init(s: &Rc) { - s.register_op_json_sync("op_start", op_start); - s.register_op_json_sync("op_main_module", op_main_module); - s.register_op_json_sync("op_metrics", op_metrics); +pub fn init(rt: &mut deno_core::JsRuntime) { + super::reg_json_sync(rt, "op_start", op_start); + super::reg_json_sync(rt, "op_main_module", op_main_module); + super::reg_json_sync(rt, "op_metrics", op_metrics); } fn op_start( - state: &State, + state: &mut OpState, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - let gs = &state.global_state; + let gs = &super::cli_state(state).global_state; Ok(json!({ // TODO(bartlomieju): `cwd` field is not used in JS, remove? @@ -44,25 +42,27 @@ fn op_start( } fn op_main_module( - state: &State, + state: &mut OpState, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - let main = &state.main_module.to_string(); + let cli_state = super::cli_state(state); + let main = &cli_state.main_module.to_string(); let main_url = ModuleSpecifier::resolve_url_or_path(&main)?; if main_url.as_url().scheme() == "file" { let main_path = std::env::current_dir().unwrap().join(main_url.to_string()); - state.check_read_blind(&main_path, "main_module")?; + cli_state.check_read_blind(&main_path, "main_module")?; } Ok(json!(&main)) } fn op_metrics( - state: &State, + state: &mut OpState, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - let m = &state.metrics.borrow(); + let cli_state = super::cli_state(state); + let m = &cli_state.metrics.borrow(); Ok(json!({ "opsDispatched": m.ops_dispatched, diff --git a/cli/ops/runtime_compiler.rs b/cli/ops/runtime_compiler.rs index 71974e6dab..d806b01330 100644 --- a/cli/ops/runtime_compiler.rs +++ b/cli/ops/runtime_compiler.rs @@ -1,21 +1,21 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. use crate::futures::FutureExt; -use crate::state::State; use crate::tsc::runtime_bundle; use crate::tsc::runtime_compile; use crate::tsc::runtime_transpile; use deno_core::BufVec; use deno_core::ErrBox; -use deno_core::OpRegistry; +use deno_core::OpState; use serde_derive::Deserialize; use serde_json::Value; +use std::cell::RefCell; use std::collections::HashMap; use std::rc::Rc; -pub fn init(s: &Rc) { - s.register_op_json_async("op_compile", op_compile); - s.register_op_json_async("op_transpile", op_transpile); +pub fn init(rt: &mut deno_core::JsRuntime) { + super::reg_json_async(rt, "op_compile", op_compile); + super::reg_json_async(rt, "op_transpile", op_transpile); } #[derive(Deserialize, Debug)] @@ -28,14 +28,15 @@ struct CompileArgs { } async fn op_compile( - state: Rc, + state: Rc>, args: Value, _data: BufVec, ) -> Result { - state.check_unstable("Deno.compile"); + let cli_state = super::cli_state2(&state); + cli_state.check_unstable("Deno.compile"); let args: CompileArgs = serde_json::from_value(args)?; - let global_state = state.global_state.clone(); - let permissions = state.permissions.borrow().clone(); + let global_state = cli_state.global_state.clone(); + let permissions = cli_state.permissions.borrow().clone(); let fut = if args.bundle { runtime_bundle( &global_state, @@ -66,14 +67,15 @@ struct TranspileArgs { } async fn op_transpile( - state: Rc, + state: Rc>, args: Value, _data: BufVec, ) -> Result { - state.check_unstable("Deno.transpile"); + let cli_state = super::cli_state2(&state); + cli_state.check_unstable("Deno.transpile"); let args: TranspileArgs = serde_json::from_value(args)?; - let global_state = state.global_state.clone(); - let permissions = state.permissions.borrow().clone(); + let global_state = cli_state.global_state.clone(); + let permissions = cli_state.permissions.borrow().clone(); let result = runtime_transpile(&global_state, permissions, &args.sources, &args.options) .await?; diff --git a/cli/ops/signal.rs b/cli/ops/signal.rs index c0b1220e05..37d1ca9146 100644 --- a/cli/ops/signal.rs +++ b/cli/ops/signal.rs @@ -1,11 +1,11 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use crate::state::State; use deno_core::BufVec; use deno_core::ErrBox; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::ZeroCopyBuf; use serde_json::Value; +use std::cell::RefCell; use std::rc::Rc; #[cfg(unix)] @@ -17,10 +17,10 @@ use std::task::Waker; #[cfg(unix)] use tokio::signal::unix::{signal, Signal, SignalKind}; -pub fn init(s: &Rc) { - s.register_op_json_sync("op_signal_bind", op_signal_bind); - s.register_op_json_sync("op_signal_unbind", op_signal_unbind); - s.register_op_json_async("op_signal_poll", op_signal_poll); +pub fn init(rt: &mut deno_core::JsRuntime) { + super::reg_json_sync(rt, "op_signal_bind", op_signal_bind); + super::reg_json_sync(rt, "op_signal_unbind", op_signal_unbind); + super::reg_json_async(rt, "op_signal_poll", op_signal_poll); } #[cfg(unix)] @@ -42,13 +42,13 @@ struct SignalArgs { #[cfg(unix)] fn op_signal_bind( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.check_unstable("Deno.signal"); + super::cli_state(state).check_unstable("Deno.signal"); let args: BindSignalArgs = serde_json::from_value(args)?; - let rid = state.resource_table.borrow_mut().add( + let rid = state.resource_table.add( "signal", Box::new(SignalStreamResource( signal(SignalKind::from_raw(args.signo)).expect(""), @@ -62,18 +62,18 @@ fn op_signal_bind( #[cfg(unix)] async fn op_signal_poll( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { - state.check_unstable("Deno.signal"); + super::cli_state2(&state).check_unstable("Deno.signal"); let args: SignalArgs = serde_json::from_value(args)?; let rid = args.rid as u32; let future = poll_fn(move |cx| { - let mut resource_table = state.resource_table.borrow_mut(); + let mut state = state.borrow_mut(); if let Some(mut signal) = - resource_table.get_mut::(rid) + state.resource_table.get_mut::(rid) { signal.1 = Some(cx.waker().clone()); return signal.0.poll_recv(cx); @@ -86,15 +86,14 @@ async fn op_signal_poll( #[cfg(unix)] pub fn op_signal_unbind( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.check_unstable("Deno.signal"); - let mut resource_table = state.resource_table.borrow_mut(); + super::cli_state(state).check_unstable("Deno.signal"); let args: SignalArgs = serde_json::from_value(args)?; let rid = args.rid as u32; - let resource = resource_table.get_mut::(rid); + let resource = state.resource_table.get_mut::(rid); if let Some(signal) = resource { if let Some(waker) = &signal.1 { // Wakes up the pending poll if exists. @@ -102,7 +101,8 @@ pub fn op_signal_unbind( waker.clone().wake(); } } - resource_table + state + .resource_table .close(rid) .ok_or_else(ErrBox::bad_resource_id)?; Ok(json!({})) @@ -110,7 +110,7 @@ pub fn op_signal_unbind( #[cfg(not(unix))] pub fn op_signal_bind( - _state: &State, + _state: &mut OpState, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -119,7 +119,7 @@ pub fn op_signal_bind( #[cfg(not(unix))] fn op_signal_unbind( - _state: &State, + _state: &mut OpState, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -128,7 +128,7 @@ fn op_signal_unbind( #[cfg(not(unix))] async fn op_signal_poll( - _state: Rc, + _state: Rc>, _args: Value, _zero_copy: BufVec, ) -> Result { diff --git a/cli/ops/timers.rs b/cli/ops/timers.rs index 36d617a854..3ce2b5633a 100644 --- a/cli/ops/timers.rs +++ b/cli/ops/timers.rs @@ -1,29 +1,30 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use crate::state::State; use deno_core::BufVec; use deno_core::ErrBox; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::ZeroCopyBuf; use futures::future::FutureExt; use serde_derive::Deserialize; use serde_json::Value; +use std::cell::RefCell; use std::rc::Rc; use std::time::Duration; use std::time::Instant; -pub fn init(s: &Rc) { - s.register_op_json_sync("op_global_timer_stop", op_global_timer_stop); - s.register_op_json_async("op_global_timer", op_global_timer); - s.register_op_json_sync("op_now", op_now); +pub fn init(rt: &mut deno_core::JsRuntime) { + super::reg_json_sync(rt, "op_global_timer_stop", op_global_timer_stop); + super::reg_json_async(rt, "op_global_timer", op_global_timer); + super::reg_json_sync(rt, "op_now", op_now); } fn op_global_timer_stop( - state: &State, + state: &mut OpState, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.global_timer.borrow_mut().cancel(); + let cli_state = super::cli_state(state); + cli_state.global_timer.borrow_mut().cancel(); Ok(json!({})) } @@ -33,7 +34,7 @@ struct GlobalTimerArgs { } async fn op_global_timer( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { @@ -41,11 +42,13 @@ async fn op_global_timer( let val = args.timeout; let deadline = Instant::now() + Duration::from_millis(val); - let timer_fut = state - .global_timer - .borrow_mut() - .new_timeout(deadline) - .boxed_local(); + let timer_fut = { + super::cli_state2(&state) + .global_timer + .borrow_mut() + .new_timeout(deadline) + .boxed_local() + }; let _ = timer_fut.await; Ok(json!({})) } @@ -55,18 +58,19 @@ async fn op_global_timer( // If the High precision flag is not set, the // nanoseconds are rounded on 2ms. fn op_now( - state: &State, + state: &mut OpState, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - let seconds = state.start_time.elapsed().as_secs(); - let mut subsec_nanos = state.start_time.elapsed().subsec_nanos(); + let cli_state = super::cli_state(state); + let seconds = cli_state.start_time.elapsed().as_secs(); + let mut subsec_nanos = cli_state.start_time.elapsed().subsec_nanos(); let reduced_time_precision = 2_000_000; // 2ms in nanoseconds // If the permission is not enabled // Round the nano result on 2 milliseconds // see: https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp#Reduced_time_precision - if state.check_hrtime().is_err() { + if cli_state.check_hrtime().is_err() { subsec_nanos -= subsec_nanos % reduced_time_precision; } diff --git a/cli/ops/tls.rs b/cli/ops/tls.rs index 3a478c3ad2..43364df1b1 100644 --- a/cli/ops/tls.rs +++ b/cli/ops/tls.rs @@ -2,14 +2,14 @@ use super::io::{StreamResource, StreamResourceHolder}; use crate::resolve_addr::resolve_addr; -use crate::state::State; use deno_core::BufVec; use deno_core::ErrBox; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::ZeroCopyBuf; use futures::future::poll_fn; use serde_derive::Deserialize; use serde_json::Value; +use std::cell::RefCell; use std::convert::From; use std::fs::File; use std::io::BufReader; @@ -31,11 +31,11 @@ use tokio_rustls::{ }; use webpki::DNSNameRef; -pub fn init(s: &Rc) { - s.register_op_json_async("op_start_tls", op_start_tls); - s.register_op_json_async("op_connect_tls", op_connect_tls); - s.register_op_json_sync("op_listen_tls", op_listen_tls); - s.register_op_json_async("op_accept_tls", op_accept_tls); +pub fn init(rt: &mut deno_core::JsRuntime) { + super::reg_json_async(rt, "op_start_tls", op_start_tls); + super::reg_json_async(rt, "op_connect_tls", op_connect_tls); + super::reg_json_sync(rt, "op_listen_tls", op_listen_tls); + super::reg_json_async(rt, "op_accept_tls", op_accept_tls); } #[derive(Deserialize)] @@ -56,11 +56,10 @@ struct StartTLSArgs { } async fn op_start_tls( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { - state.check_unstable("Deno.startTls"); let args: StartTLSArgs = serde_json::from_value(args)?; let rid = args.rid as u32; let cert_file = args.cert_file.clone(); @@ -69,15 +68,17 @@ async fn op_start_tls( if domain.is_empty() { domain.push_str("localhost"); } - - state.check_net(&domain, 0)?; - if let Some(path) = cert_file.clone() { - state.check_read(Path::new(&path))?; + { + let cli_state = super::cli_state2(&state); + cli_state.check_unstable("Deno.startTls"); + cli_state.check_net(&domain, 0)?; + if let Some(path) = cert_file.clone() { + cli_state.check_read(Path::new(&path))?; + } } - let mut resource_holder = { - let mut resource_table = state.resource_table.borrow_mut(); - match resource_table.remove::(rid) { + let mut state_ = state.borrow_mut(); + match state_.resource_table.remove::(rid) { Some(resource) => *resource, None => return Err(ErrBox::bad_resource_id()), } @@ -104,13 +105,15 @@ async fn op_start_tls( DNSNameRef::try_from_ascii_str(&domain).expect("Invalid DNS lookup"); let tls_stream = tls_connector.connect(dnsname, tcp_stream).await?; - let mut resource_table = state.resource_table.borrow_mut(); - let rid = resource_table.add( - "clientTlsStream", - Box::new(StreamResourceHolder::new(StreamResource::ClientTlsStream( - Box::new(tls_stream), - ))), - ); + let rid = { + let mut state_ = state.borrow_mut(); + state_.resource_table.add( + "clientTlsStream", + Box::new(StreamResourceHolder::new(StreamResource::ClientTlsStream( + Box::new(tls_stream), + ))), + ) + }; Ok(json!({ "rid": rid, "localAddr": { @@ -130,17 +133,19 @@ async fn op_start_tls( } async fn op_connect_tls( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { let args: ConnectTLSArgs = serde_json::from_value(args)?; let cert_file = args.cert_file.clone(); - state.check_net(&args.hostname, args.port)?; - if let Some(path) = cert_file.clone() { - state.check_read(Path::new(&path))?; + { + let cli_state = super::cli_state2(&state); + cli_state.check_net(&args.hostname, args.port)?; + if let Some(path) = cert_file.clone() { + cli_state.check_read(Path::new(&path))?; + } } - let mut domain = args.hostname.clone(); if domain.is_empty() { domain.push_str("localhost"); @@ -163,13 +168,15 @@ async fn op_connect_tls( let dnsname = DNSNameRef::try_from_ascii_str(&domain).expect("Invalid DNS lookup"); let tls_stream = tls_connector.connect(dnsname, tcp_stream).await?; - let mut resource_table = state.resource_table.borrow_mut(); - let rid = resource_table.add( - "clientTlsStream", - Box::new(StreamResourceHolder::new(StreamResource::ClientTlsStream( - Box::new(tls_stream), - ))), - ); + let rid = { + let mut state_ = state.borrow_mut(); + state_.resource_table.add( + "clientTlsStream", + Box::new(StreamResourceHolder::new(StreamResource::ClientTlsStream( + Box::new(tls_stream), + ))), + ) + }; Ok(json!({ "rid": rid, "localAddr": { @@ -298,7 +305,7 @@ struct ListenTlsArgs { } fn op_listen_tls( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -307,11 +314,12 @@ fn op_listen_tls( let cert_file = args.cert_file; let key_file = args.key_file; - - state.check_net(&args.hostname, args.port)?; - state.check_read(Path::new(&cert_file))?; - state.check_read(Path::new(&key_file))?; - + { + let cli_state = super::cli_state(state); + cli_state.check_net(&args.hostname, args.port)?; + cli_state.check_read(Path::new(&cert_file))?; + cli_state.check_read(Path::new(&key_file))?; + } let mut config = ServerConfig::new(NoClientAuth::new()); config .set_single_cert(load_certs(&cert_file)?, load_keys(&key_file)?.remove(0)) @@ -330,7 +338,6 @@ fn op_listen_tls( let rid = state .resource_table - .borrow_mut() .add("tlsListener", Box::new(tls_listener_resource)); Ok(json!({ @@ -349,15 +356,16 @@ struct AcceptTlsArgs { } async fn op_accept_tls( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { let args: AcceptTlsArgs = serde_json::from_value(args)?; let rid = args.rid as u32; let accept_fut = poll_fn(|cx| { - let mut resource_table = state.resource_table.borrow_mut(); - let listener_resource = resource_table + let mut state = state.borrow_mut(); + let listener_resource = state + .resource_table .get_mut::(rid) .ok_or_else(|| ErrBox::bad_resource("Listener has been closed"))?; let listener = &mut listener_resource.listener; @@ -380,8 +388,9 @@ async fn op_accept_tls( let local_addr = tcp_stream.local_addr()?; let remote_addr = tcp_stream.peer_addr()?; let tls_acceptor = { - let resource_table = state.resource_table.borrow(); - let resource = resource_table + let state_ = state.borrow(); + let resource = state_ + .resource_table .get::(rid) .ok_or_else(ErrBox::bad_resource_id) .expect("Can't find tls listener"); @@ -389,8 +398,8 @@ async fn op_accept_tls( }; let tls_stream = tls_acceptor.accept(tcp_stream).await?; let rid = { - let mut resource_table = state.resource_table.borrow_mut(); - resource_table.add( + let mut state_ = state.borrow_mut(); + state_.resource_table.add( "serverTlsStream", Box::new(StreamResourceHolder::new(StreamResource::ServerTlsStream( Box::new(tls_stream), diff --git a/cli/ops/tty.rs b/cli/ops/tty.rs index 9079ca57e1..84443c0bcf 100644 --- a/cli/ops/tty.rs +++ b/cli/ops/tty.rs @@ -2,15 +2,13 @@ use super::io::std_file_resource; use super::io::{StreamResource, StreamResourceHolder}; -use crate::state::State; use deno_core::ErrBox; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::ZeroCopyBuf; #[cfg(unix)] use nix::sys::termios; use serde_derive::{Deserialize, Serialize}; use serde_json::Value; -use std::rc::Rc; #[cfg(windows)] use winapi::shared::minwindef::DWORD; @@ -20,6 +18,7 @@ use winapi::um::wincon; const RAW_MODE_MASK: DWORD = wincon::ENABLE_LINE_INPUT | wincon::ENABLE_ECHO_INPUT | wincon::ENABLE_PROCESSED_INPUT; + #[cfg(windows)] fn get_windows_handle( f: &std::fs::File, @@ -36,10 +35,10 @@ fn get_windows_handle( Ok(handle) } -pub fn init(s: &Rc) { - s.register_op_json_sync("op_set_raw", op_set_raw); - s.register_op_json_sync("op_isatty", op_isatty); - s.register_op_json_sync("op_console_size", op_console_size); +pub fn init(rt: &mut deno_core::JsRuntime) { + super::reg_json_sync(rt, "op_set_raw", op_set_raw); + super::reg_json_sync(rt, "op_isatty", op_isatty); + super::reg_json_sync(rt, "op_console_size", op_console_size); } #[derive(Deserialize)] @@ -49,11 +48,12 @@ struct SetRawArgs { } fn op_set_raw( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.check_unstable("Deno.setRaw"); + super::cli_state(state).check_unstable("Deno.setRaw"); + let args: SetRawArgs = serde_json::from_value(args)?; let rid = args.rid; let is_raw = args.mode; @@ -69,8 +69,8 @@ fn op_set_raw( use winapi::shared::minwindef::FALSE; use winapi::um::{consoleapi, handleapi}; - let mut resource_table = state.resource_table.borrow_mut(); - let resource_holder = resource_table.get_mut::(rid); + let resource_holder = + state.resource_table.get_mut::(rid); if resource_holder.is_none() { return Err(ErrBox::bad_resource_id()); } @@ -135,8 +135,8 @@ fn op_set_raw( { use std::os::unix::io::AsRawFd; - let mut resource_table = state.resource_table.borrow_mut(); - let resource_holder = resource_table.get_mut::(rid); + let resource_holder = + state.resource_table.get_mut::(rid); if resource_holder.is_none() { return Err(ErrBox::bad_resource_id()); } @@ -217,7 +217,7 @@ struct IsattyArgs { } fn op_isatty( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -261,11 +261,12 @@ struct ConsoleSize { } fn op_console_size( - state: &State, + state: &mut OpState, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - state.check_unstable("Deno.consoleSize"); + super::cli_state(state).check_unstable("Deno.consoleSize"); + let args: ConsoleSizeArgs = serde_json::from_value(args)?; let rid = args.rid; diff --git a/cli/ops/web_worker.rs b/cli/ops/web_worker.rs index 9d8140d7bb..fad0b9df7a 100644 --- a/cli/ops/web_worker.rs +++ b/cli/ops/web_worker.rs @@ -1,20 +1,18 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use crate::state::State; use crate::web_worker::WebWorkerHandle; use crate::worker::WorkerEvent; -use deno_core::OpRegistry; use futures::channel::mpsc; -use std::rc::Rc; pub fn init( - s: &Rc, - sender: &mpsc::Sender, + rt: &mut deno_core::JsRuntime, + sender: mpsc::Sender, handle: WebWorkerHandle, ) { // Post message to host as guest worker. let sender_ = sender.clone(); - s.register_op_json_sync( + super::reg_json_sync( + rt, "op_worker_post_message", move |_state, _args, bufs| { assert_eq!(bufs.len(), 1, "Invalid number of arguments"); @@ -28,10 +26,9 @@ pub fn init( ); // Notify host that guest worker closes. - let sender_ = sender.clone(); - s.register_op_json_sync("op_worker_close", move |_state, _args, _bufs| { + super::reg_json_sync(rt, "op_worker_close", move |_state, _args, _bufs| { // Notify parent that we're finished - sender_.clone().close_channel(); + sender.clone().close_channel(); // Terminate execution of current worker handle.terminate(); Ok(json!({})) diff --git a/cli/ops/websocket.rs b/cli/ops/websocket.rs index 131c521790..4a5b83b888 100644 --- a/cli/ops/websocket.rs +++ b/cli/ops/websocket.rs @@ -1,10 +1,9 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use crate::state::State; use core::task::Poll; use deno_core::BufVec; use deno_core::ErrBox; -use deno_core::OpRegistry; +use deno_core::OpState; use futures::future::poll_fn; use futures::StreamExt; use futures::{ready, SinkExt}; @@ -12,6 +11,7 @@ use http::{Method, Request, Uri}; use serde_derive::Deserialize; use serde_json::Value; use std::borrow::Cow; +use std::cell::RefCell; use std::fs::File; use std::io::BufReader; use std::rc::Rc; @@ -26,11 +26,11 @@ use tokio_tungstenite::tungstenite::{ use tokio_tungstenite::{client_async, WebSocketStream}; use webpki::DNSNameRef; -pub fn init(s: &Rc) { - s.register_op_json_async("op_ws_create", op_ws_create); - s.register_op_json_async("op_ws_send", op_ws_send); - s.register_op_json_async("op_ws_close", op_ws_close); - s.register_op_json_async("op_ws_next_event", op_ws_next_event); +pub fn init(rt: &mut deno_core::JsRuntime) { + super::reg_json_async(rt, "op_ws_create", op_ws_create); + super::reg_json_async(rt, "op_ws_send", op_ws_send); + super::reg_json_async(rt, "op_ws_close", op_ws_close); + super::reg_json_async(rt, "op_ws_next_event", op_ws_next_event); } type MaybeTlsStream = @@ -46,13 +46,16 @@ struct CreateArgs { } pub async fn op_ws_create( - state: Rc, + state: Rc>, args: Value, _bufs: BufVec, ) -> Result { let args: CreateArgs = serde_json::from_value(args)?; - state.check_net_url(&url::Url::parse(&args.url)?)?; - let ca_file = state.global_state.flags.ca_file.clone(); + let ca_file = { + let cli_state = super::cli_state2(&state); + cli_state.check_net_url(&url::Url::parse(&args.url)?)?; + cli_state.global_state.flags.ca_file.clone() + }; let uri: Uri = args.url.parse().unwrap(); let request = Request::builder() .method(Method::GET) @@ -99,9 +102,9 @@ pub async fn op_ws_create( let (stream, response): (WsStream, Response) = client_async(request, socket).await.unwrap(); + let mut state = state.borrow_mut(); let rid = state .resource_table - .borrow_mut() .add("webSocketStream", Box::new(stream)); let protocol = match response.headers().get("Sec-WebSocket-Protocol") { @@ -130,7 +133,7 @@ struct SendArgs { } pub async fn op_ws_send( - state: Rc, + state: Rc>, args: Value, bufs: BufVec, ) -> Result { @@ -143,8 +146,9 @@ pub async fn op_ws_send( let rid = args.rid; poll_fn(move |cx| { - let mut resource_table = state.resource_table.borrow_mut(); - let stream = resource_table + let mut state = state.borrow_mut(); + let stream = state + .resource_table .get_mut::(rid) .ok_or_else(ErrBox::bad_resource_id)?; @@ -171,7 +175,7 @@ struct CloseArgs { } pub async fn op_ws_close( - state: Rc, + state: Rc>, args: Value, _bufs: BufVec, ) -> Result { @@ -186,8 +190,9 @@ pub async fn op_ws_close( }))); poll_fn(move |cx| { - let mut resource_table = state.resource_table.borrow_mut(); - let stream = resource_table + let mut state = state.borrow_mut(); + let stream = state + .resource_table .get_mut::(rid) .ok_or_else(ErrBox::bad_resource_id)?; @@ -213,14 +218,15 @@ struct NextEventArgs { } pub async fn op_ws_next_event( - state: Rc, + state: Rc>, args: Value, _bufs: BufVec, ) -> Result { let args: NextEventArgs = serde_json::from_value(args)?; poll_fn(move |cx| { - let mut resource_table = state.resource_table.borrow_mut(); - let stream = resource_table + let mut state = state.borrow_mut(); + let stream = state + .resource_table .get_mut::(args.rid) .ok_or_else(ErrBox::bad_resource_id)?; stream @@ -248,7 +254,7 @@ pub async fn op_ws_next_event( Some(Ok(Message::Pong(_))) => json!({"type": "pong"}), Some(Err(_)) => json!({"type": "error"}), None => { - resource_table.close(args.rid).unwrap(); + state.resource_table.close(args.rid).unwrap(); json!({"type": "closed"}) } } diff --git a/cli/ops/worker_host.rs b/cli/ops/worker_host.rs index 83f84064ba..158865abca 100644 --- a/cli/ops/worker_host.rs +++ b/cli/ops/worker_host.rs @@ -5,7 +5,6 @@ use crate::global_state::GlobalState; use crate::ops::io::get_stdio; use crate::permissions::Permissions; use crate::startup_data; -use crate::state::State; use crate::tokio_util::create_basic_runtime; use crate::web_worker::WebWorker; use crate::web_worker::WebWorkerHandle; @@ -13,21 +12,26 @@ use crate::worker::WorkerEvent; use deno_core::BufVec; use deno_core::ErrBox; use deno_core::ModuleSpecifier; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::ZeroCopyBuf; use futures::future::FutureExt; use serde_derive::Deserialize; use serde_json::Value; +use std::cell::RefCell; use std::convert::From; use std::rc::Rc; use std::sync::Arc; use std::thread::JoinHandle; -pub fn init(s: &Rc) { - s.register_op_json_sync("op_create_worker", op_create_worker); - s.register_op_json_sync("op_host_terminate_worker", op_host_terminate_worker); - s.register_op_json_sync("op_host_post_message", op_host_post_message); - s.register_op_json_async("op_host_get_message", op_host_get_message); +pub fn init(rt: &mut deno_core::JsRuntime) { + super::reg_json_sync(rt, "op_create_worker", op_create_worker); + super::reg_json_sync( + rt, + "op_host_terminate_worker", + op_host_terminate_worker, + ); + super::reg_json_sync(rt, "op_host_post_message", op_host_post_message); + super::reg_json_async(rt, "op_host_get_message", op_host_get_message); } fn create_web_worker( @@ -38,27 +42,31 @@ fn create_web_worker( specifier: ModuleSpecifier, has_deno_namespace: bool, ) -> Result { - let state = - State::new_for_worker(global_state, Some(permissions), specifier)?; + let cli_state = crate::state::State::new_for_worker( + global_state, + Some(permissions), + specifier, + )?; let mut worker = WebWorker::new( name.clone(), startup_data::deno_isolate_init(), - &state, + &cli_state, has_deno_namespace, ); if has_deno_namespace { - let mut resource_table = state.resource_table.borrow_mut(); + let state = worker.isolate.op_state(); + let mut state = state.borrow_mut(); let (stdin, stdout, stderr) = get_stdio(); if let Some(stream) = stdin { - resource_table.add("stdin", Box::new(stream)); + state.resource_table.add("stdin", Box::new(stream)); } if let Some(stream) = stdout { - resource_table.add("stdout", Box::new(stream)); + state.resource_table.add("stdout", Box::new(stream)); } if let Some(stream) = stderr { - resource_table.add("stderr", Box::new(stream)); + state.resource_table.add("stderr", Box::new(stream)); } } @@ -172,10 +180,11 @@ struct CreateWorkerArgs { /// Create worker as the host fn op_create_worker( - state: &State, + state: &mut OpState, args: Value, _data: &mut [ZeroCopyBuf], ) -> Result { + let cli_state = super::cli_state(state); let args: CreateWorkerArgs = serde_json::from_value(args)?; let specifier = args.specifier.clone(); @@ -187,12 +196,12 @@ fn op_create_worker( let args_name = args.name; let use_deno_namespace = args.use_deno_namespace; if use_deno_namespace { - state.check_unstable("Worker.deno"); + cli_state.check_unstable("Worker.deno"); } - let global_state = state.global_state.clone(); - let permissions = state.permissions.borrow().clone(); - let worker_id = state.next_worker_id.get(); - state.next_worker_id.set(worker_id + 1); + let global_state = cli_state.global_state.clone(); + let permissions = cli_state.permissions.borrow().clone(); + let worker_id = cli_state.next_worker_id.get(); + cli_state.next_worker_id.set(worker_id + 1); let module_specifier = ModuleSpecifier::resolve_url(&specifier)?; let worker_name = args_name.unwrap_or_else(|| "".to_string()); @@ -208,7 +217,8 @@ fn op_create_worker( )?; // At this point all interactions with worker happen using thread // safe handler returned from previous function call - state + let cli_state = super::cli_state(state); + cli_state .workers .borrow_mut() .insert(worker_id, (join_handle, worker_handle)); @@ -222,13 +232,14 @@ struct WorkerArgs { } fn op_host_terminate_worker( - state: &State, + state: &mut OpState, args: Value, _data: &mut [ZeroCopyBuf], ) -> Result { let args: WorkerArgs = serde_json::from_value(args)?; let id = args.id as u32; - let (join_handle, worker_handle) = state + let cli_state = super::cli_state(state); + let (join_handle, worker_handle) = cli_state .workers .borrow_mut() .remove(&id) @@ -290,40 +301,41 @@ fn serialize_worker_event(event: WorkerEvent) -> Value { /// Get message from guest worker as host async fn op_host_get_message( - state: Rc, + state: Rc>, args: Value, _zero_copy: BufVec, ) -> Result { let args: WorkerArgs = serde_json::from_value(args)?; let id = args.id as u32; - let state = state.clone(); + let cli_state = super::cli_state2(&state); - let workers_table = state.workers.borrow(); - let maybe_handle = workers_table.get(&id); - let worker_handle = if let Some(handle) = maybe_handle { - handle.1.clone() - } else { - // If handle was not found it means worker has already shutdown - return Ok(json!({ "type": "close" })); + let worker_handle = { + let workers_table = cli_state.workers.borrow(); + let maybe_handle = workers_table.get(&id); + if let Some(handle) = maybe_handle { + handle.1.clone() + } else { + // If handle was not found it means worker has already shutdown + return Ok(json!({ "type": "close" })); + } }; - drop(workers_table); let response = match worker_handle.get_event().await? { Some(event) => { // Terminal error means that worker should be removed from worker table. if let WorkerEvent::TerminalError(_) = &event { if let Some((join_handle, mut worker_handle)) = - state.workers.borrow_mut().remove(&id) + cli_state.workers.borrow_mut().remove(&id) { worker_handle.sender.close_channel(); join_handle.join().expect("Worker thread panicked"); - } + }; } serialize_worker_event(event) } None => { // Worker shuts down - let mut workers = state.workers.borrow_mut(); + let mut workers = cli_state.workers.borrow_mut(); // Try to remove worker from workers table - NOTE: `Worker.terminate()` might have been called // already meaning that we won't find worker in table - in that case ignore. if let Some((join_handle, mut worker_handle)) = workers.remove(&id) { @@ -338,7 +350,7 @@ async fn op_host_get_message( /// Post message to guest worker as host fn op_host_post_message( - state: &State, + state: &mut OpState, args: Value, data: &mut [ZeroCopyBuf], ) -> Result { @@ -348,7 +360,8 @@ fn op_host_post_message( let msg = Vec::from(&*data[0]).into_boxed_slice(); debug!("post message to worker {}", id); - let workers = state.workers.borrow(); + let cli_state = super::cli_state(state); + let workers = cli_state.workers.borrow(); let worker_handle = workers[&id].1.clone(); worker_handle.post_message(msg)?; Ok(json!({})) diff --git a/cli/state.rs b/cli/state.rs index c85701bac4..3df4ffb3bf 100644 --- a/cli/state.rs +++ b/cli/state.rs @@ -1,6 +1,5 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use crate::errors::get_error_class_name; use crate::file_fetcher::SourceFileFetcher; use crate::global_state::GlobalState; use crate::global_timer::GlobalTimer; @@ -10,17 +9,10 @@ use crate::metrics::Metrics; use crate::permissions::Permissions; use crate::tsc::TargetLib; use crate::web_worker::WebWorkerHandle; -use deno_core::BufVec; use deno_core::ErrBox; use deno_core::ModuleLoadId; use deno_core::ModuleLoader; use deno_core::ModuleSpecifier; -use deno_core::Op; -use deno_core::OpId; -use deno_core::OpRegistry; -use deno_core::OpRouter; -use deno_core::OpTable; -use deno_core::ResourceTable; use futures::future::FutureExt; use futures::Future; use rand::rngs::StdRng; @@ -36,6 +28,7 @@ use std::sync::Arc; use std::thread::JoinHandle; use std::time::Instant; +// TODO(ry) Rename to CliState to avoid confusion with other states. #[cfg_attr(feature = "cargo-clippy", allow(stutter))] pub struct State { pub global_state: Arc, @@ -54,8 +47,6 @@ pub struct State { pub is_main: bool, pub is_internal: bool, pub http_client: RefCell, - pub resource_table: RefCell, - pub op_table: RefCell>, } impl State { @@ -202,8 +193,6 @@ impl State { is_main: true, is_internal, http_client: create_http_client(fl.ca_file.as_deref())?.into(), - resource_table: Default::default(), - op_table: Default::default(), }; Ok(Rc::new(state)) } @@ -232,8 +221,6 @@ impl State { is_main: false, is_internal: false, http_client: create_http_client(fl.ca_file.as_deref())?.into(), - resource_table: Default::default(), - op_table: Default::default(), }; Ok(Rc::new(state)) } @@ -331,78 +318,3 @@ impl State { .unwrap() } } - -impl OpRouter for State { - fn route_op(self: Rc, 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) -> HashMap { - self.op_table.borrow().get_op_catalog() - } - - fn register_op(&self, name: &str, op_fn: F) -> OpId - where - F: Fn(Rc, 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) - } -} diff --git a/cli/tsc.rs b/cli/tsc.rs index 36a7cf0545..77b855dd17 100644 --- a/cli/tsc.rs +++ b/cli/tsc.rs @@ -139,15 +139,12 @@ impl CompilerWorker { startup_data: StartupData, state: &Rc, ) -> Self { - let worker = Worker::new(name, startup_data, state); + let mut worker = Worker::new(name, startup_data, state); let response = Arc::new(Mutex::new(None)); - { - ops::runtime::init(&state); - ops::errors::init(&state); - ops::timers::init(&state); - ops::compiler::init(&state, response.clone()); - } - + ops::runtime::init(&mut worker); + ops::errors::init(&mut worker); + ops::timers::init(&mut worker); + ops::compiler::init(&mut worker, response.clone()); Self { worker, response } } diff --git a/cli/web_worker.rs b/cli/web_worker.rs index 095d5b376d..ebf8fa698a 100644 --- a/cli/web_worker.rs +++ b/cli/web_worker.rs @@ -102,7 +102,7 @@ impl WebWorker { terminate_tx, }; - let web_worker = Self { + let mut web_worker = Self { worker, event_loop_idle: false, terminate_rx, @@ -110,37 +110,33 @@ impl WebWorker { has_deno_namespace, }; - let handle = web_worker.thread_safe_handle(); - { - ops::runtime::init(&state); - ops::web_worker::init( - &state, - &web_worker.worker.internal_channels.sender, - handle, - ); - ops::worker_host::init(&state); - ops::idna::init(&state); - ops::io::init(&state); - ops::resources::init(&state); - ops::errors::init(&state); - ops::timers::init(&state); - ops::fetch::init(&state); - ops::websocket::init(&state); + ops::runtime::init(&mut web_worker.worker); + let sender = web_worker.worker.internal_channels.sender.clone(); + let handle = web_worker.thread_safe_handle(); + ops::web_worker::init(&mut web_worker.worker, sender, handle); + ops::worker_host::init(&mut web_worker.worker); + ops::idna::init(&mut web_worker.worker); + ops::io::init(&mut web_worker.worker); + ops::resources::init(&mut web_worker.worker); + ops::errors::init(&mut web_worker.worker); + ops::timers::init(&mut web_worker.worker); + ops::fetch::init(&mut web_worker.worker); + ops::websocket::init(&mut web_worker.worker); if has_deno_namespace { - ops::runtime_compiler::init(&state); - ops::fs::init(&state); - ops::fs_events::init(&state); - ops::plugin::init(&state); - ops::net::init(&state); - ops::tls::init(&state); - ops::os::init(&state); - ops::permissions::init(&state); - ops::process::init(&state); - ops::random::init(&state); - ops::signal::init(&state); - ops::tty::init(&state); + ops::runtime_compiler::init(&mut web_worker.worker); + ops::fs::init(&mut web_worker.worker); + ops::fs_events::init(&mut web_worker.worker); + ops::plugin::init(&mut web_worker.worker); + ops::net::init(&mut web_worker.worker); + ops::tls::init(&mut web_worker.worker); + ops::os::init(&mut web_worker.worker); + ops::permissions::init(&mut web_worker.worker); + ops::process::init(&mut web_worker.worker); + ops::random::init(&mut web_worker.worker); + ops::signal::init(&mut web_worker.worker); + ops::tty::init(&mut web_worker.worker); } } diff --git a/cli/worker.rs b/cli/worker.rs index 9ac3bbead0..baab81ff68 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -91,7 +91,7 @@ fn create_channels() -> (WorkerChannelsInternal, WorkerHandle) { /// - `WebWorker` pub struct Worker { pub name: String, - pub isolate: deno_core::JsRuntime, + pub isolate: JsRuntime, pub inspector: Option>, pub state: Rc, pub waker: AtomicWaker, @@ -105,22 +105,22 @@ impl Worker { startup_data: StartupData, state: &Rc, ) -> Self { - let mut isolate = deno_core::JsRuntime::new_with_loader( - state.clone(), - state.clone(), - startup_data, - false, - ); - + let mut isolate = + JsRuntime::new_with_loader(state.clone(), startup_data, false); { let global_state = state.global_state.clone(); - let core_state_rc = JsRuntime::state(&isolate); - let mut core_state = core_state_rc.borrow_mut(); - core_state.set_js_error_create_fn(move |core_js_error| { + let js_runtime_state = JsRuntime::state(&isolate); + let mut js_runtime_state = js_runtime_state.borrow_mut(); + js_runtime_state.set_js_error_create_fn(move |core_js_error| { JsError::create(core_js_error, &global_state.ts_compiler) }); } - + { + let op_state = isolate.op_state(); + let mut op_state = op_state.borrow_mut(); + op_state.get_error_class_fn = &crate::errors::get_error_class_name; + op_state.put(state.clone()); + } let inspector = { let global_state = &state.global_state; global_state @@ -235,7 +235,7 @@ impl Future for Worker { } impl Deref for Worker { - type Target = deno_core::JsRuntime; + type Target = JsRuntime; fn deref(&self) -> &Self::Target { &self.isolate } @@ -258,30 +258,30 @@ pub struct MainWorker(Worker); impl MainWorker { // TODO(ry) combine MainWorker::new and MainWorker::create. fn new(name: String, startup_data: StartupData, state: &Rc) -> Self { - let worker = Worker::new(name, startup_data, state); + let mut worker = Worker::new(name, startup_data, state); { - ops::runtime::init(&state); - ops::runtime_compiler::init(&state); - ops::errors::init(&state); - ops::fetch::init(&state); - ops::websocket::init(&state); - ops::fs::init(&state); - ops::fs_events::init(&state); - ops::idna::init(&state); - ops::io::init(&state); - ops::plugin::init(&state); - ops::net::init(&state); - ops::tls::init(&state); - ops::os::init(&state); - ops::permissions::init(&state); - ops::process::init(&state); - ops::random::init(&state); - ops::repl::init(&state); - ops::resources::init(&state); - ops::signal::init(&state); - ops::timers::init(&state); - ops::tty::init(&state); - ops::worker_host::init(&state); + ops::runtime::init(&mut worker); + ops::runtime_compiler::init(&mut worker); + ops::errors::init(&mut worker); + ops::fetch::init(&mut worker); + ops::websocket::init(&mut worker); + ops::fs::init(&mut worker); + ops::fs_events::init(&mut worker); + ops::idna::init(&mut worker); + ops::io::init(&mut worker); + ops::plugin::init(&mut worker); + ops::net::init(&mut worker); + ops::tls::init(&mut worker); + ops::os::init(&mut worker); + ops::permissions::init(&mut worker); + ops::process::init(&mut worker); + ops::random::init(&mut worker); + ops::repl::init(&mut worker); + ops::resources::init(&mut worker); + ops::signal::init(&mut worker); + ops::timers::init(&mut worker); + ops::tty::init(&mut worker); + ops::worker_host::init(&mut worker); } Self(worker) } @@ -303,7 +303,9 @@ impl MainWorker { &state, ); { - let mut t = state.resource_table.borrow_mut(); + let op_state = worker.op_state(); + let mut op_state = op_state.borrow_mut(); + let t = &mut op_state.resource_table; let (stdin, stdout, stderr) = get_stdio(); if let Some(stream) = stdin { t.add("stdin", Box::new(stream)); diff --git a/core/basic_state.rs b/core/basic_state.rs deleted file mode 100644 index 54b9ee1321..0000000000 --- a/core/basic_state.rs +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. - -use crate::BufVec; -use crate::Op; -use crate::OpId; -use crate::OpRegistry; -use crate::OpRouter; -use crate::OpTable; -use crate::ResourceTable; -use std::cell::RefCell; -use std::collections::HashMap; -use std::rc::Rc; - -/// A minimal state struct for use by tests, examples etc. It contains -/// an OpTable and ResourceTable, and implements the relevant traits -/// for working with ops in the most straightforward way possible. -#[derive(Default)] -pub struct BasicState { - pub op_table: RefCell>, - pub resource_table: RefCell, -} - -impl BasicState { - pub fn new() -> Rc { - Default::default() - } -} - -impl OpRegistry for BasicState { - fn get_op_catalog(self: Rc) -> HashMap { - self.op_table.borrow().get_op_catalog() - } - - fn register_op(&self, name: &str, op_fn: F) -> OpId - where - F: Fn(Rc, 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, 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::>(&buf) - .map(|map| map.into_iter().collect::>()) - .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) - ] - ) -} diff --git a/core/bindings.rs b/core/bindings.rs index d0d916bdc4..265906990c 100644 --- a/core/bindings.rs +++ b/core/bindings.rs @@ -6,6 +6,7 @@ use crate::JsRuntime; use crate::JsRuntimeState; use crate::Op; use crate::OpId; +use crate::OpTable; use crate::ZeroCopyBuf; use futures::future::FutureExt; use rusty_v8 as v8; @@ -426,8 +427,7 @@ fn send<'s>( } }; - let op_router = state.op_router.clone(); - let op = op_router.route_op(op_id, bufs); + let op = OpTable::route_op(op_id, state.op_state.clone(), bufs); assert_eq!(state.shared.size(), 0); match op { Op::Sync(buf) if !buf.is_empty() => { diff --git a/core/examples/http_bench_bin_ops.rs b/core/examples/http_bench_bin_ops.rs index 00eb95f44c..b29af8b9d5 100644 --- a/core/examples/http_bench_bin_ops.rs +++ b/core/examples/http_bench_bin_ops.rs @@ -2,11 +2,10 @@ extern crate log; use deno_core::js_check; -use deno_core::BasicState; use deno_core::BufVec; use deno_core::JsRuntime; use deno_core::Op; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::Script; use deno_core::StartupData; use deno_core::ZeroCopyBuf; @@ -14,6 +13,7 @@ use futures::future::poll_fn; use futures::future::FutureExt; use futures::future::TryFuture; use futures::future::TryFutureExt; +use std::cell::RefCell; use std::convert::TryInto; use std::env; use std::fmt::Debug; @@ -78,23 +78,22 @@ impl From for RecordBuf { } fn create_isolate() -> JsRuntime { - let state = BasicState::new(); - register_op_bin_sync(&state, "listen", op_listen); - register_op_bin_sync(&state, "close", op_close); - register_op_bin_async(&state, "accept", op_accept); - register_op_bin_async(&state, "read", op_read); - register_op_bin_async(&state, "write", op_write); - let startup_data = StartupData::Script(Script { source: include_str!("http_bench_bin_ops.js"), filename: "http_bench_bin_ops.js", }); - JsRuntime::new(state, startup_data, false) + let mut isolate = JsRuntime::new(startup_data, false); + register_op_bin_sync(&mut isolate, "listen", op_listen); + register_op_bin_sync(&mut isolate, "close", op_close); + register_op_bin_async(&mut isolate, "accept", op_accept); + register_op_bin_async(&mut isolate, "read", op_read); + register_op_bin_async(&mut isolate, "write", op_write); + isolate } fn op_listen( - state: &BasicState, + state: &mut OpState, _rid: u32, _bufs: &mut [ZeroCopyBuf], ) -> Result { @@ -102,36 +101,33 @@ fn op_listen( let addr = "127.0.0.1:4544".parse::().unwrap(); let std_listener = std::net::TcpListener::bind(&addr)?; let listener = TcpListener::from_std(std_listener)?; - let rid = state - .resource_table - .borrow_mut() - .add("tcpListener", Box::new(listener)); + let rid = state.resource_table.add("tcpListener", Box::new(listener)); Ok(rid) } fn op_close( - state: &BasicState, + state: &mut OpState, rid: u32, _bufs: &mut [ZeroCopyBuf], ) -> Result { debug!("close rid={}", rid); state .resource_table - .borrow_mut() .close(rid) .map(|_| 0) .ok_or_else(bad_resource_id) } -fn op_accept( - state: Rc, +async fn op_accept( + state: Rc>, rid: u32, _bufs: BufVec, -) -> impl TryFuture { +) -> Result { debug!("accept rid={}", rid); poll_fn(move |cx| { - let resource_table = &mut state.resource_table.borrow_mut(); + let resource_table = &mut state.borrow_mut().resource_table; + let listener = resource_table .get_mut::(rid) .ok_or_else(bad_resource_id)?; @@ -139,10 +135,11 @@ fn op_accept( resource_table.add("tcpStream", Box::new(stream)) }) }) + .await } fn op_read( - state: Rc, + state: Rc>, rid: u32, bufs: BufVec, ) -> impl TryFuture { @@ -152,7 +149,8 @@ fn op_read( debug!("read rid={}", rid); poll_fn(move |cx| { - let resource_table = &mut state.resource_table.borrow_mut(); + let resource_table = &mut state.borrow_mut().resource_table; + let stream = resource_table .get_mut::(rid) .ok_or_else(bad_resource_id)?; @@ -161,7 +159,7 @@ fn op_read( } fn op_write( - state: Rc, + state: Rc>, rid: u32, bufs: BufVec, ) -> impl TryFuture { @@ -170,7 +168,8 @@ fn op_write( debug!("write rid={}", rid); poll_fn(move |cx| { - let resource_table = &mut state.resource_table.borrow_mut(); + let resource_table = &mut state.borrow_mut().resource_table; + let stream = resource_table .get_mut::(rid) .ok_or_else(bad_resource_id)?; @@ -178,35 +177,42 @@ fn op_write( }) } -fn register_op_bin_sync(state: &BasicState, name: &'static str, op_fn: F) -where - F: Fn(&BasicState, u32, &mut [ZeroCopyBuf]) -> Result + 'static, +fn register_op_bin_sync( + isolate: &mut JsRuntime, + name: &'static str, + op_fn: F, +) where + F: Fn(&mut OpState, u32, &mut [ZeroCopyBuf]) -> Result + 'static, { - let base_op_fn = move |state: Rc, mut bufs: BufVec| -> Op { + let base_op_fn = move |state: Rc>, mut bufs: BufVec| -> Op { let record = Record::from(bufs[0].as_ref()); let is_sync = record.promise_id == 0; assert!(is_sync); let zero_copy_bufs = &mut bufs[1..]; - let result: i32 = match op_fn(&state, record.rid, zero_copy_bufs) { - Ok(r) => r as i32, - Err(_) => -1, - }; + let result: i32 = + match op_fn(&mut state.borrow_mut(), record.rid, zero_copy_bufs) { + Ok(r) => r as i32, + Err(_) => -1, + }; let buf = RecordBuf::from(Record { result, ..record })[..].into(); Op::Sync(buf) }; - state.register_op(name, base_op_fn); + isolate.register_op(name, base_op_fn); } -fn register_op_bin_async(state: &BasicState, name: &'static str, op_fn: F) -where - F: Fn(Rc, u32, BufVec) -> R + Copy + 'static, +fn register_op_bin_async( + isolate: &mut JsRuntime, + name: &'static str, + op_fn: F, +) where + F: Fn(Rc>, u32, BufVec) -> R + Copy + 'static, R: TryFuture, R::Ok: TryInto, >::Error: Debug, { - let base_op_fn = move |state: Rc, bufs: BufVec| -> Op { + let base_op_fn = move |state: Rc>, bufs: BufVec| -> Op { let mut bufs_iter = bufs.into_iter(); let record_buf = bufs_iter.next().unwrap(); let zero_copy_bufs = bufs_iter.collect::(); @@ -227,7 +233,7 @@ where Op::Async(fut.boxed_local()) }; - state.register_op(name, base_op_fn); + isolate.register_op(name, base_op_fn); } fn bad_resource_id() -> Error { diff --git a/core/examples/http_bench_json_ops.rs b/core/examples/http_bench_json_ops.rs index de467b8adc..dc0c837e21 100644 --- a/core/examples/http_bench_json_ops.rs +++ b/core/examples/http_bench_json_ops.rs @@ -2,17 +2,17 @@ extern crate log; use deno_core::js_check; -use deno_core::BasicState; use deno_core::BufVec; use deno_core::ErrBox; use deno_core::JsRuntime; -use deno_core::OpRegistry; +use deno_core::OpState; use deno_core::Script; use deno_core::StartupData; use deno_core::ZeroCopyBuf; use futures::future::poll_fn; use futures::future::Future; use serde_json::Value; +use std::cell::RefCell; use std::convert::TryInto; use std::env; use std::net::SocketAddr; @@ -42,23 +42,21 @@ impl log::Log for Logger { } fn create_isolate() -> JsRuntime { - let state = BasicState::new(); - state.register_op_json_sync("listen", op_listen); - state.register_op_json_sync("close", op_close); - state.register_op_json_async("accept", op_accept); - state.register_op_json_async("read", op_read); - state.register_op_json_async("write", op_write); - let startup_data = StartupData::Script(Script { source: include_str!("http_bench_json_ops.js"), filename: "http_bench_json_ops.js", }); - - JsRuntime::new(state, startup_data, false) + let mut runtime = JsRuntime::new(startup_data, false); + runtime.register_op("listen", deno_core::json_op_sync(op_listen)); + runtime.register_op("close", deno_core::json_op_sync(op_close)); + runtime.register_op("accept", deno_core::json_op_async(op_accept)); + runtime.register_op("read", deno_core::json_op_async(op_read)); + runtime.register_op("write", deno_core::json_op_async(op_write)); + runtime } fn op_listen( - state: &BasicState, + state: &mut OpState, _args: Value, _bufs: &mut [ZeroCopyBuf], ) -> Result { @@ -66,15 +64,12 @@ fn op_listen( let addr = "127.0.0.1:4544".parse::().unwrap(); let std_listener = std::net::TcpListener::bind(&addr)?; let listener = TcpListener::from_std(std_listener)?; - let rid = state - .resource_table - .borrow_mut() - .add("tcpListener", Box::new(listener)); + let rid = state.resource_table.add("tcpListener", Box::new(listener)); Ok(serde_json::json!({ "rid": rid })) } fn op_close( - state: &BasicState, + state: &mut OpState, args: Value, _buf: &mut [ZeroCopyBuf], ) -> Result { @@ -86,17 +81,15 @@ fn op_close( .try_into() .unwrap(); debug!("close rid={}", rid); - state .resource_table - .borrow_mut() .close(rid) .map(|_| serde_json::json!(())) .ok_or_else(ErrBox::bad_resource_id) } fn op_accept( - state: Rc, + state: Rc>, args: Value, _bufs: BufVec, ) -> impl Future> { @@ -110,7 +103,8 @@ fn op_accept( debug!("accept rid={}", rid); poll_fn(move |cx| { - let resource_table = &mut state.resource_table.borrow_mut(); + let resource_table = &mut state.borrow_mut().resource_table; + let listener = resource_table .get_mut::(rid) .ok_or_else(ErrBox::bad_resource_id)?; @@ -122,7 +116,7 @@ fn op_accept( } fn op_read( - state: Rc, + state: Rc>, args: Value, mut bufs: BufVec, ) -> impl Future> { @@ -138,7 +132,8 @@ fn op_read( debug!("read rid={}", rid); poll_fn(move |cx| -> Poll> { - let resource_table = &mut state.resource_table.borrow_mut(); + let resource_table = &mut state.borrow_mut().resource_table; + let stream = resource_table .get_mut::(rid) .ok_or_else(ErrBox::bad_resource_id)?; @@ -149,7 +144,7 @@ fn op_read( } fn op_write( - state: Rc, + state: Rc>, args: Value, bufs: BufVec, ) -> impl Future> { @@ -165,7 +160,8 @@ fn op_write( debug!("write rid={}", rid); poll_fn(move |cx| { - let resource_table = &mut state.resource_table.borrow_mut(); + let resource_table = &mut state.borrow_mut().resource_table; + let stream = resource_table .get_mut::(rid) .ok_or_else(ErrBox::bad_resource_id)?; diff --git a/core/gotham_state.rs b/core/gotham_state.rs new file mode 100644 index 0000000000..94a2d67d4a --- /dev/null +++ b/core/gotham_state.rs @@ -0,0 +1,167 @@ +// Forked from Gotham: +// https://github.com/gotham-rs/gotham/blob/bcbbf8923789e341b7a0e62c59909428ca4e22e2/gotham/src/state/mod.rs +// Copyright 2017 Gotham Project Developers. MIT license. + +use std::any::Any; +use std::any::TypeId; +use std::collections::HashMap; + +#[derive(Default)] +pub struct GothamState { + data: HashMap>, +} + +impl GothamState { + /// Puts a value into the `GothamState` storage. One value of each type is retained. + /// Successive calls to `put` will overwrite the existing value of the same + /// type. + pub fn put(&mut self, t: T) { + let type_id = TypeId::of::(); + trace!(" inserting record to state for type_id `{:?}`", type_id); + self.data.insert(type_id, Box::new(t)); + } + + /// Determines if the current value exists in `GothamState` storage. + pub fn has(&self) -> bool { + let type_id = TypeId::of::(); + self.data.get(&type_id).is_some() + } + + /// Tries to borrow a value from the `GothamState` storage. + pub fn try_borrow(&self) -> Option<&T> { + let type_id = TypeId::of::(); + trace!(" borrowing state data for type_id `{:?}`", type_id); + self.data.get(&type_id).and_then(|b| b.downcast_ref()) + } + + /// Borrows a value from the `GothamState` storage. + pub fn borrow(&self) -> &T { + self + .try_borrow() + .expect("required type is not present in GothamState container") + } + + /// Tries to mutably borrow a value from the `GothamState` storage. + pub fn try_borrow_mut(&mut self) -> Option<&mut T> { + let type_id = TypeId::of::(); + trace!(" mutably borrowing state data for type_id `{:?}`", type_id); + self.data.get_mut(&type_id).and_then(|b| b.downcast_mut()) + } + + /// Mutably borrows a value from the `GothamState` storage. + pub fn borrow_mut(&mut self) -> &mut T { + self + .try_borrow_mut() + .expect("required type is not present in GothamState container") + } + + /// Tries to move a value out of the `GothamState` storage and return ownership. + pub fn try_take(&mut self) -> Option { + let type_id = TypeId::of::(); + trace!( + " taking ownership from state data for type_id `{:?}`", + type_id + ); + self + .data + .remove(&type_id) + .and_then(|b| b.downcast().ok()) + .map(|b| *b) + } + + /// Moves a value out of the `GothamState` storage and returns ownership. + /// + /// # Panics + /// + /// If a value of type `T` is not present in `GothamState`. + pub fn take(&mut self) -> T { + self + .try_take() + .expect("required type is not present in GothamState container") + } +} + +#[cfg(test)] +mod tests { + use super::GothamState; + + struct MyStruct { + value: i32, + } + + struct AnotherStruct { + value: &'static str, + } + + #[test] + fn put_borrow1() { + let mut state = GothamState::default(); + state.put(MyStruct { value: 1 }); + assert_eq!(state.borrow::().value, 1); + } + + #[test] + fn put_borrow2() { + let mut state = GothamState::default(); + assert!(!state.has::()); + state.put(AnotherStruct { value: "a string" }); + assert!(state.has::()); + assert!(!state.has::()); + state.put(MyStruct { value: 100 }); + assert!(state.has::()); + assert_eq!(state.borrow::().value, 100); + assert_eq!(state.borrow::().value, "a string"); + } + + #[test] + fn try_borrow() { + let mut state = GothamState::default(); + state.put(MyStruct { value: 100 }); + assert!(state.try_borrow::().is_some()); + assert_eq!(state.try_borrow::().unwrap().value, 100); + assert!(state.try_borrow::().is_none()); + } + + #[test] + fn try_borrow_mut() { + let mut state = GothamState::default(); + state.put(MyStruct { value: 100 }); + if let Some(a) = state.try_borrow_mut::() { + a.value += 10; + } + assert_eq!(state.borrow::().value, 110); + } + + #[test] + fn borrow_mut() { + let mut state = GothamState::default(); + state.put(MyStruct { value: 100 }); + { + let a = state.borrow_mut::(); + a.value += 10; + } + assert_eq!(state.borrow::().value, 110); + assert!(state.try_borrow_mut::().is_none()); + } + + #[test] + fn try_take() { + let mut state = GothamState::default(); + state.put(MyStruct { value: 100 }); + assert_eq!(state.try_take::().unwrap().value, 100); + assert!(state.try_take::().is_none()); + assert!(state.try_borrow_mut::().is_none()); + assert!(state.try_borrow::().is_none()); + assert!(state.try_take::().is_none()); + } + + #[test] + fn take() { + let mut state = GothamState::default(); + state.put(MyStruct { value: 110 }); + assert_eq!(state.take::().value, 110); + assert!(state.try_take::().is_none()); + assert!(state.try_borrow_mut::().is_none()); + assert!(state.try_borrow::().is_none()); + } +} diff --git a/core/lib.rs b/core/lib.rs index b27419ff56..450b7378ad 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -8,10 +8,10 @@ extern crate lazy_static; #[macro_use] extern crate log; -mod basic_state; mod bindings; mod errors; mod flags; +mod gotham_state; mod module_specifier; mod modules; mod normalize_path; @@ -24,7 +24,6 @@ mod zero_copy_buf; pub use rusty_v8 as v8; -pub use crate::basic_state::BasicState; pub use crate::errors::AnyError; pub use crate::errors::ErrBox; pub use crate::errors::JsError; @@ -38,12 +37,13 @@ pub use crate::modules::ModuleSource; pub use crate::modules::ModuleSourceFuture; pub use crate::modules::RecursiveModuleLoad; pub use crate::normalize_path::normalize_path; +pub use crate::ops::json_op_async; +pub use crate::ops::json_op_sync; pub use crate::ops::Op; pub use crate::ops::OpAsyncFuture; pub use crate::ops::OpFn; pub use crate::ops::OpId; -pub use crate::ops::OpRegistry; -pub use crate::ops::OpRouter; +pub use crate::ops::OpState; pub use crate::ops::OpTable; pub use crate::resources::ResourceTable; pub use crate::runtime::js_check; diff --git a/core/modules.rs b/core/modules.rs index 3caeab7b12..57068528dc 100644 --- a/core/modules.rs +++ b/core/modules.rs @@ -441,7 +441,6 @@ impl Modules { mod tests { use super::*; use crate::js_check; - use crate::BasicState; use crate::JsRuntime; use crate::StartupData; use futures::future::FutureExt; @@ -620,12 +619,8 @@ mod tests { fn test_recursive_load() { let loader = MockLoader::new(); let loads = loader.loads.clone(); - let mut runtime = JsRuntime::new_with_loader( - loader, - BasicState::new(), - StartupData::None, - false, - ); + let mut runtime = + JsRuntime::new_with_loader(loader, StartupData::None, false); let spec = ModuleSpecifier::resolve_url("file:///a.js").unwrap(); let a_id_fut = runtime.load_module(&spec, None); let a_id = futures::executor::block_on(a_id_fut).expect("Failed to load"); @@ -687,12 +682,8 @@ mod tests { fn test_circular_load() { let loader = MockLoader::new(); let loads = loader.loads.clone(); - let mut runtime = JsRuntime::new_with_loader( - loader, - BasicState::new(), - StartupData::None, - false, - ); + let mut runtime = + JsRuntime::new_with_loader(loader, StartupData::None, false); let fut = async move { let spec = ModuleSpecifier::resolve_url("file:///circular1.js").unwrap(); @@ -765,12 +756,8 @@ mod tests { fn test_redirect_load() { let loader = MockLoader::new(); let loads = loader.loads.clone(); - let mut runtime = JsRuntime::new_with_loader( - loader, - BasicState::new(), - StartupData::None, - false, - ); + let mut runtime = + JsRuntime::new_with_loader(loader, StartupData::None, false); let fut = async move { let spec = ModuleSpecifier::resolve_url("file:///redirect1.js").unwrap(); @@ -834,12 +821,8 @@ mod tests { run_in_task(|mut cx| { let loader = MockLoader::new(); let loads = loader.loads.clone(); - let mut runtime = JsRuntime::new_with_loader( - loader, - BasicState::new(), - StartupData::None, - false, - ); + let mut runtime = + JsRuntime::new_with_loader(loader, StartupData::None, false); let spec = ModuleSpecifier::resolve_url("file:///main.js").unwrap(); let mut recursive_load = runtime.load_module(&spec, None).boxed_local(); @@ -884,12 +867,8 @@ mod tests { fn loader_disappears_after_error() { run_in_task(|mut cx| { let loader = MockLoader::new(); - let mut runtime = JsRuntime::new_with_loader( - loader, - BasicState::new(), - StartupData::None, - false, - ); + let mut runtime = + JsRuntime::new_with_loader(loader, StartupData::None, false); let spec = ModuleSpecifier::resolve_url("file:///bad_import.js").unwrap(); let mut load_fut = runtime.load_module(&spec, None).boxed_local(); let result = load_fut.poll_unpin(&mut cx); @@ -917,12 +896,8 @@ mod tests { fn recursive_load_main_with_code() { let loader = MockLoader::new(); let loads = loader.loads.clone(); - let mut runtime = JsRuntime::new_with_loader( - loader, - BasicState::new(), - StartupData::None, - false, - ); + let mut runtime = + JsRuntime::new_with_loader(loader, StartupData::None, false); // In default resolution code should be empty. // Instead we explicitly pass in our own code. // The behavior should be very similar to /a.js. diff --git a/core/ops.rs b/core/ops.rs index 838596dc0b..7af4949a1e 100644 --- a/core/ops.rs +++ b/core/ops.rs @@ -1,13 +1,13 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +use crate::gotham_state::GothamState; use crate::BufVec; use crate::ErrBox; use crate::ZeroCopyBuf; use futures::Future; -use futures::FutureExt; use indexmap::IndexMap; -use serde_json::json; use serde_json::Value; +use std::cell::RefCell; use std::collections::HashMap; use std::iter::once; use std::ops::Deref; @@ -16,7 +16,7 @@ use std::pin::Pin; use std::rc::Rc; pub type OpAsyncFuture = Pin>>>; -pub type OpFn = dyn Fn(Rc, BufVec) -> Op + 'static; +pub type OpFn = dyn Fn(Rc>, BufVec) -> Op + 'static; pub type OpId = usize; pub enum Op { @@ -28,119 +28,191 @@ pub enum Op { NotFound, } -pub trait OpRouter { - fn route_op(self: Rc, op_id: OpId, bufs: BufVec) -> Op; +pub struct OpState { + pub resource_table: crate::ResourceTable, + pub op_table: OpTable, + pub get_error_class_fn: crate::runtime::GetErrorClassFn, + gotham_state: GothamState, } -pub trait OpRegistry: OpRouter + 'static { - fn get_op_catalog(self: Rc) -> HashMap; +impl Default for OpState { + // TODO(ry) Only deno_core should be able to construct an OpState. But I don't + // know how to make default private. Maybe rename to + // pub(crate) fn new() -> OpState + fn default() -> OpState { + OpState { + resource_table: crate::ResourceTable::default(), + op_table: OpTable::default(), + get_error_class_fn: &|_| "Error", + gotham_state: GothamState::default(), + } + } +} - fn register_op(&self, name: &str, op_fn: F) -> OpId - where - F: Fn(Rc, BufVec) -> Op + 'static; +impl Deref for OpState { + type Target = GothamState; - fn register_op_json_sync(self: &Rc, name: &str, op_fn: F) -> OpId + fn deref(&self) -> &Self::Target { + &self.gotham_state + } +} + +impl DerefMut for OpState { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.gotham_state + } +} + +/// Collection for storing registered ops. The special 'get_op_catalog' +/// op with OpId `0` is automatically added when the OpTable is created. +pub struct OpTable(IndexMap>); + +impl OpTable { + pub fn register_op(&mut self, name: &str, op_fn: F) -> OpId where - F: Fn(&Self, Value, &mut [ZeroCopyBuf]) -> Result + 'static, + F: Fn(Rc>, BufVec) -> Op + 'static, { - let base_op_fn = move |state: Rc, mut bufs: BufVec| -> Op { - let result = serde_json::from_slice(&bufs[0]) - .map_err(ErrBox::from) - .and_then(|args| op_fn(&state, args, &mut bufs[1..])); - let buf = state.json_serialize_op_result(None, result); - Op::Sync(buf) - }; - - self.register_op(name, base_op_fn) + let (op_id, prev) = self.0.insert_full(name.to_owned(), Rc::new(op_fn)); + assert!(prev.is_none()); + op_id } - fn register_op_json_async(self: &Rc, name: &str, op_fn: F) -> OpId - where - F: Fn(Rc, Value, BufVec) -> R + 'static, - R: Future> + 'static, + pub fn route_op( + op_id: OpId, + state: Rc>, + bufs: BufVec, + ) -> Op { + if op_id == 0 { + let ops: HashMap = + state.borrow().op_table.0.keys().cloned().zip(0..).collect(); + let buf = serde_json::to_vec(&ops).map(Into::into).unwrap(); + Op::Sync(buf) + } else { + let op_fn = state + .borrow() + .op_table + .0 + .get_index(op_id) + .map(|(_, op_fn)| op_fn.clone()); + match op_fn { + Some(f) => (f)(state, bufs), + None => Op::NotFound, + } + } + } +} + +impl Default for OpTable { + fn default() -> Self { + fn dummy(_state: Rc>, _bufs: BufVec) -> Op { + unreachable!() + } + Self(once(("ops".to_owned(), Rc::new(dummy) as _)).collect()) + } +} + +#[test] +fn op_table() { + let state = Rc::new(RefCell::new(OpState::default())); + + let foo_id; + let bar_id; { - let try_dispatch_op = move |state: Rc, - bufs: BufVec| - -> Result { + let op_table = &mut state.borrow_mut().op_table; + foo_id = op_table.register_op("foo", |_, _| Op::Sync(b"oof!"[..].into())); + assert_eq!(foo_id, 1); + bar_id = op_table.register_op("bar", |_, _| Op::Sync(b"rab!"[..].into())); + assert_eq!(bar_id, 2); + } + + let foo_res = OpTable::route_op(foo_id, state.clone(), Default::default()); + assert!(matches!(foo_res, Op::Sync(buf) if &*buf == b"oof!")); + let bar_res = OpTable::route_op(bar_id, state.clone(), Default::default()); + assert!(matches!(bar_res, Op::Sync(buf) if &*buf == b"rab!")); + + let catalog_res = OpTable::route_op(0, state, Default::default()); + let mut catalog_entries = match catalog_res { + Op::Sync(buf) => serde_json::from_slice::>(&buf) + .map(|map| map.into_iter().collect::>()) + .unwrap(), + _ => panic!("unexpected `Op` variant"), + }; + catalog_entries.sort_by(|(_, id1), (_, id2)| id1.partial_cmp(id2).unwrap()); + assert_eq!( + catalog_entries, + vec![ + ("ops".to_owned(), 0), + ("foo".to_owned(), 1), + ("bar".to_owned(), 2) + ] + ) +} + +pub fn json_op_sync(op_fn: F) -> Box +where + F: Fn(&mut OpState, Value, &mut [ZeroCopyBuf]) -> Result + + 'static, +{ + Box::new(move |state: Rc>, mut bufs: BufVec| -> Op { + let result = serde_json::from_slice(&bufs[0]) + .map_err(crate::ErrBox::from) + .and_then(|args| op_fn(&mut state.borrow_mut(), args, &mut bufs[1..])); + let buf = + json_serialize_op_result(None, result, state.borrow().get_error_class_fn); + Op::Sync(buf) + }) +} + +pub fn json_op_async(op_fn: F) -> Box +where + F: Fn(Rc>, Value, BufVec) -> R + 'static, + R: Future> + 'static, +{ + let try_dispatch_op = + move |state: Rc>, bufs: BufVec| -> Result { let args: Value = serde_json::from_slice(&bufs[0])?; let promise_id = args .get("promiseId") .and_then(Value::as_u64) .ok_or_else(|| ErrBox::type_error("missing or invalid `promiseId`"))?; let bufs = bufs[1..].into(); + use crate::futures::FutureExt; let fut = op_fn(state.clone(), args, bufs).map(move |result| { - state.json_serialize_op_result(Some(promise_id), result) + json_serialize_op_result( + Some(promise_id), + result, + state.borrow().get_error_class_fn, + ) }); Ok(Op::Async(Box::pin(fut))) }; - let base_op_fn = move |state: Rc, bufs: BufVec| -> Op { - match try_dispatch_op(state.clone(), bufs) { - Ok(op) => op, - Err(err) => Op::Sync(state.json_serialize_op_result(None, Err(err))), + Box::new(move |state: Rc>, bufs: BufVec| -> Op { + match try_dispatch_op(state.clone(), bufs) { + Ok(op) => op, + Err(err) => Op::Sync(json_serialize_op_result( + None, + Err(err), + state.borrow().get_error_class_fn, + )), + } + }) +} + +fn json_serialize_op_result( + promise_id: Option, + result: Result, + get_error_class_fn: crate::runtime::GetErrorClassFn, +) -> Box<[u8]> { + let value = match result { + Ok(v) => serde_json::json!({ "ok": v, "promiseId": promise_id }), + Err(err) => serde_json::json!({ + "promiseId": promise_id , + "err": { + "className": (get_error_class_fn)(&err), + "message": err.to_string(), } - }; - - self.register_op(name, base_op_fn) - } - - fn json_serialize_op_result( - &self, - promise_id: Option, - result: Result, - ) -> Box<[u8]> { - let value = match result { - Ok(v) => json!({ "ok": v, "promiseId": promise_id }), - Err(err) => json!({ - "promiseId": promise_id , - "err": { - "className": self.get_error_class_name(&err), - "message": err.to_string(), - } - }), - }; - serde_json::to_vec(&value).unwrap().into_boxed_slice() - } - - fn get_error_class_name(&self, _err: &ErrBox) -> &'static str { - "Error" - } -} - -/// Collection for storing registered ops. The special 'get_op_catalog' -/// op with OpId `0` is automatically added when the OpTable is created. -pub struct OpTable(IndexMap>>); - -impl OpTable { - pub fn get_op_catalog(&self) -> HashMap { - self.keys().cloned().zip(0..).collect() - } - - fn op_get_op_catalog(state: Rc, _bufs: BufVec) -> Op { - let ops = state.get_op_catalog(); - let buf = serde_json::to_vec(&ops).map(Into::into).unwrap(); - Op::Sync(buf) - } -} - -impl Default for OpTable { - fn default() -> Self { - Self( - once(("ops".to_owned(), Rc::new(Self::op_get_op_catalog) as _)).collect(), - ) - } -} - -impl Deref for OpTable { - type Target = IndexMap>>; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl DerefMut for OpTable { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } + }), + }; + serde_json::to_vec(&value).unwrap().into_boxed_slice() } diff --git a/core/runtime.rs b/core/runtime.rs index 2f574b1954..e6fc230841 100644 --- a/core/runtime.rs +++ b/core/runtime.rs @@ -19,9 +19,10 @@ use crate::modules::RecursiveModuleLoad; use crate::ops::*; use crate::shared_queue::SharedQueue; use crate::shared_queue::RECOMMENDED_SIZE; +use crate::BufVec; use crate::ErrBox; use crate::JsError; -use crate::OpRouter; +use crate::OpState; use futures::stream::FuturesUnordered; use futures::stream::StreamExt; use futures::stream::StreamFuture; @@ -94,7 +95,7 @@ impl StartupData<'_> { type JsErrorCreateFn = dyn Fn(JsError) -> ErrBox; -pub type GetErrorClassFn = dyn for<'e> Fn(&'e ErrBox) -> &'static str; +pub type GetErrorClassFn = &'static dyn for<'e> Fn(&'e ErrBox) -> &'static str; /// Objects that need to live as long as the isolate #[derive(Default)] @@ -137,7 +138,8 @@ pub struct JsRuntimeState { pub(crate) pending_ops: FuturesUnordered, pub(crate) pending_unref_ops: FuturesUnordered, pub(crate) have_unpolled_ops: Cell, - pub(crate) op_router: Rc, + //pub(crate) op_table: OpTable, + pub(crate) op_state: Rc>, loader: Rc, pub modules: Modules, pub(crate) dyn_import_map: @@ -219,7 +221,6 @@ pub struct HeapLimits { pub(crate) struct IsolateOptions { loader: Rc, - op_router: Rc, startup_script: Option, startup_snapshot: Option, will_snapshot: bool, @@ -229,15 +230,10 @@ pub(crate) struct IsolateOptions { impl JsRuntime { /// startup_data defines the snapshot or script used at startup to initialize /// the isolate. - pub fn new( - op_router: Rc, - startup_data: StartupData, - will_snapshot: bool, - ) -> Self { + pub fn new(startup_data: StartupData, will_snapshot: bool) -> Self { let (startup_script, startup_snapshot) = startup_data.into_options(); let options = IsolateOptions { loader: Rc::new(NoopModuleLoader), - op_router, startup_script, startup_snapshot, will_snapshot, @@ -251,14 +247,12 @@ impl JsRuntime { /// Create new isolate that can load and execute ESModules. pub fn new_with_loader( loader: Rc, - op_router: Rc, startup_data: StartupData, will_snapshot: bool, ) -> Self { let (startup_script, startup_snapshot) = startup_data.into_options(); let options = IsolateOptions { loader, - op_router, startup_script, startup_snapshot, will_snapshot, @@ -275,14 +269,12 @@ impl JsRuntime { /// Make sure to use [`add_near_heap_limit_callback`](#method.add_near_heap_limit_callback) /// to prevent v8 from crashing when reaching the upper limit. pub fn with_heap_limits( - op_router: Rc, startup_data: StartupData, heap_limits: HeapLimits, ) -> Self { let (startup_script, startup_snapshot) = startup_data.into_options(); let options = IsolateOptions { loader: Rc::new(NoopModuleLoader), - op_router, startup_script, startup_snapshot, will_snapshot: false, @@ -347,6 +339,8 @@ impl JsRuntime { (isolate, None) }; + let op_state = OpState::default(); + isolate.set_slot(Rc::new(RefCell::new(JsRuntimeState { global_context: Some(global_context), pending_promise_exceptions: HashMap::new(), @@ -357,8 +351,8 @@ impl JsRuntime { shared: SharedQueue::new(RECOMMENDED_SIZE), pending_ops: FuturesUnordered::new(), pending_unref_ops: FuturesUnordered::new(), + op_state: Rc::new(RefCell::new(op_state)), have_unpolled_ops: Cell::new(false), - op_router: options.op_router, modules: Modules::new(), loader: options.loader, dyn_import_map: HashMap::new(), @@ -406,6 +400,12 @@ impl JsRuntime { } } + pub fn op_state(&mut self) -> Rc> { + let state_rc = Self::state(self); + let state = state_rc.borrow(); + state.op_state.clone() + } + /// Executes traditional JavaScript code (traditional = not ES modules) /// /// ErrBox can be downcast to a type that exposes additional information about @@ -477,6 +477,18 @@ impl JsRuntime { snapshot } + pub fn register_op(&mut self, name: &str, op_fn: F) -> OpId + where + F: Fn(Rc>, BufVec) -> Op + 'static, + { + Self::state(self) + .borrow_mut() + .op_state + .borrow_mut() + .op_table + .register_op(name, op_fn) + } + /// Registers a callback on the isolate when the memory limits are approached. /// Use this to prevent V8 from crashing the process when reaching the limit. /// @@ -1283,8 +1295,6 @@ impl JsRuntime { pub mod tests { use super::*; use crate::modules::ModuleSourceFuture; - use crate::ops::*; - use crate::BasicState; use crate::BufVec; use futures::future::lazy; use futures::FutureExt; @@ -1328,89 +1338,89 @@ pub mod tests { OverflowResAsync, } - struct TestOpRouter { + struct TestState { mode: Mode, dispatch_count: Arc, } - impl OpRouter for TestOpRouter { - fn route_op(self: Rc, op_id: OpId, bufs: BufVec) -> Op { - if op_id != 1 { - return Op::NotFound; + fn dispatch(op_state: Rc>, bufs: BufVec) -> Op { + let op_state_ = op_state.borrow(); + let test_state = op_state_.borrow::(); + test_state.dispatch_count.fetch_add(1, Ordering::Relaxed); + match test_state.mode { + Mode::Async => { + assert_eq!(bufs.len(), 1); + assert_eq!(bufs[0].len(), 1); + assert_eq!(bufs[0][0], 42); + let buf = vec![43u8].into_boxed_slice(); + Op::Async(futures::future::ready(buf).boxed()) } - self.dispatch_count.fetch_add(1, Ordering::Relaxed); - match self.mode { - Mode::Async => { - assert_eq!(bufs.len(), 1); - assert_eq!(bufs[0].len(), 1); - assert_eq!(bufs[0][0], 42); - let buf = vec![43u8].into_boxed_slice(); - Op::Async(futures::future::ready(buf).boxed()) - } - Mode::AsyncUnref => { - assert_eq!(bufs.len(), 1); - assert_eq!(bufs[0].len(), 1); - assert_eq!(bufs[0][0], 42); - let fut = async { - // This future never finish. - futures::future::pending::<()>().await; - vec![43u8].into_boxed_slice() - }; - Op::AsyncUnref(fut.boxed()) - } - Mode::AsyncZeroCopy(count) => { - assert_eq!(bufs.len(), count as usize); - bufs.iter().enumerate().for_each(|(idx, buf)| { - assert_eq!(buf.len(), 1); - assert_eq!(idx, buf[0] as usize); - }); + Mode::AsyncUnref => { + assert_eq!(bufs.len(), 1); + assert_eq!(bufs[0].len(), 1); + assert_eq!(bufs[0][0], 42); + let fut = async { + // This future never finish. + futures::future::pending::<()>().await; + vec![43u8].into_boxed_slice() + }; + Op::AsyncUnref(fut.boxed()) + } + Mode::AsyncZeroCopy(count) => { + assert_eq!(bufs.len(), count as usize); + bufs.iter().enumerate().for_each(|(idx, buf)| { + assert_eq!(buf.len(), 1); + assert_eq!(idx, buf[0] as usize); + }); - let buf = vec![43u8].into_boxed_slice(); - Op::Async(futures::future::ready(buf).boxed()) - } - Mode::OverflowReqSync => { - assert_eq!(bufs.len(), 1); - assert_eq!(bufs[0].len(), 100 * 1024 * 1024); - let buf = vec![43u8].into_boxed_slice(); - Op::Sync(buf) - } - Mode::OverflowResSync => { - assert_eq!(bufs.len(), 1); - assert_eq!(bufs[0].len(), 1); - assert_eq!(bufs[0][0], 42); - let mut vec = Vec::::new(); - vec.resize(100 * 1024 * 1024, 0); - vec[0] = 99; - let buf = vec.into_boxed_slice(); - Op::Sync(buf) - } - Mode::OverflowReqAsync => { - assert_eq!(bufs.len(), 1); - assert_eq!(bufs[0].len(), 100 * 1024 * 1024); - let buf = vec![43u8].into_boxed_slice(); - Op::Async(futures::future::ready(buf).boxed()) - } - Mode::OverflowResAsync => { - assert_eq!(bufs.len(), 1); - assert_eq!(bufs[0].len(), 1); - assert_eq!(bufs[0][0], 42); - let mut vec = Vec::::new(); - vec.resize(100 * 1024 * 1024, 0); - vec[0] = 4; - let buf = vec.into_boxed_slice(); - Op::Async(futures::future::ready(buf).boxed()) - } + let buf = vec![43u8].into_boxed_slice(); + Op::Async(futures::future::ready(buf).boxed()) + } + Mode::OverflowReqSync => { + assert_eq!(bufs.len(), 1); + assert_eq!(bufs[0].len(), 100 * 1024 * 1024); + let buf = vec![43u8].into_boxed_slice(); + Op::Sync(buf) + } + Mode::OverflowResSync => { + assert_eq!(bufs.len(), 1); + assert_eq!(bufs[0].len(), 1); + assert_eq!(bufs[0][0], 42); + let mut vec = Vec::::new(); + vec.resize(100 * 1024 * 1024, 0); + vec[0] = 99; + let buf = vec.into_boxed_slice(); + Op::Sync(buf) + } + Mode::OverflowReqAsync => { + assert_eq!(bufs.len(), 1); + assert_eq!(bufs[0].len(), 100 * 1024 * 1024); + let buf = vec![43u8].into_boxed_slice(); + Op::Async(futures::future::ready(buf).boxed()) + } + Mode::OverflowResAsync => { + assert_eq!(bufs.len(), 1); + assert_eq!(bufs[0].len(), 1); + assert_eq!(bufs[0][0], 42); + let mut vec = Vec::::new(); + vec.resize(100 * 1024 * 1024, 0); + vec[0] = 4; + let buf = vec.into_boxed_slice(); + Op::Async(futures::future::ready(buf).boxed()) } } } fn setup(mode: Mode) -> (JsRuntime, Arc) { let dispatch_count = Arc::new(AtomicUsize::new(0)); - let test_state = Rc::new(TestOpRouter { + let mut runtime = JsRuntime::new(StartupData::None, false); + let op_state = runtime.op_state(); + op_state.borrow_mut().put(TestState { mode, dispatch_count: dispatch_count.clone(), }); - let mut runtime = JsRuntime::new(test_state, StartupData::None, false); + + runtime.register_op("test", dispatch); js_check(runtime.execute( "setup.js", @@ -1774,8 +1784,7 @@ pub mod tests { #[test] fn syntax_error() { - let mut runtime = - JsRuntime::new(BasicState::new(), StartupData::None, false); + let mut runtime = JsRuntime::new(StartupData::None, false); let src = "hocuspocus("; let r = runtime.execute("i.js", src); let e = r.unwrap_err(); @@ -1800,29 +1809,27 @@ pub mod tests { #[test] fn will_snapshot() { let snapshot = { - let mut runtime = - JsRuntime::new(BasicState::new(), StartupData::None, true); + let mut runtime = JsRuntime::new(StartupData::None, true); js_check(runtime.execute("a.js", "a = 1 + 2")); runtime.snapshot() }; let startup_data = StartupData::Snapshot(Snapshot::JustCreated(snapshot)); - let mut runtime2 = JsRuntime::new(BasicState::new(), startup_data, false); + let mut runtime2 = JsRuntime::new(startup_data, false); js_check(runtime2.execute("check.js", "if (a != 3) throw Error('x')")); } #[test] fn test_from_boxed_snapshot() { let snapshot = { - let mut runtime = - JsRuntime::new(BasicState::new(), StartupData::None, true); + let mut runtime = JsRuntime::new(StartupData::None, true); js_check(runtime.execute("a.js", "a = 1 + 2")); let snap: &[u8] = &*runtime.snapshot(); Vec::from(snap).into_boxed_slice() }; let startup_data = StartupData::Snapshot(Snapshot::Boxed(snapshot)); - let mut runtime2 = JsRuntime::new(BasicState::new(), startup_data, false); + let mut runtime2 = JsRuntime::new(startup_data, false); js_check(runtime2.execute("check.js", "if (a != 3) throw Error('x')")); } @@ -1832,11 +1839,8 @@ pub mod tests { initial: 0, max: 20 * 1024, // 20 kB }; - let mut runtime = JsRuntime::with_heap_limits( - BasicState::new(), - StartupData::None, - heap_limits, - ); + let mut runtime = + JsRuntime::with_heap_limits(StartupData::None, heap_limits); let cb_handle = runtime.thread_safe_handle(); let callback_invoke_count = Rc::new(AtomicUsize::default()); @@ -1864,8 +1868,7 @@ pub mod tests { #[test] fn test_heap_limit_cb_remove() { - let mut runtime = - JsRuntime::new(BasicState::new(), StartupData::None, false); + let mut runtime = JsRuntime::new(StartupData::None, false); runtime.add_near_heap_limit_callback(|current_limit, _initial_limit| { current_limit * 2 @@ -1880,11 +1883,8 @@ pub mod tests { initial: 0, max: 20 * 1024, // 20 kB }; - let mut runtime = JsRuntime::with_heap_limits( - BasicState::new(), - StartupData::None, - heap_limits, - ); + let mut runtime = + JsRuntime::with_heap_limits(StartupData::None, heap_limits); let cb_handle = runtime.thread_safe_handle(); let callback_invoke_count_first = Rc::new(AtomicUsize::default()); @@ -1952,13 +1952,12 @@ pub mod tests { } let loader = Rc::new(ModsLoader::default()); - let state = BasicState::new(); let resolve_count = loader.count.clone(); let dispatch_count = Arc::new(AtomicUsize::new(0)); let dispatch_count_ = dispatch_count.clone(); - let dispatcher = move |_state: Rc, bufs: BufVec| -> Op { + let dispatcher = move |_state: Rc>, bufs: BufVec| -> Op { dispatch_count_.fetch_add(1, Ordering::Relaxed); assert_eq!(bufs.len(), 1); assert_eq!(bufs[0].len(), 1); @@ -1966,10 +1965,10 @@ pub mod tests { let buf = [43u8, 0, 0, 0][..].into(); Op::Async(futures::future::ready(buf).boxed()) }; - state.register_op("test", dispatcher); let mut runtime = - JsRuntime::new_with_loader(loader, state, StartupData::None, false); + JsRuntime::new_with_loader(loader, StartupData::None, false); + runtime.register_op("test", dispatcher); js_check(runtime.execute( "setup.js", @@ -2063,12 +2062,8 @@ pub mod tests { run_in_task(|cx| { let loader = Rc::new(DynImportErrLoader::default()); let count = loader.count.clone(); - let mut runtime = JsRuntime::new_with_loader( - loader, - BasicState::new(), - StartupData::None, - false, - ); + let mut runtime = + JsRuntime::new_with_loader(loader, StartupData::None, false); js_check(runtime.execute( "file:///dyn_import2.js", @@ -2145,12 +2140,8 @@ pub mod tests { let prepare_load_count = loader.prepare_load_count.clone(); let resolve_count = loader.resolve_count.clone(); let load_count = loader.load_count.clone(); - let mut runtime = JsRuntime::new_with_loader( - loader, - BasicState::new(), - StartupData::None, - false, - ); + let mut runtime = + JsRuntime::new_with_loader(loader, StartupData::None, false); // Dynamically import mod_b js_check(runtime.execute( @@ -2190,12 +2181,8 @@ pub mod tests { run_in_task(|cx| { let loader = Rc::new(DynImportOkLoader::default()); let prepare_load_count = loader.prepare_load_count.clone(); - let mut runtime = JsRuntime::new_with_loader( - loader, - BasicState::new(), - StartupData::None, - false, - ); + let mut runtime = + JsRuntime::new_with_loader(loader, StartupData::None, false); js_check(runtime.execute( "file:///dyn_import3.js", r#" @@ -2246,12 +2233,8 @@ pub mod tests { } let loader = std::rc::Rc::new(ModsLoader::default()); - let mut runtime = JsRuntime::new_with_loader( - loader, - BasicState::new(), - StartupData::None, - true, - ); + let mut runtime = + JsRuntime::new_with_loader(loader, StartupData::None, true); let specifier = ModuleSpecifier::resolve_url("file:///main.js").unwrap(); let source_code = "Deno.core.print('hello\\n')".to_string(); diff --git a/op_crates/web/lib.rs b/op_crates/web/lib.rs index f98dfe7c4e..03107524aa 100644 --- a/op_crates/web/lib.rs +++ b/op_crates/web/lib.rs @@ -33,7 +33,6 @@ pub fn get_declaration() -> PathBuf { #[cfg(test)] mod tests { use deno_core::js_check; - use deno_core::BasicState; use deno_core::JsRuntime; use deno_core::StartupData; use futures::future::lazy; @@ -49,8 +48,7 @@ mod tests { } fn setup() -> JsRuntime { - let mut isolate = - JsRuntime::new(BasicState::new(), StartupData::None, false); + let mut isolate = JsRuntime::new(StartupData::None, false); crate::init(&mut isolate); isolate }