Skip to content

Commit acd8b8e

Browse files
Enable synchronous void method invocations via feature flag - RFC
Summary: Introduce a feature flag `enableSyncVoidMethods` that allows TurboModule methods with void return types to be invoked synchronously on the JS thread instead of being dispatched asynchronously. The flag only applies to pure TurboModules (not interop modules) to avoid impacting backward compatibility with legacy Native Modules. When enabled, void methods behave like other synchronous methods, improving performance for operations that don't need async dispatch. # Behavior mismatch Currently: - C++ Turbo Modules run void methods `sync` - Java / ObjC Turbo Modules run void methods `async` # Rationale JavaScript code like this ``` const buffer = new ArrayBuffer(4); const view = new Uint8Array(buffer); view[0] = 1; view[1] = 2; view[2] = 3; view[3] = 4; const result = NativeCxxModuleExample.passArrayBuffer(buffer); /** In native code do something like: * std::span<uint8_t> bytes(arg.data(rt), arg.size(rt)); * std::reverse(bytes.begin(), bytes.end()); **/ // ArrayBuffer was Shared with native code and value updates are reflected to JS code // view[0] = 4; // view[1] = 3; // view[2] = 2; // view[3] = 1; ``` for a TM spec as ``` +passArrayBuffer: (arg: ArrayBuffer) => void; ``` works for C++ Turbo Modules see: #56690 but currently fails for Java / Objc Turbo Modules as calling ``` const result = NativeCxxModuleExample.passArrayBuffer(buffer); // ``` is done `async` for Java/ObjC Modules and hence we would need to copy the `ArrayBuffer` in native code. Changelog: [Internal] Differential Revision: D104331837
1 parent c0bf154 commit acd8b8e

30 files changed

Lines changed: 241 additions & 76 deletions

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<d4e81be344e15b275d015651b4fa824d>>
7+
* @generated SignedSource<<3272436c25e63e1e2152f4af9aafcffa>>
88
*/
99

1010
/**
@@ -306,6 +306,12 @@ public object ReactNativeFeatureFlags {
306306
@JvmStatic
307307
public fun enableSwiftUIBasedFilters(): Boolean = accessor.enableSwiftUIBasedFilters()
308308

309+
/**
310+
* When enabled, TurboModule methods with void return type will be invoked synchronously on the JS thread instead of being dispatched asynchronously. Only applies to pure TurboModules, not interop modules.
311+
*/
312+
@JvmStatic
313+
public fun enableSyncVoidMethods(): Boolean = accessor.enableSyncVoidMethods()
314+
309315
/**
310316
* Enables View Culling: as soon as a view goes off screen, it can be reused anywhere in the UI and pieced together with other items to create new UI elements.
311317
*/

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<189cc2dd3b42cd736191f13b442e7317>>
7+
* @generated SignedSource<<62523747d1f721ebc68d3b3b77bc4a48>>
88
*/
99

1010
/**
@@ -66,6 +66,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
6666
private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null
6767
private var enableSchedulerDelegateInvalidationCache: Boolean? = null
6868
private var enableSwiftUIBasedFiltersCache: Boolean? = null
69+
private var enableSyncVoidMethodsCache: Boolean? = null
6970
private var enableViewCullingCache: Boolean? = null
7071
private var enableViewRecyclingCache: Boolean? = null
7172
private var enableViewRecyclingForImageCache: Boolean? = null
@@ -527,6 +528,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
527528
return cached
528529
}
529530

531+
override fun enableSyncVoidMethods(): Boolean {
532+
var cached = enableSyncVoidMethodsCache
533+
if (cached == null) {
534+
cached = ReactNativeFeatureFlagsCxxInterop.enableSyncVoidMethods()
535+
enableSyncVoidMethodsCache = cached
536+
}
537+
return cached
538+
}
539+
530540
override fun enableViewCulling(): Boolean {
531541
var cached = enableViewCullingCache
532542
if (cached == null) {

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<81c6672ae539af203fae7e0f9cf541a6>>
7+
* @generated SignedSource<<2b91d3a03ec71265f0f9d1f25cf61d66>>
88
*/
99

1010
/**
@@ -120,6 +120,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
120120

121121
@DoNotStrip @JvmStatic public external fun enableSwiftUIBasedFilters(): Boolean
122122

123+
@DoNotStrip @JvmStatic public external fun enableSyncVoidMethods(): Boolean
124+
123125
@DoNotStrip @JvmStatic public external fun enableViewCulling(): Boolean
124126

125127
@DoNotStrip @JvmStatic public external fun enableViewRecycling(): Boolean

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<053d67947ccd1a3556c8f6e1b6af5a14>>
7+
* @generated SignedSource<<46918ab06dcb1dd3c1409a2bf847e775>>
88
*/
99

1010
/**
@@ -115,6 +115,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
115115

116116
override fun enableSwiftUIBasedFilters(): Boolean = false
117117

118+
override fun enableSyncVoidMethods(): Boolean = false
119+
118120
override fun enableViewCulling(): Boolean = false
119121

120122
override fun enableViewRecycling(): Boolean = false

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<24972f077ba738a8191a2956be61b491>>
7+
* @generated SignedSource<<a478da71ad26ed30a6fd0610ec90f301>>
88
*/
99

1010
/**
@@ -70,6 +70,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
7070
private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null
7171
private var enableSchedulerDelegateInvalidationCache: Boolean? = null
7272
private var enableSwiftUIBasedFiltersCache: Boolean? = null
73+
private var enableSyncVoidMethodsCache: Boolean? = null
7374
private var enableViewCullingCache: Boolean? = null
7475
private var enableViewRecyclingCache: Boolean? = null
7576
private var enableViewRecyclingForImageCache: Boolean? = null
@@ -577,6 +578,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
577578
return cached
578579
}
579580

581+
override fun enableSyncVoidMethods(): Boolean {
582+
var cached = enableSyncVoidMethodsCache
583+
if (cached == null) {
584+
cached = currentProvider.enableSyncVoidMethods()
585+
accessedFeatureFlags.add("enableSyncVoidMethods")
586+
enableSyncVoidMethodsCache = cached
587+
}
588+
return cached
589+
}
590+
580591
override fun enableViewCulling(): Boolean {
581592
var cached = enableViewCullingCache
582593
if (cached == null) {

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<a7c69ce7e10faeb5328412c5e29552cf>>
7+
* @generated SignedSource<<6dd7973e8cdb5896dd05cc34d32b4d87>>
88
*/
99

1010
/**
@@ -115,6 +115,8 @@ public interface ReactNativeFeatureFlagsProvider {
115115

116116
@DoNotStrip public fun enableSwiftUIBasedFilters(): Boolean
117117

118+
@DoNotStrip public fun enableSyncVoidMethods(): Boolean
119+
118120
@DoNotStrip public fun enableViewCulling(): Boolean
119121

120122
@DoNotStrip public fun enableViewRecycling(): Boolean

packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<74f0602ce337a86730efe638ab8e966d>>
7+
* @generated SignedSource<<41c6ef0fd874996ba107d6e6ef8d0c56>>
88
*/
99

1010
/**
@@ -315,6 +315,12 @@ class ReactNativeFeatureFlagsJavaProvider
315315
return method(javaProvider_);
316316
}
317317

318+
bool enableSyncVoidMethods() override {
319+
static const auto method =
320+
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableSyncVoidMethods");
321+
return method(javaProvider_);
322+
}
323+
318324
bool enableViewCulling() override {
319325
static const auto method =
320326
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableViewCulling");
@@ -825,6 +831,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableSwiftUIBasedFilters(
825831
return ReactNativeFeatureFlags::enableSwiftUIBasedFilters();
826832
}
827833

834+
bool JReactNativeFeatureFlagsCxxInterop::enableSyncVoidMethods(
835+
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
836+
return ReactNativeFeatureFlags::enableSyncVoidMethods();
837+
}
838+
828839
bool JReactNativeFeatureFlagsCxxInterop::enableViewCulling(
829840
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
830841
return ReactNativeFeatureFlags::enableViewCulling();
@@ -1224,6 +1235,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
12241235
makeNativeMethod(
12251236
"enableSwiftUIBasedFilters",
12261237
JReactNativeFeatureFlagsCxxInterop::enableSwiftUIBasedFilters),
1238+
makeNativeMethod(
1239+
"enableSyncVoidMethods",
1240+
JReactNativeFeatureFlagsCxxInterop::enableSyncVoidMethods),
12271241
makeNativeMethod(
12281242
"enableViewCulling",
12291243
JReactNativeFeatureFlagsCxxInterop::enableViewCulling),

packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<2e867941f693c14c0c52475d790cfed4>>
7+
* @generated SignedSource<<4fa295306f59d64cbfe739fa68cdf7fa>>
88
*/
99

1010
/**
@@ -168,6 +168,9 @@ class JReactNativeFeatureFlagsCxxInterop
168168
static bool enableSwiftUIBasedFilters(
169169
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
170170

171+
static bool enableSyncVoidMethods(
172+
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
173+
171174
static bool enableViewCulling(
172175
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
173176

packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<9c49f2931ab219997bc29969de95805d>>
7+
* @generated SignedSource<<71a2b6b2ad1cfff01739580ab7a3e968>>
88
*/
99

1010
/**
@@ -210,6 +210,10 @@ bool ReactNativeFeatureFlags::enableSwiftUIBasedFilters() {
210210
return getAccessor().enableSwiftUIBasedFilters();
211211
}
212212

213+
bool ReactNativeFeatureFlags::enableSyncVoidMethods() {
214+
return getAccessor().enableSyncVoidMethods();
215+
}
216+
213217
bool ReactNativeFeatureFlags::enableViewCulling() {
214218
return getAccessor().enableViewCulling();
215219
}

packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<d15e79bbfac17a32fd7981538afc3683>>
7+
* @generated SignedSource<<b2ae844c39354903981ebb1b1ab700c4>>
88
*/
99

1010
/**
@@ -269,6 +269,11 @@ class ReactNativeFeatureFlags {
269269
*/
270270
RN_EXPORT static bool enableSwiftUIBasedFilters();
271271

272+
/**
273+
* When enabled, TurboModule methods with void return type will be invoked synchronously on the JS thread instead of being dispatched asynchronously. Only applies to pure TurboModules, not interop modules.
274+
*/
275+
RN_EXPORT static bool enableSyncVoidMethods();
276+
272277
/**
273278
* Enables View Culling: as soon as a view goes off screen, it can be reused anywhere in the UI and pieced together with other items to create new UI elements.
274279
*/

0 commit comments

Comments
 (0)