summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2020-04-19 23:54:46 -0400
committerGitHub <noreply@github.com>2020-04-19 23:54:46 -0400
commitc1ec042a0011eeba2480b892a335ca7804c59180 (patch)
tree02d9595a3a6be9fb646171be29f59a3c0f74f12f
parent4e3532fe7b61a1050b00611081cc83af8b02de70 (diff)
Modify op dispatcher to include &mut Isolate argument (#4821)
- Removes unnecessary RwLock and Rc around the op registry table - Preparation to move resource_table to deno_core::Isolate. - Towards #3453, #4222
-rw-r--r--cli/ops/dispatch_json.rs16
-rw-r--r--cli/ops/dispatch_minimal.rs8
-rw-r--r--cli/ops/plugins.rs21
-rw-r--r--cli/ops/web_worker.rs18
-rw-r--r--cli/state.rs47
-rw-r--r--cli/web_worker.rs3
-rw-r--r--cli/worker.rs3
-rw-r--r--core/es_isolate.rs18
-rw-r--r--core/examples/http_bench.rs64
-rw-r--r--core/isolate.rs128
-rw-r--r--core/ops.rs119
-rw-r--r--core/plugins.rs8
-rw-r--r--deno_typescript/lib.rs14
-rw-r--r--test_plugin/src/lib.rs12
14 files changed, 274 insertions, 205 deletions
diff --git a/cli/ops/dispatch_json.rs b/cli/ops/dispatch_json.rs
index b1a7bc723..bfffd6d09 100644
--- a/cli/ops/dispatch_json.rs
+++ b/cli/ops/dispatch_json.rs
@@ -41,11 +41,19 @@ struct AsyncArgs {
promise_id: Option<u64>,
}
-pub fn json_op<D>(d: D) -> impl Fn(&[u8], Option<ZeroCopyBuf>) -> Op
+pub fn json_op<D>(
+ d: D,
+) -> impl Fn(&mut deno_core::Isolate, &[u8], Option<ZeroCopyBuf>) -> Op
where
- D: Fn(Value, Option<ZeroCopyBuf>) -> Result<JsonOp, OpError>,
+ D: Fn(
+ &mut deno_core::Isolate,
+ Value,
+ Option<ZeroCopyBuf>,
+ ) -> Result<JsonOp, OpError>,
{
- move |control: &[u8], zero_copy: Option<ZeroCopyBuf>| {
+ move |isolate: &mut deno_core::Isolate,
+ control: &[u8],
+ zero_copy: Option<ZeroCopyBuf>| {
let async_args: AsyncArgs = match serde_json::from_slice(control) {
Ok(args) => args,
Err(e) => {
@@ -58,7 +66,7 @@ where
let result = serde_json::from_slice(control)
.map_err(OpError::from)
- .and_then(|args| d(args, zero_copy));
+ .and_then(|args| d(isolate, args, zero_copy));
// Convert to Op
match result {
diff --git a/cli/ops/dispatch_minimal.rs b/cli/ops/dispatch_minimal.rs
index 7fdd12401..37907d60c 100644
--- a/cli/ops/dispatch_minimal.rs
+++ b/cli/ops/dispatch_minimal.rs
@@ -113,11 +113,15 @@ fn test_parse_min_record() {
assert_eq!(parse_min_record(&buf), None);
}
-pub fn minimal_op<D>(d: D) -> impl Fn(&[u8], Option<ZeroCopyBuf>) -> Op
+pub fn minimal_op<D>(
+ d: D,
+) -> impl Fn(&mut deno_core::Isolate, &[u8], Option<ZeroCopyBuf>) -> Op
where
D: Fn(bool, i32, Option<ZeroCopyBuf>) -> MinimalOp,
{
- move |control: &[u8], zero_copy: Option<ZeroCopyBuf>| {
+ move |_isolate: &mut deno_core::Isolate,
+ control: &[u8],
+ zero_copy: Option<ZeroCopyBuf>| {
let mut record = match parse_min_record(control) {
Some(r) => r,
None => {
diff --git a/cli/ops/plugins.rs b/cli/ops/plugins.rs
index 816c7ebb4..c0dffc90f 100644
--- a/cli/ops/plugins.rs
+++ b/cli/ops/plugins.rs
@@ -3,20 +3,21 @@ use crate::fs as deno_fs;
use crate::op_error::OpError;
use crate::ops::json_op;
use crate::state::State;
-use deno_core::*;
+use deno_core::Isolate;
+use deno_core::OpDispatcher;
+use deno_core::OpId;
+use deno_core::PluginInitContext;
+use deno_core::PluginInitFn;
+use deno_core::ZeroCopyBuf;
use dlopen::symbor::Library;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::path::Path;
-use std::rc::Rc;
-pub fn init(i: &mut Isolate, s: &State, r: Rc<deno_core::OpRegistry>) {
- let r_ = r;
+pub fn init(i: &mut Isolate, s: &State) {
i.register_op(
"op_open_plugin",
- s.core_op(json_op(s.stateful_op(move |state, args, zero_copy| {
- op_open_plugin(&r_, state, args, zero_copy)
- }))),
+ s.core_op(json_op(s.stateful_op2(op_open_plugin))),
);
}
@@ -52,7 +53,7 @@ struct OpenPluginArgs {
}
pub fn op_open_plugin(
- registry: &Rc<deno_core::OpRegistry>,
+ isolate: &mut deno_core::Isolate,
state: &State,
args: Value,
_zero_copy: Option<ZeroCopyBuf>,
@@ -91,8 +92,8 @@ pub fn op_open_plugin(
// The inclusion of prefix and rid is designed to avoid any
// op name collision beyond the bound of a single loaded
// plugin instance.
- let op_id = registry
- .register(&format!("plugin_{}_{}", rid, op.0), state.core_op(op.1));
+ let op_id = isolate
+ .register_op(&format!("plugin_{}_{}", rid, op.0), state.core_op(op.1));
plugin_resource.ops.insert(op.0, op_id);
}
diff --git a/cli/ops/web_worker.rs b/cli/ops/web_worker.rs
index 8cade7d40..ee376719f 100644
--- a/cli/ops/web_worker.rs
+++ b/cli/ops/web_worker.rs
@@ -12,7 +12,11 @@ use std::convert::From;
pub fn web_worker_op<D>(
sender: mpsc::Sender<WorkerEvent>,
dispatcher: D,
-) -> impl Fn(Value, Option<ZeroCopyBuf>) -> Result<JsonOp, OpError>
+) -> impl Fn(
+ &mut deno_core::Isolate,
+ Value,
+ Option<ZeroCopyBuf>,
+) -> Result<JsonOp, OpError>
where
D: Fn(
&mpsc::Sender<WorkerEvent>,
@@ -20,7 +24,8 @@ where
Option<ZeroCopyBuf>,
) -> Result<JsonOp, OpError>,
{
- move |args: Value,
+ move |_isolate: &mut deno_core::Isolate,
+ args: Value,
zero_copy: Option<ZeroCopyBuf>|
-> Result<JsonOp, OpError> { dispatcher(&sender, args, zero_copy) }
}
@@ -29,7 +34,11 @@ pub fn web_worker_op2<D>(
handle: WebWorkerHandle,
sender: mpsc::Sender<WorkerEvent>,
dispatcher: D,
-) -> impl Fn(Value, Option<ZeroCopyBuf>) -> Result<JsonOp, OpError>
+) -> impl Fn(
+ &mut deno_core::Isolate,
+ Value,
+ Option<ZeroCopyBuf>,
+) -> Result<JsonOp, OpError>
where
D: Fn(
WebWorkerHandle,
@@ -38,7 +47,8 @@ where
Option<ZeroCopyBuf>,
) -> Result<JsonOp, OpError>,
{
- move |args: Value,
+ move |_isolate: &mut deno_core::Isolate,
+ args: Value,
zero_copy: Option<ZeroCopyBuf>|
-> Result<JsonOp, OpError> {
dispatcher(handle.clone(), &sender, args, zero_copy)
diff --git a/cli/state.rs b/cli/state.rs
index 82ac8c4c1..856190134 100644
--- a/cli/state.rs
+++ b/cli/state.rs
@@ -73,7 +73,7 @@ impl State {
pub fn stateful_json_op<D>(
&self,
dispatcher: D,
- ) -> impl Fn(&[u8], Option<ZeroCopyBuf>) -> Op
+ ) -> impl Fn(&mut deno_core::Isolate, &[u8], Option<ZeroCopyBuf>) -> Op
where
D: Fn(&State, Value, Option<ZeroCopyBuf>) -> Result<JsonOp, OpError>,
{
@@ -85,18 +85,21 @@ impl State {
pub fn core_op<D>(
&self,
dispatcher: D,
- ) -> impl Fn(&[u8], Option<ZeroCopyBuf>) -> Op
+ ) -> impl Fn(&mut deno_core::Isolate, &[u8], Option<ZeroCopyBuf>) -> Op
where
- D: Fn(&[u8], Option<ZeroCopyBuf>) -> Op,
+ D: Fn(&mut deno_core::Isolate, &[u8], Option<ZeroCopyBuf>) -> Op,
{
let state = self.clone();
- move |control: &[u8], zero_copy: Option<ZeroCopyBuf>| -> Op {
+ move |isolate: &mut deno_core::Isolate,
+ control: &[u8],
+ zero_copy: Option<ZeroCopyBuf>|
+ -> Op {
let bytes_sent_control = control.len() as u64;
let bytes_sent_zero_copy =
zero_copy.as_ref().map(|b| b.len()).unwrap_or(0) as u64;
- let op = dispatcher(control, zero_copy);
+ let op = dispatcher(isolate, control, zero_copy);
match op {
Op::Sync(buf) => {
@@ -162,15 +165,45 @@ impl State {
pub fn stateful_op<D>(
&self,
dispatcher: D,
- ) -> impl Fn(Value, Option<ZeroCopyBuf>) -> Result<JsonOp, OpError>
+ ) -> impl Fn(
+ &mut deno_core::Isolate,
+ Value,
+ Option<ZeroCopyBuf>,
+ ) -> Result<JsonOp, OpError>
where
D: Fn(&State, Value, Option<ZeroCopyBuf>) -> Result<JsonOp, OpError>,
{
let state = self.clone();
- move |args: Value,
+ move |_isolate: &mut deno_core::Isolate,
+ args: Value,
zero_copy: Option<ZeroCopyBuf>|
-> Result<JsonOp, OpError> { dispatcher(&state, args, zero_copy) }
}
+
+ pub fn stateful_op2<D>(
+ &self,
+ dispatcher: D,
+ ) -> impl Fn(
+ &mut deno_core::Isolate,
+ Value,
+ Option<ZeroCopyBuf>,
+ ) -> Result<JsonOp, OpError>
+ where
+ D: Fn(
+ &mut deno_core::Isolate,
+ &State,
+ Value,
+ Option<ZeroCopyBuf>,
+ ) -> Result<JsonOp, OpError>,
+ {
+ let state = self.clone();
+ move |isolate: &mut deno_core::Isolate,
+ args: Value,
+ zero_copy: Option<ZeroCopyBuf>|
+ -> Result<JsonOp, OpError> {
+ dispatcher(isolate, &state, args, zero_copy)
+ }
+ }
}
impl ModuleLoader for State {
diff --git a/cli/web_worker.rs b/cli/web_worker.rs
index 24318fc59..fc1575c5f 100644
--- a/cli/web_worker.rs
+++ b/cli/web_worker.rs
@@ -133,11 +133,10 @@ impl WebWorker {
ops::fetch::init(isolate, &state);
if has_deno_namespace {
- let op_registry = isolate.op_registry.clone();
ops::runtime_compiler::init(isolate, &state);
ops::fs::init(isolate, &state);
ops::fs_events::init(isolate, &state);
- ops::plugins::init(isolate, &state, op_registry);
+ ops::plugins::init(isolate, &state);
ops::net::init(isolate, &state);
ops::tls::init(isolate, &state);
ops::os::init(isolate, &state);
diff --git a/cli/worker.rs b/cli/worker.rs
index 6f2818980..cdbf8c42d 100644
--- a/cli/worker.rs
+++ b/cli/worker.rs
@@ -222,7 +222,6 @@ impl MainWorker {
let state_ = state.clone();
let mut worker = Worker::new(name, startup_data, state_);
{
- let op_registry = worker.isolate.op_registry.clone();
let isolate = &mut worker.isolate;
ops::runtime::init(isolate, &state);
ops::runtime_compiler::init(isolate, &state);
@@ -231,7 +230,7 @@ impl MainWorker {
ops::fs::init(isolate, &state);
ops::fs_events::init(isolate, &state);
ops::io::init(isolate, &state);
- ops::plugins::init(isolate, &state, op_registry);
+ ops::plugins::init(isolate, &state);
ops::net::init(isolate, &state);
ops::tls::init(isolate, &state);
ops::os::init(isolate, &state);
diff --git a/core/es_isolate.rs b/core/es_isolate.rs
index 8c2e5b26d..f50a3abb0 100644
--- a/core/es_isolate.rs
+++ b/core/es_isolate.rs
@@ -580,14 +580,16 @@ pub mod tests {
let mut isolate = EsIsolate::new(loader, StartupData::None, false);
- let dispatcher =
- move |control: &[u8], _zero_copy: Option<ZeroCopyBuf>| -> Op {
- dispatch_count_.fetch_add(1, Ordering::Relaxed);
- assert_eq!(control.len(), 1);
- assert_eq!(control[0], 42);
- let buf = vec![43u8, 0, 0, 0].into_boxed_slice();
- Op::Async(futures::future::ready(buf).boxed())
- };
+ let dispatcher = move |_isolate: &mut Isolate,
+ control: &[u8],
+ _zero_copy: Option<ZeroCopyBuf>|
+ -> Op {
+ dispatch_count_.fetch_add(1, Ordering::Relaxed);
+ assert_eq!(control.len(), 1);
+ assert_eq!(control[0], 42);
+ let buf = vec![43u8, 0, 0, 0].into_boxed_slice();
+ Op::Async(futures::future::ready(buf).boxed())
+ };
isolate.register_op("test", dispatcher);
diff --git a/core/examples/http_bench.rs b/core/examples/http_bench.rs
index 27fefc8bb..9e5808043 100644
--- a/core/examples/http_bench.rs
+++ b/core/examples/http_bench.rs
@@ -111,20 +111,22 @@ impl Isolate {
F: 'static + Fn(State, u32, Option<ZeroCopyBuf>) -> Result<u32, Error>,
{
let state = self.state.clone();
- let core_handler =
- move |control_buf: &[u8], zero_copy_buf: Option<ZeroCopyBuf>| -> Op {
- let state = state.clone();
- let record = Record::from(control_buf);
- let is_sync = record.promise_id == 0;
- assert!(is_sync);
-
- let result: i32 = match handler(state, record.rid, zero_copy_buf) {
- Ok(r) => r as i32,
- Err(_) => -1,
- };
- let buf = RecordBuf::from(Record { result, ..record })[..].into();
- Op::Sync(buf)
+ let core_handler = move |_isolate: &mut deno_core::Isolate,
+ control_buf: &[u8],
+ zero_copy_buf: Option<ZeroCopyBuf>|
+ -> Op {
+ let state = state.clone();
+ let record = Record::from(control_buf);
+ let is_sync = record.promise_id == 0;
+ assert!(is_sync);
+
+ let result: i32 = match handler(state, record.rid, zero_copy_buf) {
+ Ok(r) => r as i32,
+ Err(_) => -1,
};
+ let buf = RecordBuf::from(Record { result, ..record })[..].into();
+ Op::Sync(buf)
+ };
self.core_isolate.register_op(name, core_handler);
}
@@ -139,25 +141,27 @@ impl Isolate {
<F::Ok as TryInto<i32>>::Error: Debug,
{
let state = self.state.clone();
- let core_handler =
- move |control_buf: &[u8], zero_copy_buf: Option<ZeroCopyBuf>| -> Op {
- let state = state.clone();
- let record = Record::from(control_buf);
- let is_sync = record.promise_id == 0;
- assert!(!is_sync);
-
- let fut = async move {
- let op = handler(state, record.rid, zero_copy_buf);
- let result = op
- .map_ok(|r| r.try_into().expect("op result does not fit in i32"))
- .unwrap_or_else(|_| -1)
- .await;
- RecordBuf::from(Record { result, ..record })[..].into()
- };
-
- Op::Async(fut.boxed_local())
+ let core_handler = move |_isolate: &mut deno_core::Isolate,
+ control_buf: &[u8],
+ zero_copy_buf: Option<ZeroCopyBuf>|
+ -> Op {
+ let state = state.clone();
+ let record = Record::from(control_buf);
+ let is_sync = record.promise_id == 0;
+ assert!(!is_sync);
+
+ let fut = async move {
+ let op = handler(state, record.rid, zero_copy_buf);
+ let result = op
+ .map_ok(|r| r.try_into().expect("op result does not fit in i32"))
+ .unwrap_or_else(|_| -1)
+ .await;
+ RecordBuf::from(Record { result, ..record })[..].into()
};
+ Op::Async(fut.boxed_local())
+ };
+
self.core_isolate.register_op(name, core_handler);
}
}
diff --git a/core/isolate.rs b/core/isolate.rs
index 18cd84eae..c289f38e8 100644
--- a/core/isolate.rs
+++ b/core/isolate.rs
@@ -28,7 +28,6 @@ use std::mem::forget;
use std::ops::{Deref, DerefMut};
use std::option::Option;
use std::pin::Pin;
-use std::rc::Rc;
use std::sync::{Arc, Mutex, Once};
use std::task::Context;
use std::task::Poll;
@@ -177,7 +176,7 @@ pub struct Isolate {
pending_unref_ops: FuturesUnordered<PendingOpFuture>,
have_unpolled_ops: bool,
startup_script: Option<OwnedScript>,
- pub op_registry: Rc<OpRegistry>,
+ pub op_registry: OpRegistry,
waker: AtomicWaker,
error_handler: Option<Box<IsolateErrorHandleFn>>,
}
@@ -313,7 +312,7 @@ impl Isolate {
pending_unref_ops: FuturesUnordered::new(),
have_unpolled_ops: false,
startup_script,
- op_registry: Rc::new(OpRegistry::new()),
+ op_registry: OpRegistry::new(),
waker: AtomicWaker::new(),
error_handler: None,
};
@@ -343,9 +342,9 @@ impl Isolate {
/// corresponds to the second argument of Deno.core.dispatch().
///
/// Requires runtime to explicitly ask for op ids before using any of the ops.
- pub fn register_op<F>(&self, name: &str, op: F) -> OpId
+ pub fn register_op<F>(&mut self, name: &str, op: F) -> OpId
where
- F: Fn(&[u8], Option<ZeroCopyBuf>) -> Op + 'static,
+ F: Fn(&mut Isolate, &[u8], Option<ZeroCopyBuf>) -> Op + 'static,
{
self.op_registry.register(name, op)
}
@@ -381,17 +380,14 @@ impl Isolate {
control_buf: &[u8],
zero_copy_buf: Option<ZeroCopyBuf>,
) -> Option<(OpId, Box<[u8]>)> {
- let maybe_op = self.op_registry.call(op_id, control_buf, zero_copy_buf);
-
- let op = match maybe_op {
- Some(op) => op,
- None => {
- let message =
- v8::String::new(scope, &format!("Unknown op id: {}", op_id)).unwrap();
- let exception = v8::Exception::type_error(scope, message);
- scope.isolate().throw_exception(exception);
- return None;
- }
+ let op = if let Some(dispatcher) = self.op_registry.get(op_id) {
+ dispatcher(self, control_buf, zero_copy_buf)
+ } else {
+ let message =
+ v8::String::new(scope, &format!("Unknown op id: {}", op_id)).unwrap();
+ let exception = v8::Exception::type_error(scope, message);
+ scope.isolate().throw_exception(exception);
+ return None;
};
debug_assert_eq!(self.shared.size(), 0);
@@ -768,56 +764,58 @@ pub mod tests {
let mut isolate = Isolate::new(StartupData::None, false);
- let dispatcher =
- move |control: &[u8], _zero_copy: Option<ZeroCopyBuf>| -> Op {
- dispatch_count_.fetch_add(1, Ordering::Relaxed);
- match mode {
- Mode::Async => {
- assert_eq!(control.len(), 1);
- assert_eq!(control[0], 42);
- let buf = vec![43u8].into_boxed_slice();
- Op::Async(futures::future::ready(buf).boxed())
- }
- Mode::AsyncUnref => {
- assert_eq!(control.len(), 1);
- assert_eq!(control[0], 42);
- let fut = async {
- // This future never finish.
- futures::future::pending::<()>().await;
- vec![43u8].into_boxed_slice()
- };
- Op::AsyncUnref(fut.boxed())
- }
- Mode::OverflowReqSync => {
- assert_eq!(control.len(), 100 * 1024 * 1024);
- let buf = vec![43u8].into_boxed_slice();
- Op::Sync(buf)
- }
- Mode::OverflowResSync => {
- assert_eq!(control.len(), 1);
- assert_eq!(control[0], 42);
- let mut vec = Vec::<u8>::new();
- vec.resize(100 * 1024 * 1024, 0);
- vec[0] = 99;
- let buf = vec.into_boxed_slice();
- Op::Sync(buf)
- }
- Mode::OverflowReqAsync => {
- assert_eq!(control.len(), 100 * 1024 * 1024);
- let buf = vec![43u8].into_boxed_slice();
- Op::Async(futures::future::ready(buf).boxed())
- }
- Mode::OverflowResAsync => {
- assert_eq!(control.len(), 1);
- assert_eq!(control[0], 42);
- let mut vec = Vec::<u8>::new();
- vec.resize(100 * 1024 * 1024, 0);
- vec[0] = 4;
- let buf = vec.into_boxed_slice();
- Op::Async(futures::future::ready(buf).boxed())
- }
+ let dispatcher = move |_isolate: &mut Isolate,
+ control: &[u8],
+ _zero_copy: Option<ZeroCopyBuf>|
+ -> Op {
+ dispatch_count_.fetch_add(1, Ordering::Relaxed);
+ match mode {
+ Mode::Async => {
+ assert_eq!(control.len(), 1);
+ assert_eq!(control[0], 42);
+ let buf = vec![43u8].into_boxed_slice();
+ Op::Async(futures::future::ready(buf).boxed())
}
- };
+ Mode::AsyncUnref => {
+ assert_eq!(control.len(), 1);
+ assert_eq!(control[0], 42);
+ let fut = async {
+ // This future never finish.
+ futures::future::pending::<()>().await;
+ vec![43u8].into_boxed_slice()
+ };
+ Op::AsyncUnref(fut.boxed())
+ }
+ Mode::OverflowReqSync => {
+ assert_eq!(control.len(), 100 * 1024 * 1024);
+ let buf = vec![43u8].into_boxed_slice();
+ Op::Sync(buf)
+ }
+ Mode::OverflowResSync => {
+ assert_eq!(control.len(), 1);
+ assert_eq!(control[0], 42);
+ let mut vec = Vec::<u8>::new();
+ vec.resize(100 * 1024 * 1024, 0);
+ vec[0] = 99;
+ let buf = vec.into_boxed_slice();
+ Op::Sync(buf)
+ }
+ Mode::OverflowReqAsync => {
+ assert_eq!(control.len(), 100 * 1024 * 1024);
+ let buf = vec![43u8].into_boxed_slice();
+ Op::Async(futures::future::ready(buf).boxed())
+ }
+ Mode::OverflowResAsync => {
+ assert_eq!(control.len(), 1);
+ assert_eq!(control[0], 42);
+ let mut vec = Vec::<u8>::new();
+ vec.resize(100 * 1024 * 1024, 0);
+ vec[0] = 4;
+ let buf = vec.into_boxed_slice();
+ Op::Async(futures::future::ready(buf).boxed())
+ }
+ }
+ };
isolate.register_op("test", dispatcher);
diff --git a/core/ops.rs b/core/ops.rs
index ab183f4de..ed9b27e46 100644
--- a/core/ops.rs
+++ b/core/ops.rs
@@ -1,10 +1,10 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+use crate::Isolate;
use crate::ZeroCopyBuf;
use futures::Future;
use std::collections::HashMap;
use std::pin::Pin;
use std::rc::Rc;
-use std::sync::RwLock;
pub type OpId = u32;
@@ -21,72 +21,48 @@ pub enum Op {
}
/// Main type describing op
-pub type OpDispatcher = dyn Fn(&[u8], Option<ZeroCopyBuf>) -> Op + 'static;
+pub type OpDispatcher =
+ dyn Fn(&mut Isolate, &[u8], Option<ZeroCopyBuf>) -> Op + 'static;
#[derive(Default)]
pub struct OpRegistry {
- dispatchers: RwLock<Vec<Rc<OpDispatcher>>>,
- name_to_id: RwLock<HashMap<String, OpId>>,
+ dispatchers: Vec<Rc<OpDispatcher>>,
+ name_to_id: HashMap<String, OpId>,
}
impl OpRegistry {
pub fn new() -> Self {
- let registry = Self::default();
- let op_id = registry.register("ops", |_, _| {
- // ops is a special op which is handled in call.
- unreachable!()
+ let mut registry = Self::default();
+ let op_id = registry.register("ops", |isolate, _, _| {
+ let buf = isolate.op_registry.json_map();
+ Op::Sync(buf)
});
assert_eq!(op_id, 0);
registry
}
- pub fn register<F>(&self, name: &str, op: F) -> OpId
+ pub fn register<F>(&mut self, name: &str, op: F) -> OpId
where
- F: Fn(&[u8], Option<ZeroCopyBuf>) -> Op + 'static,
+ F: Fn(&mut Isolate, &[u8], Option<ZeroCopyBuf>) -> Op + 'static,
{
- let mut lock = self.dispatchers.write().unwrap();
- let op_id = lock.len() as u32;
+ let op_id = self.dispatchers.len() as u32;
- let mut name_lock = self.name_to_id.write().unwrap();
- let existing = name_lock.insert(name.to_string(), op_id);
+ let existing = self.name_to_id.insert(name.to_string(), op_id);
assert!(
existing.is_none(),
format!("Op already registered: {}", name)
);
- lock.push(Rc::new(op));
- drop(name_lock);
- drop(lock);
+ self.dispatchers.push(Rc::new(op));
op_id
}
fn json_map(&self) -> Buf {
- let lock = self.name_to_id.read().unwrap();
- let op_map_json = serde_json::to_string(&*lock).unwrap();
+ let op_map_json = serde_json::to_string(&self.name_to_id).unwrap();
op_map_json.as_bytes().to_owned().into_boxed_slice()
}
- /// This function returns None only if op with given id doesn't exist in registry.
- pub fn call(
- &self,
- op_id: OpId,
- control: &[u8],
- zero_copy_buf: Option<ZeroCopyBuf>,
- ) -> Option<Op> {
- // Op with id 0 has special meaning - it's a special op that is always
- // provided to retrieve op id map. The map consists of name to `OpId`
- // mappings.
- if op_id == 0 {
- return Some(Op::Sync(self.json_map()));
- }
- let lock = self.dispatchers.read().unwrap();
- if let Some(op) = lock.get(op_id as usize) {
- let op_ = Rc::clone(&op);
- // This should allow for changes to the dispatcher list during a call.
- drop(lock);
- Some(op_(control, zero_copy_buf))
- } else {
- None
- }
+ pub fn get(&self, op_id: OpId) -> Option<Rc<OpDispatcher>> {
+ self.dispatchers.get(op_id as usize).map(Rc::clone)
}
}
@@ -94,12 +70,12 @@ impl OpRegistry {
fn test_op_registry() {
use std::sync::atomic;
use std::sync::Arc;
- let op_registry = OpRegistry::new();
+ let mut op_registry = OpRegistry::new();
let c = Arc::new(atomic::AtomicUsize::new(0));
let c_ = c.clone();
- let test_id = op_registry.register("test", move |_, _| {
+ let test_id = op_registry.register("test", move |_, _, _| {
c_.fetch_add(1, atomic::Ordering::SeqCst);
Op::Sync(Box::new([]))
});
@@ -108,10 +84,12 @@ fn test_op_registry() {
let mut expected = HashMap::new();
expected.insert("ops".to_string(), 0);
expected.insert("test".to_string(), 1);
- let name_to_id = op_registry.name_to_id.read().unwrap();
- assert_eq!(*name_to_id, expected);
+ assert_eq!(op_registry.name_to_id, expected);
- let res = op_registry.call(test_id, &[], None).unwrap();
+ let mut isolate = Isolate::new(crate::StartupData::None, false);
+
+ let dispatch = op_registry.get(test_id).unwrap();
+ let res = dispatch(&mut isolate, &[], None);
if let Op::Sync(buf) = res {
assert_eq!(buf.len(), 0);
} else {
@@ -119,40 +97,57 @@ fn test_op_registry() {
}
assert_eq!(c.load(atomic::Ordering::SeqCst), 1);
- let res = op_registry.call(100, &[], None);
- assert!(res.is_none());
+ assert!(op_registry.get(100).is_none());
}
#[test]
fn register_op_during_call() {
use std::sync::atomic;
use std::sync::Arc;
- let op_registry = Arc::new(OpRegistry::new());
+ use std::sync::Mutex;
+ let op_registry = Arc::new(Mutex::new(OpRegistry::new()));
let c = Arc::new(atomic::AtomicUsize::new(0));
let c_ = c.clone();
let op_registry_ = op_registry.clone();
- let test_id = op_registry.register("dynamic_register_op", move |_, _| {
- let c__ = c_.clone();
- op_registry_.register("test", move |_, _| {
- c__.fetch_add(1, atomic::Ordering::SeqCst);
+
+ let test_id = {
+ let mut g = op_registry.lock().unwrap();
+ g.register("dynamic_register_op", move |_, _, _| {
+ let c__ = c_.clone();
+ let mut g = op_registry_.lock().unwrap();
+ g.register("test", move |_, _, _| {
+ c__.fetch_add(1, atomic::Ordering::SeqCst);
+ Op::Sync(Box::new([]))
+ });
Op::Sync(Box::new([]))
- });
- Op::Sync(Box::new([]))
- });
+ })
+ };
assert!(test_id != 0);
- op_registry.call(test_id, &[], None);
+ let mut isolate = Isolate::new(crate::StartupData::None, false);
+
+ let dispatcher1 = {
+ let g = op_registry.lock().unwrap();
+ g.get(test_id).unwrap()
+ };
+ dispatcher1(&mut isolate, &[], None);
let mut expected = HashMap::new();
expected.insert("ops".to_string(), 0);
expected.insert("dynamic_register_op".to_string(), 1);
expected.insert("test".to_string(), 2);
- let name_to_id = op_registry.name_to_id.read().unwrap();
- assert_eq!(*name_to_id, expected);
+ {
+ let g = op_registry.lock().unwrap();
+ assert_eq!(g.name_to_id, expected);
+ }
- let res = op_registry.call(2, &[], None).unwrap();
+ let dispatcher2 = {
+ let g = op_registry.lock().unwrap();
+ g.get(2).unwrap()
+ };
+ let res = dispatcher2(&mut isolate, &[], None);
if let Op::Sync(buf) = res {
assert_eq!(buf.len(), 0);
} else {
@@ -160,6 +155,6 @@ fn register_op_during_call() {
}
assert_eq!(c.load(atomic::Ordering::SeqCst), 1);
- let res = op_registry.call(100, &[], None);
- assert!(res.is_none());
+ let g = op_registry.lock().unwrap();
+ assert!(g.get(100).is_none());
}
diff --git a/core/plugins.rs b/core/plugins.rs
index c6e63c975..a423790bc 100644
--- a/core/plugins.rs
+++ b/core/plugins.rs
@@ -1,5 +1,7 @@
-use crate::isolate::ZeroCopyBuf;
-use crate::ops::Op;
+// TODO(ry) This plugin module is superfluous. Try to remove definitions for
+// "init_fn!", "PluginInitFn", and "PluginInitContext".
+
+use crate::ops::OpDispatcher;
pub type PluginInitFn = fn(context: &mut dyn PluginInitContext);
@@ -7,7 +9,7 @@ pub trait PluginInitContext {
fn register_op(
&mut self,
name: &str,
- op: Box<dyn Fn(&[u8], Option<ZeroCopyBuf>) -> Op + 'static>,
+ op: Box<OpDispatcher>, // TODO(ry) rename to dispatcher, not op.
);
}
diff --git a/deno_typescript/lib.rs b/deno_typescript/lib.rs
index cd843041e..24ecd6287 100644
--- a/deno_typescript/lib.rs
+++ b/deno_typescript/lib.rs
@@ -49,11 +49,14 @@ pub struct TSState {
fn compiler_op<D>(
ts_state: Arc<Mutex<TSState>>,
dispatcher: D,
-) -> impl Fn(&[u8], Option<ZeroCopyBuf>) -> Op
+) -> impl Fn(&mut deno_core::Isolate, &[u8], Option<ZeroCopyBuf>) -> Op
where
D: Fn(&mut TSState, &[u8]) -> Op,
{
- move |control: &[u8], zero_copy_buf: Option<ZeroCopyBuf>| -> Op {
+ move |_isolate: &mut deno_core::Isolate,
+ control: &[u8],
+ zero_copy_buf: Option<ZeroCopyBuf>|
+ -> Op {
assert!(zero_copy_buf.is_none()); // zero_copy_buf unused in compiler.
let mut s = ts_state.lock().unwrap();
dispatcher(&mut s, control)
@@ -326,11 +329,14 @@ pub fn trace_serializer() {
/// Isolate.
pub fn op_fetch_asset<S: ::std::hash::BuildHasher>(
custom_assets: HashMap<String, PathBuf, S>,
-) -> impl Fn(&[u8], Option<ZeroCopyBuf>) -> Op {
+) -> impl Fn(&mut deno_core::Isolate, &[u8], Option<ZeroCopyBuf>) -> Op {
for (_, path) in custom_assets.iter() {
println!("cargo:rerun-if-changed={}", path.display());
}
- move |control: &[u8], zero_copy_buf: Option<ZeroCopyBuf>| -> Op {
+ move |_isolate: &mut deno_core::Isolate,
+ control: &[u8],
+ zero_copy_buf: Option<ZeroCopyBuf>|
+ -> Op {
assert!(zero_copy_buf.is_none()); // zero_copy_buf unused in this op.
let name = std::str::from_utf8(control).unwrap();
diff --git a/test_plugin/src/lib.rs b/test_plugin/src/lib.rs
index 70ba6d9b2..c88052e9a 100644
--- a/test_plugin/src/lib.rs
+++ b/test_plugin/src/lib.rs
@@ -13,7 +13,11 @@ fn init(context: &mut dyn PluginInitContext) {
}
init_fn!(init);
-pub fn op_test_sync(data: &[u8], zero_copy: Option<ZeroCopyBuf>) -> Op {
+pub fn op_test_sync(
+ _isolate: &mut deno_core::Isolate,
+ data: &[u8],
+ zero_copy: Option<ZeroCopyBuf>,
+) -> Op {
if let Some(buf) = zero_copy {
let data_str = std::str::from_utf8(&data[..]).unwrap();
let buf_str = std::str::from_utf8(&buf[..]).unwrap();
@@ -27,7 +31,11 @@ pub fn op_test_sync(data: &[u8], zero_copy: Option<ZeroCopyBuf>) -> Op {
Op::Sync(result_box)
}
-pub fn op_test_async(data: &[u8], zero_copy: Option<ZeroCopyBuf>) -> Op {
+pub fn op_test_async(
+ _isolate: &mut deno_core::Isolate,
+ data: &[u8],
+ zero_copy: Option<ZeroCopyBuf>,
+) -> Op {
let data_str = std::str::from_utf8(&data[..]).unwrap().to_string();
let fut = async move {
if let Some(buf) = zero_copy {