summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorMatt Mastracci <matthew@mastracci.com>2023-03-17 12:22:15 -0600
committerGitHub <noreply@github.com>2023-03-17 18:22:15 +0000
commite55b448730160a6e4df9815a268d4049ac89deab (patch)
tree35d80fd60f2f1d1d06903caff256484a7d703d76 /core
parent0bc6bf5d33b8198253954d7f04558270de45c925 (diff)
feat(core) deno_core::extension! macro to simplify extension registration (#18210)
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 <biwanczuk@gmail.com>
Diffstat (limited to 'core')
-rw-r--r--core/extensions.rs257
-rw-r--r--core/modules.rs7
-rw-r--r--core/ops_builtin.rs103
-rw-r--r--core/ops_builtin_v8.rs37
-rw-r--r--core/runtime.rs166
5 files changed, 388 insertions, 182 deletions
diff --git a/core/extensions.rs b/core/extensions.rs
index 2c6e1669c..71b9cdb4f 100644
--- a/core/extensions.rs
+++ b/core/extensions.rs
@@ -65,6 +65,263 @@ impl OpDecl {
}
}
+/// Declares a block of Deno `#[op]`s. The first parameter determines the name of the
+/// op declaration block, and is usually `deno_ops`. This block generates a function that
+/// returns a [`Vec<OpDecl>`].
+///
+/// This can be either a compact form like:
+///
+/// ```no_compile
+/// # use deno_core::*;
+/// #[op]
+/// fn op_xyz() {}
+///
+/// deno_core::ops!(deno_ops, [
+/// op_xyz
+/// ]);
+///
+/// // Use the ops:
+/// deno_ops()
+/// ```
+///
+/// ... or a parameterized form like so that allows passing a number of type parameters
+/// to each `#[op]`:
+///
+/// ```no_compile
+/// # use deno_core::*;
+/// #[op]
+/// fn op_xyz<P>() where P: Clone {}
+///
+/// deno_core::ops!(deno_ops,
+/// parameters = [P: Clone],
+/// ops = [
+/// op_xyz<P>
+/// ]
+/// );
+///
+/// // Use the ops, with `String` as the parameter `P`:
+/// deno_ops::<String>()
+/// ```
+#[macro_export]
+macro_rules! ops {
+ ($name:ident, parameters = [ $( $param:ident : $type:ident ),+ ], ops = [ $( $(#[$m:meta])* $( $op:ident )::+ $( < $op_param:ident > )? ),+ $(,)? ]) => {
+ pub(crate) fn $name < $( $param : $type + 'static ),+ > () -> Vec<$crate::OpDecl> {
+ vec![
+ $(
+ $( #[ $m ] )*
+ $( $op )::+ :: decl $( :: <$op_param> )? () ,
+ )+
+ ]
+ }
+ };
+ ($name:ident, [ $( $(#[$m:meta])* $( $op:ident )::+ ),+ $(,)? ] ) => {
+ pub(crate) fn $name() -> Vec<$crate::OpDecl> {
+ vec![
+ $( $( #[ $m ] )* $( $op )::+ :: decl(), )+
+ ]
+ }
+ }
+}
+
+/// Defines a Deno extension. The first parameter is the name of the extension symbol namespace to create. This is the symbol you
+/// will use to refer to the extension.
+///
+/// Most extensions will define a combination of ops and ESM files, like so:
+///
+/// ```no_compile
+/// #[op]
+/// fn op_xyz() {
+/// }
+///
+/// deno_core::extension!(
+/// my_extension,
+/// ops = [ op_xyz ],
+/// esm = [ "my_script.js" ],
+/// );
+/// ```
+///
+/// The following options are available for the [`extension`] macro:
+///
+/// * deps: a comma-separated list of module dependencies, eg: `deps = [ my_other_extension ]`
+/// * parameters: a comma-separated list of parameters and base traits, eg: `parameters = [ P: MyTrait ]`
+/// * ops: a comma-separated list of [`OpDecl`]s to provide, eg: `ops = [ op_foo, op_bar ]`
+/// * esm: a comma-separated list of ESM module filenames (see [`include_js_files`]), eg: `esm = [ dir "dir", "my_file.js" ]`
+/// * esm_setup_script: see [`ExtensionBuilder::esm_setup_script`]
+/// * js: a comma-separated list of JS filenames (see [`include_js_files`]), eg: `js = [ dir "dir", "my_file.js" ]`
+/// * config: a structure-like definition for configuration parameters which will be required when initializing this extension, eg: `config = { my_param: Option<usize> }`
+/// * middleware: an [`OpDecl`] middleware function with the signature `fn (OpDecl) -> OpDecl`
+/// * state: a state initialization function, with the signature `fn (&mut OpState, ...) -> ()`, where `...` are parameters matching the fields of the config struct
+/// * event_loop_middleware: an event-loop middleware function (see [`ExtensionBuilder::event_loop_middleware`])
+#[macro_export]
+macro_rules! extension {
+ (
+ $name:ident
+ $(, deps = [ $( $dep:ident ),* ] )?
+ $(, parameters = [ $( $param:ident : $type:ident ),+ ] )?
+ $(, ops_fn = $ops_symbol:ident $( < $ops_param:ident > )? )?
+ $(, ops = [ $( $(#[$m:meta])* $( $op:ident )::+ $( < $op_param:ident > )? ),+ $(,)? ] )?
+ $(, esm_entry_point = $esm_entry_point:literal )?
+ $(, esm = [ $( dir $dir_esm:literal , )? $( $esm:literal ),* $(,)? ] )?
+ $(, esm_setup_script = $esm_setup_script:expr )?
+ $(, js = [ $( dir $dir_js:literal , )? $( $js:literal ),* $(,)? ] )?
+ $(, config = { $( $config_id:ident : $config_type:ty ),* $(,)? } )?
+ $(, middleware = $middleware_fn:expr )?
+ $(, state = $state_fn:expr )?
+ $(, event_loop_middleware = $event_loop_middleware_fn:ident )?
+ $(, customizer = $customizer_fn:expr )?
+ $(,)?
+ ) => {
+ /// Extension struct for
+ #[doc = stringify!($name)]
+ /// .
+ #[allow(non_camel_case_types)]
+ pub struct $name {
+ }
+
+ impl $name {
+ #[inline(always)]
+ fn ext() -> $crate::ExtensionBuilder {
+ $crate::Extension::builder_with_deps(stringify!($name), &[ $( $( stringify!($dep) ),* )? ])
+ }
+
+ /// If ESM or JS was specified, add those files to the extension.
+ #[inline(always)]
+ #[allow(unused_variables)]
+ fn with_js(ext: &mut $crate::ExtensionBuilder) {
+ $( ext.esm(
+ $crate::include_js_files!( $( dir $dir_esm , )? $( $esm , )* )
+ ); )?
+ $(
+ ext.esm(vec![ExtensionFileSource {
+ specifier: "ext:setup".to_string(),
+ code: ExtensionFileSourceCode::IncludedInBinary($esm_setup_script),
+ }]);
+ )?
+ $(
+ ext.esm_entry_point($esm_entry_point);
+ )?
+ $( ext.js(
+ $crate::include_js_files!( $( dir $dir_js , )? $( $js , )* )
+ ); )?
+ }
+
+ // If ops were specified, add those ops to the extension.
+ #[inline(always)]
+ #[allow(unused_variables)]
+ fn with_ops $( < $( $param : $type + Clone + 'static ),+ > )?(ext: &mut $crate::ExtensionBuilder) {
+ // If individual ops are specified, roll them up into a vector and apply them
+ $(
+ let v = vec![
+ $(
+ $( #[ $m ] )*
+ $( $op )::+ :: decl $( :: <$op_param> )? ()
+ ),+
+ ];
+ ext.ops(v);
+ )?
+
+ // Otherwise use the ops_fn, if provided
+ $crate::extension!(! __ops__ ext $( $ops_symbol $( < $ops_param > )? )? __eot__);
+ }
+
+ // Includes the state and middleware functions, if defined.
+ #[inline(always)]
+ #[allow(unused_variables)]
+ fn with_state_and_middleware$( < $( $param : $type + Clone + 'static ),+ > )?(ext: &mut $crate::ExtensionBuilder, $( $( $config_id : $config_type ),* )? ) {
+ #[allow(unused_variables)]
+ let config = $crate::extension!(! __config__ $( parameters = [ $( $param : $type ),* ] )? $( config = { $( $config_id : $config_type ),* } )? );
+
+ $(
+ ext.state(move |state: &mut $crate::OpState| {
+ config.clone().call_callback(state, $state_fn)
+ });
+ )?
+
+ $(
+ ext.event_loop_middleware($event_loop_middleware_fn);
+ )?
+
+ $(
+ ext.middleware($middleware_fn);
+ )?
+ }
+
+ #[inline(always)]
+ #[allow(unused_variables)]
+ fn with_customizer(ext: &mut $crate::ExtensionBuilder) {
+ $( ($customizer_fn)(ext); )?
+ }
+
+ #[allow(dead_code)]
+ pub fn init_js_only $( < $( $param : $type + Clone + 'static ),+ > )? () -> $crate::Extension {
+ let mut ext = Self::ext();
+ // If esm or JS was specified, add JS files
+ Self::with_js(&mut ext);
+ Self::with_ops $( ::<($( $param ),+)> )?(&mut ext);
+ Self::with_customizer(&mut ext);
+ ext.build()
+ }
+
+ #[allow(dead_code)]
+ pub fn init_ops_and_esm $( < $( $param : $type + Clone + 'static ),+ > )? ( $( $( $config_id : $config_type ),* )? ) -> $crate::Extension {
+ let mut ext = Self::ext();
+ // If esm or JS was specified, add JS files
+ Self::with_js(&mut ext);
+ Self::with_ops $( ::<($( $param ),+)> )?(&mut ext);
+ Self::with_state_and_middleware $( ::<($( $param ),+)> )?(&mut ext, $( $( $config_id , )* )? );
+ Self::with_customizer(&mut ext);
+ ext.build()
+ }
+
+ #[allow(dead_code)]
+ pub fn init_ops $( < $( $param : $type + Clone + 'static ),+ > )? ( $( $( $config_id : $config_type ),* )? ) -> $crate::Extension {
+ let mut ext = Self::ext();
+ Self::with_ops $( ::<($( $param ),+)> )?(&mut ext);
+ Self::with_state_and_middleware $( ::<($( $param ),+)> )?(&mut ext, $( $( $config_id , )* )? );
+ Self::with_customizer(&mut ext);
+ ext.build()
+ }
+ }
+ };
+
+ (! __config__ $( parameters = [ $( $param:ident : $type:ident ),+ ] )? $( config = { $( $config_id:ident : $config_type:ty ),* } )? ) => {
+ {
+ #[doc(hidden)]
+ #[derive(Clone)]
+ struct Config $( < $( $param : $type + Clone + 'static ),+ > )? {
+ $( $( pub $config_id : $config_type , )* )?
+ $( __phantom_data: ::std::marker::PhantomData<($( $param ),+)>, )?
+ }
+
+ impl $( < $( $param : $type + Clone + 'static ),+ > )? Config $( < $( $param ),+ > )? {
+ /// Call a function of |state, ...| using the fields of this configuration structure.
+ #[allow(dead_code)]
+ #[doc(hidden)]
+ #[inline(always)]
+ fn call_callback<F: Fn(&mut $crate::OpState, $( $( $config_type ),* )?)>(self, state: &mut $crate::OpState, f: F) {
+ f(state, $( $( self. $config_id ),* )? )
+ }
+ }
+
+ Config {
+ $( $( $config_id , )* )?
+ $( __phantom_data: ::std::marker::PhantomData::<($( $param ),+)>::default() )?
+ }
+ }
+ };
+
+ (! __ops__ $ext:ident __eot__) => {
+ };
+
+ (! __ops__ $ext:ident $ops_symbol:ident __eot__) => {
+ $ext.ops($ops_symbol())
+ };
+
+ (! __ops__ $ext:ident $ops_symbol:ident < $ops_param:ident > __eot__) => {
+ $ext.ops($ops_symbol::<$ops_param>())
+ };
+}
+
#[derive(Default)]
pub struct Extension {
js_files: Option<Vec<ExtensionFileSource>>,
diff --git a/core/modules.rs b/core/modules.rs
index e03f86c01..ddd55199b 100644
--- a/core/modules.rs
+++ b/core/modules.rs
@@ -1649,7 +1649,6 @@ impl ModuleMap {
#[cfg(test)]
mod tests {
use super::*;
- use crate::Extension;
use crate::JsRuntime;
use crate::RuntimeOptions;
use crate::Snapshot;
@@ -1990,12 +1989,10 @@ import "/a.js";
43
}
- let ext = Extension::builder("test_ext")
- .ops(vec![op_test::decl()])
- .build();
+ deno_core::extension!(test_ext, ops = [op_test]);
let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![ext],
+ extensions: vec![test_ext::init_ops()],
module_loader: Some(loader),
..Default::default()
});
diff --git a/core/ops_builtin.rs b/core/ops_builtin.rs
index 7b66ffaa4..668b44bc3 100644
--- a/core/ops_builtin.rs
+++ b/core/ops_builtin.rs
@@ -1,13 +1,11 @@
-use crate::ExtensionBuilder;
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use crate::error::format_file_name;
use crate::error::type_error;
-use crate::include_js_files;
use crate::io::BufMutView;
use crate::io::BufView;
+use crate::ops_builtin_v8;
use crate::ops_metrics::OpMetrics;
use crate::resources::ResourceId;
-use crate::Extension;
use crate::OpState;
use crate::Resource;
use crate::ZeroCopyBuf;
@@ -19,49 +17,62 @@ use std::io::stdout;
use std::io::Write;
use std::rc::Rc;
-fn ext() -> ExtensionBuilder {
- Extension::builder("core")
-}
-
-fn ops(ext: &mut ExtensionBuilder) -> &mut ExtensionBuilder {
- let mut ops = vec![
- op_close::decl(),
- op_try_close::decl(),
- op_print::decl(),
- op_resources::decl(),
- op_wasm_streaming_feed::decl(),
- op_wasm_streaming_set_url::decl(),
- op_void_sync::decl(),
- op_void_async::decl(),
- op_add::decl(),
- // // TODO(@AaronO): track IO metrics for builtin streams
- op_read::decl(),
- op_read_all::decl(),
- op_write::decl(),
- op_write_all::decl(),
- op_shutdown::decl(),
- op_metrics::decl(),
- op_format_file_name::decl(),
- op_is_proxy::decl(),
- op_str_byte_length::decl(),
- ];
- ops.extend(crate::ops_builtin_v8::init_builtins_v8());
- ext.ops(ops)
-}
-
-pub(crate) fn init_builtin_ops_and_esm() -> Extension {
- ops(&mut ext())
- .js(include_js_files!(
- "00_primordials.js",
- "01_core.js",
- "02_error.js",
- ))
- .build()
-}
-
-pub(crate) fn init_builtin_ops() -> Extension {
- ops(&mut ext()).build()
-}
+crate::extension!(
+ core,
+ ops = [
+ op_close,
+ op_try_close,
+ op_print,
+ op_resources,
+ op_wasm_streaming_feed,
+ op_wasm_streaming_set_url,
+ op_void_sync,
+ op_void_async,
+ op_add,
+ // TODO(@AaronO): track IO metrics for builtin streams
+ op_read,
+ op_read_all,
+ op_write,
+ op_write_all,
+ op_shutdown,
+ op_metrics,
+ op_format_file_name,
+ op_is_proxy,
+ op_str_byte_length,
+ ops_builtin_v8::op_ref_op,
+ ops_builtin_v8::op_unref_op,
+ ops_builtin_v8::op_set_macrotask_callback,
+ ops_builtin_v8::op_set_next_tick_callback,
+ ops_builtin_v8::op_set_promise_reject_callback,
+ ops_builtin_v8::op_run_microtasks,
+ ops_builtin_v8::op_has_tick_scheduled,
+ ops_builtin_v8::op_set_has_tick_scheduled,
+ ops_builtin_v8::op_eval_context,
+ ops_builtin_v8::op_queue_microtask,
+ ops_builtin_v8::op_create_host_object,
+ ops_builtin_v8::op_encode,
+ ops_builtin_v8::op_decode,
+ ops_builtin_v8::op_serialize,
+ ops_builtin_v8::op_deserialize,
+ ops_builtin_v8::op_set_promise_hooks,
+ ops_builtin_v8::op_get_promise_details,
+ ops_builtin_v8::op_get_proxy_details,
+ ops_builtin_v8::op_memory_usage,
+ ops_builtin_v8::op_set_wasm_streaming_callback,
+ ops_builtin_v8::op_abort_wasm_streaming,
+ ops_builtin_v8::op_destructure_error,
+ ops_builtin_v8::op_dispatch_exception,
+ ops_builtin_v8::op_op_names,
+ ops_builtin_v8::op_apply_source_map,
+ ops_builtin_v8::op_set_format_exception_callback,
+ ops_builtin_v8::op_event_loop_has_more_work,
+ ops_builtin_v8::op_store_pending_promise_rejection,
+ ops_builtin_v8::op_remove_pending_promise_rejection,
+ ops_builtin_v8::op_has_pending_promise_rejection,
+ ops_builtin_v8::op_arraybuffer_was_detached,
+ ],
+ js = ["00_primordials.js", "01_core.js", "02_error.js"],
+);
/// Return map of resources with id as key
/// and string representation as value.
diff --git a/core/ops_builtin_v8.rs b/core/ops_builtin_v8.rs
index 05250dc73..3d7b4a996 100644
--- a/core/ops_builtin_v8.rs
+++ b/core/ops_builtin_v8.rs
@@ -11,7 +11,6 @@ use crate::serde_v8::from_v8;
use crate::source_map::apply_source_map as apply_source_map_;
use crate::JsRealm;
use crate::JsRuntime;
-use crate::OpDecl;
use crate::ZeroCopyBuf;
use anyhow::Error;
use deno_ops::op;
@@ -21,42 +20,6 @@ use std::cell::RefCell;
use v8::ValueDeserializerHelper;
use v8::ValueSerializerHelper;
-pub(crate) fn init_builtins_v8() -> Vec<OpDecl> {
- vec![
- op_ref_op::decl(),
- op_unref_op::decl(),
- op_set_macrotask_callback::decl(),
- op_set_next_tick_callback::decl(),
- op_set_promise_reject_callback::decl(),
- op_run_microtasks::decl(),
- op_has_tick_scheduled::decl(),
- op_set_has_tick_scheduled::decl(),
- op_eval_context::decl(),
- op_queue_microtask::decl(),
- op_create_host_object::decl(),
- op_encode::decl(),
- op_decode::decl(),
- op_serialize::decl(),
- op_deserialize::decl(),
- op_set_promise_hooks::decl(),
- op_get_promise_details::decl(),
- op_get_proxy_details::decl(),
- op_memory_usage::decl(),
- op_set_wasm_streaming_callback::decl(),
- op_abort_wasm_streaming::decl(),
- op_destructure_error::decl(),
- op_dispatch_exception::decl(),
- op_op_names::decl(),
- op_apply_source_map::decl(),
- op_set_format_exception_callback::decl(),
- op_event_loop_has_more_work::decl(),
- op_store_pending_promise_rejection::decl(),
- op_remove_pending_promise_rejection::decl(),
- op_has_pending_promise_rejection::decl(),
- op_arraybuffer_was_detached::decl(),
- ]
-}
-
fn to_v8_fn(
scope: &mut v8::HandleScope,
value: serde_v8::Value,
diff --git a/core/runtime.rs b/core/runtime.rs
index c19765dd9..1ea9c0168 100644
--- a/core/runtime.rs
+++ b/core/runtime.rs
@@ -323,11 +323,11 @@ impl JsRuntime {
if !has_startup_snapshot {
options
.extensions
- .insert(0, crate::ops_builtin::init_builtin_ops_and_esm());
+ .insert(0, crate::ops_builtin::core::init_ops_and_esm());
} else {
options
.extensions
- .insert(0, crate::ops_builtin::init_builtin_ops());
+ .insert(0, crate::ops_builtin::core::init_ops());
}
let ops = Self::collect_ops(&mut options.extensions);
@@ -2683,7 +2683,7 @@ pub mod tests {
}
#[derive(Copy, Clone)]
- enum Mode {
+ pub enum Mode {
Async,
AsyncDeferred,
AsyncZeroCopy(bool),
@@ -2728,18 +2728,22 @@ pub mod tests {
fn setup(mode: Mode) -> (JsRuntime, Arc<AtomicUsize>) {
let dispatch_count = Arc::new(AtomicUsize::new(0));
- let dispatch_count2 = dispatch_count.clone();
- let ext = Extension::builder("test_ext")
- .ops(vec![op_test::decl()])
- .state(move |state| {
+ deno_core::extension!(
+ test_ext,
+ ops = [op_test],
+ config = {
+ mode: Mode,
+ dispatch_count: Arc<AtomicUsize>,
+ },
+ state = |state, mode, dispatch_count| {
state.put(TestState {
mode,
- dispatch_count: dispatch_count2.clone(),
- });
- })
- .build();
+ dispatch_count
+ })
+ }
+ );
let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![ext],
+ extensions: vec![test_ext::init_ops(mode, dispatch_count.clone())],
get_error_class_fn: Some(&|error| {
crate::error::get_custom_error_class(error).unwrap()
}),
@@ -3149,11 +3153,9 @@ pub mod tests {
"DOMExceptionOperationError"
}
- let ext = Extension::builder("test_ext")
- .ops(vec![op_err::decl()])
- .build();
+ deno_core::extension!(test_ext, ops = [op_err]);
let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![ext],
+ extensions: vec![test_ext::init_ops()],
get_error_class_fn: Some(&get_error_class_name),
..Default::default()
});
@@ -3720,11 +3722,9 @@ main();
Err(anyhow!("original async error").context("higher-level async error"))
}
- let ext = Extension::builder("test_ext")
- .ops(vec![op_err_sync::decl(), op_err_async::decl()])
- .build();
+ deno_core::extension!(test_ext, ops = [op_err_sync, op_err_async]);
let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![ext],
+ extensions: vec![test_ext::init_ops()],
..Default::default()
});
@@ -3889,15 +3889,13 @@ assertEquals(1, notify_return_value);
Ok(())
}
- let extension = Extension::builder("test_ext")
- .ops(vec![op_async_borrow::decl()])
- .state(|state| {
- state.put(InnerState(42));
- })
- .build();
-
+ deno_core::extension!(
+ test_ext,
+ ops = [op_async_borrow],
+ state = |state| state.put(InnerState(42))
+ );
let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![extension],
+ extensions: vec![test_ext::init_ops()],
..Default::default()
});
@@ -3923,12 +3921,12 @@ assertEquals(1, notify_return_value);
Ok(())
}
- let extension = Extension::builder("test_ext")
- .ops(vec![op_sync_serialize_object_with_numbers_as_keys::decl()])
- .build();
-
+ deno_core::extension!(
+ test_ext,
+ ops = [op_sync_serialize_object_with_numbers_as_keys]
+ );
let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![extension],
+ extensions: vec![test_ext::init_ops()],
..Default::default()
});
@@ -3965,12 +3963,12 @@ Deno.core.ops.op_sync_serialize_object_with_numbers_as_keys({
Ok(())
}
- let extension = Extension::builder("test_ext")
- .ops(vec![op_async_serialize_object_with_numbers_as_keys::decl()])
- .build();
-
+ deno_core::extension!(
+ test_ext,
+ ops = [op_async_serialize_object_with_numbers_as_keys]
+ );
let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![extension],
+ extensions: vec![test_ext::init_ops()],
..Default::default()
});
@@ -4004,12 +4002,9 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
Ok(())
}
- let extension = Extension::builder("test_ext")
- .ops(vec![op_async_sleep::decl()])
- .build();
-
+ deno_core::extension!(test_ext, ops = [op_async_sleep]);
let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![extension],
+ extensions: vec![test_ext::init_ops()],
..Default::default()
});
@@ -4084,12 +4079,9 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
Ok(())
}
- let extension = Extension::builder("test_ext")
- .ops(vec![op_macrotask::decl(), op_next_tick::decl()])
- .build();
-
+ deno_core::extension!(test_ext, ops = [op_macrotask, op_next_tick]);
let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![extension],
+ extensions: vec![test_ext::init_ops()],
..Default::default()
});
@@ -4214,12 +4206,9 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
Ok(())
}
- let extension = Extension::builder("test_ext")
- .ops(vec![op_promise_reject::decl()])
- .build();
-
+ deno_core::extension!(test_ext, ops = [op_promise_reject]);
let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![extension],
+ extensions: vec![test_ext::init_ops()],
..Default::default()
});
@@ -4321,9 +4310,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
Ok(())
}
- let extension = Extension::builder("test_ext")
- .ops(vec![op_promise_reject::decl()])
- .build();
+ deno_core::extension!(test_ext, ops = [op_promise_reject]);
#[derive(Default)]
struct ModsLoader;
@@ -4367,7 +4354,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
}
let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![extension],
+ extensions: vec![test_ext::init_ops()],
module_loader: Some(Rc::new(ModsLoader)),
..Default::default()
});
@@ -4390,11 +4377,9 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
Ok([(1, 2), (3, 4)].into_iter().collect()) // Maps can't have non-string keys in serde_v8
}
- let ext = Extension::builder("test_ext")
- .ops(vec![op_err::decl()])
- .build();
+ deno_core::extension!(test_ext, ops = [op_err]);
let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![ext],
+ extensions: vec![test_ext::init_ops()],
..Default::default()
});
assert!(runtime
@@ -4417,11 +4402,9 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
Ok(x1 + x2 + x3 + x4)
}
- let ext = Extension::builder("test_ext")
- .ops(vec![op_add_4::decl()])
- .build();
+ deno_core::extension!(test_ext, ops = [op_add_4]);
let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![ext],
+ extensions: vec![test_ext::init_ops()],
..Default::default()
});
let r = runtime
@@ -4438,11 +4421,13 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
Ok(42)
}
- let ext = Extension::builder("test_ext")
- .ops(vec![op_foo::decl().disable()])
- .build();
+ fn ops() -> Vec<OpDecl> {
+ vec![op_foo::decl().disable()]
+ }
+
+ deno_core::extension!(test_ext, ops_fn = ops);
let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![ext],
+ extensions: vec![test_ext::init_ops()],
..Default::default()
});
let r = runtime
@@ -4468,12 +4453,9 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
Ok(b)
}
- let ext = Extension::builder("test_ext")
- .ops(vec![op_sum_take::decl(), op_boomerang::decl()])
- .build();
-
+ deno_core::extension!(test_ext, ops = [op_sum_take, op_boomerang]);
let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![ext],
+ extensions: vec![test_ext::init_ops()],
..Default::default()
});
@@ -4536,12 +4518,13 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
Ok(42)
}
- let ext = Extension::builder("test_ext")
- .ops(vec![op_foo::decl(), op_bar::decl()])
- .middleware(|op| if op.is_unstable { op.disable() } else { op })
- .build();
+ deno_core::extension!(
+ test_ext,
+ ops = [op_foo, op_bar],
+ middleware = |op| if op.is_unstable { op.disable() } else { op }
+ );
let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![ext],
+ extensions: vec![test_ext::init_ops()],
..Default::default()
});
runtime
@@ -4587,10 +4570,9 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
Ok(String::from("Test"))
}
+ deno_core::extension!(test_ext, ops = [op_test]);
let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![Extension::builder("test_ext")
- .ops(vec![op_test::decl()])
- .build()],
+ extensions: vec![test_ext::init_ops()],
..Default::default()
});
let realm = runtime.create_realm().unwrap();
@@ -4618,11 +4600,10 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
Ok(String::from("Test"))
}
+ deno_core::extension!(test_ext, ops = [op_test]);
let mut runtime = JsRuntime::new(RuntimeOptions {
startup_snapshot: Some(Snapshot::Boxed(snapshot)),
- extensions: vec![Extension::builder("test_ext")
- .ops(vec![op_test::decl()])
- .build()],
+ extensions: vec![test_ext::init_ops()],
..Default::default()
});
let realm = runtime.create_realm().unwrap();
@@ -4650,10 +4631,9 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
}
}
+ deno_core::extension!(test_ext, ops = [op_test]);
let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![Extension::builder("test_ext")
- .ops(vec![op_test::decl()])
- .build()],
+ extensions: vec![test_ext::init_ops()],
get_error_class_fn: Some(&|error| {
crate::error::get_custom_error_class(error).unwrap()
}),
@@ -4699,10 +4679,9 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
}
}
+ deno_core::extension!(test_ext, ops = [op_test]);
let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![Extension::builder("test_ext")
- .ops(vec![op_test::decl()])
- .build()],
+ extensions: vec![test_ext::init_ops()],
get_error_class_fn: Some(&|error| {
crate::error::get_custom_error_class(error).unwrap()
}),
@@ -4759,10 +4738,9 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
futures::future::pending().await
}
+ deno_core::extension!(test_ext, ops = [op_pending]);
let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![Extension::builder("test_ext")
- .ops(vec![op_pending::decl()])
- .build()],
+ extensions: vec![test_ext::init_ops()],
..Default::default()
});