Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,48 @@ - (RCTRootViewFactory *)createRCTRootViewFactory
return [weakSelf createBridgeWithDelegate:delegate launchOptions:launchOptions];
};

configuration.sourceURLForBridge = ^NSURL *_Nullable(RCTBridge *_Nonnull bridge)
{
return [weakSelf sourceURLForBridge:bridge];
};

if ([self respondsToSelector:@selector(extraModulesForBridge:)]) {
configuration.extraModulesForBridge = ^NSArray<id<RCTBridgeModule>> *_Nonnull(RCTBridge *_Nonnull bridge)
{
return [weakSelf extraModulesForBridge:bridge];
};
}

if ([self respondsToSelector:@selector(extraLazyModuleClassesForBridge:)]) {
configuration.extraLazyModuleClassesForBridge =
^NSDictionary<NSString *, Class> *_Nonnull(RCTBridge *_Nonnull bridge)
{
return [weakSelf extraLazyModuleClassesForBridge:bridge];
};
}

if ([self respondsToSelector:@selector(bridge:didNotFindModule:)]) {
configuration.bridgeDidNotFindModule = ^BOOL(RCTBridge *_Nonnull bridge, NSString *_Nonnull moduleName) {
return [weakSelf bridge:bridge didNotFindModule:moduleName];
};
}

if ([self respondsToSelector:@selector(loadSourceForBridge:withBlock:)]) {
configuration.loadSourceForBridgeBlock =
^void(RCTBridge *_Nonnull bridge, RCTSourceLoadBlock _Nonnull loadCallback) {
[weakSelf loadSourceForBridge:bridge withBlock:loadCallback];
};
}

if ([self respondsToSelector:@selector(loadSourceForBridge:onProgress:onComplete:)]) {
configuration.loadSourceForBridgeProgressBlock =
^(RCTBridge *_Nonnull bridge,
RCTSourceLoadProgressBlock _Nonnull onProgress,
RCTSourceLoadBlock _Nonnull loadCallback) {
[weakSelf loadSourceForBridge:bridge onProgress:onProgress onComplete:loadCallback];
};
}

return [[RCTRootViewFactory alloc] initWithConfiguration:configuration andTurboModuleManagerDelegate:self];
}

Expand Down
59 changes: 59 additions & 0 deletions packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ typedef UIView *_Nonnull (
^RCTCreateRootViewWithBridgeBlock)(RCTBridge *bridge, NSString *moduleName, NSDictionary *initProps);
typedef RCTBridge *_Nonnull (
^RCTCreateBridgeWithDelegateBlock)(id<RCTBridgeDelegate> delegate, NSDictionary *launchOptions);
typedef NSURL *_Nullable (^RCTSourceURLForBridgeBlock)(RCTBridge *bridge);
typedef NSArray<id<RCTBridgeModule>> *_Nonnull (^RCTExtraModulesForBridgeBlock)(RCTBridge *bridge);
typedef NSDictionary<NSString *, Class> *_Nonnull (^RCTExtraLazyModuleClassesForBridge)(RCTBridge *bridge);
typedef BOOL (^RCTBridgeDidNotFindModuleBlock)(RCTBridge *bridge, NSString *moduleName);
typedef void (^RCTLoadSourceForBridgeBlock)(RCTBridge *bridge, RCTSourceLoadBlock loadCallback);
typedef void (^RCTLoadSourceForBridgeProgressBlock)(
RCTBridge *bridge,
RCTSourceLoadProgressBlock onProgress,
RCTSourceLoadBlock loadCallback);

#pragma mark - RCTRootViewFactory Configuration
@interface RCTRootViewFactoryConfiguration : NSObject
Expand Down Expand Up @@ -80,6 +89,56 @@ typedef RCTBridge *_Nonnull (
* @returns: a newly created instance of RCTBridge.
*/
@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;

/**
* The bridge will automatically attempt to load the JS source code from the
* location specified by the `sourceURLForBridge:` method, however, if you want
* to handle loading the JS yourself, you can do so by implementing this method.
*/
@property (nonatomic, nullable) RCTLoadSourceForBridgeProgressBlock loadSourceForBridgeProgressBlock;

/**
* Similar to loadSourceForBridge:onProgress:onComplete: but without progress
* reporting.
*/
@property (nonatomic, nullable) RCTLoadSourceForBridgeBlock loadSourceForBridgeBlock;

@end

Expand Down
43 changes: 43 additions & 0 deletions packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,54 @@ - (void)didCreateContextContainer:(std::shared_ptr<facebook::react::ContextConta
contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
}

- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge
{
if (_configuration.extraModulesForBridge != nil) {
return _configuration.extraModulesForBridge(bridge);
}
return nil;
}

- (NSDictionary<NSString *, Class> *)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;
}

- (void)loadSourceForBridge:(RCTBridge *)bridge withBlock:(RCTSourceLoadBlock)loadCallback
{
if (_configuration.loadSourceForBridgeBlock != nil) {
_configuration.loadSourceForBridgeBlock(bridge, loadCallback);
}
}

- (void)loadSourceForBridge:(RCTBridge *)bridge
onProgress:(RCTSourceLoadProgressBlock)onProgress
onComplete:(RCTSourceLoadBlock)loadCallback
{
if (_configuration.loadSourceForBridgeProgressBlock != nil) {
_configuration.loadSourceForBridgeProgressBlock(bridge, onProgress, loadCallback);
}
}

- (NSURL *)bundleURL
{
return self->_configuration.bundleURL;
Expand Down