diff --git a/ext/net/ops.rs b/ext/net/ops.rs index 96de8cff13..e567c31885 100644 --- a/ext/net/ops.rs +++ b/ext/net/ops.rs @@ -67,8 +67,8 @@ pub fn init() -> Vec { #[cfg(unix)] crate::ops_unix::op_net_send_unixpacket::decl::

(), op_dns_resolve::decl::

(), - op_set_nodelay::decl::

(), - op_set_keepalive::decl::

(), + op_set_nodelay::decl(), + op_set_keepalive::decl(), ] } @@ -509,7 +509,7 @@ where } #[op] -pub fn op_set_nodelay( +pub fn op_set_nodelay( state: &mut OpState, rid: ResourceId, nodelay: bool, @@ -521,7 +521,7 @@ pub fn op_set_nodelay( } #[op] -pub fn op_set_keepalive( +pub fn op_set_keepalive( state: &mut OpState, rid: ResourceId, keepalive: bool, @@ -836,7 +836,7 @@ mod tests { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn tcp_set_no_delay() { let set_nodelay = Box::new(|state: &mut OpState, rid| { - op_set_nodelay::call::(state, rid, true).unwrap(); + op_set_nodelay::call(state, rid, true).unwrap(); }); let test_fn = Box::new(|socket: SockRef| { assert!(socket.nodelay().unwrap()); @@ -848,7 +848,7 @@ mod tests { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn tcp_set_keepalive() { let set_keepalive = Box::new(|state: &mut OpState, rid| { - op_set_keepalive::call::(state, rid, true).unwrap(); + op_set_keepalive::call(state, rid, true).unwrap(); }); let test_fn = Box::new(|socket: SockRef| { assert!(!socket.nodelay().unwrap()); diff --git a/ops/fast_call.rs b/ops/fast_call.rs index 8f6348ec45..07bf870262 100644 --- a/ops/fast_call.rs +++ b/ops/fast_call.rs @@ -141,10 +141,19 @@ pub(crate) fn generate( if optimizer.has_fast_callback_option || optimizer.needs_opstate() || optimizer.is_async + || optimizer.needs_fast_callback_option { - fast_fn_inputs.push(parse_quote! { + let decl = parse_quote! { fast_api_callback_options: *mut #core::v8::fast_api::FastApiCallbackOptions - }); + }; + + if optimizer.has_fast_callback_option { + // Replace last parameter. + assert!(fast_fn_inputs.pop().is_some()); + fast_fn_inputs.push(decl); + } else { + fast_fn_inputs.push(decl); + } input_variants.push(q!({ CallbackOptions })); } @@ -162,14 +171,10 @@ pub(crate) fn generate( let mut output_transforms = q!({}); - if optimizer.needs_opstate() || optimizer.is_async { - // Grab the op_state identifier, the first one. ¯\_(ツ)_/¯ - let op_state = match idents.first() { - Some(ident) if optimizer.has_opstate_in_parameters() => ident.clone(), - // fn op_foo() -> Result<...> - _ => Ident::new("op_state", Span::call_site()), - }; - + if optimizer.needs_opstate() + || optimizer.is_async + || optimizer.has_fast_callback_option + { // Dark arts 🪄 ✨ // // - V8 calling convention guarantees that the callback options pointer is non-null. @@ -179,13 +184,27 @@ pub(crate) fn generate( let prelude = q!({ let __opts: &mut v8::fast_api::FastApiCallbackOptions = unsafe { &mut *fast_api_callback_options }; + }); + + pre_transforms.push_tokens(&prelude); + } + + if optimizer.needs_opstate() || optimizer.is_async { + // Grab the op_state identifier, the first one. ¯\_(ツ)_/¯ + let op_state = match idents.first() { + Some(ident) if optimizer.has_opstate_in_parameters() => ident.clone(), + // fn op_foo() -> Result<...> + _ => Ident::new("op_state", Span::call_site()), + }; + + let ctx = q!({ let __ctx = unsafe { &*(v8::Local::::cast(unsafe { __opts.data.data }).value() as *const _ops::OpCtx) }; }); - pre_transforms.push_tokens(&prelude); + pre_transforms.push_tokens(&ctx); pre_transforms.push_tokens(&match optimizer.is_async { false => q!( Vars { diff --git a/ops/lib.rs b/ops/lib.rs index a5c196c047..971b0dfa03 100644 --- a/ops/lib.rs +++ b/ops/lib.rs @@ -76,10 +76,11 @@ impl Op { fn gen(mut self) -> TokenStream2 { let mut optimizer = Optimizer::new(); match optimizer.analyze(&mut self) { - Ok(_) | Err(BailoutReason::MustBeSingleSegment) => {} - Err(BailoutReason::FastUnsupportedParamType) => { + Err(BailoutReason::MustBeSingleSegment) + | Err(BailoutReason::FastUnsupportedParamType) => { optimizer.fast_compatible = false; } + _ => {} }; let Self { diff --git a/ops/optimizer.rs b/ops/optimizer.rs index cf2c71ae42..8fa2ab1f57 100644 --- a/ops/optimizer.rs +++ b/ops/optimizer.rs @@ -9,7 +9,7 @@ use syn::{ parse_quote, punctuated::Punctuated, token::Colon2, AngleBracketedGenericArguments, FnArg, GenericArgument, PatType, Path, PathArguments, PathSegment, ReturnType, Signature, Type, TypePath, TypePtr, - TypeReference, TypeSlice, + TypeReference, TypeSlice, TypeTuple, }; #[derive(Debug)] @@ -196,7 +196,10 @@ pub(crate) struct Optimizer { pub(crate) has_rc_opstate: bool, + // Do we need an explict FastApiCallbackOptions argument? pub(crate) has_fast_callback_option: bool, + // Do we depend on FastApiCallbackOptions? + pub(crate) needs_fast_callback_option: bool, pub(crate) fast_result: Option, pub(crate) fast_parameters: Vec, @@ -218,6 +221,11 @@ impl Debug for Optimizer { "has_fast_callback_option: {}", self.has_fast_callback_option )?; + writeln!( + f, + "needs_fast_callback_option: {}", + self.needs_fast_callback_option + )?; writeln!(f, "fast_result: {:?}", self.fast_result)?; writeln!(f, "fast_parameters: {:?}", self.fast_parameters)?; writeln!(f, "transforms: {:?}", self.transforms)?; @@ -298,6 +306,9 @@ impl Optimizer { fn analyze_return_type(&mut self, ty: &Type) -> Result<(), BailoutReason> { match ty { + Type::Tuple(TypeTuple { elems, .. }) if elems.is_empty() => { + self.fast_result = Some(FastValue::Void); + } Type::Path(TypePath { path: Path { segments, .. }, .. @@ -333,6 +344,14 @@ impl Optimizer { self.fast_compatible = false; return Err(BailoutReason::FastUnsupportedParamType); } + Some(GenericArgument::Type(Type::Tuple(TypeTuple { + elems, + .. + }))) + if elems.is_empty() => + { + self.fast_result = Some(FastValue::Void); + } _ => return Err(BailoutReason::FastUnsupportedParamType), } } @@ -407,15 +426,19 @@ impl Optimizer { { let segment = single_segment(segments)?; match segment { - // Is `T` a FastApiCallbackOption? + // Is `T` a FastApiCallbackOptions? PathSegment { ident, .. } - if ident == "FastApiCallbackOption" => + if ident == "FastApiCallbackOptions" => { self.has_fast_callback_option = true; } - _ => {} + _ => return Err(BailoutReason::FastUnsupportedParamType), } + } else { + return Err(BailoutReason::FastUnsupportedParamType); } + } else { + return Err(BailoutReason::FastUnsupportedParamType); } } } @@ -517,7 +540,7 @@ impl Optimizer { match segment { // Is `T` a u8? PathSegment { ident, .. } if ident == "u8" => { - self.has_fast_callback_option = true; + self.needs_fast_callback_option = true; self.fast_parameters.push(FastValue::Uint8Array); assert!(self .transforms @@ -526,7 +549,7 @@ impl Optimizer { } // Is `T` a u32? PathSegment { ident, .. } if ident == "u32" => { - self.has_fast_callback_option = true; + self.needs_fast_callback_option = true; self.fast_parameters.push(FastValue::Uint32Array); assert!(self .transforms @@ -554,7 +577,7 @@ impl Optimizer { match segment { // Is `T` a u8? PathSegment { ident, .. } if ident == "u8" => { - self.has_fast_callback_option = true; + self.needs_fast_callback_option = true; self.fast_parameters.push(FastValue::Uint8Array); assert!(self .transforms diff --git a/ops/optimizer_tests/async_nop.expected b/ops/optimizer_tests/async_nop.expected index 78c161e8c6..42a1180bd8 100644 --- a/ops/optimizer_tests/async_nop.expected +++ b/ops/optimizer_tests/async_nop.expected @@ -3,6 +3,7 @@ returns_result: false has_ref_opstate: false has_rc_opstate: false has_fast_callback_option: false +needs_fast_callback_option: false fast_result: Some(Void) fast_parameters: [V8Value, I32] transforms: {} diff --git a/ops/optimizer_tests/async_result.expected b/ops/optimizer_tests/async_result.expected index dcd9cd1e36..be2e79ac03 100644 --- a/ops/optimizer_tests/async_result.expected +++ b/ops/optimizer_tests/async_result.expected @@ -2,7 +2,8 @@ returns_result: true has_ref_opstate: false has_rc_opstate: true -has_fast_callback_option: true +has_fast_callback_option: false +needs_fast_callback_option: true fast_result: None fast_parameters: [V8Value, I32, U32, Uint8Array] transforms: {2: Transform { kind: SliceU8(true), index: 2 }} diff --git a/ops/optimizer_tests/callback_options.expected b/ops/optimizer_tests/callback_options.expected index b309ab987c..245fdfd55d 100644 --- a/ops/optimizer_tests/callback_options.expected +++ b/ops/optimizer_tests/callback_options.expected @@ -2,7 +2,8 @@ returns_result: false has_ref_opstate: false has_rc_opstate: false -has_fast_callback_option: false +has_fast_callback_option: true +needs_fast_callback_option: false fast_result: Some(Void) fast_parameters: [V8Value] transforms: {} diff --git a/ops/optimizer_tests/callback_options.out b/ops/optimizer_tests/callback_options.out index 020cc4a3ef..81745375d3 100644 --- a/ops/optimizer_tests/callback_options.out +++ b/ops/optimizer_tests/callback_options.out @@ -61,7 +61,7 @@ impl<'scope> deno_core::v8::fast_api::FastFunction for op_fallback_fast { fn args(&self) -> &'static [deno_core::v8::fast_api::Type] { use deno_core::v8::fast_api::Type::*; use deno_core::v8::fast_api::CType; - &[V8Value] + &[V8Value, CallbackOptions] } fn return_type(&self) -> deno_core::v8::fast_api::CType { deno_core::v8::fast_api::CType::Void @@ -69,10 +69,13 @@ impl<'scope> deno_core::v8::fast_api::FastFunction for op_fallback_fast { } fn op_fallback_fast_fn<'scope>( _: deno_core::v8::Local, - options: Option<&mut FastApiCallbackOptions>, + fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions, ) -> () { use deno_core::v8; use deno_core::_ops; + let __opts: &mut v8::fast_api::FastApiCallbackOptions = unsafe { + &mut *fast_api_callback_options + }; let result = op_fallback::call(options); result } diff --git a/ops/optimizer_tests/op_blob_revoke_object_url.expected b/ops/optimizer_tests/op_blob_revoke_object_url.expected new file mode 100644 index 0000000000..0fae25e860 --- /dev/null +++ b/ops/optimizer_tests/op_blob_revoke_object_url.expected @@ -0,0 +1 @@ +MustBeSingleSegment \ No newline at end of file diff --git a/ops/optimizer_tests/op_blob_revoke_object_url.out b/ops/optimizer_tests/op_blob_revoke_object_url.out new file mode 100644 index 0000000000..72bc75e059 --- /dev/null +++ b/ops/optimizer_tests/op_blob_revoke_object_url.out @@ -0,0 +1,71 @@ +#[allow(non_camel_case_types)] +///Auto-generated by `deno_ops`, i.e: `#[op]` +/// +///Use `op_blob_revoke_object_url::decl()` to get an op-declaration +///you can include in a `deno_core::Extension`. +pub struct op_blob_revoke_object_url; +#[doc(hidden)] +impl op_blob_revoke_object_url { + pub fn name() -> &'static str { + stringify!(op_blob_revoke_object_url) + } + pub fn v8_fn_ptr<'scope>() -> deno_core::v8::FunctionCallback { + use deno_core::v8::MapFnTo; + Self::v8_func.map_fn_to() + } + pub fn decl<'scope>() -> deno_core::OpDecl { + deno_core::OpDecl { + name: Self::name(), + v8_fn_ptr: Self::v8_fn_ptr(), + enabled: true, + fast_fn: None, + is_async: false, + is_unstable: false, + is_v8: false, + argc: 1usize, + } + } + #[inline] + #[allow(clippy::too_many_arguments)] + pub fn call(state: &mut deno_core::OpState, url: String) -> Result<(), AnyError> { + let url = Url::parse(&url)?; + let blob_store = state.borrow::(); + blob_store.remove_object_url(&url); + Ok(()) + } + pub fn v8_func<'scope>( + scope: &mut deno_core::v8::HandleScope<'scope>, + args: deno_core::v8::FunctionCallbackArguments, + mut rv: deno_core::v8::ReturnValue, + ) { + let ctx = unsafe { + &*(deno_core::v8::Local::::cast(args.data()).value() + as *const deno_core::_ops::OpCtx) + }; + let arg_0 = match deno_core::v8::Local::< + deno_core::v8::String, + >::try_from(args.get(0usize as i32)) { + Ok(v8_string) => deno_core::serde_v8::to_utf8(v8_string, scope), + Err(_) => { + return deno_core::_ops::throw_type_error( + scope, + format!("Expected string at position {}", 0usize), + ); + } + }; + let result = Self::call(&mut std::cell::RefCell::borrow_mut(&ctx.state), arg_0); + let op_state = ::std::cell::RefCell::borrow(&*ctx.state); + op_state.tracker.track_sync(ctx.id); + match result { + Ok(result) => {} + Err(err) => { + let exception = deno_core::error::to_v8_error( + scope, + op_state.get_error_class_fn, + &err, + ); + scope.throw_exception(exception); + } + }; + } +} diff --git a/ops/optimizer_tests/op_blob_revoke_object_url.rs b/ops/optimizer_tests/op_blob_revoke_object_url.rs new file mode 100644 index 0000000000..8e139da06d --- /dev/null +++ b/ops/optimizer_tests/op_blob_revoke_object_url.rs @@ -0,0 +1,9 @@ +pub fn op_blob_revoke_object_url( + state: &mut deno_core::OpState, + url: String, +) -> Result<(), AnyError> { + let url = Url::parse(&url)?; + let blob_store = state.borrow::(); + blob_store.remove_object_url(&url); + Ok(()) +} diff --git a/ops/optimizer_tests/op_state.expected b/ops/optimizer_tests/op_state.expected index d8d6804557..241ea76936 100644 --- a/ops/optimizer_tests/op_state.expected +++ b/ops/optimizer_tests/op_state.expected @@ -3,6 +3,7 @@ returns_result: false has_ref_opstate: true has_rc_opstate: false has_fast_callback_option: false +needs_fast_callback_option: false fast_result: Some(Void) fast_parameters: [V8Value, I32] transforms: {} diff --git a/ops/optimizer_tests/op_state_basic1.expected b/ops/optimizer_tests/op_state_basic1.expected index 6e7b15493c..e325dd2f70 100644 --- a/ops/optimizer_tests/op_state_basic1.expected +++ b/ops/optimizer_tests/op_state_basic1.expected @@ -3,6 +3,7 @@ returns_result: false has_ref_opstate: true has_rc_opstate: false has_fast_callback_option: false +needs_fast_callback_option: false fast_result: Some(U32) fast_parameters: [V8Value, U32, U32] transforms: {} diff --git a/ops/optimizer_tests/op_state_generics.expected b/ops/optimizer_tests/op_state_generics.expected index b78c81c5fa..c29258d756 100644 --- a/ops/optimizer_tests/op_state_generics.expected +++ b/ops/optimizer_tests/op_state_generics.expected @@ -3,6 +3,7 @@ returns_result: false has_ref_opstate: true has_rc_opstate: false has_fast_callback_option: false +needs_fast_callback_option: false fast_result: Some(Void) fast_parameters: [V8Value] transforms: {} diff --git a/ops/optimizer_tests/op_state_result.expected b/ops/optimizer_tests/op_state_result.expected index e133900527..15ac033f34 100644 --- a/ops/optimizer_tests/op_state_result.expected +++ b/ops/optimizer_tests/op_state_result.expected @@ -3,6 +3,7 @@ returns_result: true has_ref_opstate: true has_rc_opstate: false has_fast_callback_option: false +needs_fast_callback_option: false fast_result: Some(U32) fast_parameters: [V8Value, U32, U32] transforms: {} diff --git a/ops/optimizer_tests/op_state_warning.expected b/ops/optimizer_tests/op_state_warning.expected index 94580fd6dc..7b33ad1ef4 100644 --- a/ops/optimizer_tests/op_state_warning.expected +++ b/ops/optimizer_tests/op_state_warning.expected @@ -3,6 +3,7 @@ returns_result: true has_ref_opstate: true has_rc_opstate: false has_fast_callback_option: false +needs_fast_callback_option: false fast_result: Some(U32) fast_parameters: [V8Value] transforms: {} diff --git a/ops/optimizer_tests/op_state_with_transforms.expected b/ops/optimizer_tests/op_state_with_transforms.expected index 0fc9c99494..d6757801ee 100644 --- a/ops/optimizer_tests/op_state_with_transforms.expected +++ b/ops/optimizer_tests/op_state_with_transforms.expected @@ -2,7 +2,8 @@ returns_result: false has_ref_opstate: true has_rc_opstate: false -has_fast_callback_option: true +has_fast_callback_option: false +needs_fast_callback_option: true fast_result: Some(Void) fast_parameters: [V8Value, Uint8Array] transforms: {1: Transform { kind: SliceU8(true), index: 1 }} diff --git a/ops/optimizer_tests/opstate_with_arity.expected b/ops/optimizer_tests/opstate_with_arity.expected index 4be888c333..b38455d0dd 100644 --- a/ops/optimizer_tests/opstate_with_arity.expected +++ b/ops/optimizer_tests/opstate_with_arity.expected @@ -3,6 +3,7 @@ returns_result: true has_ref_opstate: false has_rc_opstate: false has_fast_callback_option: false +needs_fast_callback_option: false fast_result: Some(U32) fast_parameters: [V8Value, U32, U32, U32, U32] transforms: {} diff --git a/ops/optimizer_tests/option_arg.expected b/ops/optimizer_tests/option_arg.expected new file mode 100644 index 0000000000..250ff1022d --- /dev/null +++ b/ops/optimizer_tests/option_arg.expected @@ -0,0 +1 @@ +FastUnsupportedParamType \ No newline at end of file diff --git a/ops/optimizer_tests/option_arg.out b/ops/optimizer_tests/option_arg.out new file mode 100644 index 0000000000..9f647765f4 --- /dev/null +++ b/ops/optimizer_tests/option_arg.out @@ -0,0 +1,66 @@ +#[allow(non_camel_case_types)] +///Auto-generated by `deno_ops`, i.e: `#[op]` +/// +///Use `op_try_close::decl()` to get an op-declaration +///you can include in a `deno_core::Extension`. +pub struct op_try_close; +#[doc(hidden)] +impl op_try_close { + pub fn name() -> &'static str { + stringify!(op_try_close) + } + pub fn v8_fn_ptr<'scope>() -> deno_core::v8::FunctionCallback { + use deno_core::v8::MapFnTo; + Self::v8_func.map_fn_to() + } + pub fn decl<'scope>() -> deno_core::OpDecl { + deno_core::OpDecl { + name: Self::name(), + v8_fn_ptr: Self::v8_fn_ptr(), + enabled: true, + fast_fn: None, + is_async: false, + is_unstable: false, + is_v8: false, + argc: 1usize, + } + } + #[inline] + #[allow(clippy::too_many_arguments)] + pub fn call(state: &mut OpState, rid: Option) -> Result<(), Error> {} + pub fn v8_func<'scope>( + scope: &mut deno_core::v8::HandleScope<'scope>, + args: deno_core::v8::FunctionCallbackArguments, + mut rv: deno_core::v8::ReturnValue, + ) { + let ctx = unsafe { + &*(deno_core::v8::Local::::cast(args.data()).value() + as *const deno_core::_ops::OpCtx) + }; + let arg_0 = args.get(0usize as i32); + let arg_0 = match deno_core::serde_v8::from_v8(scope, arg_0) { + Ok(v) => v, + Err(err) => { + let msg = format!( + "Error parsing args at position {}: {}", 0usize, + deno_core::anyhow::Error::from(err) + ); + return deno_core::_ops::throw_type_error(scope, msg); + } + }; + let result = Self::call(&mut std::cell::RefCell::borrow_mut(&ctx.state), arg_0); + let op_state = ::std::cell::RefCell::borrow(&*ctx.state); + op_state.tracker.track_sync(ctx.id); + match result { + Ok(result) => {} + Err(err) => { + let exception = deno_core::error::to_v8_error( + scope, + op_state.get_error_class_fn, + &err, + ); + scope.throw_exception(exception); + } + }; + } +} diff --git a/ops/optimizer_tests/option_arg.rs b/ops/optimizer_tests/option_arg.rs new file mode 100644 index 0000000000..47a02974d7 --- /dev/null +++ b/ops/optimizer_tests/option_arg.rs @@ -0,0 +1,6 @@ +pub fn op_try_close( + state: &mut OpState, + rid: Option, +) -> Result<(), Error> { + // ... +} diff --git a/ops/optimizer_tests/raw_ptr.expected b/ops/optimizer_tests/raw_ptr.expected index 12577eb77f..badd6e3f49 100644 --- a/ops/optimizer_tests/raw_ptr.expected +++ b/ops/optimizer_tests/raw_ptr.expected @@ -2,7 +2,8 @@ returns_result: false has_ref_opstate: true has_rc_opstate: false -has_fast_callback_option: true +has_fast_callback_option: false +needs_fast_callback_option: true fast_result: Some(Void) fast_parameters: [V8Value, Uint8Array, Uint32Array] transforms: {1: Transform { kind: PtrU8, index: 1 }, 2: Transform { kind: SliceU32(true), index: 2 }} diff --git a/ops/optimizer_tests/serde_v8_value.expected b/ops/optimizer_tests/serde_v8_value.expected index 058b17b1c2..411fbec0bc 100644 --- a/ops/optimizer_tests/serde_v8_value.expected +++ b/ops/optimizer_tests/serde_v8_value.expected @@ -3,6 +3,7 @@ returns_result: false has_ref_opstate: false has_rc_opstate: false has_fast_callback_option: false +needs_fast_callback_option: false fast_result: Some(Bool) fast_parameters: [V8Value, V8Value] transforms: {0: Transform { kind: V8Value, index: 0 }} diff --git a/ops/optimizer_tests/uint8array.expected b/ops/optimizer_tests/uint8array.expected new file mode 100644 index 0000000000..0e5667a637 --- /dev/null +++ b/ops/optimizer_tests/uint8array.expected @@ -0,0 +1,11 @@ +=== Optimizer Dump === +returns_result: false +has_ref_opstate: false +has_rc_opstate: false +has_fast_callback_option: false +needs_fast_callback_option: true +fast_result: Some(Bool) +fast_parameters: [V8Value, Uint8Array, Uint8Array] +transforms: {0: Transform { kind: SliceU8(false), index: 0 }, 1: Transform { kind: SliceU8(true), index: 1 }} +is_async: false +fast_compatible: true diff --git a/ops/optimizer_tests/uint8array.out b/ops/optimizer_tests/uint8array.out new file mode 100644 index 0000000000..90d420fa0d --- /dev/null +++ b/ops/optimizer_tests/uint8array.out @@ -0,0 +1,191 @@ +#[allow(non_camel_case_types)] +///Auto-generated by `deno_ops`, i.e: `#[op]` +/// +///Use `op_import_spki_x25519::decl()` to get an op-declaration +///you can include in a `deno_core::Extension`. +pub struct op_import_spki_x25519; +#[doc(hidden)] +impl op_import_spki_x25519 { + pub fn name() -> &'static str { + stringify!(op_import_spki_x25519) + } + pub fn v8_fn_ptr<'scope>() -> deno_core::v8::FunctionCallback { + use deno_core::v8::MapFnTo; + Self::v8_func.map_fn_to() + } + pub fn decl<'scope>() -> deno_core::OpDecl { + deno_core::OpDecl { + name: Self::name(), + v8_fn_ptr: Self::v8_fn_ptr(), + enabled: true, + fast_fn: Some( + Box::new(op_import_spki_x25519_fast { + _phantom: ::std::marker::PhantomData, + }), + ), + is_async: false, + is_unstable: false, + is_v8: false, + argc: 2usize, + } + } + #[inline] + #[allow(clippy::too_many_arguments)] + pub fn call(key_data: &[u8], out: &mut [u8]) -> bool {} + pub fn v8_func<'scope>( + scope: &mut deno_core::v8::HandleScope<'scope>, + args: deno_core::v8::FunctionCallbackArguments, + mut rv: deno_core::v8::ReturnValue, + ) { + let ctx = unsafe { + &*(deno_core::v8::Local::::cast(args.data()).value() + as *const deno_core::_ops::OpCtx) + }; + let arg_0 = { + let value = args.get(0usize as i32); + match deno_core::v8::Local::::try_from(value) { + Ok(b) => { + let byte_length = b.byte_length(); + if let Some(data) = b.data() { + let store = data.cast::().as_ptr(); + unsafe { ::std::slice::from_raw_parts_mut(store, byte_length) } + } else { + &mut [] + } + } + Err(_) => { + if let Ok(view) + = deno_core::v8::Local::< + deno_core::v8::ArrayBufferView, + >::try_from(value) { + let len = view.byte_length(); + let offset = view.byte_offset(); + let buffer = match view.buffer(scope) { + Some(v) => v, + None => { + return deno_core::_ops::throw_type_error( + scope, + format!("Expected ArrayBufferView at position {}", 0usize), + ); + } + }; + if let Some(data) = buffer.data() { + let store = data.cast::().as_ptr(); + unsafe { + ::std::slice::from_raw_parts_mut(store.add(offset), len) + } + } else { + &mut [] + } + } else { + return deno_core::_ops::throw_type_error( + scope, + format!("Expected ArrayBufferView at position {}", 0usize), + ); + } + } + } + }; + let arg_1 = { + let value = args.get(1usize as i32); + match deno_core::v8::Local::::try_from(value) { + Ok(b) => { + let byte_length = b.byte_length(); + if let Some(data) = b.data() { + let store = data.cast::().as_ptr(); + unsafe { ::std::slice::from_raw_parts_mut(store, byte_length) } + } else { + &mut [] + } + } + Err(_) => { + if let Ok(view) + = deno_core::v8::Local::< + deno_core::v8::ArrayBufferView, + >::try_from(value) { + let len = view.byte_length(); + let offset = view.byte_offset(); + let buffer = match view.buffer(scope) { + Some(v) => v, + None => { + return deno_core::_ops::throw_type_error( + scope, + format!("Expected ArrayBufferView at position {}", 1usize), + ); + } + }; + if let Some(data) = buffer.data() { + let store = data.cast::().as_ptr(); + unsafe { + ::std::slice::from_raw_parts_mut(store.add(offset), len) + } + } else { + &mut [] + } + } else { + return deno_core::_ops::throw_type_error( + scope, + format!("Expected ArrayBufferView at position {}", 1usize), + ); + } + } + } + }; + let result = Self::call(arg_0, arg_1); + let op_state = ::std::cell::RefCell::borrow(&*ctx.state); + op_state.tracker.track_sync(ctx.id); + match deno_core::serde_v8::to_v8(scope, result) { + Ok(ret) => rv.set(ret), + Err(err) => { + deno_core::_ops::throw_type_error( + scope, + format!( + "Error serializing return: {}", + deno_core::anyhow::Error::from(err) + ), + ) + } + }; + } +} +struct op_import_spki_x25519_fast { + _phantom: ::std::marker::PhantomData<()>, +} +impl<'scope> deno_core::v8::fast_api::FastFunction for op_import_spki_x25519_fast { + fn function(&self) -> *const ::std::ffi::c_void { + op_import_spki_x25519_fast_fn as *const ::std::ffi::c_void + } + fn args(&self) -> &'static [deno_core::v8::fast_api::Type] { + use deno_core::v8::fast_api::Type::*; + use deno_core::v8::fast_api::CType; + &[V8Value, TypedArray(CType::Uint8), TypedArray(CType::Uint8), CallbackOptions] + } + fn return_type(&self) -> deno_core::v8::fast_api::CType { + deno_core::v8::fast_api::CType::Bool + } +} +fn op_import_spki_x25519_fast_fn<'scope>( + _: deno_core::v8::Local, + key_data: *const deno_core::v8::fast_api::FastApiTypedArray, + out: *const deno_core::v8::fast_api::FastApiTypedArray, + fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions, +) -> bool { + use deno_core::v8; + use deno_core::_ops; + let key_data = match unsafe { &*key_data }.get_storage_if_aligned() { + Some(v) => v, + None => { + unsafe { &mut *fast_api_callback_options }.fallback = true; + return Default::default(); + } + }; + let out = match unsafe { &*out }.get_storage_if_aligned() { + Some(v) => v, + None => { + unsafe { &mut *fast_api_callback_options }.fallback = true; + return Default::default(); + } + }; + let result = op_import_spki_x25519::call(key_data, out); + result +} diff --git a/ops/optimizer_tests/uint8array.rs b/ops/optimizer_tests/uint8array.rs new file mode 100644 index 0000000000..f4507b21f5 --- /dev/null +++ b/ops/optimizer_tests/uint8array.rs @@ -0,0 +1,3 @@ +pub fn op_import_spki_x25519(key_data: &[u8], out: &mut [u8]) -> bool { + // ... +} diff --git a/ops/optimizer_tests/unit_result.expected b/ops/optimizer_tests/unit_result.expected new file mode 100644 index 0000000000..693a771e9a --- /dev/null +++ b/ops/optimizer_tests/unit_result.expected @@ -0,0 +1,11 @@ +=== Optimizer Dump === +returns_result: true +has_ref_opstate: false +has_rc_opstate: false +has_fast_callback_option: false +needs_fast_callback_option: false +fast_result: Some(Void) +fast_parameters: [V8Value] +transforms: {} +is_async: false +fast_compatible: true diff --git a/ops/optimizer_tests/unit_result.out b/ops/optimizer_tests/unit_result.out new file mode 100644 index 0000000000..f9d1e0c341 --- /dev/null +++ b/ops/optimizer_tests/unit_result.out @@ -0,0 +1,113 @@ +#[allow(non_camel_case_types)] +///Auto-generated by `deno_ops`, i.e: `#[op]` +/// +///Use `op_unit_result::decl()` to get an op-declaration +///you can include in a `deno_core::Extension`. +pub struct op_unit_result; +#[doc(hidden)] +impl op_unit_result { + pub fn name() -> &'static str { + stringify!(op_unit_result) + } + pub fn v8_fn_ptr<'scope>() -> deno_core::v8::FunctionCallback { + use deno_core::v8::MapFnTo; + Self::v8_func.map_fn_to() + } + pub fn decl<'scope>() -> deno_core::OpDecl { + deno_core::OpDecl { + name: Self::name(), + v8_fn_ptr: Self::v8_fn_ptr(), + enabled: true, + fast_fn: Some( + Box::new(op_unit_result_fast { + _phantom: ::std::marker::PhantomData, + }), + ), + is_async: false, + is_unstable: false, + is_v8: false, + argc: 0usize, + } + } + #[inline] + #[allow(clippy::too_many_arguments)] + fn call() -> Result<(), AnyError> { + Ok(()) + } + pub fn v8_func<'scope>( + scope: &mut deno_core::v8::HandleScope<'scope>, + args: deno_core::v8::FunctionCallbackArguments, + mut rv: deno_core::v8::ReturnValue, + ) { + let ctx = unsafe { + &*(deno_core::v8::Local::::cast(args.data()).value() + as *const deno_core::_ops::OpCtx) + }; + { + let op_state = &mut std::cell::RefCell::borrow_mut(&ctx.state); + if let Some(err) = op_state.last_fast_op_error.take() { + let exception = deno_core::error::to_v8_error( + scope, + op_state.get_error_class_fn, + &err, + ); + scope.throw_exception(exception); + return; + } + } + let result = Self::call(); + let op_state = ::std::cell::RefCell::borrow(&*ctx.state); + op_state.tracker.track_sync(ctx.id); + match result { + Ok(result) => {} + Err(err) => { + let exception = deno_core::error::to_v8_error( + scope, + op_state.get_error_class_fn, + &err, + ); + scope.throw_exception(exception); + } + }; + } +} +struct op_unit_result_fast { + _phantom: ::std::marker::PhantomData<()>, +} +impl<'scope> deno_core::v8::fast_api::FastFunction for op_unit_result_fast { + fn function(&self) -> *const ::std::ffi::c_void { + op_unit_result_fast_fn as *const ::std::ffi::c_void + } + fn args(&self) -> &'static [deno_core::v8::fast_api::Type] { + use deno_core::v8::fast_api::Type::*; + use deno_core::v8::fast_api::CType; + &[V8Value, CallbackOptions] + } + fn return_type(&self) -> deno_core::v8::fast_api::CType { + deno_core::v8::fast_api::CType::Void + } +} +fn op_unit_result_fast_fn<'scope>( + _: deno_core::v8::Local, + fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions, +) -> () { + use deno_core::v8; + use deno_core::_ops; + let __opts: &mut v8::fast_api::FastApiCallbackOptions = unsafe { + &mut *fast_api_callback_options + }; + let __ctx = unsafe { + &*(v8::Local::::cast(unsafe { __opts.data.data }).value() + as *const _ops::OpCtx) + }; + let op_state = &mut ::std::cell::RefCell::borrow_mut(&__ctx.state); + let result = op_unit_result::call(); + match result { + Ok(result) => result, + Err(err) => { + op_state.last_fast_op_error.replace(err); + __opts.fallback = true; + Default::default() + } + } +} diff --git a/ops/optimizer_tests/unit_result.rs b/ops/optimizer_tests/unit_result.rs new file mode 100644 index 0000000000..207896929c --- /dev/null +++ b/ops/optimizer_tests/unit_result.rs @@ -0,0 +1,3 @@ +fn op_unit_result() -> Result<(), AnyError> { + Ok(()) +} diff --git a/ops/optimizer_tests/unit_result2.expected b/ops/optimizer_tests/unit_result2.expected new file mode 100644 index 0000000000..d799a77b2f --- /dev/null +++ b/ops/optimizer_tests/unit_result2.expected @@ -0,0 +1,11 @@ +=== Optimizer Dump === +returns_result: true +has_ref_opstate: true +has_rc_opstate: false +has_fast_callback_option: false +needs_fast_callback_option: false +fast_result: Some(Void) +fast_parameters: [V8Value, U32, Bool] +transforms: {} +is_async: false +fast_compatible: true diff --git a/ops/optimizer_tests/unit_result2.out b/ops/optimizer_tests/unit_result2.out new file mode 100644 index 0000000000..87e0ee0b56 --- /dev/null +++ b/ops/optimizer_tests/unit_result2.out @@ -0,0 +1,149 @@ +#[allow(non_camel_case_types)] +///Auto-generated by `deno_ops`, i.e: `#[op]` +/// +///Use `op_set_nodelay::decl()` to get an op-declaration +///you can include in a `deno_core::Extension`. +pub struct op_set_nodelay; +#[doc(hidden)] +impl op_set_nodelay { + pub fn name() -> &'static str { + stringify!(op_set_nodelay) + } + pub fn v8_fn_ptr<'scope>() -> deno_core::v8::FunctionCallback { + use deno_core::v8::MapFnTo; + Self::v8_func.map_fn_to() + } + pub fn decl<'scope>() -> deno_core::OpDecl { + deno_core::OpDecl { + name: Self::name(), + v8_fn_ptr: Self::v8_fn_ptr(), + enabled: true, + fast_fn: Some( + Box::new(op_set_nodelay_fast { + _phantom: ::std::marker::PhantomData, + }), + ), + is_async: false, + is_unstable: false, + is_v8: false, + argc: 2usize, + } + } + #[inline] + #[allow(clippy::too_many_arguments)] + pub fn call( + state: &mut OpState, + rid: ResourceId, + nodelay: bool, + ) -> Result<(), AnyError> { + super::check_unstable(state, "Deno.Conn#setNoDelay"); + let resource: Rc = state + .resource_table + .get::(rid)?; + resource.set_nodelay(nodelay) + } + pub fn v8_func<'scope>( + scope: &mut deno_core::v8::HandleScope<'scope>, + args: deno_core::v8::FunctionCallbackArguments, + mut rv: deno_core::v8::ReturnValue, + ) { + let ctx = unsafe { + &*(deno_core::v8::Local::::cast(args.data()).value() + as *const deno_core::_ops::OpCtx) + }; + { + let op_state = &mut std::cell::RefCell::borrow_mut(&ctx.state); + if let Some(err) = op_state.last_fast_op_error.take() { + let exception = deno_core::error::to_v8_error( + scope, + op_state.get_error_class_fn, + &err, + ); + scope.throw_exception(exception); + return; + } + } + let arg_0 = args.get(0usize as i32); + let arg_0 = match deno_core::serde_v8::from_v8(scope, arg_0) { + Ok(v) => v, + Err(err) => { + let msg = format!( + "Error parsing args at position {}: {}", 0usize, + deno_core::anyhow::Error::from(err) + ); + return deno_core::_ops::throw_type_error(scope, msg); + } + }; + let arg_1 = args.get(1usize as i32); + let arg_1 = match deno_core::serde_v8::from_v8(scope, arg_1) { + Ok(v) => v, + Err(err) => { + let msg = format!( + "Error parsing args at position {}: {}", 1usize, + deno_core::anyhow::Error::from(err) + ); + return deno_core::_ops::throw_type_error(scope, msg); + } + }; + let result = Self::call( + &mut std::cell::RefCell::borrow_mut(&ctx.state), + arg_0, + arg_1, + ); + let op_state = ::std::cell::RefCell::borrow(&*ctx.state); + op_state.tracker.track_sync(ctx.id); + match result { + Ok(result) => {} + Err(err) => { + let exception = deno_core::error::to_v8_error( + scope, + op_state.get_error_class_fn, + &err, + ); + scope.throw_exception(exception); + } + }; + } +} +struct op_set_nodelay_fast { + _phantom: ::std::marker::PhantomData<()>, +} +impl<'scope> deno_core::v8::fast_api::FastFunction for op_set_nodelay_fast { + fn function(&self) -> *const ::std::ffi::c_void { + op_set_nodelay_fast_fn as *const ::std::ffi::c_void + } + fn args(&self) -> &'static [deno_core::v8::fast_api::Type] { + use deno_core::v8::fast_api::Type::*; + use deno_core::v8::fast_api::CType; + &[V8Value, Uint32, Bool, CallbackOptions] + } + fn return_type(&self) -> deno_core::v8::fast_api::CType { + deno_core::v8::fast_api::CType::Void + } +} +fn op_set_nodelay_fast_fn<'scope>( + _: deno_core::v8::Local, + rid: ResourceId, + nodelay: bool, + fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions, +) -> () { + use deno_core::v8; + use deno_core::_ops; + let __opts: &mut v8::fast_api::FastApiCallbackOptions = unsafe { + &mut *fast_api_callback_options + }; + let __ctx = unsafe { + &*(v8::Local::::cast(unsafe { __opts.data.data }).value() + as *const _ops::OpCtx) + }; + let state = &mut ::std::cell::RefCell::borrow_mut(&__ctx.state); + let result = op_set_nodelay::call(state, rid, nodelay); + match result { + Ok(result) => result, + Err(err) => { + state.last_fast_op_error.replace(err); + __opts.fallback = true; + Default::default() + } + } +} diff --git a/ops/optimizer_tests/unit_result2.rs b/ops/optimizer_tests/unit_result2.rs new file mode 100644 index 0000000000..d3e8ced6a3 --- /dev/null +++ b/ops/optimizer_tests/unit_result2.rs @@ -0,0 +1,10 @@ +pub fn op_set_nodelay( + state: &mut OpState, + rid: ResourceId, + nodelay: bool, +) -> Result<(), AnyError> { + super::check_unstable(state, "Deno.Conn#setNoDelay"); + let resource: Rc = + state.resource_table.get::(rid)?; + resource.set_nodelay(nodelay) +} diff --git a/ops/optimizer_tests/unit_ret.expected b/ops/optimizer_tests/unit_ret.expected new file mode 100644 index 0000000000..5d414e1e33 --- /dev/null +++ b/ops/optimizer_tests/unit_ret.expected @@ -0,0 +1,11 @@ +=== Optimizer Dump === +returns_result: false +has_ref_opstate: false +has_rc_opstate: false +has_fast_callback_option: false +needs_fast_callback_option: false +fast_result: Some(Void) +fast_parameters: [V8Value] +transforms: {} +is_async: false +fast_compatible: true diff --git a/ops/optimizer_tests/unit_ret.out b/ops/optimizer_tests/unit_ret.out new file mode 100644 index 0000000000..c18fa19152 --- /dev/null +++ b/ops/optimizer_tests/unit_ret.out @@ -0,0 +1,84 @@ +#[allow(non_camel_case_types)] +///Auto-generated by `deno_ops`, i.e: `#[op]` +/// +///Use `op_unit::decl()` to get an op-declaration +///you can include in a `deno_core::Extension`. +pub struct op_unit; +#[doc(hidden)] +impl op_unit { + pub fn name() -> &'static str { + stringify!(op_unit) + } + pub fn v8_fn_ptr<'scope>() -> deno_core::v8::FunctionCallback { + use deno_core::v8::MapFnTo; + Self::v8_func.map_fn_to() + } + pub fn decl<'scope>() -> deno_core::OpDecl { + deno_core::OpDecl { + name: Self::name(), + v8_fn_ptr: Self::v8_fn_ptr(), + enabled: true, + fast_fn: Some( + Box::new(op_unit_fast { + _phantom: ::std::marker::PhantomData, + }), + ), + is_async: false, + is_unstable: false, + is_v8: false, + argc: 0usize, + } + } + #[inline] + #[allow(clippy::too_many_arguments)] + fn call() -> () { + () + } + pub fn v8_func<'scope>( + scope: &mut deno_core::v8::HandleScope<'scope>, + args: deno_core::v8::FunctionCallbackArguments, + mut rv: deno_core::v8::ReturnValue, + ) { + let ctx = unsafe { + &*(deno_core::v8::Local::::cast(args.data()).value() + as *const deno_core::_ops::OpCtx) + }; + let result = Self::call(); + let op_state = ::std::cell::RefCell::borrow(&*ctx.state); + op_state.tracker.track_sync(ctx.id); + match deno_core::serde_v8::to_v8(scope, result) { + Ok(ret) => rv.set(ret), + Err(err) => { + deno_core::_ops::throw_type_error( + scope, + format!( + "Error serializing return: {}", + deno_core::anyhow::Error::from(err) + ), + ) + } + }; + } +} +struct op_unit_fast { + _phantom: ::std::marker::PhantomData<()>, +} +impl<'scope> deno_core::v8::fast_api::FastFunction for op_unit_fast { + fn function(&self) -> *const ::std::ffi::c_void { + op_unit_fast_fn as *const ::std::ffi::c_void + } + fn args(&self) -> &'static [deno_core::v8::fast_api::Type] { + use deno_core::v8::fast_api::Type::*; + use deno_core::v8::fast_api::CType; + &[V8Value] + } + fn return_type(&self) -> deno_core::v8::fast_api::CType { + deno_core::v8::fast_api::CType::Void + } +} +fn op_unit_fast_fn<'scope>(_: deno_core::v8::Local) -> () { + use deno_core::v8; + use deno_core::_ops; + let result = op_unit::call(); + result +} diff --git a/ops/optimizer_tests/unit_ret.rs b/ops/optimizer_tests/unit_ret.rs new file mode 100644 index 0000000000..4cf3651db7 --- /dev/null +++ b/ops/optimizer_tests/unit_ret.rs @@ -0,0 +1,3 @@ +fn op_unit() -> () { + () +}