From 4adef35e97f31db466e536aa21d5eeec6ee34fc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwas=CC=81niewski?= Date: Fri, 8 Mar 2024 04:53:42 -0800 Subject: [PATCH] fix(iOS) [0.74]: RCTRedBox not appearing in Bridgeless when metro is not running (#43147) Summary: When testing out `0.74.0-rc0` I found that when the metro is not running we are not displaying RedBox which bumps users to start the packager and reload the app. It also fixes the case where users try to reload by clicking the "Reload" button on RedBox. ## Before https://github.com/facebook/react-native/assets/52801365/086c557f-ea1f-4a97-b4c7-df8a945cc7a0 ## After https://github.com/facebook/react-native/assets/52801365/9f8421b3-5e83-466f-8cdb-38f97981275d ## Changelog: [IOS] [FIXED] - RCTRedBox not appearing in Bridgeless when metro is not running Pull Request resolved: https://github.com/facebook/react-native/pull/43147 Test Plan: Build the app without metro running check if RedBox is shown Reviewed By: javache Differential Revision: D54632056 Pulled By: dmytrorykun fbshipit-source-id: fb6742898d3bd82545bfffd9175208e1a5984cb6 --- .../React/CoreModules/RCTRedBox.mm | 8 +++- .../platform/ios/ReactCommon/RCTInstance.mm | 43 ++++++++++++++++--- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/packages/react-native/React/CoreModules/RCTRedBox.mm b/packages/react-native/React/CoreModules/RCTRedBox.mm index 822e17ab570baf..15cf2f023aaa4c 100644 --- a/packages/react-native/React/CoreModules/RCTRedBox.mm +++ b/packages/react-native/React/CoreModules/RCTRedBox.mm @@ -274,7 +274,13 @@ - (void)dismiss - (void)reload { - [_actionDelegate reloadFromRedBoxController:self]; + if (_actionDelegate != nil) { + [_actionDelegate reloadFromRedBoxController:self]; + } else { + // In bridgeless mode `RCTRedBox` gets deallocated, we need to notify listeners anyway. + RCTTriggerReloadCommandListeners(@"Redbox"); + [self dismiss]; + } } - (void)showExtraDataViewController diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm index 6b9f987123c53d..38f17f96129091 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm @@ -28,6 +28,8 @@ #import #import #import +#import +#import #import #import #import @@ -122,10 +124,17 @@ - (instancetype)initWithDelegate:(id)delegate }]; } - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(_notifyEventDispatcherObserversOfEvent_DEPRECATED:) - name:@"RCTNotifyEventDispatcherObserversOfEvent_DEPRECATED" - object:nil]; + NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter]; + + [defaultCenter addObserver:self + selector:@selector(_notifyEventDispatcherObserversOfEvent_DEPRECATED:) + name:@"RCTNotifyEventDispatcherObserversOfEvent_DEPRECATED" + object:nil]; + + [defaultCenter addObserver:self + selector:@selector(didReceiveReloadCommand) + name:RCTTriggerReloadCommandNotification + object:nil]; [self _start]; } @@ -389,6 +398,24 @@ - (void)_attachBridgelessAPIsToModule:(id)module } } +- (void)handleBundleLoadingError:(NSError *)error +{ + if (!_valid) { + return; + } + + RCTRedBox *redBox = [_turboModuleManager moduleForName:"RedBox"]; + + RCTExecuteOnMainQueue(^{ + [[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptDidFailToLoadNotification + object:self + userInfo:@{@"error" : error}]; + [redBox showErrorMessage:[error localizedDescription]]; + + RCTFatal(error); + }); +} + - (void)_loadJSBundle:(NSURL *)sourceURL { #if RCT_DEV_MENU && __has_include() @@ -420,8 +447,7 @@ - (void)_loadJSBundle:(NSURL *)sourceURL } if (error) { - // TODO(T91461138): Properly address bundle loading errors. - RCTLogError(@"RCTInstance: Error while loading bundle: %@", error); + [strongSelf handleBundleLoadingError:error]; [strongSelf invalidate]; return; } @@ -490,4 +516,9 @@ - (void)_handleJSErrorMap:(facebook::react::MapBuffer)errorMap isFatal:errorMap.getBool(JSErrorHandlerKey::kIsFatal)]; } +- (void)didReceiveReloadCommand +{ + [self _loadJSBundle:[_bridgeModuleDecorator.bundleManager bundleURL]]; +} + @end