mirror of
https://github.com/denoland/deno.git
synced 2025-01-03 04:48:52 -05:00
feat(ops): support v8::FastApiCallbackOptions
(#15721)
This commit is contained in:
parent
cbd8307710
commit
805ce6fdf7
5 changed files with 72 additions and 11 deletions
32
ops/lib.rs
32
ops/lib.rs
|
@ -304,17 +304,18 @@ fn codegen_fast_impl(
|
|||
args,
|
||||
ret,
|
||||
use_recv,
|
||||
use_fast_cb_opts,
|
||||
v8_values,
|
||||
}) = fast_info
|
||||
{
|
||||
let offset = if use_recv { 1 } else { 0 };
|
||||
let inputs = &f
|
||||
.sig
|
||||
.inputs
|
||||
.iter()
|
||||
.skip(if use_recv { 1 } else { 0 })
|
||||
.skip(offset)
|
||||
.enumerate()
|
||||
.map(|(idx, arg)| {
|
||||
if v8_values.contains(&idx) {
|
||||
let ident = match arg {
|
||||
FnArg::Receiver(_) => unreachable!(),
|
||||
FnArg::Typed(t) => match &*t.pat {
|
||||
|
@ -322,6 +323,10 @@ fn codegen_fast_impl(
|
|||
_ => unreachable!(),
|
||||
},
|
||||
};
|
||||
if use_fast_cb_opts && idx == f.sig.inputs.len() - 1 {
|
||||
return quote! { #ident: *mut #core::v8::fast_api::FastApiCallbackOptions };
|
||||
}
|
||||
if v8_values.contains(&idx) {
|
||||
return quote! { #ident: #core::v8::Local < #core::v8::Value > };
|
||||
}
|
||||
quote!(#arg)
|
||||
|
@ -340,6 +345,9 @@ fn codegen_fast_impl(
|
|||
_ => unreachable!(),
|
||||
},
|
||||
};
|
||||
if use_fast_cb_opts && idx == f.sig.inputs.len() - 1 {
|
||||
return quote! { Some(unsafe { &mut * #ident }) };
|
||||
}
|
||||
if v8_values.contains(&idx) {
|
||||
return quote! {
|
||||
#core::serde_v8::Value {
|
||||
|
@ -479,6 +487,7 @@ struct FastApiSyn {
|
|||
args: TokenStream2,
|
||||
ret: TokenStream2,
|
||||
use_recv: bool,
|
||||
use_fast_cb_opts: bool,
|
||||
v8_values: Vec<usize>,
|
||||
}
|
||||
|
||||
|
@ -493,9 +502,16 @@ fn can_be_fast_api(core: &TokenStream2, f: &syn::ItemFn) -> Option<FastApiSyn> {
|
|||
};
|
||||
|
||||
let mut use_recv = false;
|
||||
let mut use_fast_cb_opts = false;
|
||||
let mut v8_values = Vec::new();
|
||||
let mut args = vec![quote! { #core::v8::fast_api::Type::V8Value }];
|
||||
for (pos, input) in inputs.iter().enumerate() {
|
||||
if pos == inputs.len() - 1 && is_optional_fast_callback_option(input) {
|
||||
args.push(quote! { #core::v8::fast_api::Type::CallbackOptions });
|
||||
use_fast_cb_opts = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if pos == 0 && is_mut_ref_opstate(input) {
|
||||
use_recv = true;
|
||||
continue;
|
||||
|
@ -535,6 +551,7 @@ fn can_be_fast_api(core: &TokenStream2, f: &syn::ItemFn) -> Option<FastApiSyn> {
|
|||
ret,
|
||||
use_recv,
|
||||
v8_values,
|
||||
use_fast_cb_opts,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -638,7 +655,12 @@ fn codegen_arg(
|
|||
) -> TokenStream2 {
|
||||
let ident = quote::format_ident!("{name}");
|
||||
let (pat, ty) = match arg {
|
||||
syn::FnArg::Typed(pat) => (&pat.pat, &pat.ty),
|
||||
syn::FnArg::Typed(pat) => {
|
||||
if is_optional_fast_callback_option(&pat.ty) {
|
||||
return quote! { let #ident = None; };
|
||||
}
|
||||
(&pat.pat, &pat.ty)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
// Fast path if arg should be skipped
|
||||
|
@ -753,6 +775,10 @@ fn is_option_string(ty: impl ToTokens) -> bool {
|
|||
tokens(ty) == "Option < String >"
|
||||
}
|
||||
|
||||
fn is_optional_fast_callback_option(ty: impl ToTokens) -> bool {
|
||||
tokens(&ty).contains("Option < & mut FastApiCallbackOptions")
|
||||
}
|
||||
|
||||
/// Detects if the type can be set using `rv.set_uint32` fast path
|
||||
fn is_u32_rv(ty: impl ToTokens) -> bool {
|
||||
["u32", "u8", "u16"].iter().any(|&s| tokens(&ty) == s) || is_resource_id(&ty)
|
||||
|
|
11
ops/tests/01_fast_callback_options.rs
Normal file
11
ops/tests/01_fast_callback_options.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
use deno_core::v8::fast_api::FastApiCallbackOptions;
|
||||
use deno_ops::op;
|
||||
|
||||
#[op(fast)]
|
||||
fn op_fallback(options: Option<&mut FastApiCallbackOptions>) {
|
||||
if let Some(options) = options {
|
||||
options.fallback = true;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -17,6 +17,13 @@ fn op_u16_arg(a: u16, b: u16) {
|
|||
//
|
||||
}
|
||||
|
||||
use deno_core::v8::fast_api::FastApiCallbackOptions;
|
||||
|
||||
#[op(fast)]
|
||||
fn op_callback_options(options: &mut FastApiCallbackOptions) {
|
||||
// fast callback options must be an Option.
|
||||
}
|
||||
|
||||
#[op(fast)]
|
||||
async fn op_async_fn(a: i32, b: i32) -> i32 {
|
||||
a + b
|
||||
|
|
|
@ -23,9 +23,25 @@ error: custom attribute panicked
|
|||
= help: message: op cannot be a fast api. enforced by #[op(fast)]
|
||||
|
||||
error: custom attribute panicked
|
||||
--> tests/compile_fail/unsupported.rs:20:1
|
||||
--> tests/compile_fail/unsupported.rs:22:1
|
||||
|
|
||||
20 | #[op(fast)]
|
||||
22 | #[op(fast)]
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: message: op cannot be a fast api. enforced by #[op(fast)]
|
||||
|
||||
error: custom attribute panicked
|
||||
--> tests/compile_fail/unsupported.rs:27:1
|
||||
|
|
||||
27 | #[op(fast)]
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: message: async op cannot be a fast api. enforced by #[op(fast)]
|
||||
|
||||
warning: unused import: `deno_core::v8::fast_api::FastApiCallbackOptions`
|
||||
--> tests/compile_fail/unsupported.rs:20:5
|
||||
|
|
||||
20 | use deno_core::v8::fast_api::FastApiCallbackOptions;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(unused_imports)]` on by default
|
||||
|
|
|
@ -2,4 +2,5 @@
|
|||
fn op_macro() {
|
||||
let t = trybuild::TestCases::new();
|
||||
t.compile_fail("tests/compile_fail/*.rs");
|
||||
t.pass("tests/01_fast_callback_options.rs");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue