From e55b448730160a6e4df9815a268d4049ac89deab Mon Sep 17 00:00:00 2001 From: Matt Mastracci Date: Fri, 17 Mar 2023 12:22:15 -0600 Subject: feat(core) deno_core::extension! macro to simplify extension registration (#18210) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This implements two macros to simplify extension registration and centralize a lot of the boilerplate as a base for future improvements: * `deno_core::ops!` registers a block of `#[op]`s, optionally with type parameters, useful for places where we share lists of ops * `deno_core::extension!` is used to register an extension, and creates two methods that can be used at runtime/snapshot generation time: `init_ops` and `init_ops_and_esm`. --------- Co-authored-by: Bartek IwaƄczuk --- ext/ffi/lib.rs | 168 +++++++++++++++++++++++++++------------------------------ 1 file changed, 78 insertions(+), 90 deletions(-) (limited to 'ext/ffi') diff --git a/ext/ffi/lib.rs b/ext/ffi/lib.rs index 2b90cd1c4..1fd01c9d2 100644 --- a/ext/ffi/lib.rs +++ b/ext/ffi/lib.rs @@ -2,10 +2,7 @@ use deno_core::error::AnyError; use deno_core::futures::channel::mpsc; -use deno_core::include_js_files; use deno_core::v8; -use deno_core::Extension; -use deno_core::ExtensionBuilder; use deno_core::OpState; use std::cell::RefCell; @@ -82,92 +79,83 @@ pub(crate) struct FfiState { pub(crate) async_work_receiver: mpsc::UnboundedReceiver, } -fn ext() -> ExtensionBuilder { - Extension::builder_with_deps(env!("CARGO_PKG_NAME"), &["deno_web"]) -} - -fn ops( - ext: &mut ExtensionBuilder, - unstable: bool, -) -> &mut ExtensionBuilder { - ext - .ops(vec![ - op_ffi_load::decl::

(), - op_ffi_get_static::decl(), - op_ffi_call_nonblocking::decl(), - op_ffi_call_ptr::decl::

(), - op_ffi_call_ptr_nonblocking::decl::

(), - op_ffi_ptr_create::decl::

(), - op_ffi_ptr_equals::decl::

(), - op_ffi_ptr_of::decl::

(), - op_ffi_ptr_offset::decl::

(), - op_ffi_ptr_value::decl::

(), - op_ffi_get_buf::decl::

(), - op_ffi_buf_copy_into::decl::

(), - op_ffi_cstr_read::decl::

(), - op_ffi_read_bool::decl::

(), - op_ffi_read_u8::decl::

(), - op_ffi_read_i8::decl::

(), - op_ffi_read_u16::decl::

(), - op_ffi_read_i16::decl::

(), - op_ffi_read_u32::decl::

(), - op_ffi_read_i32::decl::

(), - op_ffi_read_u64::decl::

(), - op_ffi_read_i64::decl::

(), - op_ffi_read_f32::decl::

(), - op_ffi_read_f64::decl::

(), - op_ffi_read_ptr::decl::

(), - op_ffi_unsafe_callback_create::decl::

(), - op_ffi_unsafe_callback_ref::decl(), - ]) - .event_loop_middleware(|op_state_rc, _cx| { - // FFI callbacks coming in from other threads will call in and get queued. - let mut maybe_scheduling = false; - - let mut work_items: Vec = vec![]; - - { - let mut op_state = op_state_rc.borrow_mut(); - let ffi_state = op_state.borrow_mut::(); - - while let Ok(Some(async_work_fut)) = - ffi_state.async_work_receiver.try_next() - { - // Move received items to a temporary vector so that we can drop the `op_state` borrow before we do the work. - work_items.push(async_work_fut); - maybe_scheduling = true; - } - - drop(op_state); - } - while let Some(async_work_fut) = work_items.pop() { - async_work_fut(); - } - - maybe_scheduling - }) - .state(move |state| { - // Stolen from deno_webgpu, is there a better option? - state.put(Unstable(unstable)); - - let (async_work_sender, async_work_receiver) = - mpsc::unbounded::(); - - state.put(FfiState { - async_work_receiver, - async_work_sender, - }); - }) -} - -pub fn init_ops_and_esm( - unstable: bool, -) -> Extension { - ops::

(&mut ext(), unstable) - .esm(include_js_files!("00_ffi.js",)) - .build() -} +deno_core::extension!(deno_ffi, + deps = [ deno_web ], + parameters = [P: FfiPermissions], + ops = [ + op_ffi_load

, + op_ffi_get_static, + op_ffi_call_nonblocking, + op_ffi_call_ptr

, + op_ffi_call_ptr_nonblocking

, + op_ffi_ptr_create

, + op_ffi_ptr_equals

, + op_ffi_ptr_of

, + op_ffi_ptr_offset

, + op_ffi_ptr_value

, + op_ffi_get_buf

, + op_ffi_buf_copy_into

, + op_ffi_cstr_read

, + op_ffi_read_bool

, + op_ffi_read_u8

, + op_ffi_read_i8

, + op_ffi_read_u16

, + op_ffi_read_i16

, + op_ffi_read_u32

, + op_ffi_read_i32

, + op_ffi_read_u64

, + op_ffi_read_i64

, + op_ffi_read_f32

, + op_ffi_read_f64

, + op_ffi_read_ptr

, + op_ffi_unsafe_callback_create

, + op_ffi_unsafe_callback_ref, + ], + esm = [ "00_ffi.js" ], + config = { + unstable: bool, + }, + state = |state, unstable| { + // Stolen from deno_webgpu, is there a better option? + state.put(Unstable(unstable)); + + let (async_work_sender, async_work_receiver) = + mpsc::unbounded::(); + + state.put(FfiState { + async_work_receiver, + async_work_sender, + }); + }, + event_loop_middleware = event_loop_middleware, +); + +fn event_loop_middleware( + op_state_rc: Rc>, + _cx: &mut std::task::Context, +) -> bool { + // FFI callbacks coming in from other threads will call in and get queued. + let mut maybe_scheduling = false; + + let mut work_items: Vec = vec![]; + + { + let mut op_state = op_state_rc.borrow_mut(); + let ffi_state = op_state.borrow_mut::(); + + while let Ok(Some(async_work_fut)) = + ffi_state.async_work_receiver.try_next() + { + // Move received items to a temporary vector so that we can drop the `op_state` borrow before we do the work. + work_items.push(async_work_fut); + maybe_scheduling = true; + } + + drop(op_state); + } + while let Some(async_work_fut) = work_items.pop() { + async_work_fut(); + } -pub fn init_ops(unstable: bool) -> Extension { - ops::

(&mut ext(), unstable).build() + maybe_scheduling } -- cgit v1.2.3