diff options
author | Divy Srivastava <dj.srivastava23@gmail.com> | 2022-03-14 23:14:15 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-14 18:44:15 +0100 |
commit | b4e42953e1d243f2eda20e5be6b845d60b7bf688 (patch) | |
tree | 10b3bfff165f9c04f9174c7c399d44b9b724c3b3 /core/ops.rs | |
parent | 4e3ed37037a2aa1edeac260dc3463a81d9cf9b88 (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.rs | 147 |
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) - ] - ); - } -} |