summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ops/lib.rs44
-rw-r--r--ops/tests/01_fast_callback_options.rs11
-rw-r--r--ops/tests/compile_fail/unsupported.rs7
-rw-r--r--ops/tests/compile_fail/unsupported.stderr20
-rw-r--r--ops/tests/mod.rs1
5 files changed, 72 insertions, 11 deletions
diff --git a/ops/lib.rs b/ops/lib.rs
index 7d291d1da..437fa3b7e 100644
--- a/ops/lib.rs
+++ b/ops/lib.rs
@@ -304,24 +304,29 @@ 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)| {
+ 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) {
- 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 > };
}
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)
diff --git a/ops/tests/01_fast_callback_options.rs b/ops/tests/01_fast_callback_options.rs
new file mode 100644
index 000000000..815d9262c
--- /dev/null
+++ b/ops/tests/01_fast_callback_options.rs
@@ -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() {}
diff --git a/ops/tests/compile_fail/unsupported.rs b/ops/tests/compile_fail/unsupported.rs
index 1c4d6407a..52d55de5b 100644
--- a/ops/tests/compile_fail/unsupported.rs
+++ b/ops/tests/compile_fail/unsupported.rs
@@ -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
diff --git a/ops/tests/compile_fail/unsupported.stderr b/ops/tests/compile_fail/unsupported.stderr
index 68c9f7f16..88d1c1fe4 100644
--- a/ops/tests/compile_fail/unsupported.stderr
+++ b/ops/tests/compile_fail/unsupported.stderr
@@ -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
diff --git a/ops/tests/mod.rs b/ops/tests/mod.rs
index 522647f51..699bcf9f4 100644
--- a/ops/tests/mod.rs
+++ b/ops/tests/mod.rs
@@ -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");
}