1
0
Fork 0
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:
Divy Srivastava 2022-09-01 15:53:06 +05:30 committed by GitHub
parent cbd8307710
commit 805ce6fdf7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 72 additions and 11 deletions

View file

@ -304,24 +304,29 @@ fn codegen_fast_impl(
args, args,
ret, ret,
use_recv, use_recv,
use_fast_cb_opts,
v8_values, v8_values,
}) = fast_info }) = fast_info
{ {
let offset = if use_recv { 1 } else { 0 };
let inputs = &f let inputs = &f
.sig .sig
.inputs .inputs
.iter() .iter()
.skip(if use_recv { 1 } else { 0 }) .skip(offset)
.enumerate() .enumerate()
.map(|(idx, arg)| { .map(|(idx, arg)| {
let ident = match arg {
FnArg::Receiver(_) => unreachable!(),
FnArg::Typed(t) => match &*t.pat {
syn::Pat::Ident(i) => format_ident!("{}", i.ident),
_ => 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) { if v8_values.contains(&idx) {
let ident = match arg {
FnArg::Receiver(_) => unreachable!(),
FnArg::Typed(t) => match &*t.pat {
syn::Pat::Ident(i) => format_ident!("{}", i.ident),
_ => unreachable!(),
},
};
return quote! { #ident: #core::v8::Local < #core::v8::Value > }; return quote! { #ident: #core::v8::Local < #core::v8::Value > };
} }
quote!(#arg) quote!(#arg)
@ -340,6 +345,9 @@ fn codegen_fast_impl(
_ => unreachable!(), _ => unreachable!(),
}, },
}; };
if use_fast_cb_opts && idx == f.sig.inputs.len() - 1 {
return quote! { Some(unsafe { &mut * #ident }) };
}
if v8_values.contains(&idx) { if v8_values.contains(&idx) {
return quote! { return quote! {
#core::serde_v8::Value { #core::serde_v8::Value {
@ -479,6 +487,7 @@ struct FastApiSyn {
args: TokenStream2, args: TokenStream2,
ret: TokenStream2, ret: TokenStream2,
use_recv: bool, use_recv: bool,
use_fast_cb_opts: bool,
v8_values: Vec<usize>, 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_recv = false;
let mut use_fast_cb_opts = false;
let mut v8_values = Vec::new(); let mut v8_values = Vec::new();
let mut args = vec![quote! { #core::v8::fast_api::Type::V8Value }]; let mut args = vec![quote! { #core::v8::fast_api::Type::V8Value }];
for (pos, input) in inputs.iter().enumerate() { 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) { if pos == 0 && is_mut_ref_opstate(input) {
use_recv = true; use_recv = true;
continue; continue;
@ -535,6 +551,7 @@ fn can_be_fast_api(core: &TokenStream2, f: &syn::ItemFn) -> Option<FastApiSyn> {
ret, ret,
use_recv, use_recv,
v8_values, v8_values,
use_fast_cb_opts,
}) })
} }
@ -638,7 +655,12 @@ fn codegen_arg(
) -> TokenStream2 { ) -> TokenStream2 {
let ident = quote::format_ident!("{name}"); let ident = quote::format_ident!("{name}");
let (pat, ty) = match arg { 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!(), _ => unreachable!(),
}; };
// Fast path if arg should be skipped // Fast path if arg should be skipped
@ -753,6 +775,10 @@ fn is_option_string(ty: impl ToTokens) -> bool {
tokens(ty) == "Option < String >" 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 /// Detects if the type can be set using `rv.set_uint32` fast path
fn is_u32_rv(ty: impl ToTokens) -> bool { fn is_u32_rv(ty: impl ToTokens) -> bool {
["u32", "u8", "u16"].iter().any(|&s| tokens(&ty) == s) || is_resource_id(&ty) ["u32", "u8", "u16"].iter().any(|&s| tokens(&ty) == s) || is_resource_id(&ty)

View 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() {}

View file

@ -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)] #[op(fast)]
async fn op_async_fn(a: i32, b: i32) -> i32 { async fn op_async_fn(a: i32, b: i32) -> i32 {
a + b a + b

View file

@ -23,9 +23,25 @@ error: custom attribute panicked
= help: message: op cannot be a fast api. enforced by #[op(fast)] = help: message: op cannot be a fast api. enforced by #[op(fast)]
error: custom attribute panicked 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)] = 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

View file

@ -2,4 +2,5 @@
fn op_macro() { fn op_macro() {
let t = trybuild::TestCases::new(); let t = trybuild::TestCases::new();
t.compile_fail("tests/compile_fail/*.rs"); t.compile_fail("tests/compile_fail/*.rs");
t.pass("tests/01_fast_callback_options.rs");
} }