summaryrefslogtreecommitdiff
path: root/ops/op2
diff options
context:
space:
mode:
Diffstat (limited to 'ops/op2')
-rw-r--r--ops/op2/dispatch_fast.rs52
-rw-r--r--ops/op2/dispatch_slow.rs66
-rw-r--r--ops/op2/signature.rs12
-rw-r--r--ops/op2/test_cases/sync/add.out4
-rw-r--r--ops/op2/test_cases/sync/smi.out4
-rw-r--r--ops/op2/test_cases/sync/string_cow.out75
-rw-r--r--ops/op2/test_cases/sync/string_cow.rs4
-rw-r--r--ops/op2/test_cases/sync/string_option_return.out53
-rw-r--r--ops/op2/test_cases/sync/string_option_return.rs5
-rw-r--r--ops/op2/test_cases/sync/string_owned.out73
-rw-r--r--ops/op2/test_cases/sync/string_owned.rs4
-rw-r--r--ops/op2/test_cases/sync/string_ref.out75
-rw-r--r--ops/op2/test_cases/sync/string_ref.rs4
-rw-r--r--ops/op2/test_cases/sync/string_return.out49
-rw-r--r--ops/op2/test_cases/sync/string_return.rs5
15 files changed, 475 insertions, 10 deletions
diff --git a/ops/op2/dispatch_fast.rs b/ops/op2/dispatch_fast.rs
index 5262196f4..f9d74416a 100644
--- a/ops/op2/dispatch_fast.rs
+++ b/ops/op2/dispatch_fast.rs
@@ -4,10 +4,13 @@ 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)]
@@ -49,10 +52,12 @@ impl V8FastCallType {
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
- | V8FastCallType::SeqOneByteString => unreachable!(),
+ | V8FastCallType::Float64Array => unreachable!(),
}
}
@@ -190,7 +195,10 @@ pub fn generate_dispatch_fast(
.map(|rv| rv.quote_rust_type(deno_core))
.collect::<Vec<_>>();
- let call_args = names.clone();
+ 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));
@@ -219,7 +227,8 @@ pub fn generate_dispatch_fast(
) -> #output_type {
#with_fast_api_callback_options
#with_opctx
- let #result = Self::call(#(#call_args as _),*);
+ #(#call_args)*
+ let #result = Self::call(#(#call_idents),*);
#handle_error
#result
}
@@ -228,6 +237,32 @@ pub fn generate_dispatch_fast(
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> {
@@ -247,6 +282,13 @@ fn map_arg_to_v8_fastcall_type(
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))
@@ -271,6 +313,8 @@ fn map_retval_to_v8_fastcall_type(
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(
diff --git a/ops/op2/dispatch_slow.rs b/ops/op2/dispatch_slow.rs
index bf36e5d83..2ec67cc76 100644
--- a/ops/op2/dispatch_slow.rs
+++ b/ops/op2/dispatch_slow.rs
@@ -8,6 +8,7 @@ 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(
@@ -151,10 +152,14 @@ pub fn from_arg(
arg: &Arg,
) -> Result<TokenStream, V8MappingError> {
let GeneratorState {
- deno_core, args, ..
+ 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();
@@ -198,13 +203,31 @@ pub fn from_arg(
}
}
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();
+ 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! {
- let #arg_ident = #arg_ident.to_rust_string_lossy();
+ // 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())),
@@ -243,9 +266,12 @@ pub fn return_value_infallible(
ret_type: &Arg,
) -> Result<TokenStream, V8MappingError> {
let GeneratorState {
+ deno_core,
+ scope,
result,
retval,
needs_retval,
+ needs_scope,
..
} = generator_state;
@@ -265,6 +291,38 @@ pub fn return_value_infallible(
*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",
diff --git a/ops/op2/signature.rs b/ops/op2/signature.rs
index 15c40e007..5d472fcf3 100644
--- a/ops/op2/signature.rs
+++ b/ops/op2/signature.rs
@@ -106,6 +106,7 @@ pub enum Special {
HandleScope,
OpState,
String,
+ CowStr,
RefStr,
FastApiCallbackOptions,
}
@@ -431,6 +432,17 @@ fn parse_type_path(attrs: Attributes, tp: &TypePath) -> Result<Arg, ArgError> {
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)),
diff --git a/ops/op2/test_cases/sync/add.out b/ops/op2/test_cases/sync/add.out
index c8f77ab92..a73f032aa 100644
--- a/ops/op2/test_cases/sync/add.out
+++ b/ops/op2/test_cases/sync/add.out
@@ -52,7 +52,9 @@ impl op_add {
arg0: u32,
arg1: u32,
) -> u32 {
- let result = Self::call(arg0 as _, arg1 as _);
+ 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) {
diff --git a/ops/op2/test_cases/sync/smi.out b/ops/op2/test_cases/sync/smi.out
index 85db2576e..24b81ae47 100644
--- a/ops/op2/test_cases/sync/smi.out
+++ b/ops/op2/test_cases/sync/smi.out
@@ -52,7 +52,9 @@ impl op_add {
arg0: i32,
arg1: u32,
) -> u32 {
- let result = Self::call(arg0 as _, arg1 as _);
+ 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) {
diff --git a/ops/op2/test_cases/sync/string_cow.out b/ops/op2/test_cases/sync/string_cow.out
new file mode 100644
index 000000000..7d388e598
--- /dev/null
+++ b/ops/op2/test_cases/sync/string_cow.out
@@ -0,0 +1,75 @@
+#[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
new file mode 100644
index 000000000..ed4dfca82
--- /dev/null
+++ b/ops/op2/test_cases/sync/string_cow.rs
@@ -0,0 +1,4 @@
+// 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
new file mode 100644
index 000000000..6143ac217
--- /dev/null
+++ b/ops/op2/test_cases/sync/string_option_return.out
@@ -0,0 +1,53 @@
+#[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
new file mode 100644
index 000000000..932836d2f
--- /dev/null
+++ b/ops/op2/test_cases/sync/string_option_return.rs
@@ -0,0 +1,5 @@
+// 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
new file mode 100644
index 000000000..7418a311c
--- /dev/null
+++ b/ops/op2/test_cases/sync/string_owned.out
@@ -0,0 +1,73 @@
+#[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
new file mode 100644
index 000000000..b81d7ece9
--- /dev/null
+++ b/ops/op2/test_cases/sync/string_owned.rs
@@ -0,0 +1,4 @@
+// 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
new file mode 100644
index 000000000..1b853fccc
--- /dev/null
+++ b/ops/op2/test_cases/sync/string_ref.out
@@ -0,0 +1,75 @@
+#[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
new file mode 100644
index 000000000..a7efa9f0c
--- /dev/null
+++ b/ops/op2/test_cases/sync/string_ref.rs
@@ -0,0 +1,4 @@
+// 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
new file mode 100644
index 000000000..5e68b9314
--- /dev/null
+++ b/ops/op2/test_cases/sync/string_return.out
@@ -0,0 +1,49 @@
+#[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
new file mode 100644
index 000000000..667b68a14
--- /dev/null
+++ b/ops/op2/test_cases/sync/string_return.rs
@@ -0,0 +1,5 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+
+#[op2]
+#[string]
+pub fn op_string_return() -> String {}