summaryrefslogtreecommitdiff
path: root/core/ops.rs
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2022-03-14 23:14:15 +0530
committerGitHub <noreply@github.com>2022-03-14 18:44:15 +0100
commitb4e42953e1d243f2eda20e5be6b845d60b7bf688 (patch)
tree10b3bfff165f9c04f9174c7c399d44b9b724c3b3 /core/ops.rs
parent4e3ed37037a2aa1edeac260dc3463a81d9cf9b88 (diff)
feat(core): codegen ops (#13861)
Co-authored-by: Aaron O'Mullan <aaron.omullan@gmail.com>
Diffstat (limited to 'core/ops.rs')
-rw-r--r--core/ops.rs147
1 files changed, 23 insertions, 124 deletions
diff --git a/core/ops.rs b/core/ops.rs
index 50197c9be..42718b8ff 100644
--- a/core/ops.rs
+++ b/core/ops.rs
@@ -1,10 +1,9 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
-use crate::error::type_error;
use crate::gotham_state::GothamState;
-use crate::ops_metrics::OpsTracker;
use crate::resources::ResourceTable;
use crate::runtime::GetErrorClassFn;
+use crate::OpsTracker;
use anyhow::Error;
use futures::future::maybe_done;
use futures::future::FusedFuture;
@@ -12,23 +11,19 @@ use futures::future::MaybeDone;
use futures::ready;
use futures::task::noop_waker;
use futures::Future;
-use indexmap::IndexMap;
-use serde::de::DeserializeOwned;
use serde::Serialize;
-use std::cell::RefCell;
use std::cell::UnsafeCell;
-use std::iter::once;
use std::ops::Deref;
use std::ops::DerefMut;
use std::pin::Pin;
-use std::rc::Rc;
use std::task::Context;
use std::task::Poll;
/// Wrapper around a Future, which causes that Future to be polled immediately.
-/// (Background: ops are stored in a `FuturesUnordered` structure which polls
+///
+/// Background: ops are stored in a `FuturesUnordered` structure which polls
/// them, but without the `OpCall` wrapper this doesn't happen until the next
-/// turn of the event loop, which is too late for certain ops.)
+/// turn of the event loop, which is too late for certain ops.
pub struct OpCall<T>(MaybeDone<Pin<Box<dyn Future<Output = T>>>>);
impl<T> OpCall<T> {
@@ -83,32 +78,10 @@ where
pub type PromiseId = i32;
pub type OpAsyncFuture = OpCall<(PromiseId, OpId, OpResult)>;
-pub type OpFn = dyn Fn(Rc<RefCell<OpState>>, OpPayload) -> Op + 'static;
+pub type OpFn =
+ fn(&mut v8::HandleScope, v8::FunctionCallbackArguments, v8::ReturnValue);
pub type OpId = usize;
-pub struct OpPayload<'a, 'b, 'c> {
- pub(crate) scope: &'a mut v8::HandleScope<'b>,
- pub(crate) a: v8::Local<'c, v8::Value>,
- pub(crate) b: v8::Local<'c, v8::Value>,
- pub(crate) op_id: OpId,
- pub(crate) promise_id: PromiseId,
-}
-
-impl<'a, 'b, 'c> OpPayload<'a, 'b, 'c> {
- pub fn deserialize<T: DeserializeOwned, U: DeserializeOwned>(
- self,
- ) -> Result<(T, U), Error> {
- let a: T = serde_v8::from_v8(self.scope, self.a)
- .map_err(Error::from)
- .map_err(|e| type_error(format!("Error parsing args: {}", e)))?;
-
- let b: U = serde_v8::from_v8(self.scope, self.b)
- .map_err(Error::from)
- .map_err(|e| type_error(format!("Error parsing args: {}", e)))?;
- Ok((a, b))
- }
-}
-
pub enum Op {
Sync(OpResult),
Async(OpAsyncFuture),
@@ -141,39 +114,43 @@ pub struct OpError {
code: Option<&'static str>,
}
-pub fn serialize_op_result<R: Serialize + 'static>(
+impl OpError {
+ pub fn new(get_class: GetErrorClassFn, err: Error) -> Self {
+ Self {
+ class_name: (get_class)(&err),
+ message: err.to_string(),
+ code: crate::error_codes::get_error_code(&err),
+ }
+ }
+}
+
+pub fn to_op_result<R: Serialize + 'static>(
+ get_class: GetErrorClassFn,
result: Result<R, Error>,
- state: Rc<RefCell<OpState>>,
) -> OpResult {
match result {
Ok(v) => OpResult::Ok(v.into()),
- Err(err) => OpResult::Err(OpError {
- class_name: (state.borrow().get_error_class_fn)(&err),
- message: err.to_string(),
- code: crate::error_codes::get_error_code(&err),
- }),
+ Err(err) => OpResult::Err(OpError::new(get_class, err)),
}
}
/// Maintains the resources and ops inside a JS runtime.
pub struct OpState {
pub resource_table: ResourceTable,
- pub op_table: OpTable,
pub get_error_class_fn: GetErrorClassFn,
- pub(crate) tracker: OpsTracker,
+ pub tracker: OpsTracker,
gotham_state: GothamState,
}
impl OpState {
- pub(crate) fn new() -> OpState {
+ pub fn new(ops_count: usize) -> OpState {
OpState {
resource_table: Default::default(),
- op_table: OpTable::default(),
get_error_class_fn: &|_| "Error",
+ gotham_state: Default::default(),
tracker: OpsTracker {
- ops: UnsafeCell::new(Vec::with_capacity(256)),
+ ops: UnsafeCell::new(vec![Default::default(); ops_count]),
},
- gotham_state: Default::default(),
}
}
}
@@ -191,81 +168,3 @@ impl DerefMut for OpState {
&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<String, Rc<OpFn>>);
-
-impl OpTable {
- pub fn register_op<F>(&mut self, name: &str, op_fn: F) -> OpId
- where
- F: Fn(Rc<RefCell<OpState>>, OpPayload) -> Op + 'static,
- {
- let (op_id, prev) = self.0.insert_full(name.to_owned(), Rc::new(op_fn));
- assert!(prev.is_none());
- op_id
- }
-
- pub fn op_entries(state: Rc<RefCell<OpState>>) -> Vec<(String, OpId)> {
- state.borrow().op_table.0.keys().cloned().zip(0..).collect()
- }
-
- pub fn route_op(
- op_id: OpId,
- state: Rc<RefCell<OpState>>,
- payload: OpPayload,
- ) -> Op {
- 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, payload),
- None => Op::NotFound,
- }
- }
-}
-
-impl Default for OpTable {
- fn default() -> Self {
- fn dummy(_state: Rc<RefCell<OpState>>, _p: OpPayload) -> Op {
- unreachable!()
- }
- Self(once(("ops".to_owned(), Rc::new(dummy) as _)).collect())
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn op_table() {
- let state = Rc::new(RefCell::new(OpState::new()));
-
- let foo_id;
- let bar_id;
- {
- let op_table = &mut state.borrow_mut().op_table;
- foo_id =
- op_table.register_op("foo", |_, _| Op::Sync(OpResult::Ok(321.into())));
- assert_eq!(foo_id, 1);
- bar_id =
- op_table.register_op("bar", |_, _| Op::Sync(OpResult::Ok(123.into())));
- assert_eq!(bar_id, 2);
- }
-
- let mut catalog_entries = OpTable::op_entries(state);
- 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)
- ]
- );
- }
-}