From f500b47a957dea5e1ca2687965fb7a6a3fa64001 Mon Sep 17 00:00:00 2001 From: zhongwuzw Date: Wed, 29 May 2024 08:14:09 -0700 Subject: [PATCH] Bridgeless: Expose host delegate methods (#44158) Summary: Expose host delegate methods that users can do some customize work. ## Changelog: [IOS] [ADDED] - Bridgeless: Expose host delegate methods Pull Request resolved: https://github.com/facebook/react-native/pull/44158 Test Plan: Users can do some customized work by `RCTRootViewFactory`. Reviewed By: sammy-SC Differential Revision: D56521470 Pulled By: cipolleschi fbshipit-source-id: dd22d0978b9fd4385380945a514eb6596b7d874f --- .../Libraries/AppDelegate/RCTAppDelegate.mm | 30 ++++++++++++++++++- .../AppDelegate/RCTRootViewFactory.h | 23 ++++++++++++++ .../AppDelegate/RCTRootViewFactory.mm | 24 +++++++++++++-- 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm index b02fe560843..da4f793c6cd 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm @@ -11,6 +11,7 @@ #import #import #import +#import #import #import #import @@ -32,7 +33,7 @@ #endif #import -@interface RCTAppDelegate () +@interface RCTAppDelegate () @end @implementation RCTAppDelegate @@ -158,6 +159,20 @@ return nullptr; } +#pragma mark - RCTHostDelegate + +- (void)hostDidStart:(RCTHost *)host +{ +} + +- (void)host:(RCTHost *)host + didReceiveJSErrorStack:(NSArray *> *)stack + message:(NSString *)message + exceptionId:(NSUInteger)exceptionId + isFatal:(BOOL)isFatal +{ +} + #pragma mark - Bridge and Bridge Adapter properties - (RCTBridge *)bridge @@ -243,6 +258,19 @@ return [weakSelf sourceURLForBridge:bridge]; }; + configuration.hostDidStartBlock = ^(RCTHost *_Nonnull host) { + [weakSelf hostDidStart:host]; + }; + + configuration.hostDidReceiveJSErrorStackBlock = + ^(RCTHost *_Nonnull host, + NSArray *> *_Nonnull stack, + NSString *_Nonnull message, + NSUInteger exceptionId, + BOOL isFatal) { + [weakSelf host:host didReceiveJSErrorStack:stack message:message exceptionId:exceptionId isFatal:isFatal]; + }; + if ([self respondsToSelector:@selector(extraModulesForBridge:)]) { configuration.extraModulesForBridge = ^NSArray> *_Nonnull(RCTBridge *_Nonnull bridge) { diff --git a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h index bc52c1712cc..6c60403ea29 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h +++ b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h @@ -29,6 +29,13 @@ typedef NSURL *_Nullable (^RCTBundleURLBlock)(void); typedef NSArray> *_Nonnull (^RCTExtraModulesForBridgeBlock)(RCTBridge *bridge); typedef NSDictionary *_Nonnull (^RCTExtraLazyModuleClassesForBridge)(RCTBridge *bridge); typedef BOOL (^RCTBridgeDidNotFindModuleBlock)(RCTBridge *bridge, NSString *moduleName); +typedef void (^RCTHostDidStartBlock)(RCTHost *host); +typedef void (^RCTHostDidReceiveJSErrorStackBlock)( + RCTHost *host, + NSArray *> *stack, + NSString *message, + NSUInteger exceptionId, + BOOL isFatal); #pragma mark - RCTRootViewFactory Configuration @interface RCTRootViewFactoryConfiguration : NSObject @@ -132,6 +139,22 @@ typedef BOOL (^RCTBridgeDidNotFindModuleBlock)(RCTBridge *bridge, NSString *modu */ @property (nonatomic, nullable) RCTBridgeDidNotFindModuleBlock bridgeDidNotFindModule; +/** + * Called when `RCTHost` started. + * @parameter: host - The started `RCTHost`. + */ +@property (nonatomic, nullable) RCTHostDidStartBlock hostDidStartBlock; + +/** + * Called when `RCTHost` received JS error. + * @parameter: host - `RCTHost` which received js error. + * @parameter: stack - JS error stack. + * @parameter: message - Error message. + * @parameter: exceptionId - Exception ID. + * @parameter: isFatal - YES if JS error is fatal. + */ +@property (nonatomic, nullable) RCTHostDidReceiveJSErrorStackBlock hostDidReceiveJSErrorStackBlock; + @end #pragma mark - RCTRootViewFactory diff --git a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm index dd85650179a..2ae542f450c 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm @@ -83,7 +83,7 @@ static NSDictionary *updateInitialProps(NSDictionary *initialProps, BOOL isFabri @end -@interface RCTRootViewFactory () { +@interface RCTRootViewFactory () { std::shared_ptr _reactNativeConfig; facebook::react::ContextContainer::Shared _contextContainer; } @@ -180,6 +180,26 @@ static NSDictionary *updateInitialProps(NSDictionary *initialProps, BOOL isFabri return rootView; } +#pragma mark - RCTHostDelegate + +- (void)hostDidStart:(RCTHost *)host +{ + if (self->_configuration.hostDidStartBlock) { + self->_configuration.hostDidStartBlock(host); + } +} + +- (void)host:(RCTHost *)host + didReceiveJSErrorStack:(NSArray *> *)stack + message:(NSString *)message + exceptionId:(NSUInteger)exceptionId + isFatal:(BOOL)isFatal +{ + if (self->_configuration.hostDidReceiveJSErrorStackBlock) { + self->_configuration.hostDidReceiveJSErrorStackBlock(host, stack, message, exceptionId, isFatal); + } +} + #pragma mark - RCTCxxBridgeDelegate - (std::unique_ptr)jsExecutorFactoryForBridge:(RCTBridge *)bridge { @@ -238,7 +258,7 @@ static NSDictionary *updateInitialProps(NSDictionary *initialProps, BOOL isFabri __weak __typeof(self) weakSelf = self; RCTHost *reactHost = [[RCTHost alloc] initWithBundleURLProvider:self->_configuration.bundleURLBlock - hostDelegate:nil + hostDelegate:self turboModuleManagerDelegate:_turboModuleManagerDelegate jsEngineProvider:^std::shared_ptr() { return [weakSelf createJSRuntimeFactory];