diff options
Diffstat (limited to 'ops/op2')
29 files changed, 0 insertions, 2783 deletions
diff --git a/ops/op2/dispatch_fast.rs b/ops/op2/dispatch_fast.rs deleted file mode 100644 index f9d74416a..000000000 --- a/ops/op2/dispatch_fast.rs +++ /dev/null @@ -1,327 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. -use super::generator_state::GeneratorState; -use super::signature::Arg; -use super::signature::NumericArg; -use super::signature::ParsedSignature; -use super::signature::RetVal; -use super::signature::Special; -use super::V8MappingError; -use proc_macro2::Ident; -use proc_macro2::TokenStream; -use quote::format_ident; -use quote::quote; -use std::iter::zip; - -#[allow(unused)] -#[derive(Debug, Default, PartialEq, Clone)] -pub(crate) enum V8FastCallType { - #[default] - Void, - Bool, - U32, - I32, - U64, - I64, - F32, - F64, - Pointer, - V8Value, - Uint8Array, - Uint32Array, - Float64Array, - SeqOneByteString, - CallbackOptions, -} - -impl V8FastCallType { - /// Quote fast value type. - fn quote_rust_type(&self, deno_core: &TokenStream) -> TokenStream { - match self { - V8FastCallType::Void => quote!(()), - V8FastCallType::Bool => quote!(bool), - V8FastCallType::U32 => quote!(u32), - V8FastCallType::I32 => quote!(i32), - V8FastCallType::U64 => quote!(u64), - V8FastCallType::I64 => quote!(i64), - V8FastCallType::F32 => quote!(f32), - V8FastCallType::F64 => quote!(f64), - V8FastCallType::Pointer => quote!(*mut ::std::ffi::c_void), - V8FastCallType::V8Value => { - quote!(#deno_core::v8::Local<#deno_core::v8::Value>) - } - V8FastCallType::CallbackOptions => { - quote!(*mut #deno_core::v8::fast_api::FastApiCallbackOptions) - } - V8FastCallType::SeqOneByteString => { - quote!(*mut #deno_core::v8::fast_api::FastApiOneByteString) - } - V8FastCallType::Uint8Array - | V8FastCallType::Uint32Array - | V8FastCallType::Float64Array => unreachable!(), - } - } - - /// Quote fast value type's variant. - fn quote_ctype(&self) -> TokenStream { - match &self { - V8FastCallType::Void => quote!(CType::Void), - V8FastCallType::Bool => quote!(CType::Bool), - V8FastCallType::U32 => quote!(CType::Uint32), - V8FastCallType::I32 => quote!(CType::Int32), - V8FastCallType::U64 => quote!(CType::Uint64), - V8FastCallType::I64 => quote!(CType::Int64), - V8FastCallType::F32 => quote!(CType::Float32), - V8FastCallType::F64 => quote!(CType::Float64), - V8FastCallType::Pointer => quote!(CType::Pointer), - V8FastCallType::V8Value => quote!(CType::V8Value), - V8FastCallType::CallbackOptions => quote!(CType::CallbackOptions), - V8FastCallType::Uint8Array => unreachable!(), - V8FastCallType::Uint32Array => unreachable!(), - V8FastCallType::Float64Array => unreachable!(), - V8FastCallType::SeqOneByteString => quote!(CType::SeqOneByteString), - } - } - - /// Quote fast value type's variant. - fn quote_type(&self) -> TokenStream { - match &self { - V8FastCallType::Void => quote!(Type::Void), - V8FastCallType::Bool => quote!(Type::Bool), - V8FastCallType::U32 => quote!(Type::Uint32), - V8FastCallType::I32 => quote!(Type::Int32), - V8FastCallType::U64 => quote!(Type::Uint64), - V8FastCallType::I64 => quote!(Type::Int64), - V8FastCallType::F32 => quote!(Type::Float32), - V8FastCallType::F64 => quote!(Type::Float64), - V8FastCallType::Pointer => quote!(Type::Pointer), - V8FastCallType::V8Value => quote!(Type::V8Value), - V8FastCallType::CallbackOptions => quote!(Type::CallbackOptions), - V8FastCallType::Uint8Array => quote!(Type::TypedArray(CType::Uint8)), - V8FastCallType::Uint32Array => quote!(Type::TypedArray(CType::Uint32)), - V8FastCallType::Float64Array => quote!(Type::TypedArray(CType::Float64)), - V8FastCallType::SeqOneByteString => quote!(Type::SeqOneByteString), - } - } -} - -pub fn generate_dispatch_fast( - generator_state: &mut GeneratorState, - signature: &ParsedSignature, -) -> Result<Option<(TokenStream, TokenStream)>, V8MappingError> { - let mut inputs = vec![]; - for arg in &signature.args { - let Some(fv) = map_arg_to_v8_fastcall_type(arg)? else { - return Ok(None); - }; - inputs.push(fv); - } - let mut names = inputs - .iter() - .enumerate() - .map(|(i, _)| format_ident!("arg{i}")) - .collect::<Vec<_>>(); - - let ret_val = match &signature.ret_val { - RetVal::Infallible(arg) => arg, - RetVal::Result(arg) => arg, - }; - - let output = match map_retval_to_v8_fastcall_type(ret_val)? { - None => return Ok(None), - Some(rv) => rv, - }; - - let GeneratorState { - fast_function, - deno_core, - result, - opctx, - fast_api_callback_options, - needs_fast_api_callback_options, - needs_fast_opctx, - .. - } = generator_state; - - let handle_error = match signature.ret_val { - RetVal::Infallible(_) => quote!(), - RetVal::Result(_) => { - *needs_fast_api_callback_options = true; - *needs_fast_opctx = true; - inputs.push(V8FastCallType::CallbackOptions); - quote! { - let #result = match #result { - Ok(#result) => #result, - Err(err) => { - // FASTCALL FALLBACK: This is where we set the errors for the slow-call error pickup path. There - // is no code running between this and the other FASTCALL FALLBACK comment, except some V8 code - // required to perform the fallback process. This is why the below call is safe. - - // The reason we need to do this is because V8 does not allow exceptions to be thrown from the - // fast call. Instead, you are required to set the fallback flag, which indicates to V8 that it - // should re-call the slow version of the function. Technically the slow call should perform the - // same operation and then throw the same error (because it should be idempotent), but in our - // case we stash the error and pick it up on the slow path before doing any work. - - // TODO(mmastrac): We should allow an #[op] flag to re-perform slow calls without the error path when - // the method is performance sensitive. - - // SAFETY: We guarantee that OpCtx has no mutable references once ops are live and being called, - // allowing us to perform this one little bit of mutable magic. - unsafe { #opctx.unsafely_set_last_error_for_ops_only(err); } - #fast_api_callback_options.fallback = true; - return ::std::default::Default::default(); - } - }; - } - } - }; - - let input_types = inputs.iter().map(|fv| fv.quote_type()).collect::<Vec<_>>(); - let output_type = output.quote_ctype(); - - let fast_definition = quote! { - use #deno_core::v8::fast_api::Type; - use #deno_core::v8::fast_api::CType; - #deno_core::v8::fast_api::FastFunction::new( - &[ Type::V8Value, #( #input_types ),* ], - #output_type, - Self::#fast_function as *const ::std::ffi::c_void - ) - }; - - let output_type = output.quote_rust_type(deno_core); - let mut types = inputs - .iter() - .map(|rv| rv.quote_rust_type(deno_core)) - .collect::<Vec<_>>(); - - let call_idents = names.clone(); - let call_args = zip(names.iter(), signature.args.iter()) - .map(|(name, arg)| map_v8_fastcall_arg_to_arg(deno_core, name, arg)) - .collect::<Vec<_>>(); - - let with_fast_api_callback_options = if *needs_fast_api_callback_options { - types.push(V8FastCallType::CallbackOptions.quote_rust_type(deno_core)); - names.push(fast_api_callback_options.clone()); - quote! { - let #fast_api_callback_options = unsafe { &mut *#fast_api_callback_options }; - } - } else { - quote!() - }; - let with_opctx = if *needs_fast_opctx { - quote!( - let #opctx = unsafe { - &*(#deno_core::v8::Local::<v8::External>::cast(unsafe { #fast_api_callback_options.data.data }).value() - as *const #deno_core::_ops::OpCtx) - }; - ) - } else { - quote!() - }; - - let fast_fn = quote!( - fn #fast_function( - _: #deno_core::v8::Local<#deno_core::v8::Object>, - #( #names: #types, )* - ) -> #output_type { - #with_fast_api_callback_options - #with_opctx - #(#call_args)* - let #result = Self::call(#(#call_idents),*); - #handle_error - #result - } - ); - - Ok(Some((fast_definition, fast_fn))) -} - -fn map_v8_fastcall_arg_to_arg( - deno_core: &TokenStream, - arg_ident: &Ident, - arg: &Arg, -) -> TokenStream { - let arg_temp = format_ident!("{}_temp", arg_ident); - match arg { - Arg::Special(Special::RefStr) => { - quote! { - let mut #arg_temp: [::std::mem::MaybeUninit<u8>; 1024] = [::std::mem::MaybeUninit::uninit(); 1024]; - let #arg_ident = &#deno_core::_ops::to_str_ptr(unsafe { &mut *#arg_ident }, &mut #arg_temp); - } - } - Arg::Special(Special::String) => { - quote!(let #arg_ident = #deno_core::_ops::to_string_ptr(unsafe { &mut *#arg_ident });) - } - Arg::Special(Special::CowStr) => { - quote! { - let mut #arg_temp: [::std::mem::MaybeUninit<u8>; 1024] = [::std::mem::MaybeUninit::uninit(); 1024]; - let #arg_ident = #deno_core::_ops::to_str_ptr(unsafe { &mut *#arg_ident }, &mut #arg_temp); - } - } - _ => quote!(let #arg_ident = #arg_ident as _;), - } -} - -fn map_arg_to_v8_fastcall_type( - arg: &Arg, -) -> Result<Option<V8FastCallType>, V8MappingError> { - let rv = match arg { - Arg::OptionNumeric(_) | Arg::SerdeV8(_) => return Ok(None), - Arg::Numeric(NumericArg::bool) => V8FastCallType::Bool, - Arg::Numeric(NumericArg::u32) - | Arg::Numeric(NumericArg::u16) - | Arg::Numeric(NumericArg::u8) => V8FastCallType::U32, - Arg::Numeric(NumericArg::i32) - | Arg::Numeric(NumericArg::i16) - | Arg::Numeric(NumericArg::i8) - | Arg::Numeric(NumericArg::__SMI__) => V8FastCallType::I32, - Arg::Numeric(NumericArg::u64) | Arg::Numeric(NumericArg::usize) => { - V8FastCallType::U64 - } - Arg::Numeric(NumericArg::i64) | Arg::Numeric(NumericArg::isize) => { - V8FastCallType::I64 - } - // Ref strings that are one byte internally may be passed as a SeqOneByteString, - // which gives us a FastApiOneByteString. - Arg::Special(Special::RefStr) => V8FastCallType::SeqOneByteString, - // Owned strings can be fast, but we'll have to copy them. - Arg::Special(Special::String) => V8FastCallType::SeqOneByteString, - // Cow strings can be fast, but may require copying - Arg::Special(Special::CowStr) => V8FastCallType::SeqOneByteString, - _ => return Err(V8MappingError::NoMapping("a fast argument", arg.clone())), - }; - Ok(Some(rv)) -} - -fn map_retval_to_v8_fastcall_type( - arg: &Arg, -) -> Result<Option<V8FastCallType>, V8MappingError> { - let rv = match arg { - Arg::OptionNumeric(_) | Arg::SerdeV8(_) => return Ok(None), - Arg::Void => V8FastCallType::Void, - Arg::Numeric(NumericArg::bool) => V8FastCallType::Bool, - Arg::Numeric(NumericArg::u32) - | Arg::Numeric(NumericArg::u16) - | Arg::Numeric(NumericArg::u8) => V8FastCallType::U32, - Arg::Numeric(NumericArg::i32) - | Arg::Numeric(NumericArg::i16) - | Arg::Numeric(NumericArg::i8) => V8FastCallType::I32, - Arg::Numeric(NumericArg::u64) | Arg::Numeric(NumericArg::usize) => { - V8FastCallType::U64 - } - Arg::Numeric(NumericArg::i64) | Arg::Numeric(NumericArg::isize) => { - V8FastCallType::I64 - } - // We don't return special return types - Arg::Option(_) => return Ok(None), - Arg::Special(_) => return Ok(None), - _ => { - return Err(V8MappingError::NoMapping( - "a fast return value", - arg.clone(), - )) - } - }; - Ok(Some(rv)) -} diff --git a/ops/op2/dispatch_slow.rs b/ops/op2/dispatch_slow.rs deleted file mode 100644 index 2ec67cc76..000000000 --- a/ops/op2/dispatch_slow.rs +++ /dev/null @@ -1,401 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. -use super::generator_state::GeneratorState; -use super::signature::Arg; -use super::signature::NumericArg; -use super::signature::ParsedSignature; -use super::signature::RetVal; -use super::signature::Special; -use super::MacroConfig; -use super::V8MappingError; -use proc_macro2::TokenStream; -use quote::format_ident; -use quote::quote; - -pub(crate) fn generate_dispatch_slow( - config: &MacroConfig, - generator_state: &mut GeneratorState, - signature: &ParsedSignature, -) -> Result<TokenStream, V8MappingError> { - let mut output = TokenStream::new(); - - // Fast ops require the slow op to check op_ctx for the last error - if config.fast && matches!(signature.ret_val, RetVal::Result(_)) { - generator_state.needs_opctx = true; - let throw_exception = throw_exception(generator_state)?; - // If the fast op returned an error, we must throw it rather than doing work. - output.extend(quote!{ - // FASTCALL FALLBACK: This is where we pick up the errors for the slow-call error pickup - // path. There is no code running between this and the other FASTCALL FALLBACK comment, - // except some V8 code required to perform the fallback process. This is why the below call is safe. - - // SAFETY: We guarantee that OpCtx has no mutable references once ops are live and being called, - // allowing us to perform this one little bit of mutable magic. - if let Some(err) = unsafe { opctx.unsafely_take_last_error_for_ops_only() } { - #throw_exception - } - }); - } - - for (index, arg) in signature.args.iter().enumerate() { - output.extend(extract_arg(generator_state, index)?); - output.extend(from_arg(generator_state, index, arg)?); - } - output.extend(call(generator_state)?); - output.extend(return_value(generator_state, &signature.ret_val)?); - - let with_scope = if generator_state.needs_scope { - with_scope(generator_state) - } else { - quote!() - }; - - let with_opctx = if generator_state.needs_opctx { - with_opctx(generator_state) - } else { - quote!() - }; - - let with_retval = if generator_state.needs_retval { - with_retval(generator_state) - } else { - quote!() - }; - - let with_args = if generator_state.needs_args { - with_fn_args(generator_state) - } else { - quote!() - }; - - let GeneratorState { - deno_core, - info, - slow_function, - .. - } = &generator_state; - - Ok(quote! { - extern "C" fn #slow_function(#info: *const #deno_core::v8::FunctionCallbackInfo) { - #with_scope - #with_retval - #with_args - #with_opctx - - #output - }}) -} - -fn with_scope(generator_state: &mut GeneratorState) -> TokenStream { - let GeneratorState { - deno_core, - scope, - info, - .. - } = &generator_state; - - quote!(let #scope = &mut unsafe { #deno_core::v8::CallbackScope::new(&*#info) };) -} - -fn with_retval(generator_state: &mut GeneratorState) -> TokenStream { - let GeneratorState { - deno_core, - retval, - info, - .. - } = &generator_state; - - quote!(let mut #retval = #deno_core::v8::ReturnValue::from_function_callback_info(unsafe { &*#info });) -} - -fn with_fn_args(generator_state: &mut GeneratorState) -> TokenStream { - let GeneratorState { - deno_core, - fn_args, - info, - .. - } = &generator_state; - - quote!(let #fn_args = #deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe { &*#info });) -} - -fn with_opctx(generator_state: &mut GeneratorState) -> TokenStream { - let GeneratorState { - deno_core, - opctx, - fn_args, - needs_args, - .. - } = generator_state; - - *needs_args = true; - quote!(let #opctx = unsafe { - &*(#deno_core::v8::Local::<#deno_core::v8::External>::cast(#fn_args.data()).value() - as *const #deno_core::_ops::OpCtx) - };) -} - -pub fn extract_arg( - generator_state: &mut GeneratorState, - index: usize, -) -> Result<TokenStream, V8MappingError> { - let GeneratorState { fn_args, .. } = &generator_state; - let arg_ident = generator_state.args.get(index); - - Ok(quote!( - let #arg_ident = #fn_args.get(#index as i32); - )) -} - -pub fn from_arg( - mut generator_state: &mut GeneratorState, - index: usize, - arg: &Arg, -) -> Result<TokenStream, V8MappingError> { - let GeneratorState { - deno_core, - args, - scope, - needs_scope, - .. - } = &mut generator_state; - let arg_ident = args.get_mut(index).expect("Argument at index was missing"); - let arg_temp = format_ident!("{}_temp", arg_ident); - let res = match arg { - Arg::Numeric(NumericArg::bool) => quote! { - let #arg_ident = #arg_ident.is_true(); - }, - Arg::Numeric(NumericArg::u8) - | Arg::Numeric(NumericArg::u16) - | Arg::Numeric(NumericArg::u32) => { - quote! { - let #arg_ident = #deno_core::_ops::to_u32(&#arg_ident) as _; - } - } - Arg::Numeric(NumericArg::i8) - | Arg::Numeric(NumericArg::i16) - | Arg::Numeric(NumericArg::i32) - | Arg::Numeric(NumericArg::__SMI__) => { - quote! { - let #arg_ident = #deno_core::_ops::to_i32(&#arg_ident) as _; - } - } - Arg::Numeric(NumericArg::u64) | Arg::Numeric(NumericArg::usize) => { - quote! { - let #arg_ident = #deno_core::_ops::to_u64(&#arg_ident) as _; - } - } - Arg::Numeric(NumericArg::i64) | Arg::Numeric(NumericArg::isize) => { - quote! { - let #arg_ident = #deno_core::_ops::to_i64(&#arg_ident) as _; - } - } - Arg::OptionNumeric(numeric) => { - // Ends the borrow of generator_state - let arg_ident = arg_ident.clone(); - let some = from_arg(generator_state, index, &Arg::Numeric(*numeric))?; - quote! { - let #arg_ident = if #arg_ident.is_null_or_undefined() { - None - } else { - #some - Some(#arg_ident) - }; - } - } - Arg::Option(Special::String) => { - *needs_scope = true; - quote! { - let #arg_ident = #arg_ident.to_rust_string_lossy(#scope); - } - } - Arg::Special(Special::String) => { - *needs_scope = true; - quote! { - let #arg_ident = #arg_ident.to_rust_string_lossy(#scope); - } - } - Arg::Special(Special::RefStr) => { - *needs_scope = true; - quote! { - // Trade 1024 bytes of stack space for potentially non-allocating strings - let mut #arg_temp: [::std::mem::MaybeUninit<u8>; 1024] = [::std::mem::MaybeUninit::uninit(); 1024]; - let #arg_ident = &#deno_core::_ops::to_str(#scope, &#arg_ident, &mut #arg_temp); - } - } - Arg::Special(Special::CowStr) => { - *needs_scope = true; - quote! { - // Trade 1024 bytes of stack space for potentially non-allocating strings - let mut #arg_temp: [::std::mem::MaybeUninit<u8>; 1024] = [::std::mem::MaybeUninit::uninit(); 1024]; - let #arg_ident = #deno_core::_ops::to_str(#scope, &#arg_ident, &mut #arg_temp); - } - } - _ => return Err(V8MappingError::NoMapping("a slow argument", arg.clone())), - }; - Ok(res) -} - -pub fn call( - generator_state: &mut GeneratorState, -) -> Result<TokenStream, V8MappingError> { - let GeneratorState { result, .. } = &generator_state; - - let mut tokens = TokenStream::new(); - for arg in &generator_state.args { - tokens.extend(quote!( #arg , )); - } - Ok(quote! { - let #result = Self::call( #tokens ); - }) -} - -pub fn return_value( - generator_state: &mut GeneratorState, - ret_type: &RetVal, -) -> Result<TokenStream, V8MappingError> { - match ret_type { - RetVal::Infallible(ret_type) => { - return_value_infallible(generator_state, ret_type) - } - RetVal::Result(ret_type) => return_value_result(generator_state, ret_type), - } -} - -pub fn return_value_infallible( - generator_state: &mut GeneratorState, - ret_type: &Arg, -) -> Result<TokenStream, V8MappingError> { - let GeneratorState { - deno_core, - scope, - result, - retval, - needs_retval, - needs_scope, - .. - } = generator_state; - - let res = match ret_type { - Arg::Void => { - quote! {/* void */} - } - Arg::Numeric(NumericArg::u8) - | Arg::Numeric(NumericArg::u16) - | Arg::Numeric(NumericArg::u32) => { - *needs_retval = true; - quote!(#retval.set_uint32(#result as u32);) - } - Arg::Numeric(NumericArg::i8) - | Arg::Numeric(NumericArg::i16) - | Arg::Numeric(NumericArg::i32) => { - *needs_retval = true; - quote!(#retval.set_int32(#result as i32);) - } - Arg::Special(Special::String) => { - *needs_retval = true; - *needs_scope = true; - quote! { - if #result.is_empty() { - #retval.set_empty_string(); - } else { - // This should not fail in normal cases - // TODO(mmastrac): This has extra allocations that we need to get rid of, especially if the string - // is ASCII. We could make an "external Rust String" string in V8 from these and re-use the allocation. - let temp = #deno_core::v8::String::new(#scope, &#result).unwrap(); - #retval.set(temp.into()); - } - } - } - Arg::Option(Special::String) => { - *needs_retval = true; - *needs_scope = true; - // End the generator_state borrow - let (result, retval) = (result.clone(), retval.clone()); - let some = return_value_infallible( - generator_state, - &Arg::Special(Special::String), - )?; - quote! { - if let Some(#result) = #result { - #some - } else { - #retval.set_null(); - } - } - } - _ => { - return Err(V8MappingError::NoMapping( - "a slow return value", - ret_type.clone(), - )) - } - }; - - Ok(res) -} - -fn return_value_result( - generator_state: &mut GeneratorState, - ret_type: &Arg, -) -> Result<TokenStream, V8MappingError> { - let infallible = return_value_infallible(generator_state, ret_type)?; - let exception = throw_exception(generator_state)?; - - let GeneratorState { result, .. } = &generator_state; - - let tokens = quote!( - match #result { - Ok(#result) => { - #infallible - } - Err(err) => { - #exception - } - }; - ); - Ok(tokens) -} - -/// Generates code to throw an exception, adding required additional dependencies as needed. -fn throw_exception( - generator_state: &mut GeneratorState, -) -> Result<TokenStream, V8MappingError> { - let maybe_scope = if generator_state.needs_scope { - quote!() - } else { - with_scope(generator_state) - }; - - let maybe_opctx = if generator_state.needs_opctx { - quote!() - } else { - with_opctx(generator_state) - }; - - let maybe_args = if generator_state.needs_args { - quote!() - } else { - with_fn_args(generator_state) - }; - - let GeneratorState { - deno_core, - scope, - opctx, - .. - } = &generator_state; - - Ok(quote! { - #maybe_scope - #maybe_args - #maybe_opctx - let opstate = ::std::cell::RefCell::borrow(&*#opctx.state); - let exception = #deno_core::error::to_v8_error( - #scope, - opstate.get_error_class_fn, - &err, - ); - scope.throw_exception(exception); - return; - }) -} diff --git a/ops/op2/generator_state.rs b/ops/op2/generator_state.rs deleted file mode 100644 index e437ea47c..000000000 --- a/ops/op2/generator_state.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. -use proc_macro2::Ident; -use proc_macro2::TokenStream; - -pub struct GeneratorState { - /// The path to the `deno_core` crate (either `deno_core` or `crate`, the latter used if the op is `(core)`). - pub deno_core: TokenStream, - - /// Identifiers for each of the arguments of the original function - pub args: Vec<Ident>, - /// The new identifier for the original function's contents. - pub call: Ident, - /// The result of the `call` function - pub result: Ident, - - /// The `v8::CallbackScope` used if necessary for the function. - pub scope: Ident, - /// The `v8::FunctionCallbackInfo` used to pass args into the slow function. - pub info: Ident, - /// The `v8::FunctionCallbackArguments` used to pass args into the slow function. - pub fn_args: Ident, - /// The `OpCtx` used for various information required for some ops. - pub opctx: Ident, - /// The `FastApiCallbackOptions` used in fast calls for fallback returns. - pub fast_api_callback_options: Ident, - /// The `v8::ReturnValue` used in the slow function - pub retval: Ident, - /// The "slow" function (ie: the one that isn't a fastcall) - pub slow_function: Ident, - /// The "fast" function (ie: a fastcall) - pub fast_function: Ident, - - pub needs_args: bool, - pub needs_retval: bool, - pub needs_scope: bool, - pub needs_opstate: bool, - pub needs_opctx: bool, - pub needs_fast_opctx: bool, - pub needs_fast_api_callback_options: bool, -} diff --git a/ops/op2/mod.rs b/ops/op2/mod.rs deleted file mode 100644 index 7f652fe1b..000000000 --- a/ops/op2/mod.rs +++ /dev/null @@ -1,326 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. -use deno_proc_macro_rules::rules; -use proc_macro2::Ident; -use proc_macro2::Span; -use proc_macro2::TokenStream; -use quote::format_ident; -use quote::quote; -use quote::ToTokens; -use std::iter::zip; -use syn2::parse2; -use syn2::parse_str; -use syn2::FnArg; -use syn2::ItemFn; -use syn2::Path; -use thiserror::Error; - -use self::dispatch_fast::generate_dispatch_fast; -use self::dispatch_slow::generate_dispatch_slow; -use self::generator_state::GeneratorState; -use self::signature::parse_signature; -use self::signature::Arg; -use self::signature::SignatureError; - -pub mod dispatch_fast; -pub mod dispatch_slow; -pub mod generator_state; -pub mod signature; - -#[derive(Debug, Error)] -pub enum Op2Error { - #[error("Failed to match a pattern for '{0}': (input was '{1}')")] - PatternMatchFailed(&'static str, String), - #[error("Invalid attribute: '{0}'")] - InvalidAttribute(String), - #[error("Failed to parse syntax tree")] - ParseError(#[from] syn2::Error), - #[error("Failed to map a parsed signature to a V8 call")] - V8MappingError(#[from] V8MappingError), - #[error("Failed to parse signature")] - SignatureError(#[from] SignatureError), - #[error("This op is fast-compatible and should be marked as (fast)")] - ShouldBeFast, - #[error("This op is not fast-compatible and should not be marked as (fast)")] - ShouldNotBeFast, -} - -#[derive(Debug, Error)] -pub enum V8MappingError { - #[error("Unable to map {1:?} to {0}")] - NoMapping(&'static str, Arg), -} - -#[derive(Default)] -pub(crate) struct MacroConfig { - pub core: bool, - pub fast: bool, -} - -impl MacroConfig { - pub fn from_flags(flags: Vec<Ident>) -> Result<Self, Op2Error> { - let mut config: MacroConfig = Self::default(); - for flag in flags { - if flag == "core" { - config.core = true; - } else if flag == "fast" { - config.fast = true; - } else { - return Err(Op2Error::InvalidAttribute(flag.to_string())); - } - } - Ok(config) - } - - pub fn from_tokens(tokens: TokenStream) -> Result<Self, Op2Error> { - let attr_string = tokens.to_string(); - let config = std::panic::catch_unwind(|| { - rules!(tokens => { - () => { - Ok(MacroConfig::default()) - } - ($($flags:ident),+) => { - Self::from_flags(flags) - } - }) - }) - .map_err(|_| Op2Error::PatternMatchFailed("attribute", attr_string))??; - Ok(config) - } -} - -pub fn op2( - attr: TokenStream, - item: TokenStream, -) -> Result<TokenStream, Op2Error> { - let func = parse2::<ItemFn>(item)?; - let config = MacroConfig::from_tokens(attr)?; - generate_op2(config, func) -} - -fn generate_op2( - config: MacroConfig, - func: ItemFn, -) -> Result<TokenStream, Op2Error> { - // Create a copy of the original function, named "call" - let call = Ident::new("call", Span::call_site()); - let mut op_fn = func.clone(); - op_fn.attrs.clear(); - op_fn.sig.generics.params.clear(); - op_fn.sig.ident = call.clone(); - - // Clear inert attributes - // TODO(mmastrac): This should limit itself to clearing ours only - for arg in op_fn.sig.inputs.iter_mut() { - match arg { - FnArg::Receiver(slf) => slf.attrs.clear(), - FnArg::Typed(ty) => ty.attrs.clear(), - } - } - - let signature = parse_signature(func.attrs, func.sig.clone())?; - let processed_args = - zip(signature.args.iter(), &func.sig.inputs).collect::<Vec<_>>(); - - let mut args = vec![]; - let mut needs_args = false; - for (index, _) in processed_args.iter().enumerate() { - let input = format_ident!("arg{index}"); - args.push(input); - needs_args = true; - } - - let retval = Ident::new("rv", Span::call_site()); - let result = Ident::new("result", Span::call_site()); - let fn_args = Ident::new("args", Span::call_site()); - let scope = Ident::new("scope", Span::call_site()); - let info = Ident::new("info", Span::call_site()); - let opctx = Ident::new("opctx", Span::call_site()); - let slow_function = Ident::new("v8_fn_ptr", Span::call_site()); - let fast_function = Ident::new("v8_fn_ptr_fast", Span::call_site()); - let fast_api_callback_options = - Ident::new("fast_api_callback_options", Span::call_site()); - - let deno_core = if config.core { - syn2::parse_str::<Path>("crate") - } else { - syn2::parse_str::<Path>("deno_core") - } - .expect("Parsing crate should not fail") - .into_token_stream(); - - let mut generator_state = GeneratorState { - args, - fn_args, - call, - scope, - info, - opctx, - fast_api_callback_options, - deno_core, - result, - retval, - needs_args, - slow_function, - fast_function, - needs_retval: false, - needs_scope: false, - needs_opctx: false, - needs_opstate: false, - needs_fast_opctx: false, - needs_fast_api_callback_options: false, - }; - - let name = func.sig.ident; - - let slow_fn = - generate_dispatch_slow(&config, &mut generator_state, &signature)?; - let (fast_definition, fast_fn) = - match generate_dispatch_fast(&mut generator_state, &signature)? { - Some((fast_definition, fast_fn)) => { - if !config.fast { - return Err(Op2Error::ShouldBeFast); - } - (quote!(Some({#fast_definition})), fast_fn) - } - None => { - if config.fast { - return Err(Op2Error::ShouldNotBeFast); - } - (quote!(None), quote!()) - } - }; - - let GeneratorState { - deno_core, - slow_function, - .. - } = &generator_state; - - let arg_count: usize = generator_state.args.len(); - let vis = func.vis; - let generic = signature - .generic_bounds - .keys() - .map(|s| format_ident!("{s}")) - .collect::<Vec<_>>(); - let bound = signature - .generic_bounds - .values() - .map(|p| parse_str::<Path>(p).expect("Failed to reparse path")) - .collect::<Vec<_>>(); - - Ok(quote! { - #[allow(non_camel_case_types)] - #vis struct #name <#(#generic),*> { - // We need to mark these type parameters as used, so we use a PhantomData - _unconstructable: ::std::marker::PhantomData<(#(#generic),*)> - } - - impl <#(#generic : #bound),*> #deno_core::_ops::Op for #name <#(#generic),*> { - const NAME: &'static str = stringify!(#name); - const DECL: #deno_core::_ops::OpDecl = #deno_core::_ops::OpDecl { - name: stringify!(#name), - v8_fn_ptr: Self::#slow_function as _, - enabled: true, - fast_fn: #fast_definition, - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: #arg_count as u8, - }; - } - - impl <#(#generic : #bound),*> #name <#(#generic),*> { - pub const fn name() -> &'static str { - stringify!(#name) - } - - pub const fn decl() -> #deno_core::_ops::OpDecl { - #deno_core::_ops::OpDecl { - name: stringify!(#name), - v8_fn_ptr: Self::#slow_function as _, - enabled: true, - fast_fn: #fast_definition, - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: #arg_count as u8, - } - } - - #fast_fn - #slow_fn - - #[inline(always)] - #op_fn - } - }) -} - -#[cfg(test)] -mod tests { - use super::*; - use pretty_assertions::assert_eq; - use std::path::PathBuf; - use syn2::parse_str; - use syn2::File; - use syn2::Item; - - #[testing_macros::fixture("op2/test_cases/**/*.rs")] - fn test_signature_parser(input: PathBuf) { - let update_expected = std::env::var("UPDATE_EXPECTED").is_ok(); - - let source = - std::fs::read_to_string(&input).expect("Failed to read test file"); - let file = parse_str::<File>(&source).expect("Failed to parse Rust file"); - let mut expected_out = vec![]; - for item in file.items { - if let Item::Fn(mut func) = item { - let mut config = None; - func.attrs.retain(|attr| { - let tokens = attr.into_token_stream(); - let attr_string = attr.clone().into_token_stream().to_string(); - println!("{}", attr_string); - use syn2 as syn; - if let Some(new_config) = rules!(tokens => { - (#[op2]) => { - Some(MacroConfig::default()) - } - (#[op2( $($x:ident),* )]) => { - Some(MacroConfig::from_flags(x).expect("Failed to parse attribute")) - } - (#[$_attr:meta]) => { - None - } - }) { - config = Some(new_config); - false - } else { - true - } - }); - let tokens = - generate_op2(config.unwrap(), func).expect("Failed to generate op"); - println!("======== Raw tokens ========:\n{}", tokens.clone()); - let tree = syn::parse2(tokens).unwrap(); - let actual = prettyplease::unparse(&tree); - println!("======== Generated ========:\n{}", actual); - expected_out.push(actual); - } - } - - let expected_out = expected_out.join("\n"); - - if update_expected { - std::fs::write(input.with_extension("out"), expected_out) - .expect("Failed to write expectation file"); - } else { - let expected = std::fs::read_to_string(input.with_extension("out")) - .expect("Failed to read expectation file"); - assert_eq!( - expected, expected_out, - "Failed to match expectation. Use UPDATE_EXPECTED=1." - ); - } - } -} diff --git a/ops/op2/signature.rs b/ops/op2/signature.rs deleted file mode 100644 index 5d472fcf3..000000000 --- a/ops/op2/signature.rs +++ /dev/null @@ -1,741 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. -use deno_proc_macro_rules::rules; -use proc_macro2::Ident; -use proc_macro2::Span; -use quote::quote; -use quote::ToTokens; -use std::collections::BTreeMap; -use strum::IntoEnumIterator; -use strum::IntoStaticStr; -use strum_macros::EnumIter; -use strum_macros::EnumString; -use syn2::Attribute; -use syn2::FnArg; -use syn2::GenericParam; -use syn2::Generics; -use syn2::Pat; -use syn2::ReturnType; -use syn2::Signature; -use syn2::Type; -use syn2::TypePath; -use thiserror::Error; - -#[allow(non_camel_case_types)] -#[derive( - Copy, Clone, Debug, Eq, PartialEq, IntoStaticStr, EnumString, EnumIter, -)] -pub enum NumericArg { - /// A placeholder argument for arguments annotated with #[smi]. - __SMI__, - /// A placeholder argument for void data. - __VOID__, - bool, - i8, - u8, - i16, - u16, - i32, - u32, - i64, - u64, - f32, - f64, - isize, - usize, -} - -impl ToTokens for NumericArg { - fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { - let ident = Ident::new(self.into(), Span::call_site()); - tokens.extend(quote! { #ident }) - } -} - -#[derive( - Copy, Clone, Debug, Eq, PartialEq, IntoStaticStr, EnumString, EnumIter, -)] -pub enum V8Arg { - External, - Object, - Array, - ArrayBuffer, - ArrayBufferView, - DataView, - TypedArray, - BigInt64Array, - BigUint64Array, - Float32Array, - Float64Array, - Int16Array, - Int32Array, - Int8Array, - Uint16Array, - Uint32Array, - Uint8Array, - Uint8ClampedArray, - BigIntObject, - BooleanObject, - Date, - Function, - Map, - NumberObject, - Promise, - PromiseResolver, - Proxy, - RegExp, - Set, - SharedArrayBuffer, - StringObject, - SymbolObject, - WasmMemoryObject, - WasmModuleObject, - Primitive, - BigInt, - Boolean, - Name, - String, - Symbol, - Number, - Integer, - Int32, - Uint32, -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub enum Special { - HandleScope, - OpState, - String, - CowStr, - RefStr, - FastApiCallbackOptions, -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub enum RefType { - Ref, - Mut, -} - -#[derive(Clone, Debug, Eq, PartialEq)] -pub enum Arg { - Void, - Special(Special), - Ref(RefType, Special), - RcRefCell(Special), - Option(Special), - OptionNumeric(NumericArg), - Slice(RefType, NumericArg), - Ptr(RefType, NumericArg), - V8Local(V8Arg), - Numeric(NumericArg), - SerdeV8(String), -} - -#[derive(Clone, Debug, Eq, PartialEq)] -pub enum RetVal { - Infallible(Arg), - Result(Arg), -} - -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct ParsedSignature { - // The parsed arguments - pub args: Vec<Arg>, - // The argument names - pub names: Vec<String>, - // The parsed return value - pub ret_val: RetVal, - // One and only one lifetime allowed - pub lifetime: Option<String>, - // Generic bounds: each generic must have one and only simple trait bound - pub generic_bounds: BTreeMap<String, String>, -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -enum AttributeModifier { - /// #[serde], for serde_v8 types. - Serde, - /// #[smi], for small integers - Smi, - /// #[string], for strings. - String, -} - -#[derive(Error, Debug)] -pub enum SignatureError { - #[error("Invalid argument: '{0}'")] - ArgError(String, #[source] ArgError), - #[error("Invalid return type")] - RetError(#[from] ArgError), - #[error("Only one lifetime is permitted")] - TooManyLifetimes, - #[error("Generic '{0}' must have one and only bound (either <T> and 'where T: Trait', or <T: Trait>)")] - GenericBoundCardinality(String), - #[error("Where clause predicate '{0}' (eg: where T: Trait) must appear in generics list (eg: <T>)")] - WherePredicateMustAppearInGenerics(String), - #[error("All generics must appear only once in the generics parameter list or where clause")] - DuplicateGeneric(String), - #[error("Generic lifetime '{0}' may not have bounds (eg: <'a: 'b>)")] - LifetimesMayNotHaveBounds(String), - #[error("Invalid generic: '{0}' Only simple generics bounds are allowed (eg: T: Trait)")] - InvalidGeneric(String), - #[error("Invalid predicate: '{0}' Only simple where predicates are allowed (eg: T: Trait)")] - InvalidWherePredicate(String), -} - -#[derive(Error, Debug)] -pub enum ArgError { - #[error("Invalid self argument")] - InvalidSelf, - #[error("Invalid argument type: {0}")] - InvalidType(String), - #[error( - "Invalid argument type path (should this be #[smi] or #[serde]?): {0}" - )] - InvalidTypePath(String), - #[error("Too many attributes")] - TooManyAttributes, - #[error("Invalid #[serde] type: {0}")] - InvalidSerdeType(String), - #[error("Cannot use #[serde] for type: {0}")] - InvalidSerdeAttributeType(String), - #[error("Invalid v8 type: {0}")] - InvalidV8Type(String), - #[error("Internal error: {0}")] - InternalError(String), - #[error("Missing a #[string] attribute")] - MissingStringAttribute, -} - -#[derive(Copy, Clone, Default)] -struct Attributes { - primary: Option<AttributeModifier>, -} - -fn stringify_token(tokens: impl ToTokens) -> String { - tokens - .into_token_stream() - .into_iter() - .map(|s| s.to_string()) - .collect::<Vec<_>>() - .join("") -} - -pub fn parse_signature( - attributes: Vec<Attribute>, - signature: Signature, -) -> Result<ParsedSignature, SignatureError> { - let mut args = vec![]; - let mut names = vec![]; - for input in signature.inputs { - let name = match &input { - FnArg::Receiver(_) => "self".to_owned(), - FnArg::Typed(ty) => match &*ty.pat { - Pat::Ident(ident) => ident.ident.to_string(), - _ => "(complex)".to_owned(), - }, - }; - names.push(name.clone()); - args.push( - parse_arg(input).map_err(|err| SignatureError::ArgError(name, err))?, - ); - } - let ret_val = - parse_return(parse_attributes(&attributes)?, &signature.output)?; - let lifetime = parse_lifetime(&signature.generics)?; - let generic_bounds = parse_generics(&signature.generics)?; - Ok(ParsedSignature { - args, - names, - ret_val, - lifetime, - generic_bounds, - }) -} - -/// Extract one lifetime from the [`syn2::Generics`], ensuring that the lifetime is valid -/// and has no bounds. -fn parse_lifetime( - generics: &Generics, -) -> Result<Option<String>, SignatureError> { - let mut res = None; - for param in &generics.params { - if let GenericParam::Lifetime(lt) = param { - if !lt.bounds.is_empty() { - return Err(SignatureError::LifetimesMayNotHaveBounds( - lt.lifetime.to_string(), - )); - } - if res.is_some() { - return Err(SignatureError::TooManyLifetimes); - } - res = Some(lt.lifetime.ident.to_string()); - } - } - Ok(res) -} - -/// Parse and validate generics. We require one and only one trait bound for each generic -/// parameter. Tries to sanity check and return reasonable errors for possible signature errors. -fn parse_generics( - generics: &Generics, -) -> Result<BTreeMap<String, String>, SignatureError> { - let mut where_clauses = BTreeMap::new(); - - // First, extract the where clause so we can detect duplicated predicates - if let Some(where_clause) = &generics.where_clause { - for predicate in &where_clause.predicates { - let predicate = predicate.to_token_stream(); - let (generic_name, bound) = std::panic::catch_unwind(|| { - use syn2 as syn; - rules!(predicate => { - ($t:ident : $bound:path) => (t.to_string(), stringify_token(bound)), - }) - }) - .map_err(|_| { - SignatureError::InvalidWherePredicate(predicate.to_string()) - })?; - if where_clauses.insert(generic_name.clone(), bound).is_some() { - return Err(SignatureError::DuplicateGeneric(generic_name)); - } - } - } - - let mut res = BTreeMap::new(); - for param in &generics.params { - if let GenericParam::Type(ty) = param { - let ty = ty.to_token_stream(); - let (name, bound) = std::panic::catch_unwind(|| { - use syn2 as syn; - rules!(ty => { - ($t:ident : $bound:path) => (t.to_string(), Some(stringify_token(bound))), - ($t:ident) => (t.to_string(), None), - }) - }).map_err(|_| SignatureError::InvalidGeneric(ty.to_string()))?; - let bound = match bound { - Some(bound) => { - if where_clauses.contains_key(&name) { - return Err(SignatureError::GenericBoundCardinality(name)); - } - bound - } - None => { - let Some(bound) = where_clauses.remove(&name) else { - return Err(SignatureError::GenericBoundCardinality(name)); - }; - bound - } - }; - if res.contains_key(&name) { - return Err(SignatureError::DuplicateGeneric(name)); - } - res.insert(name, bound); - } - } - if !where_clauses.is_empty() { - return Err(SignatureError::WherePredicateMustAppearInGenerics( - where_clauses.into_keys().next().unwrap(), - )); - } - - Ok(res) -} - -fn parse_attributes(attributes: &[Attribute]) -> Result<Attributes, ArgError> { - let attrs = attributes - .iter() - .filter_map(parse_attribute) - .collect::<Vec<_>>(); - - if attrs.is_empty() { - return Ok(Attributes::default()); - } - if attrs.len() > 1 { - return Err(ArgError::TooManyAttributes); - } - Ok(Attributes { - primary: Some(*attrs.get(0).unwrap()), - }) -} - -fn parse_attribute(attr: &Attribute) -> Option<AttributeModifier> { - let tokens = attr.into_token_stream(); - use syn2 as syn; - std::panic::catch_unwind(|| { - rules!(tokens => { - (#[serde]) => Some(AttributeModifier::Serde), - (#[smi]) => Some(AttributeModifier::Smi), - (#[string]) => Some(AttributeModifier::String), - (#[$_attr:meta]) => None, - }) - }) - .expect("Failed to parse an attribute") -} - -fn parse_return( - attrs: Attributes, - rt: &ReturnType, -) -> Result<RetVal, ArgError> { - match rt { - ReturnType::Default => Ok(RetVal::Infallible(Arg::Void)), - ReturnType::Type(_, ty) => { - let s = stringify_token(ty); - let tokens = ty.into_token_stream(); - use syn2 as syn; - - std::panic::catch_unwind(|| { - rules!(tokens => { - // x::y::Result<Value>, like io::Result and other specialty result types - ($($_package:ident ::)* Result < $ty:ty >) => { - Ok(RetVal::Result(parse_type(attrs, &ty)?)) - } - // x::y::Result<Value, Error> - ($($_package:ident ::)* Result < $ty:ty, $_error:ty >) => { - Ok(RetVal::Result(parse_type(attrs, &ty)?)) - } - ($ty:ty) => { - Ok(RetVal::Infallible(parse_type(attrs, &ty)?)) - } - }) - }) - .map_err(|e| { - ArgError::InternalError(format!( - "parse_return({}) {}", - s, - e.downcast::<&str>().unwrap_or_default() - )) - })? - } - } -} - -fn parse_type_path(attrs: Attributes, tp: &TypePath) -> Result<Arg, ArgError> { - if tp.path.segments.len() == 1 { - let segment = tp.path.segments.first().unwrap().ident.to_string(); - for numeric in NumericArg::iter() { - if Into::<&'static str>::into(numeric) == segment.as_str() { - return Ok(Arg::Numeric(numeric)); - } - } - } - - use syn2 as syn; - - let tokens = tp.clone().into_token_stream(); - std::panic::catch_unwind(|| { - rules!(tokens => { - ( $( std :: str :: )? String ) => { - if attrs.primary == Some(AttributeModifier::String) { - Ok(Arg::Special(Special::String)) - } else { - Err(ArgError::MissingStringAttribute) - } - } - ( $( std :: str :: )? str ) => { - // We should not hit this path with a #[string] argument - Err(ArgError::MissingStringAttribute) - } - ( $( std :: borrow :: )? Cow < str > ) => { - if attrs.primary == Some(AttributeModifier::String) { - Ok(Arg::Special(Special::CowStr)) - } else { - Err(ArgError::MissingStringAttribute) - } - } - ( $( std :: ffi :: )? c_void ) => Ok(Arg::Numeric(NumericArg::__VOID__)), - ( OpState ) => Ok(Arg::Special(Special::OpState)), - ( v8 :: HandleScope ) => Ok(Arg::Special(Special::HandleScope)), - ( v8 :: FastApiCallbackOptions ) => Ok(Arg::Special(Special::FastApiCallbackOptions)), - ( v8 :: Local < $( $_scope:lifetime , )? v8 :: $v8:ident >) => Ok(Arg::V8Local(parse_v8_type(&v8)?)), - ( Rc < RefCell < $ty:ty > > ) => Ok(Arg::RcRefCell(parse_type_special(attrs, &ty)?)), - ( Option < $ty:ty > ) => { - match parse_type(attrs, &ty)? { - Arg::Special(special) => Ok(Arg::Option(special)), - Arg::Numeric(numeric) => Ok(Arg::OptionNumeric(numeric)), - _ => Err(ArgError::InvalidType(stringify_token(ty))) - } - } - ( $any:ty ) => Err(ArgError::InvalidTypePath(stringify_token(any))), - }) - }).map_err(|e| ArgError::InternalError(format!("parse_type_path {e:?}")))? -} - -fn parse_v8_type(v8: &Ident) -> Result<V8Arg, ArgError> { - let v8 = v8.to_string(); - V8Arg::try_from(v8.as_str()).map_err(|_| ArgError::InvalidV8Type(v8)) -} - -fn parse_type_special( - attrs: Attributes, - ty: &Type, -) -> Result<Special, ArgError> { - match parse_type(attrs, ty)? { - Arg::Special(special) => Ok(special), - _ => Err(ArgError::InvalidType(stringify_token(ty))), - } -} - -fn parse_type(attrs: Attributes, ty: &Type) -> Result<Arg, ArgError> { - if let Some(primary) = attrs.primary { - match primary { - AttributeModifier::Serde => match ty { - Type::Path(of) => { - // If this type will parse without #[serde], it is illegal to use this type with #[serde] - if parse_type_path(Attributes::default(), of).is_ok() { - return Err(ArgError::InvalidSerdeAttributeType(stringify_token( - ty, - ))); - } - return Ok(Arg::SerdeV8(stringify_token(of.path.clone()))); - } - _ => return Err(ArgError::InvalidSerdeType(stringify_token(ty))), - }, - AttributeModifier::String => match ty { - Type::Path(of) => { - return parse_type_path(attrs, of); - } - Type::Reference(of) => { - let mut_type = if of.mutability.is_some() { - RefType::Mut - } else { - RefType::Ref - }; - let tokens = of.elem.clone().into_token_stream(); - use syn2 as syn; - return rules!(tokens => { - (str) => Ok(Arg::Special(Special::RefStr)), - ($_ty:ty) => Ok(Arg::Ref(mut_type, parse_type_special(attrs, &of.elem)?)), - }); - } - _ => return Err(ArgError::InvalidSerdeType(stringify_token(ty))), - }, - AttributeModifier::Smi => { - return Ok(Arg::Numeric(NumericArg::__SMI__)); - } - } - }; - match ty { - Type::Tuple(of) => { - if of.elems.is_empty() { - Ok(Arg::Void) - } else { - Err(ArgError::InvalidType(stringify_token(ty))) - } - } - Type::Reference(of) => { - let mut_type = if of.mutability.is_some() { - RefType::Mut - } else { - RefType::Ref - }; - match &*of.elem { - Type::Slice(of) => match parse_type(attrs, &of.elem)? { - Arg::Numeric(numeric) => Ok(Arg::Slice(mut_type, numeric)), - _ => Err(ArgError::InvalidType(stringify_token(ty))), - }, - Type::Path(of) => match parse_type_path(attrs, of)? { - Arg::Special(special) => Ok(Arg::Ref(mut_type, special)), - _ => Err(ArgError::InvalidType(stringify_token(ty))), - }, - _ => Err(ArgError::InvalidType(stringify_token(ty))), - } - } - Type::Ptr(of) => { - let mut_type = if of.mutability.is_some() { - RefType::Mut - } else { - RefType::Ref - }; - match &*of.elem { - Type::Path(of) => match parse_type_path(attrs, of)? { - Arg::Numeric(numeric) => Ok(Arg::Ptr(mut_type, numeric)), - _ => Err(ArgError::InvalidType(stringify_token(ty))), - }, - _ => Err(ArgError::InvalidType(stringify_token(ty))), - } - } - Type::Path(of) => parse_type_path(attrs, of), - _ => Err(ArgError::InvalidType(stringify_token(ty))), - } -} - -fn parse_arg(arg: FnArg) -> Result<Arg, ArgError> { - let FnArg::Typed(typed) = arg else { - return Err(ArgError::InvalidSelf); - }; - parse_type(parse_attributes(&typed.attrs)?, &typed.ty) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::op2::signature::parse_signature; - use syn2::parse_str; - use syn2::ItemFn; - - // We can't test pattern args :/ - // https://github.com/rust-lang/rfcs/issues/2688 - macro_rules! test { - ( - // Function attributes - $(# [ $fn_attr:ident ])? - // fn name < 'scope, GENERIC1, GENERIC2, ... > - fn $name:ident $( < $scope:lifetime $( , $generic:ident)* >)? - ( - // Argument attribute, argument - $( $(# [ $attr:ident ])? $ident:ident : $ty:ty ),* - ) - // Return value - $(-> $(# [ $ret_attr:ident ])? $ret:ty)? - // Where clause - $( where $($trait:ident : $bounds:path),* )? - ; - // Expected return value - $( < $( $lifetime_res:lifetime )? $(, $generic_res:ident : $bounds_res:path )* >)? ( $( $arg_res:expr ),* ) -> $ret_res:expr ) => { - #[test] - fn $name() { - test( - stringify!($( #[$fn_attr] )? fn op $( < $scope $( , $generic)* >)? ( $( $( #[$attr] )? $ident : $ty ),* ) $(-> $( #[$ret_attr] )? $ret)? $( where $($trait : $bounds),* )? {}), - stringify!($( < $( $lifetime_res )? $(, $generic_res : $bounds_res)* > )?), - stringify!($($arg_res),*), - stringify!($ret_res) - ); - } - }; - } - - fn test( - op: &str, - generics_expected: &str, - args_expected: &str, - return_expected: &str, - ) { - // Parse the provided macro input as an ItemFn - let item_fn = parse_str::<ItemFn>(op) - .unwrap_or_else(|_| panic!("Failed to parse {op} as a ItemFn")); - - let attrs = item_fn.attrs; - let sig = parse_signature(attrs, item_fn.sig).unwrap_or_else(|err| { - panic!("Failed to successfully parse signature from {op} ({err:?})") - }); - println!("Raw parsed signatures = {sig:?}"); - - let mut generics_res = vec![]; - if let Some(lifetime) = sig.lifetime { - generics_res.push(format!("'{lifetime}")); - } - for (name, bounds) in sig.generic_bounds { - generics_res.push(format!("{name} : {bounds}")); - } - if !generics_res.is_empty() { - assert_eq!( - generics_expected, - format!("< {} >", generics_res.join(", ")) - ); - } - assert_eq!( - args_expected, - format!("{:?}", sig.args).trim_matches(|c| c == '[' || c == ']') - ); - assert_eq!(return_expected, format!("{:?}", sig.ret_val)); - } - - macro_rules! expect_fail { - ($name:ident, $error:expr, $f:item) => { - #[test] - pub fn $name() { - expect_fail(stringify!($f), stringify!($error)); - } - }; - } - - fn expect_fail(op: &str, error: &str) { - // Parse the provided macro input as an ItemFn - let item_fn = parse_str::<ItemFn>(op) - .unwrap_or_else(|_| panic!("Failed to parse {op} as a ItemFn")); - let attrs = item_fn.attrs; - let err = parse_signature(attrs, item_fn.sig) - .expect_err("Expected function to fail to parse"); - assert_eq!(format!("{err:?}"), error.to_owned()); - } - - test!( - fn op_state_and_number(opstate: &mut OpState, a: u32) -> (); - (Ref(Mut, OpState), Numeric(u32)) -> Infallible(Void) - ); - test!( - fn op_slices(r#in: &[u8], out: &mut [u8]); - (Slice(Ref, u8), Slice(Mut, u8)) -> Infallible(Void) - ); - test!( - #[serde] fn op_serde(#[serde] input: package::SerdeInputType) -> Result<package::SerdeReturnType, Error>; - (SerdeV8("package::SerdeInputType")) -> Result(SerdeV8("package::SerdeReturnType")) - ); - test!( - fn op_local(input: v8::Local<v8::String>) -> Result<v8::Local<v8::String>, Error>; - (V8Local(String)) -> Result(V8Local(String)) - ); - test!( - fn op_resource(#[smi] rid: ResourceId, buffer: &[u8]); - (Numeric(__SMI__), Slice(Ref, u8)) -> Infallible(Void) - ); - test!( - fn op_option_numeric_result(state: &mut OpState) -> Result<Option<u32>, AnyError>; - (Ref(Mut, OpState)) -> Result(OptionNumeric(u32)) - ); - test!( - fn op_ffi_read_f64(state: &mut OpState, ptr: * mut c_void, offset: isize) -> Result <f64, AnyError>; - (Ref(Mut, OpState), Ptr(Mut, __VOID__), Numeric(isize)) -> Result(Numeric(f64)) - ); - test!( - fn op_print(#[string] msg: &str, is_err: bool) -> Result<(), Error>; - (Special(RefStr), Numeric(bool)) -> Result(Void) - ); - test!( - fn op_scope<'s>(#[string] msg: &'s str); - <'s> (Special(RefStr)) -> Infallible(Void) - ); - test!( - fn op_scope_and_generics<'s, AB, BC>(#[string] msg: &'s str) where AB: some::Trait, BC: OtherTrait; - <'s, AB: some::Trait, BC: OtherTrait> (Special(RefStr)) -> Infallible(Void) - ); - - expect_fail!(op_with_two_lifetimes, TooManyLifetimes, fn f<'a, 'b>() {}); - expect_fail!( - op_with_lifetime_bounds, - LifetimesMayNotHaveBounds("'a"), - fn f<'a: 'b, 'b>() {} - ); - expect_fail!( - op_with_missing_bounds, - GenericBoundCardinality("B"), - fn f<'a, B>() {} - ); - expect_fail!( - op_with_duplicate_bounds, - GenericBoundCardinality("B"), - fn f<'a, B: Trait>() - where - B: Trait, - { - } - ); - expect_fail!( - op_with_extra_bounds, - WherePredicateMustAppearInGenerics("C"), - fn f<'a, B>() - where - B: Trait, - C: Trait, - { - } - ); - - #[test] - fn test_parse_result() { - let rt = parse_str::<ReturnType>("-> Result < (), Error >") - .expect("Failed to parse"); - println!("{:?}", parse_return(Attributes::default(), &rt)); - } -} diff --git a/ops/op2/test_cases/sync/add.out b/ops/op2/test_cases/sync/add.out deleted file mode 100644 index a73f032aa..000000000 --- a/ops/op2/test_cases/sync/add.out +++ /dev/null @@ -1,78 +0,0 @@ -#[allow(non_camel_case_types)] -struct op_add { - _unconstructable: ::std::marker::PhantomData<()>, -} -impl deno_core::_ops::Op for op_add { - const NAME: &'static str = stringify!(op_add); - const DECL: deno_core::_ops::OpDecl = deno_core::_ops::OpDecl { - name: stringify!(op_add), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: Some({ - use deno_core::v8::fast_api::Type; - use deno_core::v8::fast_api::CType; - deno_core::v8::fast_api::FastFunction::new( - &[Type::V8Value, Type::Uint32, Type::Uint32], - CType::Uint32, - Self::v8_fn_ptr_fast as *const ::std::ffi::c_void, - ) - }), - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 2usize as u8, - }; -} -impl op_add { - pub const fn name() -> &'static str { - stringify!(op_add) - } - pub const fn decl() -> deno_core::_ops::OpDecl { - deno_core::_ops::OpDecl { - name: stringify!(op_add), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: Some({ - use deno_core::v8::fast_api::Type; - use deno_core::v8::fast_api::CType; - deno_core::v8::fast_api::FastFunction::new( - &[Type::V8Value, Type::Uint32, Type::Uint32], - CType::Uint32, - Self::v8_fn_ptr_fast as *const ::std::ffi::c_void, - ) - }), - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 2usize as u8, - } - } - fn v8_fn_ptr_fast( - _: deno_core::v8::Local<deno_core::v8::Object>, - arg0: u32, - arg1: u32, - ) -> u32 { - let arg0 = arg0 as _; - let arg1 = arg1 as _; - let result = Self::call(arg0, arg1); - result - } - extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) { - let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe { - &*info - }); - let args = deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe { - &*info - }); - let arg0 = args.get(0usize as i32); - let arg0 = deno_core::_ops::to_u32(&arg0) as _; - let arg1 = args.get(1usize as i32); - let arg1 = deno_core::_ops::to_u32(&arg1) as _; - let result = Self::call(arg0, arg1); - rv.set_uint32(result as u32); - } - #[inline(always)] - fn call(a: u32, b: u32) -> u32 { - a + b - } -} diff --git a/ops/op2/test_cases/sync/add.rs b/ops/op2/test_cases/sync/add.rs deleted file mode 100644 index 74dbb1893..000000000 --- a/ops/op2/test_cases/sync/add.rs +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. - -#[op2(fast)] -fn op_add(a: u32, b: u32) -> u32 { - a + b -} diff --git a/ops/op2/test_cases/sync/add_options.out b/ops/op2/test_cases/sync/add_options.out deleted file mode 100644 index 9fada187f..000000000 --- a/ops/op2/test_cases/sync/add_options.out +++ /dev/null @@ -1,57 +0,0 @@ -#[allow(non_camel_case_types)] -pub struct op_test_add_option { - _unconstructable: ::std::marker::PhantomData<()>, -} -impl crate::_ops::Op for op_test_add_option { - const NAME: &'static str = stringify!(op_test_add_option); - const DECL: crate::_ops::OpDecl = crate::_ops::OpDecl { - name: stringify!(op_test_add_option), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: None, - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 2usize as u8, - }; -} -impl op_test_add_option { - pub const fn name() -> &'static str { - stringify!(op_test_add_option) - } - pub const fn decl() -> crate::_ops::OpDecl { - crate::_ops::OpDecl { - name: stringify!(op_test_add_option), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: None, - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 2usize as u8, - } - } - extern "C" fn v8_fn_ptr(info: *const crate::v8::FunctionCallbackInfo) { - let mut rv = crate::v8::ReturnValue::from_function_callback_info(unsafe { - &*info - }); - let args = crate::v8::FunctionCallbackArguments::from_function_callback_info(unsafe { - &*info - }); - let arg0 = args.get(0usize as i32); - let arg0 = crate::_ops::to_u32(&arg0) as _; - let arg1 = args.get(1usize as i32); - let arg1 = if arg1.is_null_or_undefined() { - None - } else { - let arg1 = crate::_ops::to_u32(&arg1) as _; - Some(arg1) - }; - let result = Self::call(arg0, arg1); - rv.set_uint32(result as u32); - } - #[inline(always)] - pub fn call(a: u32, b: Option<u32>) -> u32 { - a + b.unwrap_or(100) - } -} diff --git a/ops/op2/test_cases/sync/add_options.rs b/ops/op2/test_cases/sync/add_options.rs deleted file mode 100644 index a5f2c8f4a..000000000 --- a/ops/op2/test_cases/sync/add_options.rs +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. - -#[op2(core)] -pub fn op_test_add_option(a: u32, b: Option<u32>) -> u32 { - a + b.unwrap_or(100) -} diff --git a/ops/op2/test_cases/sync/doc_comment.out b/ops/op2/test_cases/sync/doc_comment.out deleted file mode 100644 index d7e8005d9..000000000 --- a/ops/op2/test_cases/sync/doc_comment.out +++ /dev/null @@ -1,59 +0,0 @@ -#[allow(non_camel_case_types)] -pub struct op_has_doc_comment { - _unconstructable: ::std::marker::PhantomData<()>, -} -impl deno_core::_ops::Op for op_has_doc_comment { - const NAME: &'static str = stringify!(op_has_doc_comment); - const DECL: deno_core::_ops::OpDecl = deno_core::_ops::OpDecl { - name: stringify!(op_has_doc_comment), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: Some({ - use deno_core::v8::fast_api::Type; - use deno_core::v8::fast_api::CType; - deno_core::v8::fast_api::FastFunction::new( - &[Type::V8Value], - CType::Void, - Self::v8_fn_ptr_fast as *const ::std::ffi::c_void, - ) - }), - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 0usize as u8, - }; -} -impl op_has_doc_comment { - pub const fn name() -> &'static str { - stringify!(op_has_doc_comment) - } - pub const fn decl() -> deno_core::_ops::OpDecl { - deno_core::_ops::OpDecl { - name: stringify!(op_has_doc_comment), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: Some({ - use deno_core::v8::fast_api::Type; - use deno_core::v8::fast_api::CType; - deno_core::v8::fast_api::FastFunction::new( - &[Type::V8Value], - CType::Void, - Self::v8_fn_ptr_fast as *const ::std::ffi::c_void, - ) - }), - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 0usize as u8, - } - } - fn v8_fn_ptr_fast(_: deno_core::v8::Local<deno_core::v8::Object>) -> () { - let result = Self::call(); - result - } - extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) { - let result = Self::call(); - } - #[inline(always)] - pub fn call() -> () {} -} diff --git a/ops/op2/test_cases/sync/doc_comment.rs b/ops/op2/test_cases/sync/doc_comment.rs deleted file mode 100644 index b729a64bd..000000000 --- a/ops/op2/test_cases/sync/doc_comment.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. - -/// This is a doc comment. -#[op2(fast)] -pub fn op_has_doc_comment() -> () {} diff --git a/ops/op2/test_cases/sync/generics.out b/ops/op2/test_cases/sync/generics.out deleted file mode 100644 index 26e3af9b7..000000000 --- a/ops/op2/test_cases/sync/generics.out +++ /dev/null @@ -1,59 +0,0 @@ -#[allow(non_camel_case_types)] -pub struct op_generics<T> { - _unconstructable: ::std::marker::PhantomData<(T)>, -} -impl<T: Trait> deno_core::_ops::Op for op_generics<T> { - const NAME: &'static str = stringify!(op_generics); - const DECL: deno_core::_ops::OpDecl = deno_core::_ops::OpDecl { - name: stringify!(op_generics), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: Some({ - use deno_core::v8::fast_api::Type; - use deno_core::v8::fast_api::CType; - deno_core::v8::fast_api::FastFunction::new( - &[Type::V8Value], - CType::Void, - Self::v8_fn_ptr_fast as *const ::std::ffi::c_void, - ) - }), - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 0usize as u8, - }; -} -impl<T: Trait> op_generics<T> { - pub const fn name() -> &'static str { - stringify!(op_generics) - } - pub const fn decl() -> deno_core::_ops::OpDecl { - deno_core::_ops::OpDecl { - name: stringify!(op_generics), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: Some({ - use deno_core::v8::fast_api::Type; - use deno_core::v8::fast_api::CType; - deno_core::v8::fast_api::FastFunction::new( - &[Type::V8Value], - CType::Void, - Self::v8_fn_ptr_fast as *const ::std::ffi::c_void, - ) - }), - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 0usize as u8, - } - } - fn v8_fn_ptr_fast(_: deno_core::v8::Local<deno_core::v8::Object>) -> () { - let result = Self::call(); - result - } - extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) { - let result = Self::call(); - } - #[inline(always)] - pub fn call() {} -} diff --git a/ops/op2/test_cases/sync/generics.rs b/ops/op2/test_cases/sync/generics.rs deleted file mode 100644 index b412a7f93..000000000 --- a/ops/op2/test_cases/sync/generics.rs +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. - -#[op2(fast)] -pub fn op_generics<T: Trait>() {} diff --git a/ops/op2/test_cases/sync/result_primitive.out b/ops/op2/test_cases/sync/result_primitive.out deleted file mode 100644 index 4f296a893..000000000 --- a/ops/op2/test_cases/sync/result_primitive.out +++ /dev/null @@ -1,122 +0,0 @@ -#[allow(non_camel_case_types)] -pub struct op_u32_with_result { - _unconstructable: ::std::marker::PhantomData<()>, -} -impl deno_core::_ops::Op for op_u32_with_result { - const NAME: &'static str = stringify!(op_u32_with_result); - const DECL: deno_core::_ops::OpDecl = deno_core::_ops::OpDecl { - name: stringify!(op_u32_with_result), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: Some({ - use deno_core::v8::fast_api::Type; - use deno_core::v8::fast_api::CType; - deno_core::v8::fast_api::FastFunction::new( - &[Type::V8Value, Type::CallbackOptions], - CType::Uint32, - Self::v8_fn_ptr_fast as *const ::std::ffi::c_void, - ) - }), - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 0usize as u8, - }; -} -impl op_u32_with_result { - pub const fn name() -> &'static str { - stringify!(op_u32_with_result) - } - pub const fn decl() -> deno_core::_ops::OpDecl { - deno_core::_ops::OpDecl { - name: stringify!(op_u32_with_result), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: Some({ - use deno_core::v8::fast_api::Type; - use deno_core::v8::fast_api::CType; - deno_core::v8::fast_api::FastFunction::new( - &[Type::V8Value, Type::CallbackOptions], - CType::Uint32, - Self::v8_fn_ptr_fast as *const ::std::ffi::c_void, - ) - }), - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 0usize as u8, - } - } - fn v8_fn_ptr_fast( - _: deno_core::v8::Local<deno_core::v8::Object>, - fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions, - ) -> u32 { - let fast_api_callback_options = unsafe { &mut *fast_api_callback_options }; - let opctx = unsafe { - &*(deno_core::v8::Local::< - v8::External, - >::cast(unsafe { fast_api_callback_options.data.data }) - .value() as *const deno_core::_ops::OpCtx) - }; - let result = Self::call(); - let result = match result { - Ok(result) => result, - Err(err) => { - unsafe { - opctx.unsafely_set_last_error_for_ops_only(err); - } - fast_api_callback_options.fallback = true; - return ::std::default::Default::default(); - } - }; - result - } - extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) { - let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe { - &*info - }); - let args = deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe { - &*info - }); - let opctx = unsafe { - &*(deno_core::v8::Local::<deno_core::v8::External>::cast(args.data()).value() - as *const deno_core::_ops::OpCtx) - }; - if let Some(err) = unsafe { opctx.unsafely_take_last_error_for_ops_only() } { - let scope = &mut unsafe { deno_core::v8::CallbackScope::new(&*info) }; - let args = deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe { - &*info - }); - let opstate = ::std::cell::RefCell::borrow(&*opctx.state); - let exception = deno_core::error::to_v8_error( - scope, - opstate.get_error_class_fn, - &err, - ); - scope.throw_exception(exception); - return; - } - let result = Self::call(); - match result { - Ok(result) => { - rv.set_uint32(result as u32); - } - Err(err) => { - let scope = &mut unsafe { deno_core::v8::CallbackScope::new(&*info) }; - let args = deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe { - &*info - }); - let opstate = ::std::cell::RefCell::borrow(&*opctx.state); - let exception = deno_core::error::to_v8_error( - scope, - opstate.get_error_class_fn, - &err, - ); - scope.throw_exception(exception); - return; - } - }; - } - #[inline(always)] - pub fn call() -> Result<u32, AnyError> {} -} diff --git a/ops/op2/test_cases/sync/result_primitive.rs b/ops/op2/test_cases/sync/result_primitive.rs deleted file mode 100644 index df89c2432..000000000 --- a/ops/op2/test_cases/sync/result_primitive.rs +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. - -#[op2(fast)] -pub fn op_u32_with_result() -> Result<u32, AnyError> {} diff --git a/ops/op2/test_cases/sync/result_void.out b/ops/op2/test_cases/sync/result_void.out deleted file mode 100644 index 74aa84a8d..000000000 --- a/ops/op2/test_cases/sync/result_void.out +++ /dev/null @@ -1,117 +0,0 @@ -#[allow(non_camel_case_types)] -pub struct op_void_with_result { - _unconstructable: ::std::marker::PhantomData<()>, -} -impl deno_core::_ops::Op for op_void_with_result { - const NAME: &'static str = stringify!(op_void_with_result); - const DECL: deno_core::_ops::OpDecl = deno_core::_ops::OpDecl { - name: stringify!(op_void_with_result), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: Some({ - use deno_core::v8::fast_api::Type; - use deno_core::v8::fast_api::CType; - deno_core::v8::fast_api::FastFunction::new( - &[Type::V8Value, Type::CallbackOptions], - CType::Void, - Self::v8_fn_ptr_fast as *const ::std::ffi::c_void, - ) - }), - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 0usize as u8, - }; -} -impl op_void_with_result { - pub const fn name() -> &'static str { - stringify!(op_void_with_result) - } - pub const fn decl() -> deno_core::_ops::OpDecl { - deno_core::_ops::OpDecl { - name: stringify!(op_void_with_result), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: Some({ - use deno_core::v8::fast_api::Type; - use deno_core::v8::fast_api::CType; - deno_core::v8::fast_api::FastFunction::new( - &[Type::V8Value, Type::CallbackOptions], - CType::Void, - Self::v8_fn_ptr_fast as *const ::std::ffi::c_void, - ) - }), - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 0usize as u8, - } - } - fn v8_fn_ptr_fast( - _: deno_core::v8::Local<deno_core::v8::Object>, - fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions, - ) -> () { - let fast_api_callback_options = unsafe { &mut *fast_api_callback_options }; - let opctx = unsafe { - &*(deno_core::v8::Local::< - v8::External, - >::cast(unsafe { fast_api_callback_options.data.data }) - .value() as *const deno_core::_ops::OpCtx) - }; - let result = Self::call(); - let result = match result { - Ok(result) => result, - Err(err) => { - unsafe { - opctx.unsafely_set_last_error_for_ops_only(err); - } - fast_api_callback_options.fallback = true; - return ::std::default::Default::default(); - } - }; - result - } - extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) { - let args = deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe { - &*info - }); - let opctx = unsafe { - &*(deno_core::v8::Local::<deno_core::v8::External>::cast(args.data()).value() - as *const deno_core::_ops::OpCtx) - }; - if let Some(err) = unsafe { opctx.unsafely_take_last_error_for_ops_only() } { - let scope = &mut unsafe { deno_core::v8::CallbackScope::new(&*info) }; - let args = deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe { - &*info - }); - let opstate = ::std::cell::RefCell::borrow(&*opctx.state); - let exception = deno_core::error::to_v8_error( - scope, - opstate.get_error_class_fn, - &err, - ); - scope.throw_exception(exception); - return; - } - let result = Self::call(); - match result { - Ok(result) => {} - Err(err) => { - let scope = &mut unsafe { deno_core::v8::CallbackScope::new(&*info) }; - let args = deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe { - &*info - }); - let opstate = ::std::cell::RefCell::borrow(&*opctx.state); - let exception = deno_core::error::to_v8_error( - scope, - opstate.get_error_class_fn, - &err, - ); - scope.throw_exception(exception); - return; - } - }; - } - #[inline(always)] - pub fn call() -> Result<(), AnyError> {} -} diff --git a/ops/op2/test_cases/sync/result_void.rs b/ops/op2/test_cases/sync/result_void.rs deleted file mode 100644 index ef3aa7b32..000000000 --- a/ops/op2/test_cases/sync/result_void.rs +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. - -#[op2(fast)] -pub fn op_void_with_result() -> Result<(), AnyError> {} diff --git a/ops/op2/test_cases/sync/smi.out b/ops/op2/test_cases/sync/smi.out deleted file mode 100644 index 24b81ae47..000000000 --- a/ops/op2/test_cases/sync/smi.out +++ /dev/null @@ -1,76 +0,0 @@ -#[allow(non_camel_case_types)] -struct op_add { - _unconstructable: ::std::marker::PhantomData<()>, -} -impl deno_core::_ops::Op for op_add { - const NAME: &'static str = stringify!(op_add); - const DECL: deno_core::_ops::OpDecl = deno_core::_ops::OpDecl { - name: stringify!(op_add), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: Some({ - use deno_core::v8::fast_api::Type; - use deno_core::v8::fast_api::CType; - deno_core::v8::fast_api::FastFunction::new( - &[Type::V8Value, Type::Int32, Type::Uint32], - CType::Uint32, - Self::v8_fn_ptr_fast as *const ::std::ffi::c_void, - ) - }), - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 2usize as u8, - }; -} -impl op_add { - pub const fn name() -> &'static str { - stringify!(op_add) - } - pub const fn decl() -> deno_core::_ops::OpDecl { - deno_core::_ops::OpDecl { - name: stringify!(op_add), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: Some({ - use deno_core::v8::fast_api::Type; - use deno_core::v8::fast_api::CType; - deno_core::v8::fast_api::FastFunction::new( - &[Type::V8Value, Type::Int32, Type::Uint32], - CType::Uint32, - Self::v8_fn_ptr_fast as *const ::std::ffi::c_void, - ) - }), - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 2usize as u8, - } - } - fn v8_fn_ptr_fast( - _: deno_core::v8::Local<deno_core::v8::Object>, - arg0: i32, - arg1: u32, - ) -> u32 { - let arg0 = arg0 as _; - let arg1 = arg1 as _; - let result = Self::call(arg0, arg1); - result - } - extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) { - let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe { - &*info - }); - let args = deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe { - &*info - }); - let arg0 = args.get(0usize as i32); - let arg0 = deno_core::_ops::to_i32(&arg0) as _; - let arg1 = args.get(1usize as i32); - let arg1 = deno_core::_ops::to_u32(&arg1) as _; - let result = Self::call(arg0, arg1); - rv.set_uint32(result as u32); - } - #[inline(always)] - fn call(id: ResourceId, extra: u16) -> u32 {} -} diff --git a/ops/op2/test_cases/sync/smi.rs b/ops/op2/test_cases/sync/smi.rs deleted file mode 100644 index a5a441845..000000000 --- a/ops/op2/test_cases/sync/smi.rs +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. - -#[op2(fast)] -fn op_add(#[smi] id: ResourceId, extra: u16) -> u32 {} diff --git a/ops/op2/test_cases/sync/string_cow.out b/ops/op2/test_cases/sync/string_cow.out deleted file mode 100644 index 7d388e598..000000000 --- a/ops/op2/test_cases/sync/string_cow.out +++ /dev/null @@ -1,75 +0,0 @@ -#[allow(non_camel_case_types)] -struct op_string_cow { - _unconstructable: ::std::marker::PhantomData<()>, -} -impl deno_core::_ops::Op for op_string_cow { - const NAME: &'static str = stringify!(op_string_cow); - const DECL: deno_core::_ops::OpDecl = deno_core::_ops::OpDecl { - name: stringify!(op_string_cow), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: Some({ - use deno_core::v8::fast_api::Type; - use deno_core::v8::fast_api::CType; - deno_core::v8::fast_api::FastFunction::new( - &[Type::V8Value, Type::SeqOneByteString], - CType::Uint32, - Self::v8_fn_ptr_fast as *const ::std::ffi::c_void, - ) - }), - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 1usize as u8, - }; -} -impl op_string_cow { - pub const fn name() -> &'static str { - stringify!(op_string_cow) - } - pub const fn decl() -> deno_core::_ops::OpDecl { - deno_core::_ops::OpDecl { - name: stringify!(op_string_cow), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: Some({ - use deno_core::v8::fast_api::Type; - use deno_core::v8::fast_api::CType; - deno_core::v8::fast_api::FastFunction::new( - &[Type::V8Value, Type::SeqOneByteString], - CType::Uint32, - Self::v8_fn_ptr_fast as *const ::std::ffi::c_void, - ) - }), - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 1usize as u8, - } - } - fn v8_fn_ptr_fast( - _: deno_core::v8::Local<deno_core::v8::Object>, - arg0: *mut deno_core::v8::fast_api::FastApiOneByteString, - ) -> u32 { - let mut arg0_temp: [::std::mem::MaybeUninit<u8>; 1024] = [::std::mem::MaybeUninit::uninit(); 1024]; - let arg0 = deno_core::_ops::to_str_ptr(unsafe { &mut *arg0 }, &mut arg0_temp); - let result = Self::call(arg0); - result - } - extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) { - let scope = &mut unsafe { deno_core::v8::CallbackScope::new(&*info) }; - let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe { - &*info - }); - let args = deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe { - &*info - }); - let arg0 = args.get(0usize as i32); - let mut arg0_temp: [::std::mem::MaybeUninit<u8>; 1024] = [::std::mem::MaybeUninit::uninit(); 1024]; - let arg0 = deno_core::_ops::to_str(scope, &arg0, &mut arg0_temp); - let result = Self::call(arg0); - rv.set_uint32(result as u32); - } - #[inline(always)] - fn call(s: Cow<str>) -> u32 {} -} diff --git a/ops/op2/test_cases/sync/string_cow.rs b/ops/op2/test_cases/sync/string_cow.rs deleted file mode 100644 index ed4dfca82..000000000 --- a/ops/op2/test_cases/sync/string_cow.rs +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. - -#[op2(fast)] -fn op_string_cow(#[string] s: Cow<str>) -> u32 {} diff --git a/ops/op2/test_cases/sync/string_option_return.out b/ops/op2/test_cases/sync/string_option_return.out deleted file mode 100644 index 6143ac217..000000000 --- a/ops/op2/test_cases/sync/string_option_return.out +++ /dev/null @@ -1,53 +0,0 @@ -#[allow(non_camel_case_types)] -pub struct op_string_return { - _unconstructable: ::std::marker::PhantomData<()>, -} -impl deno_core::_ops::Op for op_string_return { - const NAME: &'static str = stringify!(op_string_return); - const DECL: deno_core::_ops::OpDecl = deno_core::_ops::OpDecl { - name: stringify!(op_string_return), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: None, - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 0usize as u8, - }; -} -impl op_string_return { - pub const fn name() -> &'static str { - stringify!(op_string_return) - } - pub const fn decl() -> deno_core::_ops::OpDecl { - deno_core::_ops::OpDecl { - name: stringify!(op_string_return), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: None, - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 0usize as u8, - } - } - extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) { - let scope = &mut unsafe { deno_core::v8::CallbackScope::new(&*info) }; - let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe { - &*info - }); - let result = Self::call(); - if let Some(result) = result { - if result.is_empty() { - rv.set_empty_string(); - } else { - let temp = deno_core::v8::String::new(scope, &result).unwrap(); - rv.set(temp.into()); - } - } else { - rv.set_null(); - } - } - #[inline(always)] - pub fn call() -> Option<String> {} -} diff --git a/ops/op2/test_cases/sync/string_option_return.rs b/ops/op2/test_cases/sync/string_option_return.rs deleted file mode 100644 index 932836d2f..000000000 --- a/ops/op2/test_cases/sync/string_option_return.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. - -#[op2] -#[string] -pub fn op_string_return() -> Option<String> {} diff --git a/ops/op2/test_cases/sync/string_owned.out b/ops/op2/test_cases/sync/string_owned.out deleted file mode 100644 index 7418a311c..000000000 --- a/ops/op2/test_cases/sync/string_owned.out +++ /dev/null @@ -1,73 +0,0 @@ -#[allow(non_camel_case_types)] -struct op_string_owned { - _unconstructable: ::std::marker::PhantomData<()>, -} -impl deno_core::_ops::Op for op_string_owned { - const NAME: &'static str = stringify!(op_string_owned); - const DECL: deno_core::_ops::OpDecl = deno_core::_ops::OpDecl { - name: stringify!(op_string_owned), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: Some({ - use deno_core::v8::fast_api::Type; - use deno_core::v8::fast_api::CType; - deno_core::v8::fast_api::FastFunction::new( - &[Type::V8Value, Type::SeqOneByteString], - CType::Uint32, - Self::v8_fn_ptr_fast as *const ::std::ffi::c_void, - ) - }), - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 1usize as u8, - }; -} -impl op_string_owned { - pub const fn name() -> &'static str { - stringify!(op_string_owned) - } - pub const fn decl() -> deno_core::_ops::OpDecl { - deno_core::_ops::OpDecl { - name: stringify!(op_string_owned), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: Some({ - use deno_core::v8::fast_api::Type; - use deno_core::v8::fast_api::CType; - deno_core::v8::fast_api::FastFunction::new( - &[Type::V8Value, Type::SeqOneByteString], - CType::Uint32, - Self::v8_fn_ptr_fast as *const ::std::ffi::c_void, - ) - }), - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 1usize as u8, - } - } - fn v8_fn_ptr_fast( - _: deno_core::v8::Local<deno_core::v8::Object>, - arg0: *mut deno_core::v8::fast_api::FastApiOneByteString, - ) -> u32 { - let arg0 = deno_core::_ops::to_string_ptr(unsafe { &mut *arg0 }); - let result = Self::call(arg0); - result - } - extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) { - let scope = &mut unsafe { deno_core::v8::CallbackScope::new(&*info) }; - let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe { - &*info - }); - let args = deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe { - &*info - }); - let arg0 = args.get(0usize as i32); - let arg0 = arg0.to_rust_string_lossy(scope); - let result = Self::call(arg0); - rv.set_uint32(result as u32); - } - #[inline(always)] - fn call(s: String) -> u32 {} -} diff --git a/ops/op2/test_cases/sync/string_owned.rs b/ops/op2/test_cases/sync/string_owned.rs deleted file mode 100644 index b81d7ece9..000000000 --- a/ops/op2/test_cases/sync/string_owned.rs +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. - -#[op2(fast)] -fn op_string_owned(#[string] s: String) -> u32 {} diff --git a/ops/op2/test_cases/sync/string_ref.out b/ops/op2/test_cases/sync/string_ref.out deleted file mode 100644 index 1b853fccc..000000000 --- a/ops/op2/test_cases/sync/string_ref.out +++ /dev/null @@ -1,75 +0,0 @@ -#[allow(non_camel_case_types)] -struct op_string_owned { - _unconstructable: ::std::marker::PhantomData<()>, -} -impl deno_core::_ops::Op for op_string_owned { - const NAME: &'static str = stringify!(op_string_owned); - const DECL: deno_core::_ops::OpDecl = deno_core::_ops::OpDecl { - name: stringify!(op_string_owned), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: Some({ - use deno_core::v8::fast_api::Type; - use deno_core::v8::fast_api::CType; - deno_core::v8::fast_api::FastFunction::new( - &[Type::V8Value, Type::SeqOneByteString], - CType::Uint32, - Self::v8_fn_ptr_fast as *const ::std::ffi::c_void, - ) - }), - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 1usize as u8, - }; -} -impl op_string_owned { - pub const fn name() -> &'static str { - stringify!(op_string_owned) - } - pub const fn decl() -> deno_core::_ops::OpDecl { - deno_core::_ops::OpDecl { - name: stringify!(op_string_owned), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: Some({ - use deno_core::v8::fast_api::Type; - use deno_core::v8::fast_api::CType; - deno_core::v8::fast_api::FastFunction::new( - &[Type::V8Value, Type::SeqOneByteString], - CType::Uint32, - Self::v8_fn_ptr_fast as *const ::std::ffi::c_void, - ) - }), - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 1usize as u8, - } - } - fn v8_fn_ptr_fast( - _: deno_core::v8::Local<deno_core::v8::Object>, - arg0: *mut deno_core::v8::fast_api::FastApiOneByteString, - ) -> u32 { - let mut arg0_temp: [::std::mem::MaybeUninit<u8>; 1024] = [::std::mem::MaybeUninit::uninit(); 1024]; - let arg0 = &deno_core::_ops::to_str_ptr(unsafe { &mut *arg0 }, &mut arg0_temp); - let result = Self::call(arg0); - result - } - extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) { - let scope = &mut unsafe { deno_core::v8::CallbackScope::new(&*info) }; - let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe { - &*info - }); - let args = deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe { - &*info - }); - let arg0 = args.get(0usize as i32); - let mut arg0_temp: [::std::mem::MaybeUninit<u8>; 1024] = [::std::mem::MaybeUninit::uninit(); 1024]; - let arg0 = &deno_core::_ops::to_str(scope, &arg0, &mut arg0_temp); - let result = Self::call(arg0); - rv.set_uint32(result as u32); - } - #[inline(always)] - fn call(s: &str) -> u32 {} -} diff --git a/ops/op2/test_cases/sync/string_ref.rs b/ops/op2/test_cases/sync/string_ref.rs deleted file mode 100644 index a7efa9f0c..000000000 --- a/ops/op2/test_cases/sync/string_ref.rs +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. - -#[op2(fast)] -fn op_string_owned(#[string] s: &str) -> u32 {} diff --git a/ops/op2/test_cases/sync/string_return.out b/ops/op2/test_cases/sync/string_return.out deleted file mode 100644 index 5e68b9314..000000000 --- a/ops/op2/test_cases/sync/string_return.out +++ /dev/null @@ -1,49 +0,0 @@ -#[allow(non_camel_case_types)] -pub struct op_string_return { - _unconstructable: ::std::marker::PhantomData<()>, -} -impl deno_core::_ops::Op for op_string_return { - const NAME: &'static str = stringify!(op_string_return); - const DECL: deno_core::_ops::OpDecl = deno_core::_ops::OpDecl { - name: stringify!(op_string_return), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: None, - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 0usize as u8, - }; -} -impl op_string_return { - pub const fn name() -> &'static str { - stringify!(op_string_return) - } - pub const fn decl() -> deno_core::_ops::OpDecl { - deno_core::_ops::OpDecl { - name: stringify!(op_string_return), - v8_fn_ptr: Self::v8_fn_ptr as _, - enabled: true, - fast_fn: None, - is_async: false, - is_unstable: false, - is_v8: false, - arg_count: 0usize as u8, - } - } - extern "C" fn v8_fn_ptr(info: *const deno_core::v8::FunctionCallbackInfo) { - let scope = &mut unsafe { deno_core::v8::CallbackScope::new(&*info) }; - let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe { - &*info - }); - let result = Self::call(); - if result.is_empty() { - rv.set_empty_string(); - } else { - let temp = deno_core::v8::String::new(scope, &result).unwrap(); - rv.set(temp.into()); - } - } - #[inline(always)] - pub fn call() -> String {} -} diff --git a/ops/op2/test_cases/sync/string_return.rs b/ops/op2/test_cases/sync/string_return.rs deleted file mode 100644 index 667b68a14..000000000 --- a/ops/op2/test_cases/sync/string_return.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. - -#[op2] -#[string] -pub fn op_string_return() -> String {} |