Skip to content

Commit aad41b4

Browse files
christophpurrermeta-codesync[bot]
authored andcommitted
Enable synchronous void method invocations via feature flag - RFC (#56740)
Summary: Pull Request resolved: #56740 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 ab8b40d commit aad41b4

30 files changed

Lines changed: 242 additions & 77 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<<4342ccb696b4123b9d463a31c024b9bc>>
7+
* @generated SignedSource<<4b2133f0c7c9b0a7ef37e9b928faad64>>
88
*/
99

1010
/**
@@ -300,6 +300,12 @@ public object ReactNativeFeatureFlags {
300300
@JvmStatic
301301
public fun enableSwiftUIBasedFilters(): Boolean = accessor.enableSwiftUIBasedFilters()
302302

303+
/**
304+
* 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.
305+
*/
306+
@JvmStatic
307+
public fun enableSyncVoidMethods(): Boolean = accessor.enableSyncVoidMethods()
308+
303309
/**
304310
* 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.
305311
*/

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<<ec375fbc64b2b2b8995c1640a0369923>>
7+
* @generated SignedSource<<65e4bd35f7b92d56d1b26176b8c08b90>>
88
*/
99

1010
/**
@@ -65,6 +65,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
6565
private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null
6666
private var enableSchedulerDelegateInvalidationCache: Boolean? = null
6767
private var enableSwiftUIBasedFiltersCache: Boolean? = null
68+
private var enableSyncVoidMethodsCache: Boolean? = null
6869
private var enableViewCullingCache: Boolean? = null
6970
private var enableViewRecyclingCache: Boolean? = null
7071
private var enableViewRecyclingForImageCache: Boolean? = null
@@ -518,6 +519,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
518519
return cached
519520
}
520521

522+
override fun enableSyncVoidMethods(): Boolean {
523+
var cached = enableSyncVoidMethodsCache
524+
if (cached == null) {
525+
cached = ReactNativeFeatureFlagsCxxInterop.enableSyncVoidMethods()
526+
enableSyncVoidMethodsCache = cached
527+
}
528+
return cached
529+
}
530+
521531
override fun enableViewCulling(): Boolean {
522532
var cached = enableViewCullingCache
523533
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<<81989dbed82df7bd963d8023c595ff44>>
7+
* @generated SignedSource<<9cc7f5ffd7c0951db9bbf397e96aa83d>>
88
*/
99

1010
/**
@@ -118,6 +118,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
118118

119119
@DoNotStrip @JvmStatic public external fun enableSwiftUIBasedFilters(): Boolean
120120

121+
@DoNotStrip @JvmStatic public external fun enableSyncVoidMethods(): Boolean
122+
121123
@DoNotStrip @JvmStatic public external fun enableViewCulling(): Boolean
122124

123125
@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<<93e83fb3dc9577acd9678803321e0fe1>>
7+
* @generated SignedSource<<2efb60076f46168bacb0cf064cc574b9>>
88
*/
99

1010
/**
@@ -113,6 +113,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
113113

114114
override fun enableSwiftUIBasedFilters(): Boolean = false
115115

116+
override fun enableSyncVoidMethods(): Boolean = false
117+
116118
override fun enableViewCulling(): Boolean = false
117119

118120
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<<9d07e8adeee69583b788069649306d8e>>
7+
* @generated SignedSource<<9481147f7c9af5ba0c2c3c3f609f7050>>
88
*/
99

1010
/**
@@ -69,6 +69,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
6969
private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null
7070
private var enableSchedulerDelegateInvalidationCache: Boolean? = null
7171
private var enableSwiftUIBasedFiltersCache: Boolean? = null
72+
private var enableSyncVoidMethodsCache: Boolean? = null
7273
private var enableViewCullingCache: Boolean? = null
7374
private var enableViewRecyclingCache: Boolean? = null
7475
private var enableViewRecyclingForImageCache: Boolean? = null
@@ -567,6 +568,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
567568
return cached
568569
}
569570

571+
override fun enableSyncVoidMethods(): Boolean {
572+
var cached = enableSyncVoidMethodsCache
573+
if (cached == null) {
574+
cached = currentProvider.enableSyncVoidMethods()
575+
accessedFeatureFlags.add("enableSyncVoidMethods")
576+
enableSyncVoidMethodsCache = cached
577+
}
578+
return cached
579+
}
580+
570581
override fun enableViewCulling(): Boolean {
571582
var cached = enableViewCullingCache
572583
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<<bcc599e04e3672d4bff293e267b3efa2>>
7+
* @generated SignedSource<<ccd35df7079700d8e7dc95e8fac53039>>
88
*/
99

1010
/**
@@ -113,6 +113,8 @@ public interface ReactNativeFeatureFlagsProvider {
113113

114114
@DoNotStrip public fun enableSwiftUIBasedFilters(): Boolean
115115

116+
@DoNotStrip public fun enableSyncVoidMethods(): Boolean
117+
116118
@DoNotStrip public fun enableViewCulling(): Boolean
117119

118120
@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<<32c8c18771d6690f50d60dbc8e3d07e2>>
7+
* @generated SignedSource<<f8fe31da669d498efb3d3b580ee57853>>
88
*/
99

1010
/**
@@ -309,6 +309,12 @@ class ReactNativeFeatureFlagsJavaProvider
309309
return method(javaProvider_);
310310
}
311311

312+
bool enableSyncVoidMethods() override {
313+
static const auto method =
314+
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableSyncVoidMethods");
315+
return method(javaProvider_);
316+
}
317+
312318
bool enableViewCulling() override {
313319
static const auto method =
314320
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableViewCulling");
@@ -820,6 +826,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableSwiftUIBasedFilters(
820826
return ReactNativeFeatureFlags::enableSwiftUIBasedFilters();
821827
}
822828

829+
bool JReactNativeFeatureFlagsCxxInterop::enableSyncVoidMethods(
830+
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
831+
return ReactNativeFeatureFlags::enableSyncVoidMethods();
832+
}
833+
823834
bool JReactNativeFeatureFlagsCxxInterop::enableViewCulling(
824835
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
825836
return ReactNativeFeatureFlags::enableViewCulling();
@@ -1221,6 +1232,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
12211232
makeNativeMethod(
12221233
"enableSwiftUIBasedFilters",
12231234
JReactNativeFeatureFlagsCxxInterop::enableSwiftUIBasedFilters),
1235+
makeNativeMethod(
1236+
"enableSyncVoidMethods",
1237+
JReactNativeFeatureFlagsCxxInterop::enableSyncVoidMethods),
12241238
makeNativeMethod(
12251239
"enableViewCulling",
12261240
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<<aacbc520b40625dbdba328590cc78112>>
7+
* @generated SignedSource<<ea2ed97e3e835c1fc96dd4d50daef879>>
88
*/
99

1010
/**
@@ -165,6 +165,9 @@ class JReactNativeFeatureFlagsCxxInterop
165165
static bool enableSwiftUIBasedFilters(
166166
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
167167

168+
static bool enableSyncVoidMethods(
169+
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
170+
168171
static bool enableViewCulling(
169172
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
170173

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<<483ac339c0d636c85f4639c60982c504>>
7+
* @generated SignedSource<<e32e9b6fc8c8872a64a2a5f53ce20a60>>
88
*/
99

1010
/**
@@ -206,6 +206,10 @@ bool ReactNativeFeatureFlags::enableSwiftUIBasedFilters() {
206206
return getAccessor().enableSwiftUIBasedFilters();
207207
}
208208

209+
bool ReactNativeFeatureFlags::enableSyncVoidMethods() {
210+
return getAccessor().enableSyncVoidMethods();
211+
}
212+
209213
bool ReactNativeFeatureFlags::enableViewCulling() {
210214
return getAccessor().enableViewCulling();
211215
}

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<<771a335070649f38cb559a95d80947aa>>
7+
* @generated SignedSource<<7d77e761aea48d71ac2f19195bbedced>>
88
*/
99

1010
/**
@@ -264,6 +264,11 @@ class ReactNativeFeatureFlags {
264264
*/
265265
RN_EXPORT static bool enableSwiftUIBasedFilters();
266266

267+
/**
268+
* 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.
269+
*/
270+
RN_EXPORT static bool enableSyncVoidMethods();
271+
267272
/**
268273
* 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.
269274
*/

0 commit comments

Comments
 (0)