Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: improve extension! macro #881

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 38 additions & 22 deletions core/extensions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,11 +369,13 @@ macro_rules! or {
/// * lazy_loaded_esm: a comma-separated list of ESM module filenames (see [`include_js_files`]), that will be included in
/// the produced binary, but not automatically evaluated. Eg: `lazy_loaded_esm = [ dir "dir", "my_file.js" ]`
/// * 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> }`
/// * options: a structure-like definition for configuration parameters which will be required when initializing this extension, eg: `options = { 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
/// * state: a state initialization function, with the signature `fn (&mut OpState, ...) -> ()`, where `...` are parameters matching the fields of the options struct
/// * global_template_middleware: a global template middleware function (see [`Extension::global_template_middleware`])
/// * global_object_middleware: a global object middleware function (see [`Extension::global_object_middleware`])
/// * external_references: a comma-separated list of [`v8::ExternalReference`], eg: `external_references = [ ref1, ref2 ]`
/// * customizer: a customizer function with the signature `fn (&mut Extension) -> ()`, eg. `customizer = |ext: &mut deno_core::Extension| { ext.enabled = false; }`
/// * docs: comma separated list of toplevel #[doc=...] tags to be applied to the extension's resulting struct
#[macro_export]
macro_rules! extension {
Expand Down Expand Up @@ -447,7 +449,7 @@ macro_rules! extension {
$( #[ $m ] )*
$( $op )::+ $( :: < $($op_param),* > )? ()
}),+)?]),
external_references: ::std::borrow::Cow::Borrowed(&[ $( $external_reference ),* ]),
external_references: ::std::borrow::Cow::Borrowed(&[ $( $( $external_reference ),* )? ]),
global_template_middleware: ::std::option::Option::None,
global_object_middleware: ::std::option::Option::None,
// Computed at runtime:
Expand All @@ -473,7 +475,7 @@ macro_rules! extension {
fn with_state_and_middleware$( < $( $param : $type + 'static ),+ > )?(ext: &mut $crate::Extension, $( $( $options_id : $options_type ),* )? )
$( where $( $bound : $bound_type ),+ )?
{
$crate::extension!(! __config__ ext $( parameters = [ $( $param : $type ),* ] )? $( config = { $( $options_id : $options_type ),* } )? $( state_fn = $state_fn )? );
$crate::__internal__extension_config_state_fn!(ext $( parameters = [ $( $param : $type ),* ] )? $( config = { $( $options_id : $options_type ),* } )? $( state_fn = $state_fn )? );

$(
ext.global_template_middleware = ::std::option::Option::Some($global_template_middleware_fn);
Expand Down Expand Up @@ -536,8 +538,37 @@ macro_rules! extension {
}
};

// This branch of the macro generates a config object that calls the state function with itself.
(! __config__ $ext:ident $( parameters = [ $( $param:ident : $type:ident ),+ ] )? config = { $( $options_id:ident : $options_type:ty ),* } $( state_fn = $state_fn:expr )? ) => {
(! __ops__ $ext:ident __eot__) => {
};

(! __ops__ $ext:ident $ops_symbol:ident __eot__) => {
$ext.ops.to_mut().extend($ops_symbol())
};

(! __ops__ $ext:ident $ops_symbol:ident < $ops_param:ident > __eot__) => {
$ext.ops.to_mut().extend($ops_symbol::<$ops_param>())
};
}

// This private macro generates a config object that calls the state_fn with
// itself, depending on the presence of the config and state_fn.
#[macro_export]
macro_rules! __internal__extension_config_state_fn {
// Neither config nor state_fn are provided
($ext:ident $( parameters = [ $( $param:ident : $type:ident ),+ ] )? ) => {
};

// Config values are provided, but state_fn is not
($ext:ident $( parameters = [ $( $param:ident : $type:ident ),+ ] )? config = { $( $options_id:ident : $options_type:ty ),* }) => {
};

// Config values are not provided, but state_fn is
($ext:ident $( parameters = [ $( $param:ident : $type:ident ),+ ] )? state_fn = $state_fn:expr ) => {
$ext.op_state_fn = ::std::option::Option::Some(::std::boxed::Box::new($state_fn));
};

// Both config values and state_fn are provided
($ext:ident $( parameters = [ $( $param:ident : $type:ident ),+ ] )? config = { $( $options_id:ident : $options_type:ty ),* } state_fn = $state_fn:expr ) => {
{
#[doc(hidden)]
struct Config $( < $( $param : $type + 'static ),+ > )? {
Expand All @@ -549,27 +580,12 @@ macro_rules! extension {
$( __phantom_data: ::std::marker::PhantomData::<($( $param ),+)>::default() )?
};

let state_fn: fn(&mut $crate::OpState, Config $( < $( $param ),+ > )? ) = $( $state_fn )?;
let state_fn: fn(&mut $crate::OpState, Config $( < $( $param ),+ > )? ) = $state_fn;
$ext.op_state_fn = ::std::option::Option::Some(::std::boxed::Box::new(move |state: &mut $crate::OpState| {
state_fn(state, config);
}));
}
};

(! __config__ $ext:ident $( parameters = [ $( $param:ident : $type:ident ),+ ] )? $( state_fn = $state_fn:expr )? ) => {
$( $ext.op_state_fn = ::std::option::Option::Some(::std::boxed::Box::new($state_fn)); )?
};

(! __ops__ $ext:ident __eot__) => {
};

(! __ops__ $ext:ident $ops_symbol:ident __eot__) => {
$ext.ops.to_mut().extend($ops_symbol())
};

(! __ops__ $ext:ident $ops_symbol:ident < $ops_param:ident > __eot__) => {
$ext.ops.to_mut().extend($ops_symbol::<$ops_param>())
};
}

pub struct Extension {
Expand Down
Loading