@@ -12,18 +12,19 @@ for (const relativePath of [
1212
1313 const invokeBaseCount = source . match ( / r e t u r n a p i \. _ _ i n v o k e B a s e \( \. \. \. b a s e A r g s \) ; / g) ?. length ?? 0 ;
1414 assert (
15- invokeBaseCount >= 2 ,
16- `${ relativePath } : class and instance selector wrappers should route native receivers through __invokeBase` ,
15+ invokeBaseCount === 1 ,
16+ `${ relativePath } : only class selector wrappers should route native receivers through __invokeBase` ,
1717 ) ;
1818 assert (
19- source . includes ( "return fn.apply(this, arguments);" ) ,
20- `${ relativePath } : instance selector wrapper should preserve normal this-bound fallback dispatch ` ,
19+ ! source . includes ( "return fn.apply(this, arguments);" ) ,
20+ `${ relativePath } : instance selector wrappers should not globally reroute native receivers through __invokeBase ` ,
2121 ) ;
2222 assert (
2323 source . includes ( "value: receiverIsClass" ) &&
24- source . includes ( ": (function(fn, memberName) {" ) &&
25- source . includes ( "var baseArgs = [nativeClass, this, memberName];" ) ,
26- `${ relativePath } : instance selector wrapper should build base invocation arguments from nativeClass, receiver, and member name` ,
24+ source . includes ( "? (function(fn, memberName) {" ) &&
25+ source . includes ( "var baseArgs = [nativeClass, this, memberName];" ) &&
26+ source . includes ( ": selectorFunction" ) ,
27+ `${ relativePath } : class selector wrappers should keep base invocation support while instance selectors use engine dispatch` ,
2728 ) ;
2829}
2930
@@ -34,19 +35,39 @@ for (const relativePath of [
3435 const source = fs . readFileSync ( path . join ( repoRoot , relativePath ) , "utf8" ) ;
3536
3637 assert (
37- source . includes ( "Value callNativeApiBaseObjectSelector (" ) ,
38- `${ relativePath } : base dispatch should go through the receiver-preserving helper` ,
38+ source . includes ( "std::optional< Value> preservedNativeApiInitializerSelfReturn (" ) ,
39+ `${ relativePath } : runtime should expose the initializer self-preservation helper` ,
3940 ) ;
4041 assert (
41- source . includes ( 'selectorName.rfind("init", 0 ) != 0' ) &&
42+ source . includes ( "receiverHostObject->object( ) != receiver" ) &&
4243 source . includes ( "NativeApiObjectHostObject::nativeObjectFromValue(runtime, result)" ) &&
4344 source . includes ( "bridge->rememberRoundTripValue(runtime, receiver," ) &&
44- source . includes ( "return Value(runtime, receiverObject) ;" ) ,
45- `${ relativePath } : base initializer dispatch should preserve receiver wrapper identity when init returns self` ,
45+ source . includes ( "return preserved ;" ) ,
46+ `${ relativePath } : initializer dispatch should preserve the original JS receiver when native init returns self` ,
4647 ) ;
4748 assert (
48- source . includes ( "return callNativeApiBaseObjectSelector(" ) ,
49- `${ relativePath } : __invokeBase should use receiver-preserving selector calls` ,
49+ source . includes ( "preservedNativeApiInitializerSelfReturn(" ) &&
50+ source . includes ( "Value(runtime, receiverObject)" ) ,
51+ `${ relativePath } : __invokeBase should use the shared initializer self-preservation helper` ,
52+ ) ;
53+ }
54+
55+ for ( const relativePath of [
56+ "NativeScript/ffi/jsc/NativeApiJSCSelectorGroups.mm" ,
57+ "NativeScript/ffi/v8/NativeApiV8SelectorGroups.mm" ,
58+ "NativeScript/ffi/quickjs/NativeApiQuickJSSelectorGroups.mm" ,
59+ "NativeScript/ffi/hermes/NativeApiJsi.mm" ,
60+ "packages/react-native/native-api/ffi/hermes/NativeApiJsi.mm" ,
61+ ] ) {
62+ const fullPath = path . join ( repoRoot , relativePath ) ;
63+ if ( ! fs . existsSync ( fullPath ) ) {
64+ continue ;
65+ }
66+ const source = fs . readFileSync ( fullPath , "utf8" ) ;
67+ assert (
68+ source . includes ( "prepared->isInitMethod" ) &&
69+ source . includes ( "preservedNativeApiInitializerSelfReturn(" ) ,
70+ `${ relativePath } : engine selector groups should preserve the original receiver when init returns self` ,
5071 ) ;
5172}
5273
0 commit comments