diff --git a/packages/react-native/React/Base/RCTUtils.h b/packages/react-native/React/Base/RCTUtils.h index d4459badcea009..2de1c02f223ad7 100644 --- a/packages/react-native/React/Base/RCTUtils.h +++ b/packages/react-native/React/Base/RCTUtils.h @@ -49,7 +49,7 @@ RCT_EXTERN void RCTExecuteOnMainQueue(dispatch_block_t block); // Legacy function to execute the specified block on the main queue synchronously. // Please do not use this unless you know what you're doing. RCT_EXTERN void RCTUnsafeExecuteOnMainQueueSync(dispatch_block_t block); -RCT_EXTERN void RCTUnsafeExecuteOnMainQueueSyncWithError(dispatch_block_t block, NSString *context); +RCT_EXTERN void RCTUnsafeExecuteOnMainQueueSyncWithError(dispatch_block_t block, NSString *_Nullable context); // Get screen metrics in a thread-safe way RCT_EXTERN CGFloat RCTScreenScale(void); diff --git a/packages/react-native/React/Base/RCTUtils.mm b/packages/react-native/React/Base/RCTUtils.mm index 97330a33caf176..6ff52ae1c40fb5 100644 --- a/packages/react-native/React/Base/RCTUtils.mm +++ b/packages/react-native/React/Base/RCTUtils.mm @@ -299,32 +299,27 @@ void RCTExecuteOnMainQueue(dispatch_block_t block) // unless you know what you are doing. void RCTUnsafeExecuteOnMainQueueSync(dispatch_block_t block) { - if (RCTIsMainQueue()) { - block(); - } else { - if (facebook::react::ReactNativeFeatureFlags::disableMainQueueSyncDispatchIOS()) { - RCTLogError(@"RCTUnsafeExecuteOnMainQueueSync: Sync dispatches to the main queue can deadlock React Native."); - } - dispatch_sync(dispatch_get_main_queue(), ^{ - block(); - }); - } + RCTUnsafeExecuteOnMainQueueSyncWithError(block, nil); } // Please do not use this method // unless you know what you are doing. -void RCTUnsafeExecuteOnMainQueueSyncWithError(dispatch_block_t block, NSString *context) +void RCTUnsafeExecuteOnMainQueueSyncWithError(dispatch_block_t block, NSString *_Nullable context) { if (RCTIsMainQueue()) { block(); - } else { - if (facebook::react::ReactNativeFeatureFlags::disableMainQueueSyncDispatchIOS()) { - RCTLogError(@"RCTUnsafeExecuteOnMainQueueSync: %@", context); - } - dispatch_sync(dispatch_get_main_queue(), ^{ - block(); - }); + return; } + + if (facebook::react::ReactNativeFeatureFlags::disableMainQueueSyncDispatchIOS()) { + RCTLogError( + @"RCTUnsafeExecuteOnMainQueueSync: %@", + context ?: @"Sync dispatches to the main queue can deadlock React Native."); + } + + dispatch_sync(dispatch_get_main_queue(), ^{ + block(); + }); } static void RCTUnsafeExecuteOnMainQueueOnceSync(dispatch_once_t *onceToken, dispatch_block_t block) @@ -332,19 +327,24 @@ static void RCTUnsafeExecuteOnMainQueueOnceSync(dispatch_once_t *onceToken, disp // The solution was borrowed from a post by Sophie Alpert: // https://sophiebits.com/2014/04/02/dispatch-once-initialization-on-the-main-thread // See also: https://www.mikeash.com/pyblog/friday-qa-2014-06-06-secrets-of-dispatch_once.html - if (RCTIsMainQueue()) { + auto executeOnce = ^{ dispatch_once(onceToken, block); - } else { - if (DISPATCH_EXPECT(*onceToken == 0L, NO)) { - if (facebook::react::ReactNativeFeatureFlags::disableMainQueueSyncDispatchIOS()) { - RCTLogError( - @"RCTUnsafeExecuteOnMainQueueOnceSync: Sync dispatches to the main queue can deadlock React Native."); - } - dispatch_sync(dispatch_get_main_queue(), ^{ - dispatch_once(onceToken, block); - }); - } + }; + + if (RCTIsMainQueue()) { + executeOnce(); + return; + } + + if (!DISPATCH_EXPECT(*onceToken == 0L, NO)) { + return; + } + + if (facebook::react::ReactNativeFeatureFlags::disableMainQueueSyncDispatchIOS()) { + RCTLogError(@"RCTUnsafeExecuteOnMainQueueOnceSync: Sync dispatches to the main queue can deadlock React Native."); } + + dispatch_sync(dispatch_get_main_queue(), executeOnce); } CGFloat RCTScreenScale(void)