Skip to content

Commit d0672fb

Browse files
fkgozalimeta-codesync[bot]
authored andcommitted
Add enableSchedulerDelegateInvalidation feature flag (#56678)
Summary: Pull Request resolved: #56678 Introduces a new common React Native feature flag, `enableSchedulerDelegateInvalidation`, that gates a defensive guard around `Scheduler::uiManagerDidDispatchCommand` and `uiManagerDidFinishTransaction`. Those call sites enqueue a lambda via `runtimeScheduler_->scheduleRenderingUpdate` that captures the raw `SchedulerDelegate` pointer by value. With `RuntimeScheduler_Modern` (bridgeless) the lambda runs asynchronously, so if the `SchedulerDelegate` is destroyed between enqueue and execution the lambda dereferences dangling memory and the process crashes (`EXC_BAD_ACCESS` / `KERN_INVALID_ADDRESS`). The follow-up commit adds the actual guard wired to this flag. Defaults to `false` so behavior is unchanged on landing. Apps opt in by overriding the flag in their own `ReactNativeFeatureFlagsDefaults` subclass. Includes the regenerated feature-flag boilerplate (Kotlin/Java/Cxx accessors, defaults, providers, JS spec, native module) emitted by `yarn featureflags --update`. Changelog: [Internal] Reviewed By: shwanton Differential Revision: D103757271 fbshipit-source-id: 85991de4a21e3946a25571b6488bee9c0a4e1caf
1 parent 52ff392 commit d0672fb

22 files changed

Lines changed: 192 additions & 69 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<<c9be40b9d016463d1531057598a6aa88>>
7+
* @generated SignedSource<<1eca66b21554b00725f2a9be894a0db9>>
88
*/
99

1010
/**
@@ -294,6 +294,12 @@ public object ReactNativeFeatureFlags {
294294
@JvmStatic
295295
public fun enablePropsUpdateReconciliationAndroid(): Boolean = accessor.enablePropsUpdateReconciliationAndroid()
296296

297+
/**
298+
* Gates a defensive guard around Scheduler::uiManagerDidDispatchCommand and uiManagerDidFinishTransaction that prevents queued rendering-update lambdas from dereferencing the SchedulerDelegate after it has been destroyed (use-after-free).
299+
*/
300+
@JvmStatic
301+
public fun enableSchedulerDelegateInvalidation(): Boolean = accessor.enableSchedulerDelegateInvalidation()
302+
297303
/**
298304
* When enabled, it will use SwiftUI for filter effects like blur on iOS.
299305
*/

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<<d07f1b96cf6e0a1798f86fc9f61caf73>>
7+
* @generated SignedSource<<76d977ea53cb2a37fc2ea8549e31cebd>>
88
*/
99

1010
/**
@@ -64,6 +64,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
6464
private var enableNetworkEventReportingCache: Boolean? = null
6565
private var enablePreparedTextLayoutCache: Boolean? = null
6666
private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null
67+
private var enableSchedulerDelegateInvalidationCache: Boolean? = null
6768
private var enableSwiftUIBasedFiltersCache: Boolean? = null
6869
private var enableViewCullingCache: Boolean? = null
6970
private var enableViewRecyclingCache: Boolean? = null
@@ -508,6 +509,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
508509
return cached
509510
}
510511

512+
override fun enableSchedulerDelegateInvalidation(): Boolean {
513+
var cached = enableSchedulerDelegateInvalidationCache
514+
if (cached == null) {
515+
cached = ReactNativeFeatureFlagsCxxInterop.enableSchedulerDelegateInvalidation()
516+
enableSchedulerDelegateInvalidationCache = cached
517+
}
518+
return cached
519+
}
520+
511521
override fun enableSwiftUIBasedFilters(): Boolean {
512522
var cached = enableSwiftUIBasedFiltersCache
513523
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<<d9aa2a16720aa9fd4378c0c14e4f8ffa>>
7+
* @generated SignedSource<<a737810bf0211590401c2afb464aaf37>>
88
*/
99

1010
/**
@@ -116,6 +116,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
116116

117117
@DoNotStrip @JvmStatic public external fun enablePropsUpdateReconciliationAndroid(): Boolean
118118

119+
@DoNotStrip @JvmStatic public external fun enableSchedulerDelegateInvalidation(): Boolean
120+
119121
@DoNotStrip @JvmStatic public external fun enableSwiftUIBasedFilters(): Boolean
120122

121123
@DoNotStrip @JvmStatic public external fun enableViewCulling(): 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<<54a4f6d01a052e5ab19b15652d5ab1a5>>
7+
* @generated SignedSource<<9e5b3192d1bec953c116d959ad63283d>>
88
*/
99

1010
/**
@@ -111,6 +111,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
111111

112112
override fun enablePropsUpdateReconciliationAndroid(): Boolean = false
113113

114+
override fun enableSchedulerDelegateInvalidation(): Boolean = false
115+
114116
override fun enableSwiftUIBasedFilters(): Boolean = false
115117

116118
override fun enableViewCulling(): 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<<4d09d820304f454bc3850da89087caec>>
7+
* @generated SignedSource<<378d6a8de497d26ebbbf55885be27a21>>
88
*/
99

1010
/**
@@ -68,6 +68,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
6868
private var enableNetworkEventReportingCache: Boolean? = null
6969
private var enablePreparedTextLayoutCache: Boolean? = null
7070
private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null
71+
private var enableSchedulerDelegateInvalidationCache: Boolean? = null
7172
private var enableSwiftUIBasedFiltersCache: Boolean? = null
7273
private var enableViewCullingCache: Boolean? = null
7374
private var enableViewRecyclingCache: Boolean? = null
@@ -556,6 +557,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
556557
return cached
557558
}
558559

560+
override fun enableSchedulerDelegateInvalidation(): Boolean {
561+
var cached = enableSchedulerDelegateInvalidationCache
562+
if (cached == null) {
563+
cached = currentProvider.enableSchedulerDelegateInvalidation()
564+
accessedFeatureFlags.add("enableSchedulerDelegateInvalidation")
565+
enableSchedulerDelegateInvalidationCache = cached
566+
}
567+
return cached
568+
}
569+
559570
override fun enableSwiftUIBasedFilters(): Boolean {
560571
var cached = enableSwiftUIBasedFiltersCache
561572
if (cached == null) {

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android.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<<187ac62197545fbce9d537527b4aed3b>>
7+
* @generated SignedSource<<6a5fd95dffcab319acb765aa25a33d8d>>
88
*/
99

1010
/**
@@ -27,6 +27,8 @@ public open class ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android :
2727

2828
override fun enableAccessibilityOrder(): Boolean = true
2929

30+
override fun enableSchedulerDelegateInvalidation(): Boolean = true
31+
3032
override fun enableSwiftUIBasedFilters(): Boolean = true
3133

3234
override fun preventShadowTreeCommitExhaustion(): Boolean = true

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<<592acf445c4b4e56651cd6afb57e46fa>>
7+
* @generated SignedSource<<42e555a40da280b24f84e3ee5b45051d>>
88
*/
99

1010
/**
@@ -111,6 +111,8 @@ public interface ReactNativeFeatureFlagsProvider {
111111

112112
@DoNotStrip public fun enablePropsUpdateReconciliationAndroid(): Boolean
113113

114+
@DoNotStrip public fun enableSchedulerDelegateInvalidation(): Boolean
115+
114116
@DoNotStrip public fun enableSwiftUIBasedFilters(): Boolean
115117

116118
@DoNotStrip public fun enableViewCulling(): 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<<55e4d6d6dc930b4ccf3e20cb77f7a042>>
7+
* @generated SignedSource<<d9ed25122f1ff64122bfc83f8e5e9545>>
88
*/
99

1010
/**
@@ -303,6 +303,12 @@ class ReactNativeFeatureFlagsJavaProvider
303303
return method(javaProvider_);
304304
}
305305

306+
bool enableSchedulerDelegateInvalidation() override {
307+
static const auto method =
308+
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableSchedulerDelegateInvalidation");
309+
return method(javaProvider_);
310+
}
311+
306312
bool enableSwiftUIBasedFilters() override {
307313
static const auto method =
308314
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableSwiftUIBasedFilters");
@@ -809,6 +815,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enablePropsUpdateReconciliationAndroid(
809815
return ReactNativeFeatureFlags::enablePropsUpdateReconciliationAndroid();
810816
}
811817

818+
bool JReactNativeFeatureFlagsCxxInterop::enableSchedulerDelegateInvalidation(
819+
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
820+
return ReactNativeFeatureFlags::enableSchedulerDelegateInvalidation();
821+
}
822+
812823
bool JReactNativeFeatureFlagsCxxInterop::enableSwiftUIBasedFilters(
813824
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
814825
return ReactNativeFeatureFlags::enableSwiftUIBasedFilters();
@@ -1207,6 +1218,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
12071218
makeNativeMethod(
12081219
"enablePropsUpdateReconciliationAndroid",
12091220
JReactNativeFeatureFlagsCxxInterop::enablePropsUpdateReconciliationAndroid),
1221+
makeNativeMethod(
1222+
"enableSchedulerDelegateInvalidation",
1223+
JReactNativeFeatureFlagsCxxInterop::enableSchedulerDelegateInvalidation),
12101224
makeNativeMethod(
12111225
"enableSwiftUIBasedFilters",
12121226
JReactNativeFeatureFlagsCxxInterop::enableSwiftUIBasedFilters),

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<<f1db4e44d0b5d3daa11aec0e6a83e09f>>
7+
* @generated SignedSource<<d87a80a2a88acb2187ea20b8181a7588>>
88
*/
99

1010
/**
@@ -162,6 +162,9 @@ class JReactNativeFeatureFlagsCxxInterop
162162
static bool enablePropsUpdateReconciliationAndroid(
163163
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
164164

165+
static bool enableSchedulerDelegateInvalidation(
166+
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
167+
165168
static bool enableSwiftUIBasedFilters(
166169
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
167170

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<<16024bed6914b4b74d4a50de142e872a>>
7+
* @generated SignedSource<<ad7a835ef9cbe3a9a6121ac127038668>>
88
*/
99

1010
/**
@@ -202,6 +202,10 @@ bool ReactNativeFeatureFlags::enablePropsUpdateReconciliationAndroid() {
202202
return getAccessor().enablePropsUpdateReconciliationAndroid();
203203
}
204204

205+
bool ReactNativeFeatureFlags::enableSchedulerDelegateInvalidation() {
206+
return getAccessor().enableSchedulerDelegateInvalidation();
207+
}
208+
205209
bool ReactNativeFeatureFlags::enableSwiftUIBasedFilters() {
206210
return getAccessor().enableSwiftUIBasedFilters();
207211
}

0 commit comments

Comments
 (0)