@@ -97,18 +97,29 @@ impl FastSignature {
9797 & self ,
9898 generator_state : & mut GeneratorState ,
9999 ) -> Result < Vec < TokenStream > , V8SignatureMappingError > {
100+ // Collect virtual arguments in a deferred list that we compute at the very end. This allows us to borrow
101+ // the scope/opstate in the intermediate stages.
100102 let mut call_args = vec ! [ ] ;
103+ let mut deferred = vec ! [ ] ;
104+
101105 for arg in & self . args {
102106 match arg {
103- FastArg :: Actual { arg, name_out, .. }
104- | FastArg :: Virtual { name_out, arg } => call_args. push (
107+ FastArg :: Actual { arg, name_out, .. } => call_args. push (
108+ map_v8_fastcall_arg_to_arg ( generator_state, name_out, arg) . map_err (
109+ |s| V8SignatureMappingError :: NoArgMapping ( s, arg. clone ( ) ) ,
110+ ) ?,
111+ ) ,
112+ FastArg :: Virtual { name_out, arg } => deferred. push (
105113 map_v8_fastcall_arg_to_arg ( generator_state, name_out, arg) . map_err (
106114 |s| V8SignatureMappingError :: NoArgMapping ( s, arg. clone ( ) ) ,
107115 ) ?,
108116 ) ,
109117 FastArg :: CallbackOptions | FastArg :: PromiseId => { }
110118 }
111119 }
120+
121+ call_args. extend ( deferred) ;
122+
112123 Ok ( call_args)
113124 }
114125
@@ -313,6 +324,14 @@ pub(crate) fn get_fast_signature(
313324 } ) )
314325}
315326
327+ fn create_isolate ( generator_state : & mut GeneratorState ) -> TokenStream {
328+ generator_state. needs_fast_api_callback_options = true ;
329+ gs_quote ! ( generator_state( fast_api_callback_options) => {
330+ // SAFETY: This is using an &FastApiCallbackOptions inside a fast call.
331+ unsafe { & mut * #fast_api_callback_options. isolate } ;
332+ } )
333+ }
334+
316335fn create_scope ( generator_state : & mut GeneratorState ) -> TokenStream {
317336 generator_state. needs_fast_api_callback_options = true ;
318337 gs_quote ! ( generator_state( fast_api_callback_options) => {
@@ -478,6 +497,11 @@ pub(crate) fn generate_dispatch_fast(
478497 gs_quote ! ( generator_state( scope) => {
479498 let mut #scope = #create_scope;
480499 } )
500+ } else if generator_state. needs_isolate {
501+ let create_isolate = create_isolate ( generator_state) ;
502+ gs_quote ! ( generator_state( scope) => {
503+ let mut #scope = #create_isolate;
504+ } )
481505 } else {
482506 quote ! ( )
483507 } ;
@@ -590,6 +614,7 @@ fn map_v8_fastcall_arg_to_arg(
590614 opctx,
591615 js_runtime_state,
592616 scope,
617+ needs_isolate,
593618 needs_scope,
594619 needs_opctx,
595620 needs_fast_api_callback_options,
@@ -658,9 +683,9 @@ fn map_v8_fastcall_arg_to_arg(
658683 fast_api_typed_array_to_buffer ( arg_ident, arg_ident, * buffer) ?
659684 }
660685 Arg :: Special ( Special :: Isolate ) => {
661- * needs_fast_api_callback_options = true ;
662- gs_quote ! ( generator_state( fast_api_callback_options ) => {
663- let #arg_ident = #fast_api_callback_options . isolate ;
686+ * needs_isolate = true ;
687+ gs_quote ! ( generator_state( scope ) => {
688+ let #arg_ident = & mut * #scope ;
664689 } )
665690 }
666691 Arg :: Ref ( RefType :: Ref , Special :: OpState ) => {
@@ -720,22 +745,46 @@ fn map_v8_fastcall_arg_to_arg(
720745 }
721746 }
722747 Arg :: String ( Strings :: RefStr ) => {
723- quote ! {
724- let mut #arg_temp: [ :: std:: mem:: MaybeUninit <u8 >; deno_core:: _ops:: STRING_STACK_BUFFER_SIZE ] = [ :: std:: mem:: MaybeUninit :: uninit( ) ; deno_core:: _ops:: STRING_STACK_BUFFER_SIZE ] ;
725- let #arg_ident = & deno_core:: _ops:: to_str_ptr( unsafe { & mut * #arg_ident } , & mut #arg_temp) ;
726- }
748+ // quote! {
749+ // let mut #arg_temp: [::std::mem::MaybeUninit<u8>; deno_core::_ops::STRING_STACK_BUFFER_SIZE] = [::std::mem::MaybeUninit::uninit(); deno_core::_ops::STRING_STACK_BUFFER_SIZE];
750+ // let #arg_ident = &deno_core::_ops::to_str_ptr(unsafe { &mut *#arg_ident }, &mut #arg_temp);
751+ // }
752+ * needs_isolate = true ;
753+ gs_quote ! ( generator_state( scope) => {
754+ let mut #arg_temp: ( [ :: std:: mem:: MaybeUninit <u8 >; deno_core:: _ops:: STRING_STACK_BUFFER_SIZE ] , Option <v8:: ValueView >) = {
755+ let buf = [ :: std:: mem:: MaybeUninit :: uninit( ) ; deno_core:: _ops:: STRING_STACK_BUFFER_SIZE ] ;
756+ let value_view = deno_core:: _ops:: to_string_view( & mut * #scope, #arg_ident) ;
757+ ( buf, value_view)
758+ } ;
759+ let #arg_ident = if let Some ( value_view) = & #arg_temp. 1 {
760+ & deno_core:: _ops:: to_str_from_view( value_view, & mut #arg_temp. 0 )
761+ } else {
762+ ""
763+ } ;
764+ // let value_view = deno_core::_ops::to_string_view(&mut *#scope, #arg_ident);
765+ // let #arg_ident = "";
766+ } )
727767 }
728768 Arg :: String ( Strings :: String ) => {
729- quote ! ( let #arg_ident = deno_core:: _ops:: to_string_ptr( unsafe { & mut * #arg_ident } ) ; )
769+ * needs_isolate = true ;
770+ quote ! ( let #arg_ident = deno_core:: _ops:: to_string( & mut * #scope, & * #arg_ident) ; )
730771 }
731772 Arg :: String ( Strings :: CowStr ) => {
732- quote ! {
773+ * needs_isolate = true ;
774+ gs_quote ! ( generator_state( scope) => {
733775 let mut #arg_temp: [ :: std:: mem:: MaybeUninit <u8 >; deno_core:: _ops:: STRING_STACK_BUFFER_SIZE ] = [ :: std:: mem:: MaybeUninit :: uninit( ) ; deno_core:: _ops:: STRING_STACK_BUFFER_SIZE ] ;
734- let #arg_ident = deno_core:: _ops:: to_str_ptr ( unsafe { & mut * #arg_ident } , & mut #arg_temp) ;
735- }
776+ let #arg_ident = deno_core:: _ops:: to_str ( & mut * #scope , & * #arg_ident , & mut #arg_temp) ;
777+ } )
736778 }
737779 Arg :: String ( Strings :: CowByte ) => {
738- quote ! ( let #arg_ident = deno_core:: _ops:: to_cow_byte_ptr( unsafe { & mut * #arg_ident } ) ; )
780+ * needs_isolate = true ;
781+ let throw_exception =
782+ throw_type_error ( generator_state, "expected one byte string" ) ;
783+ gs_quote ! ( generator_state( scope) => {
784+ let Ok ( #arg_ident) = deno_core:: _ops:: to_cow_one_byte( & mut * #scope, & * #arg_ident) else {
785+ #throw_exception
786+ } ;
787+ } )
739788 }
740789 Arg :: V8Local ( v8)
741790 | Arg :: OptionV8Local ( v8)
@@ -755,13 +804,11 @@ fn map_v8_fastcall_arg_to_arg(
755804 let ty =
756805 syn:: parse_str :: < syn:: Path > ( ty) . expect ( "Failed to reparse state type" ) ;
757806
758- * needs_fast_api_callback_options = true ;
807+ * needs_isolate = true ;
759808 let throw_exception =
760809 throw_type_error ( generator_state, format ! ( "expected {ty:?}" ) ) ;
761- gs_quote ! ( generator_state( fast_api_callback_options) => {
762- // SAFETY: Isolate is valid if this function is being called.
763- let isolate = unsafe { & mut * #fast_api_callback_options. isolate } ;
764- let Some ( #arg_ident) = deno_core:: _ops:: try_unwrap_cppgc_object:: <#ty>( isolate, #arg_ident) else {
810+ gs_quote ! ( generator_state( scope) => {
811+ let Some ( #arg_ident) = deno_core:: _ops:: try_unwrap_cppgc_object:: <#ty>( & mut * #scope, #arg_ident) else {
765812 #throw_exception
766813 } ;
767814 let #arg_ident = & * #arg_ident;
@@ -851,7 +898,6 @@ fn map_arg_to_v8_fastcall_type(
851898 // Other types + ref types are not handled
852899 Arg :: OptionNumeric ( ..)
853900 | Arg :: Option ( _)
854- | Arg :: OptionString ( _)
855901 | Arg :: OptionBuffer ( ..)
856902 | Arg :: SerdeV8 ( _)
857903 | Arg :: FromV8 ( _)
@@ -885,15 +931,16 @@ fn map_arg_to_v8_fastcall_type(
885931 ) => V8FastCallType :: F64 ,
886932 Arg :: Numeric ( NumericArg :: f32, _) => V8FastCallType :: F32 ,
887933 Arg :: Numeric ( NumericArg :: f64, _) => V8FastCallType :: F64 ,
888- // Ref strings that are one byte internally may be passed as a SeqOneByteString,
889- // which gives us a FastApiOneByteString.
890- Arg :: String ( Strings :: RefStr ) => V8FastCallType :: SeqOneByteString ,
891- // Owned strings can be fast, but we'll have to copy them.
892- Arg :: String ( Strings :: String ) => V8FastCallType :: SeqOneByteString ,
893- // Cow strings can be fast, but may require copying
894- Arg :: String ( Strings :: CowStr ) => V8FastCallType :: SeqOneByteString ,
895- // Cow byte strings can be fast and don't require copying
896- Arg :: String ( Strings :: CowByte ) => V8FastCallType :: SeqOneByteString ,
934+ // Strings are passed as v8::Value, because SeqOneByteString is too
935+ // restrictive in what values are eligible for fastcalls.
936+ Arg :: OptionString ( Strings :: RefStr ) => return Ok ( None ) ,
937+ Arg :: OptionString ( Strings :: String ) => return Ok ( None ) ,
938+ Arg :: OptionString ( Strings :: CowStr ) => return Ok ( None ) ,
939+ Arg :: OptionString ( Strings :: CowByte ) => return Ok ( None ) ,
940+ Arg :: String ( Strings :: RefStr ) => V8FastCallType :: V8Value ,
941+ Arg :: String ( Strings :: String ) => V8FastCallType :: V8Value ,
942+ Arg :: String ( Strings :: CowStr ) => V8FastCallType :: V8Value ,
943+ Arg :: String ( Strings :: CowByte ) => V8FastCallType :: V8Value ,
897944 Arg :: External ( ..) => V8FastCallType :: Pointer ,
898945 Arg :: CppGcResource ( ..) => V8FastCallType :: V8Value ,
899946 Arg :: OptionCppGcResource ( ..) => V8FastCallType :: V8Value ,
0 commit comments