@@ -97,18 +97,29 @@ impl FastSignature {
97
97
& self ,
98
98
generator_state : & mut GeneratorState ,
99
99
) -> 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.
100
102
let mut call_args = vec ! [ ] ;
103
+ let mut deferred = vec ! [ ] ;
104
+
101
105
for arg in & self . args {
102
106
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 (
105
113
map_v8_fastcall_arg_to_arg ( generator_state, name_out, arg) . map_err (
106
114
|s| V8SignatureMappingError :: NoArgMapping ( s, arg. clone ( ) ) ,
107
115
) ?,
108
116
) ,
109
117
FastArg :: CallbackOptions | FastArg :: PromiseId => { }
110
118
}
111
119
}
120
+
121
+ call_args. extend ( deferred) ;
122
+
112
123
Ok ( call_args)
113
124
}
114
125
@@ -313,6 +324,14 @@ pub(crate) fn get_fast_signature(
313
324
} ) )
314
325
}
315
326
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
+
316
335
fn create_scope ( generator_state : & mut GeneratorState ) -> TokenStream {
317
336
generator_state. needs_fast_api_callback_options = true ;
318
337
gs_quote ! ( generator_state( fast_api_callback_options) => {
@@ -478,6 +497,11 @@ pub(crate) fn generate_dispatch_fast(
478
497
gs_quote ! ( generator_state( scope) => {
479
498
let mut #scope = #create_scope;
480
499
} )
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
+ } )
481
505
} else {
482
506
quote ! ( )
483
507
} ;
@@ -590,6 +614,7 @@ fn map_v8_fastcall_arg_to_arg(
590
614
opctx,
591
615
js_runtime_state,
592
616
scope,
617
+ needs_isolate,
593
618
needs_scope,
594
619
needs_opctx,
595
620
needs_fast_api_callback_options,
@@ -658,9 +683,9 @@ fn map_v8_fastcall_arg_to_arg(
658
683
fast_api_typed_array_to_buffer ( arg_ident, arg_ident, * buffer) ?
659
684
}
660
685
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 ;
664
689
} )
665
690
}
666
691
Arg :: Ref ( RefType :: Ref , Special :: OpState ) => {
@@ -720,22 +745,32 @@ fn map_v8_fastcall_arg_to_arg(
720
745
}
721
746
}
722
747
Arg :: String ( Strings :: RefStr ) => {
723
- quote ! {
748
+ * needs_isolate = true ;
749
+ gs_quote ! ( generator_state( scope) => {
724
750
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
- }
751
+ let #arg_ident = & deno_core:: _ops:: to_str ( & mut * #scope , & * #arg_ident , & mut #arg_temp) ;
752
+ } )
727
753
}
728
754
Arg :: String ( Strings :: String ) => {
729
- quote ! ( let #arg_ident = deno_core:: _ops:: to_string_ptr( unsafe { & mut * #arg_ident } ) ; )
755
+ * needs_isolate = true ;
756
+ quote ! ( let #arg_ident = deno_core:: _ops:: to_string( & mut * #scope, & * #arg_ident) ; )
730
757
}
731
758
Arg :: String ( Strings :: CowStr ) => {
732
- quote ! {
759
+ * needs_isolate = true ;
760
+ gs_quote ! ( generator_state( scope) => {
733
761
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
- }
762
+ let #arg_ident = deno_core:: _ops:: to_str ( & mut * #scope , & * #arg_ident , & mut #arg_temp) ;
763
+ } )
736
764
}
737
765
Arg :: String ( Strings :: CowByte ) => {
738
- quote ! ( let #arg_ident = deno_core:: _ops:: to_cow_byte_ptr( unsafe { & mut * #arg_ident } ) ; )
766
+ * needs_isolate = true ;
767
+ let throw_exception =
768
+ throw_type_error ( generator_state, "expected one byte string" ) ;
769
+ gs_quote ! ( generator_state( scope) => {
770
+ let Ok ( #arg_ident) = deno_core:: _ops:: to_cow_one_byte( & mut * #scope, & * #arg_ident) else {
771
+ #throw_exception
772
+ } ;
773
+ } )
739
774
}
740
775
Arg :: V8Local ( v8)
741
776
| Arg :: OptionV8Local ( v8)
@@ -755,13 +790,11 @@ fn map_v8_fastcall_arg_to_arg(
755
790
let ty =
756
791
syn:: parse_str :: < syn:: Path > ( ty) . expect ( "Failed to reparse state type" ) ;
757
792
758
- * needs_fast_api_callback_options = true ;
793
+ * needs_isolate = true ;
759
794
let throw_exception =
760
795
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 {
796
+ gs_quote ! ( generator_state( scope) => {
797
+ let Some ( #arg_ident) = deno_core:: _ops:: try_unwrap_cppgc_object:: <#ty>( & mut * #scope, #arg_ident) else {
765
798
#throw_exception
766
799
} ;
767
800
let #arg_ident = & * #arg_ident;
@@ -851,7 +884,6 @@ fn map_arg_to_v8_fastcall_type(
851
884
// Other types + ref types are not handled
852
885
Arg :: OptionNumeric ( ..)
853
886
| Arg :: Option ( _)
854
- | Arg :: OptionString ( _)
855
887
| Arg :: OptionBuffer ( ..)
856
888
| Arg :: SerdeV8 ( _)
857
889
| Arg :: FromV8 ( _)
@@ -885,15 +917,16 @@ fn map_arg_to_v8_fastcall_type(
885
917
) => V8FastCallType :: F64 ,
886
918
Arg :: Numeric ( NumericArg :: f32, _) => V8FastCallType :: F32 ,
887
919
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 ,
920
+ // Strings are passed as v8::Value, because SeqOneByteString is too
921
+ // restrictive in what values are eligible for fastcalls.
922
+ Arg :: OptionString ( Strings :: RefStr ) => return Ok ( None ) ,
923
+ Arg :: OptionString ( Strings :: String ) => return Ok ( None ) ,
924
+ Arg :: OptionString ( Strings :: CowStr ) => return Ok ( None ) ,
925
+ Arg :: OptionString ( Strings :: CowByte ) => return Ok ( None ) ,
926
+ Arg :: String ( Strings :: RefStr ) => V8FastCallType :: V8Value ,
927
+ Arg :: String ( Strings :: String ) => V8FastCallType :: V8Value ,
928
+ Arg :: String ( Strings :: CowStr ) => V8FastCallType :: V8Value ,
929
+ Arg :: String ( Strings :: CowByte ) => V8FastCallType :: V8Value ,
897
930
Arg :: External ( ..) => V8FastCallType :: Pointer ,
898
931
Arg :: CppGcResource ( ..) => V8FastCallType :: V8Value ,
899
932
Arg :: OptionCppGcResource ( ..) => V8FastCallType :: V8Value ,
0 commit comments