diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm index 4e3fa2f8bdbca5..68ca2adae9d569 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm @@ -260,6 +260,25 @@ - (RCTRootViewFactory *)createRCTRootViewFactory return [weakSelf createBridgeWithDelegate:delegate launchOptions:launchOptions]; }; + configuration.sourceURLForBridge = ^NSURL *_Nullable(RCTBridge *_Nonnull bridge) + { + return [weakSelf sourceURLForBridge:bridge]; + }; + + configuration.extraModulesForBridge = ^NSArray> *_Nonnull(RCTBridge *_Nonnull bridge) + { + return [weakSelf extraModulesForBridge:bridge]; + }; + + configuration.extraLazyModuleClassesForBridge = ^NSDictionary *_Nonnull(RCTBridge *_Nonnull bridge) + { + return [weakSelf extraLazyModuleClassesForBridge:bridge]; + }; + + configuration.bridgeDidNotFindModule = ^BOOL(RCTBridge *_Nonnull bridge, NSString *_Nonnull moduleName) { + return [weakSelf bridge:bridge didNotFindModule:moduleName]; + }; + return [[RCTRootViewFactory alloc] initWithConfiguration:configuration andTurboModuleManagerDelegate:self]; } diff --git a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h index 5047802ebc5eda..2c7d3600320987 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h +++ b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h @@ -23,6 +23,10 @@ typedef UIView *_Nonnull ( ^RCTCreateRootViewWithBridgeBlock)(RCTBridge *bridge, NSString *moduleName, NSDictionary *initProps); typedef RCTBridge *_Nonnull ( ^RCTCreateBridgeWithDelegateBlock)(id delegate, NSDictionary *launchOptions); +typedef NSURL *_Nullable (^RCTSourceURLForBridgeBlock)(RCTBridge *bridge); +typedef NSArray> *_Nonnull (^RCTExtraModulesForBridgeBlock)(RCTBridge *bridge); +typedef NSDictionary *_Nonnull (^RCTExtraLazyModuleClassesForBridge)(RCTBridge *bridge); +typedef BOOL (^RCTBridgeDidNotFindModuleBlock)(RCTBridge *bridge, NSString *moduleName); #pragma mark - RCTRootViewFactory Configuration @interface RCTRootViewFactoryConfiguration : NSObject @@ -81,6 +85,44 @@ typedef RCTBridge *_Nonnull ( */ @property (nonatomic, nullable) RCTCreateBridgeWithDelegateBlock createBridgeWithDelegate; +/** + * Block that returns the location of the JavaScript source file. When running from the packager + * this should be an absolute URL, e.g. `http://localhost:8081/index.ios.bundle`. + * When running from a locally bundled JS file, this should be a `file://` url + * pointing to a path inside the app resources, e.g. `file://.../main.jsbundle`. + */ +@property (nonatomic, nullable) RCTSourceURLForBridgeBlock sourceURLForBridge; + +/** + * The bridge initializes any registered RCTBridgeModules automatically, however + * if you wish to instantiate your own module instances, you can return them + * from this block. + * + * Note: You should always return a new instance for each call, rather than + * returning the same instance each time the bridge is reloaded. Module instances + * should not be shared between bridges, and this may cause unexpected behavior. + * + * It is also possible to override standard modules with your own implementations + * by returning a class with the same `moduleName` from this method, but this is + * not recommended in most cases - if the module methods and behavior do not + * match exactly, it may lead to bugs or crashes. + */ +@property (nonatomic, nullable) RCTExtraModulesForBridgeBlock extraModulesForBridge; + +/** + * Retrieve the list of lazy-native-modules names for the given bridge. + */ +@property (nonatomic, nullable) RCTExtraLazyModuleClassesForBridge extraLazyModuleClassesForBridge; + +/** + * The bridge will call this block when a module been called from JS + * cannot be found among registered modules. + * It should return YES if the module with name 'moduleName' was registered + * in the implementation, and the system must attempt to look for it again among registered. + * If the module was not registered, return NO to prevent further searches. + */ +@property (nonatomic, nullable) RCTBridgeDidNotFindModuleBlock bridgeDidNotFindModule; + @end #pragma mark - RCTRootViewFactory diff --git a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm index c71ea624423433..30aa86f91c0ba3 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm @@ -241,11 +241,38 @@ - (void)didCreateContextContainer:(std::shared_ptrinsert("ReactNativeConfig", _reactNativeConfig); } +- (NSArray> *)extraModulesForBridge:(RCTBridge *)bridge +{ + if (_configuration.extraModulesForBridge != nil) { + return _configuration.extraModulesForBridge(bridge); + } + return nil; +} + +- (NSDictionary *)extraLazyModuleClassesForBridge:(RCTBridge *)bridge +{ + if (_configuration.extraLazyModuleClassesForBridge != nil) { + return _configuration.extraLazyModuleClassesForBridge(bridge); + } + return nil; +} + - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { + if (_configuration.sourceURLForBridge != nil) { + return _configuration.sourceURLForBridge(bridge); + } return [self bundleURL]; } +- (BOOL)bridge:(RCTBridge *)bridge didNotFindModule:(NSString *)moduleName +{ + if (_configuration.bridgeDidNotFindModule != nil) { + return _configuration.bridgeDidNotFindModule(bridge, moduleName); + } + return NO; +} + - (NSURL *)bundleURL { return self->_configuration.bundleURL;