Back out "Throw exception with name of TurboModule instead of deadlock during sync rendering" (#49554)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/49554

For some reason, this diff completely breaks the linker on iOS.

I tried to look for a fix forward, but unsuccessfully.

I'm reverting this diff to get CI green again, but this requires more investigation.

## Changelog:
[Internal] - Revert D69805065

Reviewed By: sammy-SC, huntie

Differential Revision: D69920338

fbshipit-source-id: 8e1d34b5314d8ead51c127208ae2d2250f7d3724
This commit is contained in:
Riccardo Cipolleschi
2025-02-20 06:31:34 -08:00
committed by Facebook GitHub Bot
parent feb27cbf0f
commit 3eec4a3ea9
24 changed files with 31 additions and 210 deletions
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<99417ea22d1bf969d71388c600d42e85>>
* @generated SignedSource<<6e8144a48ab65f3b5ad8dd601cee2114>>
*/
/**
@@ -226,12 +226,6 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun lazyAnimationCallbacks(): Boolean = accessor.lazyAnimationCallbacks()
/**
* Throw an exception instead of deadlocking when a TurboModule that requires main queue setup is initialized during a synchronous render on iOS.
*/
@JvmStatic
public fun throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS(): Boolean = accessor.throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS()
/**
* Enables storing js caller stack when creating promise in native module. This is useful in case of Promise rejection and tracing the cause.
*/
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<3ede8912be1a2874050bab4c88a0a416>>
* @generated SignedSource<<dd2fa7d4fb722350d77094f8bcc38872>>
*/
/**
@@ -53,7 +53,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
private var fuseboxEnabledReleaseCache: Boolean? = null
private var fuseboxNetworkInspectionEnabledCache: Boolean? = null
private var lazyAnimationCallbacksCache: Boolean? = null
private var throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOSCache: Boolean? = null
private var traceTurboModulePromiseRejectionsOnAndroidCache: Boolean? = null
private var useAlwaysAvailableJSErrorHandlingCache: Boolean? = null
private var useEditTextStockAndroidFocusBehaviorCache: Boolean? = null
@@ -361,15 +360,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS(): Boolean {
var cached = throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOSCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS()
throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOSCache = cached
}
return cached
}
override fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean {
var cached = traceTurboModulePromiseRejectionsOnAndroidCache
if (cached == null) {
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<33adb23bfdb99c531c674f4c6d09ddbd>>
* @generated SignedSource<<eb52a136ba489460c2131105f4cc5b3f>>
*/
/**
@@ -94,8 +94,6 @@ public object ReactNativeFeatureFlagsCxxInterop {
@DoNotStrip @JvmStatic public external fun lazyAnimationCallbacks(): Boolean
@DoNotStrip @JvmStatic public external fun throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS(): Boolean
@DoNotStrip @JvmStatic public external fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean
@DoNotStrip @JvmStatic public external fun useAlwaysAvailableJSErrorHandling(): Boolean
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<94ffd31d788dae979b92c7a347f2ad40>>
* @generated SignedSource<<5315bd93234b8c00b7d029081231eeeb>>
*/
/**
@@ -89,8 +89,6 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun lazyAnimationCallbacks(): Boolean = false
override fun throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS(): Boolean = false
override fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean = false
override fun useAlwaysAvailableJSErrorHandling(): Boolean = false
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<15176fdf014740aa34039cfd82943ae2>>
* @generated SignedSource<<a97afc0515bcfc2e4ed60565af08ce8a>>
*/
/**
@@ -57,7 +57,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
private var fuseboxEnabledReleaseCache: Boolean? = null
private var fuseboxNetworkInspectionEnabledCache: Boolean? = null
private var lazyAnimationCallbacksCache: Boolean? = null
private var throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOSCache: Boolean? = null
private var traceTurboModulePromiseRejectionsOnAndroidCache: Boolean? = null
private var useAlwaysAvailableJSErrorHandlingCache: Boolean? = null
private var useEditTextStockAndroidFocusBehaviorCache: Boolean? = null
@@ -398,16 +397,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}
override fun throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS(): Boolean {
var cached = throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOSCache
if (cached == null) {
cached = currentProvider.throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS()
accessedFeatureFlags.add("throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS")
throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOSCache = cached
}
return cached
}
override fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean {
var cached = traceTurboModulePromiseRejectionsOnAndroidCache
if (cached == null) {
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<98ad5281b51418af43620a89a40a3c45>>
* @generated SignedSource<<51121a77716b7748f993496eff5f6bfb>>
*/
/**
@@ -89,8 +89,6 @@ public interface ReactNativeFeatureFlagsProvider {
@DoNotStrip public fun lazyAnimationCallbacks(): Boolean
@DoNotStrip public fun throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS(): Boolean
@DoNotStrip public fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean
@DoNotStrip public fun useAlwaysAvailableJSErrorHandling(): Boolean
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<b02f04930c4c998668d6ad522717f914>>
* @generated SignedSource<<b0dab4690bff769baf4e83f508a6e514>>
*/
/**
@@ -237,12 +237,6 @@ class ReactNativeFeatureFlagsProviderHolder
return method(javaProvider_);
}
bool throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS");
return method(javaProvider_);
}
bool traceTurboModulePromiseRejectionsOnAndroid() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("traceTurboModulePromiseRejectionsOnAndroid");
@@ -466,11 +460,6 @@ bool JReactNativeFeatureFlagsCxxInterop::lazyAnimationCallbacks(
return ReactNativeFeatureFlags::lazyAnimationCallbacks();
}
bool JReactNativeFeatureFlagsCxxInterop::throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS();
}
bool JReactNativeFeatureFlagsCxxInterop::traceTurboModulePromiseRejectionsOnAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::traceTurboModulePromiseRejectionsOnAndroid();
@@ -646,9 +635,6 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"lazyAnimationCallbacks",
JReactNativeFeatureFlagsCxxInterop::lazyAnimationCallbacks),
makeNativeMethod(
"throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS",
JReactNativeFeatureFlagsCxxInterop::throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS),
makeNativeMethod(
"traceTurboModulePromiseRejectionsOnAndroid",
JReactNativeFeatureFlagsCxxInterop::traceTurboModulePromiseRejectionsOnAndroid),
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<a34eb273660e3fecbc6d9fba66176462>>
* @generated SignedSource<<0bf1c23eda1c41a60eaae19e87c541e9>>
*/
/**
@@ -129,9 +129,6 @@ class JReactNativeFeatureFlagsCxxInterop
static bool lazyAnimationCallbacks(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool traceTurboModulePromiseRejectionsOnAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<5ea68e0bf3cbf7822d7a3e80f7dffc72>>
* @generated SignedSource<<0a3119b99e455127d8a404963a23eb96>>
*/
/**
@@ -158,10 +158,6 @@ bool ReactNativeFeatureFlags::lazyAnimationCallbacks() {
return getAccessor().lazyAnimationCallbacks();
}
bool ReactNativeFeatureFlags::throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS() {
return getAccessor().throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS();
}
bool ReactNativeFeatureFlags::traceTurboModulePromiseRejectionsOnAndroid() {
return getAccessor().traceTurboModulePromiseRejectionsOnAndroid();
}
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<9be3692ca63703f32de54e24d4ceb6e9>>
* @generated SignedSource<<b354e1b9ffc58e74ffff200c14728d1d>>
*/
/**
@@ -204,11 +204,6 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool lazyAnimationCallbacks();
/**
* Throw an exception instead of deadlocking when a TurboModule that requires main queue setup is initialized during a synchronous render on iOS.
*/
RN_EXPORT static bool throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS();
/**
* Enables storing js caller stack when creating promise in native module. This is useful in case of Promise rejection and tracing the cause.
*/
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<12be545f9fb06b76cb6c521e1d381bf1>>
* @generated SignedSource<<41f3b407b98e268ba80f8cd8bb960321>>
*/
/**
@@ -623,24 +623,6 @@ bool ReactNativeFeatureFlagsAccessor::lazyAnimationCallbacks() {
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS() {
auto flagValue = throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS_.load();
if (!flagValue.has_value()) {
// This block is not exclusive but it is not necessary.
// If multiple threads try to initialize the feature flag, we would only
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(33, "throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS");
flagValue = currentProvider_->throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS();
throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS_ = flagValue;
}
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::traceTurboModulePromiseRejectionsOnAndroid() {
auto flagValue = traceTurboModulePromiseRejectionsOnAndroid_.load();
@@ -650,7 +632,7 @@ bool ReactNativeFeatureFlagsAccessor::traceTurboModulePromiseRejectionsOnAndroid
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(34, "traceTurboModulePromiseRejectionsOnAndroid");
markFlagAsAccessed(33, "traceTurboModulePromiseRejectionsOnAndroid");
flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid();
traceTurboModulePromiseRejectionsOnAndroid_ = flagValue;
@@ -668,7 +650,7 @@ bool ReactNativeFeatureFlagsAccessor::useAlwaysAvailableJSErrorHandling() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(35, "useAlwaysAvailableJSErrorHandling");
markFlagAsAccessed(34, "useAlwaysAvailableJSErrorHandling");
flagValue = currentProvider_->useAlwaysAvailableJSErrorHandling();
useAlwaysAvailableJSErrorHandling_ = flagValue;
@@ -686,7 +668,7 @@ bool ReactNativeFeatureFlagsAccessor::useEditTextStockAndroidFocusBehavior() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(36, "useEditTextStockAndroidFocusBehavior");
markFlagAsAccessed(35, "useEditTextStockAndroidFocusBehavior");
flagValue = currentProvider_->useEditTextStockAndroidFocusBehavior();
useEditTextStockAndroidFocusBehavior_ = flagValue;
@@ -704,7 +686,7 @@ bool ReactNativeFeatureFlagsAccessor::useFabricInterop() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(37, "useFabricInterop");
markFlagAsAccessed(36, "useFabricInterop");
flagValue = currentProvider_->useFabricInterop();
useFabricInterop_ = flagValue;
@@ -722,7 +704,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(38, "useNativeViewConfigsInBridgelessMode");
markFlagAsAccessed(37, "useNativeViewConfigsInBridgelessMode");
flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode();
useNativeViewConfigsInBridgelessMode_ = flagValue;
@@ -740,7 +722,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimizedEventBatchingOnAndroid() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(39, "useOptimizedEventBatchingOnAndroid");
markFlagAsAccessed(38, "useOptimizedEventBatchingOnAndroid");
flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid();
useOptimizedEventBatchingOnAndroid_ = flagValue;
@@ -758,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::useRawPropsJsiValue() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(40, "useRawPropsJsiValue");
markFlagAsAccessed(39, "useRawPropsJsiValue");
flagValue = currentProvider_->useRawPropsJsiValue();
useRawPropsJsiValue_ = flagValue;
@@ -776,7 +758,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModuleInterop() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(41, "useTurboModuleInterop");
markFlagAsAccessed(40, "useTurboModuleInterop");
flagValue = currentProvider_->useTurboModuleInterop();
useTurboModuleInterop_ = flagValue;
@@ -794,7 +776,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModules() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(42, "useTurboModules");
markFlagAsAccessed(41, "useTurboModules");
flagValue = currentProvider_->useTurboModules();
useTurboModules_ = flagValue;
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<65caac2e749261ca919780dff302ef57>>
* @generated SignedSource<<cf03a6e938df9988c00249dc78576cbf>>
*/
/**
@@ -65,7 +65,6 @@ class ReactNativeFeatureFlagsAccessor {
bool fuseboxEnabledRelease();
bool fuseboxNetworkInspectionEnabled();
bool lazyAnimationCallbacks();
bool throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS();
bool traceTurboModulePromiseRejectionsOnAndroid();
bool useAlwaysAvailableJSErrorHandling();
bool useEditTextStockAndroidFocusBehavior();
@@ -86,7 +85,7 @@ class ReactNativeFeatureFlagsAccessor {
std::unique_ptr<ReactNativeFeatureFlagsProvider> currentProvider_;
bool wasOverridden_;
std::array<std::atomic<const char*>, 43> accessedFeatureFlags_;
std::array<std::atomic<const char*>, 42> accessedFeatureFlags_;
std::atomic<std::optional<bool>> commonTestFlag_;
std::atomic<std::optional<bool>> disableMountItemReorderingAndroid_;
@@ -121,7 +120,6 @@ class ReactNativeFeatureFlagsAccessor {
std::atomic<std::optional<bool>> fuseboxEnabledRelease_;
std::atomic<std::optional<bool>> fuseboxNetworkInspectionEnabled_;
std::atomic<std::optional<bool>> lazyAnimationCallbacks_;
std::atomic<std::optional<bool>> throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS_;
std::atomic<std::optional<bool>> traceTurboModulePromiseRejectionsOnAndroid_;
std::atomic<std::optional<bool>> useAlwaysAvailableJSErrorHandling_;
std::atomic<std::optional<bool>> useEditTextStockAndroidFocusBehavior_;
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<acc0b73730fe5e0a8e329735481bc579>>
* @generated SignedSource<<1ade51e6e5c82275c5c01b72df630eee>>
*/
/**
@@ -159,10 +159,6 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
return false;
}
bool throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS() override {
return false;
}
bool traceTurboModulePromiseRejectionsOnAndroid() override {
return false;
}
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<c36182568c56dd82ef777bc477a9a4fe>>
* @generated SignedSource<<95aa462c1a48b2299c2a82adf74c58df>>
*/
/**
@@ -342,15 +342,6 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef
return ReactNativeFeatureFlagsDefaults::lazyAnimationCallbacks();
}
bool throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS() override {
auto value = values_["throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS"];
if (!value.isNull()) {
return value.getBool();
}
return ReactNativeFeatureFlagsDefaults::throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS();
}
bool traceTurboModulePromiseRejectionsOnAndroid() override {
auto value = values_["traceTurboModulePromiseRejectionsOnAndroid"];
if (!value.isNull()) {
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<716d5779133c4ee8c9d20e4a71065d59>>
* @generated SignedSource<<f3241de0ced5e6ea54e6debf2a453c36>>
*/
/**
@@ -58,7 +58,6 @@ class ReactNativeFeatureFlagsProvider {
virtual bool fuseboxEnabledRelease() = 0;
virtual bool fuseboxNetworkInspectionEnabled() = 0;
virtual bool lazyAnimationCallbacks() = 0;
virtual bool throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS() = 0;
virtual bool traceTurboModulePromiseRejectionsOnAndroid() = 0;
virtual bool useAlwaysAvailableJSErrorHandling() = 0;
virtual bool useEditTextStockAndroidFocusBehavior() = 0;
@@ -34,7 +34,7 @@ Pod::Spec.new do |s|
s.platforms = min_supported_versions
s.source = source
s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags
s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/fast_float/include\" \"$(PODS_ROOT)/fmt/include\" \"$(PODS_ROOT)/Headers/Private/React-Core\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-debug/React_featureflags.framework/Headers\"",
s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/fast_float/include\" \"$(PODS_ROOT)/fmt/include\" \"$(PODS_ROOT)/Headers/Private/React-Core\"",
"USE_HEADERMAP" => "YES",
"CLANG_CXX_LANGUAGE_STANDARD" => rct_cxx_language_standard(),
"GCC_WARN_PEDANTIC" => "YES" }
@@ -51,7 +51,6 @@ Pod::Spec.new do |s|
s.dependency "React-Core"
s.dependency "React-cxxreact"
s.dependency "React-jsi"
s.dependency "React-featureflags"
s.dependency "React-runtimeexecutor"
add_dependency(s, "React-jsinspector", :framework_name => 'jsinspector_modern')
@@ -29,11 +29,9 @@
#import <React/RCTUtils.h>
#import <ReactCommon/CxxTurboModuleUtils.h>
#import <ReactCommon/RCTTurboModuleWithJSIBindings.h>
#import <ReactCommon/RuntimeExecutor.h>
#import <ReactCommon/TurboCxxModule.h>
#import <ReactCommon/TurboModulePerfLogger.h>
#import <ReactCommon/TurboModuleUtils.h>
#import <react/featureflags/ReactNativeFeatureFlags.h>
using namespace facebook;
using namespace facebook::react;
@@ -576,35 +574,7 @@ typedef struct {
};
if ([self _requiresMainQueueSetup:moduleClass]) {
if (ReactNativeFeatureFlags::throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS()) {
static int32_t modulesSettingUpOnMainQueueCount = 0;
bool needsUnlock = NO;
// This function can be recursive. If it's called recursively, we need to skip the lock.
// We can't use a recursive mutex instead because the lock is needed on multiple threads.
if (modulesSettingUpOnMainQueueCount == 0) {
if (!facebook::react::getMainThreadMutex()->try_lock()) {
NSString *reason = [NSString
stringWithFormat:
@"TurboModule %@ which requires main queue setup is initializing during sync rendering. This would have caused a deadlock. Please fix this by avoiding main queue setup or eager initializing this TurboModule.",
NSStringFromClass(moduleClass)];
NSException *exception = [NSException exceptionWithName:@"UnsafeTurboModuleException"
reason:reason
userInfo:nil];
@throw exception;
}
needsUnlock = true;
}
modulesSettingUpOnMainQueueCount++;
RCTUnsafeExecuteOnMainQueueSync(work);
modulesSettingUpOnMainQueueCount--;
if (needsUnlock) {
facebook::react::getMainThreadMutex()->unlock();
}
} else {
RCTUnsafeExecuteOnMainQueueSync(work);
}
RCTUnsafeExecuteOnMainQueueSync(work);
} else {
work();
}
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<f6c8f26ac2c00989c489cde342384a99>>
* @generated SignedSource<<9a4f0e72b7e6518347f65253c018220a>>
*/
/**
@@ -209,11 +209,6 @@ bool NativeReactNativeFeatureFlags::lazyAnimationCallbacks(
return ReactNativeFeatureFlags::lazyAnimationCallbacks();
}
bool NativeReactNativeFeatureFlags::throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS();
}
bool NativeReactNativeFeatureFlags::traceTurboModulePromiseRejectionsOnAndroid(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::traceTurboModulePromiseRejectionsOnAndroid();
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<805e70470028c1a98ef49e6aaf18fd03>>
* @generated SignedSource<<16deece14930c9b259f6f7594127fe55>>
*/
/**
@@ -103,8 +103,6 @@ class NativeReactNativeFeatureFlags
bool lazyAnimationCallbacks(jsi::Runtime& runtime);
bool throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS(jsi::Runtime& runtime);
bool traceTurboModulePromiseRejectionsOnAndroid(jsi::Runtime& runtime);
bool useAlwaysAvailableJSErrorHandling(jsi::Runtime& runtime);
@@ -1,17 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "RuntimeExecutor.h"
namespace facebook::react {
std::mutex* getMainThreadMutex() {
static std::mutex mainThreadMutex;
return &mainThreadMutex;
}
} // namespace facebook::react
@@ -14,8 +14,6 @@
namespace facebook::react {
std::mutex* getMainThreadMutex();
/*
* Takes a function and calls it with a reference to a Runtime. The function
* will be called when it is safe to do so (i.e. it ensures non-concurrent
@@ -33,16 +31,6 @@ using RuntimeExecutor =
* Use this method when the caller needs to *be blocked* by executing the
* `callback` and requires that the callback will be executed on the same
* thread.
* Example order of events (when not a sync call in runtimeExecutor callback):
* - [UI thread] Lock all mutexes at start
* - [UI thread] mutex1.lock before callback
* - [JS thread] Set runtimePtr in runtimeExecutor callback
* - [JS thread] mutex1.unlock in runtimeExecutor callback
* - [UI thread] Call callback
* - [JS thread] mutex2.lock in runtimeExecutor callback
* - [UI thread] mutex2.unlock after callback
* - [UI thread] mutex3.lock after callback
* - [JS thread] mutex3.unlock in runtimeExecutor callback
*/
inline static void executeSynchronouslyOnSameThread_CAN_DEADLOCK(
const RuntimeExecutor& runtimeExecutor,
@@ -54,7 +42,6 @@ inline static void executeSynchronouslyOnSameThread_CAN_DEADLOCK(
std::mutex mutex2;
std::mutex mutex3;
getMainThreadMutex()->lock();
mutex1.lock();
mutex2.lock();
mutex3.lock();
@@ -83,7 +70,6 @@ inline static void executeSynchronouslyOnSameThread_CAN_DEADLOCK(
callback(*runtimePtr);
mutex2.unlock();
mutex3.lock();
getMainThreadMutex()->unlock();
}
template <typename DataT>
@@ -398,17 +398,6 @@ const definitions: FeatureFlagDefinitions = {
},
ossReleaseStage: 'none',
},
throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS: {
defaultValue: false,
metadata: {
dateAdded: '2025-02-18',
description:
'Throw an exception instead of deadlocking when a TurboModule that requires main queue setup is initialized during a synchronous render on iOS.',
expectedReleaseValue: true,
purpose: 'experimentation',
},
ossReleaseStage: 'none',
},
traceTurboModulePromiseRejectionsOnAndroid: {
defaultValue: false,
metadata: {
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<a8dd33d3160b800bc7afa18045e3ac7a>>
* @generated SignedSource<<4bdedb6bbe2199cb99e72e86bfffe372>>
* @flow strict
*/
@@ -82,7 +82,6 @@ export type ReactNativeFeatureFlags = $ReadOnly<{
fuseboxEnabledRelease: Getter<boolean>,
fuseboxNetworkInspectionEnabled: Getter<boolean>,
lazyAnimationCallbacks: Getter<boolean>,
throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS: Getter<boolean>,
traceTurboModulePromiseRejectionsOnAndroid: Getter<boolean>,
useAlwaysAvailableJSErrorHandling: Getter<boolean>,
useEditTextStockAndroidFocusBehavior: Getter<boolean>,
@@ -305,10 +304,6 @@ export const fuseboxNetworkInspectionEnabled: Getter<boolean> = createNativeFlag
* Only enqueue Choreographer calls if there is an ongoing animation, instead of enqueueing every frame.
*/
export const lazyAnimationCallbacks: Getter<boolean> = createNativeFlagGetter('lazyAnimationCallbacks', false);
/**
* Throw an exception instead of deadlocking when a TurboModule that requires main queue setup is initialized during a synchronous render on iOS.
*/
export const throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS: Getter<boolean> = createNativeFlagGetter('throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS', false);
/**
* Enables storing js caller stack when creating promise in native module. This is useful in case of Promise rejection and tracing the cause.
*/
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<f6bbbe19810cafad5142bf528f04165a>>
* @generated SignedSource<<06a03507366a38dfc43868e94d75fcf1>>
* @flow strict
*/
@@ -57,7 +57,6 @@ export interface Spec extends TurboModule {
+fuseboxEnabledRelease?: () => boolean;
+fuseboxNetworkInspectionEnabled?: () => boolean;
+lazyAnimationCallbacks?: () => boolean;
+throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS?: () => boolean;
+traceTurboModulePromiseRejectionsOnAndroid?: () => boolean;
+useAlwaysAvailableJSErrorHandling?: () => boolean;
+useEditTextStockAndroidFocusBehavior?: () => boolean;