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
44
ops/lib.rs
44
ops/lib.rs
|
@ -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)
|
||||||
|
|
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)]
|
#[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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue