mirror of
https://github.com/denoland/deno.git
synced 2024-11-28 16:20:57 -05:00
feat(ops): support Result<impl Future<Output = Result<T, AnyError>> + 'static, AnyError>
(#14869)
feat(ops): support a result returning a future returning a result
This commit is contained in:
parent
e7ea4edc8a
commit
364da468d2
1 changed files with 61 additions and 30 deletions
91
ops/lib.rs
91
ops/lib.rs
|
@ -73,7 +73,14 @@ pub fn op(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
let MacroArgs { is_unstable, is_v8 } = margs;
|
let MacroArgs { is_unstable, is_v8 } = margs;
|
||||||
let func = syn::parse::<syn::ItemFn>(item).expect("expected a function");
|
let func = syn::parse::<syn::ItemFn>(item).expect("expected a function");
|
||||||
let name = &func.sig.ident;
|
let name = &func.sig.ident;
|
||||||
let generics = &func.sig.generics;
|
let mut generics = func.sig.generics.clone();
|
||||||
|
let scope_lifetime =
|
||||||
|
syn::LifetimeDef::new(syn::Lifetime::new("'scope", Span::call_site()));
|
||||||
|
if !generics.lifetimes().any(|def| *def == scope_lifetime) {
|
||||||
|
generics
|
||||||
|
.params
|
||||||
|
.push(syn::GenericParam::Lifetime(scope_lifetime));
|
||||||
|
}
|
||||||
let type_params = exclude_lifetime_params(&func.sig.generics.params);
|
let type_params = exclude_lifetime_params(&func.sig.generics.params);
|
||||||
let where_clause = &func.sig.generics.where_clause;
|
let where_clause = &func.sig.generics.where_clause;
|
||||||
|
|
||||||
|
@ -131,7 +138,7 @@ pub fn op(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
#original_func
|
#original_func
|
||||||
|
|
||||||
pub fn v8_func #generics (
|
pub fn v8_func #generics (
|
||||||
scope: &mut #core::v8::HandleScope,
|
scope: &mut #core::v8::HandleScope<'scope>,
|
||||||
args: #core::v8::FunctionCallbackArguments,
|
args: #core::v8::FunctionCallbackArguments,
|
||||||
mut rv: #core::v8::ReturnValue,
|
mut rv: #core::v8::ReturnValue,
|
||||||
) #where_clause {
|
) #where_clause {
|
||||||
|
@ -145,32 +152,49 @@ pub fn op(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
fn codegen_v8_async(
|
fn codegen_v8_async(
|
||||||
core: &TokenStream2,
|
core: &TokenStream2,
|
||||||
f: &syn::ItemFn,
|
f: &syn::ItemFn,
|
||||||
_margs: MacroArgs,
|
margs: MacroArgs,
|
||||||
asyncness: bool,
|
asyncness: bool,
|
||||||
) -> TokenStream2 {
|
) -> TokenStream2 {
|
||||||
let arg0 = f.sig.inputs.first();
|
let MacroArgs { is_v8, .. } = margs;
|
||||||
let uses_opstate = arg0.map(is_rc_refcell_opstate).unwrap_or_default();
|
let special_args = f
|
||||||
let args_head = if uses_opstate {
|
.sig
|
||||||
quote! { state, }
|
.inputs
|
||||||
} else {
|
.iter()
|
||||||
quote! {}
|
.map_while(|a| {
|
||||||
};
|
(if is_v8 { scope_arg(a) } else { None }).or_else(|| opstate_arg(a))
|
||||||
let rust_i0 = if uses_opstate { 1 } else { 0 };
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let rust_i0 = special_args.len();
|
||||||
|
let args_head = special_args.into_iter().collect::<TokenStream2>();
|
||||||
|
|
||||||
let (arg_decls, args_tail) = codegen_args(core, f, rust_i0, 1);
|
let (arg_decls, args_tail) = codegen_args(core, f, rust_i0, 1);
|
||||||
let type_params = exclude_lifetime_params(&f.sig.generics.params);
|
let type_params = exclude_lifetime_params(&f.sig.generics.params);
|
||||||
|
|
||||||
let (pre_result, result_fut) = match asyncness {
|
let (pre_result, mut result_fut) = match asyncness {
|
||||||
true => (
|
true => (
|
||||||
quote! {},
|
quote! {},
|
||||||
quote! { Self::call::<#type_params>(#args_head #args_tail) },
|
quote! { Self::call::<#type_params>(#args_head #args_tail).await; },
|
||||||
),
|
),
|
||||||
false => (
|
false => (
|
||||||
quote! { let result_fut = Self::call::<#type_params>(#args_head #args_tail); },
|
quote! { let result_fut = Self::call::<#type_params>(#args_head #args_tail); },
|
||||||
quote! { result_fut },
|
quote! { result_fut.await; },
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
let result_wrapper = match is_result(&f.sig.output) {
|
let result_wrapper = match is_result(&f.sig.output) {
|
||||||
true => quote! {},
|
true => {
|
||||||
|
// Support `Result<impl Future<Output = Result<T, AnyError>> + 'static, AnyError>`
|
||||||
|
if !asyncness {
|
||||||
|
result_fut = quote! { result_fut; };
|
||||||
|
quote! {
|
||||||
|
let result = match result {
|
||||||
|
Ok(fut) => fut.await,
|
||||||
|
Err(e) => return (promise_id, op_id, #core::_ops::to_op_result::<()>(get_class, Err(e))),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {}
|
||||||
|
}
|
||||||
|
}
|
||||||
false => quote! { let result = Ok(result); },
|
false => quote! { let result = Ok(result); },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -209,13 +233,31 @@ fn codegen_v8_async(
|
||||||
|
|
||||||
#pre_result
|
#pre_result
|
||||||
#core::_ops::queue_async_op(scope, async move {
|
#core::_ops::queue_async_op(scope, async move {
|
||||||
let result = #result_fut.await;
|
let result = #result_fut
|
||||||
#result_wrapper
|
#result_wrapper
|
||||||
(promise_id, op_id, #core::_ops::to_op_result(get_class, result))
|
(promise_id, op_id, #core::_ops::to_op_result(get_class, result))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn scope_arg(arg: &FnArg) -> Option<TokenStream2> {
|
||||||
|
if is_handle_scope(arg) {
|
||||||
|
Some(quote! { scope, })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn opstate_arg(arg: &FnArg) -> Option<TokenStream2> {
|
||||||
|
match arg {
|
||||||
|
arg if is_rc_refcell_opstate(arg) => Some(quote! { ctx.state.clone(), }),
|
||||||
|
arg if is_mut_ref_opstate(arg) => {
|
||||||
|
Some(quote! { &mut ctx.state.borrow_mut(), })
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Generate the body of a v8 func for a sync op
|
/// Generate the body of a v8 func for a sync op
|
||||||
fn codegen_v8_sync(
|
fn codegen_v8_sync(
|
||||||
core: &TokenStream2,
|
core: &TokenStream2,
|
||||||
|
@ -223,20 +265,6 @@ fn codegen_v8_sync(
|
||||||
margs: MacroArgs,
|
margs: MacroArgs,
|
||||||
) -> TokenStream2 {
|
) -> TokenStream2 {
|
||||||
let MacroArgs { is_v8, .. } = margs;
|
let MacroArgs { is_v8, .. } = margs;
|
||||||
let scope_arg = |arg: &FnArg| {
|
|
||||||
if is_handle_scope(arg) {
|
|
||||||
Some(quote! { scope, })
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let opstate_arg = |arg: &FnArg| match arg {
|
|
||||||
arg if is_rc_refcell_opstate(arg) => Some(quote! { ctx.state.clone(), }),
|
|
||||||
arg if is_mut_ref_opstate(arg) => {
|
|
||||||
Some(quote! { &mut ctx.state.borrow_mut(), })
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
let special_args = f
|
let special_args = f
|
||||||
.sig
|
.sig
|
||||||
.inputs
|
.inputs
|
||||||
|
@ -386,6 +414,7 @@ fn is_unit_result(ty: impl ToTokens) -> bool {
|
||||||
fn is_mut_ref_opstate(arg: &syn::FnArg) -> bool {
|
fn is_mut_ref_opstate(arg: &syn::FnArg) -> bool {
|
||||||
tokens(arg).ends_with(": & mut OpState")
|
tokens(arg).ends_with(": & mut OpState")
|
||||||
|| tokens(arg).ends_with(": & mut deno_core :: OpState")
|
|| tokens(arg).ends_with(": & mut deno_core :: OpState")
|
||||||
|
|| tokens(arg).ends_with("mut OpState")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_rc_refcell_opstate(arg: &syn::FnArg) -> bool {
|
fn is_rc_refcell_opstate(arg: &syn::FnArg) -> bool {
|
||||||
|
@ -398,6 +427,8 @@ fn is_handle_scope(arg: &syn::FnArg) -> bool {
|
||||||
|| tokens(arg).ends_with(": & mut v8 :: HandleScope < 'a >")
|
|| tokens(arg).ends_with(": & mut v8 :: HandleScope < 'a >")
|
||||||
|| tokens(arg).ends_with(": & mut deno_core :: v8 :: HandleScope")
|
|| tokens(arg).ends_with(": & mut deno_core :: v8 :: HandleScope")
|
||||||
|| tokens(arg).ends_with(": & mut deno_core :: v8 :: HandleScope < 'a >")
|
|| tokens(arg).ends_with(": & mut deno_core :: v8 :: HandleScope < 'a >")
|
||||||
|
|| tokens(arg).contains("mut v8 :: HandleScope")
|
||||||
|
|| tokens(arg).ends_with(": & mut v8 :: HandeScope < 'scope >")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_future(ty: impl ToTokens) -> bool {
|
fn is_future(ty: impl ToTokens) -> bool {
|
||||||
|
|
Loading…
Reference in a new issue