diff --git a/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.h b/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.h index 455d23e42cb525..1671d7080907ab 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.h +++ b/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.h @@ -24,6 +24,7 @@ @class RCTBridge; @protocol RCTComponentViewProtocol; @class RCTSurfacePresenterBridgeAdapter; +@class RCTBundleConfiguration; @class RCTDevMenuConfiguration; NS_ASSUME_NONNULL_BEGIN @@ -117,6 +118,8 @@ typedef NS_ENUM(NSInteger, RCTReleaseLevel) { Canary, Experimental, Stable }; @property (nonatomic, weak) id delegate; +@property (nonatomic, strong, nonnull) RCTBundleConfiguration *bundleConfiguration; + @property (nonatomic, nullable) RCTDevMenuConfiguration *devMenuConfiguration; @end diff --git a/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm b/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm index a54e17796f05cc..e1eecb0ae73bb3 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm @@ -6,6 +6,7 @@ */ #import "RCTReactNativeFactory.h" +#import #import #import #import @@ -42,6 +43,8 @@ @interface RCTReactNativeFactory () < @implementation RCTReactNativeFactory +@synthesize bundleConfiguration = _bundleConfiguration; + - (instancetype)initWithDelegate:(id)delegate { return [self initWithDelegate:delegate releaseLevel:Stable]; @@ -84,6 +87,7 @@ - (void)startReactNativeWithModuleName:(NSString *)moduleName UIView *rootView = [self.rootViewFactory viewWithModuleName:moduleName initialProperties:initialProperties launchOptions:launchOptions + bundleConfiguration:self.bundleConfiguration devMenuConfiguration:self.devMenuConfiguration]; UIViewController *rootViewController = [_delegate createRootViewController]; [_delegate setRootView:rootView toRootViewController:rootViewController]; @@ -112,6 +116,14 @@ - (NSURL *_Nullable)bundleURL return _delegate.bundleURL; } +- (RCTBundleConfiguration *)bundleConfiguration +{ + if (_bundleConfiguration == nullptr) { + _bundleConfiguration = [RCTBundleConfiguration defaultConfiguration]; + } + return _bundleConfiguration; +} + #pragma mark - RCTJSRuntimeConfiguratorProtocol - (JSRuntimeFactoryRef)createJSRuntimeFactory diff --git a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h index 119d91a9ee29fc..7473c01a8b25c7 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h +++ b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h @@ -18,6 +18,7 @@ @class RCTHost; @class RCTRootView; @class RCTSurfacePresenterBridgeAdapter; +@class RCTBundleConfiguration; @class RCTDevMenuConfiguration; NS_ASSUME_NONNULL_BEGIN @@ -202,12 +203,14 @@ typedef void (^RCTLoadSourceForBridgeBlock)(RCTBridge *bridge, RCTSourceLoadBloc * @parameter: moduleName - the name of the app, used by Metro to resolve the module. * @parameter: initialProperties - a set of initial properties. * @parameter: launchOptions - a dictionary with a set of options. + * @parameter: bundleConfiguration - a configuration for custom bundle source URL. * @parameter: devMenuConfiguration - a configuration for enabling/disabling dev menu. */ - (UIView *_Nonnull)viewWithModuleName:(NSString *)moduleName initialProperties:(NSDictionary *__nullable)initialProperties launchOptions:(NSDictionary *__nullable)launchOptions - devMenuConfiguration:(RCTDevMenuConfiguration *__nullable)devMenuConfiguration; + bundleConfiguration:(RCTBundleConfiguration *)bundleConfiguration + devMenuConfiguration:(RCTDevMenuConfiguration *)devMenuConfiguration; - (UIView *_Nonnull)viewWithModuleName:(NSString *)moduleName initialProperties:(NSDictionary *__nullable)initialProperties @@ -226,15 +229,18 @@ typedef void (^RCTLoadSourceForBridgeBlock)(RCTBridge *bridge, RCTSourceLoadBloc * Use it to speed up later viewWithModuleName: calls. * * @parameter: launchOptions - a dictionary with a set of options. + * @parameter: bundleConfiguration - a configuration for custom bundle source URL. * @parameter: devMenuConfiguration - a configuration for enabling/disabling dev menu. */ - (void)initializeReactHostWithLaunchOptions:(NSDictionary *__nullable)launchOptions + bundleConfiguration:(RCTBundleConfiguration *)bundleConfiguration devMenuConfiguration:(RCTDevMenuConfiguration *)devMenuConfiguration; -- (RCTHost *)createReactHost:(NSDictionary *__nullable)launchOptions; - - (RCTHost *)createReactHost:(NSDictionary *__nullable)launchOptions - devMenuConfiguration:(RCTDevMenuConfiguration *__nullable)devMenuConfiguration; + bundleConfiguration:(RCTBundleConfiguration *)bundleConfiguration + devMenuConfiguration:(RCTDevMenuConfiguration *)devMenuConfiguration; + +- (RCTHost *)createReactHost:(NSDictionary *__nullable)launchOptions; @end diff --git a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm index 77201b675ec53b..266d6bab211cdb 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm @@ -21,7 +21,6 @@ #else #import #endif -#import #import #import #import @@ -137,6 +136,7 @@ - (UIView *)viewWithModuleName:(NSString *)moduleName initialProperties:(NSDicti return [self viewWithModuleName:moduleName initialProperties:initialProperties launchOptions:nil + bundleConfiguration:[RCTBundleConfiguration defaultConfiguration] devMenuConfiguration:[RCTDevMenuConfiguration defaultConfiguration]]; } @@ -145,17 +145,21 @@ - (UIView *)viewWithModuleName:(NSString *)moduleName return [self viewWithModuleName:moduleName initialProperties:nil launchOptions:nil + bundleConfiguration:[RCTBundleConfiguration defaultConfiguration] devMenuConfiguration:[RCTDevMenuConfiguration defaultConfiguration]]; } - (void)initializeReactHostWithLaunchOptions:(NSDictionary *)launchOptions + bundleConfiguration:(RCTBundleConfiguration *)bundleConfiguration devMenuConfiguration:(RCTDevMenuConfiguration *)devMenuConfiguration { // Enable TurboModule interop by default in Bridgeless mode RCTEnableTurboModuleInterop(YES); RCTEnableTurboModuleInteropBridgeProxy(YES); - [self createReactHostIfNeeded:launchOptions devMenuConfiguration:devMenuConfiguration]; + [self createReactHostIfNeeded:launchOptions + bundleConfiguration:bundleConfiguration + devMenuConfiguration:devMenuConfiguration]; return; } @@ -166,15 +170,19 @@ - (UIView *)viewWithModuleName:(NSString *)moduleName return [self viewWithModuleName:moduleName initialProperties:initialProperties launchOptions:launchOptions + bundleConfiguration:[RCTBundleConfiguration defaultConfiguration] devMenuConfiguration:[RCTDevMenuConfiguration defaultConfiguration]]; } - (UIView *)viewWithModuleName:(NSString *)moduleName initialProperties:(NSDictionary *)initProps launchOptions:(NSDictionary *)launchOptions + bundleConfiguration:(RCTBundleConfiguration *)bundleConfiguration devMenuConfiguration:(RCTDevMenuConfiguration *)devMenuConfiguration { - [self initializeReactHostWithLaunchOptions:launchOptions devMenuConfiguration:devMenuConfiguration]; + [self initializeReactHostWithLaunchOptions:launchOptions + bundleConfiguration:bundleConfiguration + devMenuConfiguration:devMenuConfiguration]; RCTFabricSurface *surface = [self.reactHost createSurfaceWithModuleName:moduleName initialProperties:initProps ? initProps : @{}]; @@ -245,20 +253,27 @@ - (void)createBridgeAdapterIfNeeded #pragma mark - New Arch Utilities - (void)createReactHostIfNeeded:(NSDictionary *)launchOptions + bundleConfiguration:(RCTBundleConfiguration *)bundleConfiguration devMenuConfiguration:(RCTDevMenuConfiguration *)devMenuConfiguration { if (self.reactHost) { return; } - self.reactHost = [self createReactHost:launchOptions devMenuConfiguration:devMenuConfiguration]; + + self.reactHost = [self createReactHost:launchOptions + bundleConfiguration:bundleConfiguration + devMenuConfiguration:devMenuConfiguration]; } - (RCTHost *)createReactHost:(NSDictionary *)launchOptions { - return [self createReactHost:launchOptions devMenuConfiguration:[RCTDevMenuConfiguration defaultConfiguration]]; + return [self createReactHost:launchOptions + bundleConfiguration:[RCTBundleConfiguration defaultConfiguration] + devMenuConfiguration:[RCTDevMenuConfiguration defaultConfiguration]]; } - (RCTHost *)createReactHost:(NSDictionary *)launchOptions + bundleConfiguration:(RCTBundleConfiguration *)bundleConfiguration devMenuConfiguration:(RCTDevMenuConfiguration *)devMenuConfiguration { __weak __typeof(self) weakSelf = self; @@ -270,6 +285,7 @@ - (RCTHost *)createReactHost:(NSDictionary *)launchOptions return [weakSelf createJSRuntimeFactory]; } launchOptions:launchOptions + bundleConfiguration:bundleConfiguration devMenuConfiguration:devMenuConfiguration]; [reactHost setBundleURLProvider:^NSURL *() { return [weakSelf bundleURL]; diff --git a/packages/react-native/React/Base/RCTBundleManager.h b/packages/react-native/React/Base/RCTBundleManager.h index fa0559ba50cd22..34e7f23e95c0ea 100644 --- a/packages/react-native/React/Base/RCTBundleManager.h +++ b/packages/react-native/React/Base/RCTBundleManager.h @@ -9,19 +9,71 @@ @class RCTBridge; -typedef NSURL * (^RCTBridgelessBundleURLGetter)(void); -typedef void (^RCTBridgelessBundleURLSetter)(NSURL *bundleURL); +typedef NSURL *_Nullable (^RCTBridgelessBundleURLGetter)(void); +typedef void (^RCTBridgelessBundleURLSetter)(NSURL *_Nullable bundleURL); +typedef NSMutableArray *_Nullable (^RCTPackagerOptionsUpdater)( + NSMutableArray *_Nullable options); + +/** + * Configuration class for setting up custom bundle locations + */ +@interface RCTBundleConfiguration : NSObject + ++ (nonnull instancetype)defaultConfiguration; + +/** + * The URL of the bundle to load from the file system + */ +@property (nonatomic, readonly, nullable) NSURL *bundleFilePath; + +/** + * The server scheme (e.g. http or https) to use when loading from the packager + */ +@property (nonatomic, readonly, nullable) NSString *packagerServerScheme; + +/** + * The server host (e.g. localhost) to use when loading from the packager + */ +@property (nonatomic, readonly, nullable) NSString *packagerServerHost; + +/** + * A block that modifies the packager options when loading from the packager + */ +@property (nonatomic, copy, nullable) RCTPackagerOptionsUpdater packagerOptionsUpdater; + +/** + * The relative path to the bundle. + */ +@property (nonatomic, readonly, nullable) NSString *bundlePath; + +- (nonnull instancetype)initWithBundleFilePath:(nullable NSURL *)bundleFilePath; + +- (nonnull instancetype)initWithPackagerServerScheme:(nullable NSString *)packagerServerScheme + packagerServerHost:(nullable NSString *)packagerServerHost + bundlePath:(nullable NSString *)bundlePath; + +- (nullable NSURL *)getBundleURL:(NSURL *_Nullable (^_Nullable)(void))fallbackURLProvider; + +- (nullable NSString *)getPackagerServerScheme; + +- (nullable NSString *)getPackagerServerHost; + +@end /** * A class that allows NativeModules/TurboModules to read/write the bundleURL, with or without the bridge. */ @interface RCTBundleManager : NSObject + +- (nullable instancetype)initWithBundleConfig:(nullable RCTBundleConfiguration *)bundleConfig; + #ifndef RCT_REMOVE_LEGACY_ARCH -- (void)setBridge:(RCTBridge *)bridge; +- (void)setBridge:(nullable RCTBridge *)bridge; #endif // RCT_REMOVE_LEGACY_ARCH -- (void)setBridgelessBundleURLGetter:(RCTBridgelessBundleURLGetter)getter - andSetter:(RCTBridgelessBundleURLSetter)setter - andDefaultGetter:(RCTBridgelessBundleURLGetter)defaultGetter; +- (void)setBridgelessBundleURLGetter:(nullable RCTBridgelessBundleURLGetter)getter + andSetter:(nullable RCTBridgelessBundleURLSetter)setter + andDefaultGetter:(nullable RCTBridgelessBundleURLGetter)defaultGetter; - (void)resetBundleURL; -@property NSURL *bundleURL; +@property (nonatomic, nullable) NSURL *bundleURL; +@property (nonatomic, nonnull) RCTBundleConfiguration *bundleConfig; @end diff --git a/packages/react-native/React/Base/RCTBundleManager.m b/packages/react-native/React/Base/RCTBundleManager.m index baa23d9123653a..c98eeb0de0493d 100644 --- a/packages/react-native/React/Base/RCTBundleManager.m +++ b/packages/react-native/React/Base/RCTBundleManager.m @@ -6,9 +6,99 @@ */ #import "RCTBundleManager.h" +#import #import "RCTAssert.h" #import "RCTBridge+Private.h" #import "RCTBridge.h" +#import "RCTLog.h" + +@implementation RCTBundleConfiguration + ++ (instancetype)defaultConfiguration +{ + return [[self alloc] initWithBundleFilePath:nil packagerServerScheme:nil packagerServerHost:nil bundlePath:nil]; +} + +- (instancetype)initWithBundleFilePath:(NSURL *)bundleFilePath +{ + return [self initWithBundleFilePath:bundleFilePath packagerServerScheme:nil packagerServerHost:nil bundlePath:nil]; +} + +- (instancetype)initWithPackagerServerScheme:(NSString *)packagerServerScheme + packagerServerHost:(NSString *)packagerServerHost + bundlePath:(NSString *)bundlePath +{ + return [self initWithBundleFilePath:nil + packagerServerScheme:packagerServerScheme + packagerServerHost:packagerServerHost + bundlePath:bundlePath]; +} + +- (instancetype)initWithBundleFilePath:(NSURL *)bundleFilePath + packagerServerScheme:(NSString *)packagerServerScheme + packagerServerHost:(NSString *)packagerServerHost + bundlePath:(NSString *)bundlePath +{ + if (self = [super init]) { + _bundleFilePath = bundleFilePath; + _packagerServerScheme = packagerServerScheme; + _packagerServerHost = packagerServerHost; + _bundlePath = bundlePath; + _packagerOptionsUpdater = ^NSMutableArray *(NSMutableArray *options) + { + return options; + }; + } + + return self; +} + +- (NSString *)getPackagerServerScheme +{ + if (!_packagerServerScheme) { + return [[RCTBundleURLProvider sharedSettings] packagerScheme]; + } + + return _packagerServerScheme; +} + +- (NSString *)getPackagerServerHost +{ + if (!_packagerServerHost) { + return [[RCTBundleURLProvider sharedSettings] packagerServerHostPort]; + } + + return _packagerServerHost; +} + +- (NSURL *)getBundleURL:(NSURL * (^)(void))fallbackURLProvider +{ + if (_packagerServerScheme && _packagerServerHost) { + NSArray *jsBundleURLQuery = + [[RCTBundleURLProvider sharedSettings] createJSBundleURLQuery:_packagerServerHost + packagerScheme:_packagerServerScheme]; + + NSArray *updatedBundleURLQuery = _packagerOptionsUpdater((NSMutableArray *)jsBundleURLQuery); + NSString *path = [NSString stringWithFormat:@"/%@.bundle", _bundlePath]; + return [[RCTBundleURLProvider class] resourceURLForResourcePath:path + packagerHost:_packagerServerHost + scheme:_packagerServerScheme + queryItems:updatedBundleURLQuery]; + } + + if (_bundleFilePath) { + if (!_bundleFilePath.fileURL) { + RCTLogError(@"Bundle file path must be a file URL"); + return nil; + } + + return _bundleFilePath; + } + + return fallbackURLProvider(); +} + +@end @implementation RCTBundleManager { #ifndef RCT_REMOVE_LEGACY_ARCH @@ -19,6 +109,20 @@ @implementation RCTBundleManager { RCTBridgelessBundleURLGetter _bridgelessBundleURLDefaultGetter; } +- (instancetype)initWithBundleConfig:(RCTBundleConfiguration *)bundleConfig +{ + if (self = [super init]) { + self.bundleConfig = bundleConfig ? bundleConfig : [RCTBundleConfiguration defaultConfiguration]; + } + + return self; +} + +- (instancetype)init +{ + return [self initWithBundleConfig:[RCTBundleConfiguration defaultConfiguration]]; +} + #ifndef RCT_REMOVE_LEGACY_ARCH - (void)setBridge:(RCTBridge *)bridge { diff --git a/packages/react-native/React/Base/RCTBundleURLProvider.h b/packages/react-native/React/Base/RCTBundleURLProvider.h index 3ade62f9c2f2ba..7882dd4de84a66 100644 --- a/packages/react-native/React/Base/RCTBundleURLProvider.h +++ b/packages/react-native/React/Base/RCTBundleURLProvider.h @@ -97,6 +97,19 @@ NS_ASSUME_NONNULL_BEGIN resourceExtension:(NSString *)extension offlineBundle:(NSBundle *)offlineBundle; +- (NSArray *)createJSBundleURLQuery:(NSString *)packagerHost + packagerScheme:(NSString *__nullable)scheme; + ++ (NSArray *)createJSBundleURLQuery:(NSString *)packagerHost + packagerScheme:(NSString *__nullable)scheme + enableDev:(BOOL)enableDev + enableMinification:(BOOL)enableMinification + inlineSourceMap:(BOOL)inlineSourceMap + modulesOnly:(BOOL)modulesOnly + runModule:(BOOL)runModule + additionalOptions: + (NSDictionary *__nullable)additionalOptions; + /** * The IP address or hostname of the packager. */ diff --git a/packages/react-native/React/Base/RCTBundleURLProvider.mm b/packages/react-native/React/Base/RCTBundleURLProvider.mm index 89ccd0c7ad7a58..55949a1d1bebcf 100644 --- a/packages/react-native/React/Base/RCTBundleURLProvider.mm +++ b/packages/react-native/React/Base/RCTBundleURLProvider.mm @@ -313,6 +313,44 @@ + (NSURL *__nullable)jsBundleURLForBundleRoot:(NSString *)bundleRoot additionalOptions:(NSDictionary *__nullable)additionalOptions { NSString *path = [NSString stringWithFormat:@"/%@.bundle", bundleRoot]; + NSArray *queryItems = [self createJSBundleURLQuery:packagerHost + packagerScheme:scheme + enableDev:enableDev + enableMinification:enableMinification + inlineSourceMap:inlineSourceMap + modulesOnly:modulesOnly + runModule:runModule + additionalOptions:additionalOptions]; + + return [[self class] resourceURLForResourcePath:path + packagerHost:packagerHost + scheme:scheme + queryItems:[queryItems copy]]; +} + +- (NSArray *)createJSBundleURLQuery:(NSString *)packagerHost + packagerScheme:(NSString *__nullable)scheme +{ + return [[self class] createJSBundleURLQuery:packagerHost + packagerScheme:scheme + enableDev:[self enableDev] + enableMinification:[self enableMinification] + inlineSourceMap:[self inlineSourceMap] + modulesOnly:NO + runModule:YES + additionalOptions:nil]; +} + ++ (NSArray *)createJSBundleURLQuery:(NSString *)packagerHost + packagerScheme:(NSString *__nullable)scheme + enableDev:(BOOL)enableDev + enableMinification:(BOOL)enableMinification + inlineSourceMap:(BOOL)inlineSourceMap + modulesOnly:(BOOL)modulesOnly + runModule:(BOOL)runModule + additionalOptions: + (NSDictionary *__nullable)additionalOptions +{ BOOL lazy = enableDev; NSMutableArray *queryItems = [[NSMutableArray alloc] initWithArray:@[ [[NSURLQueryItem alloc] initWithName:@"platform" value:RCTPlatformName], @@ -345,10 +383,7 @@ + (NSURL *__nullable)jsBundleURLForBundleRoot:(NSString *)bundleRoot } } - return [[self class] resourceURLForResourcePath:path - packagerHost:packagerHost - scheme:scheme - queryItems:[queryItems copy]]; + return queryItems; } + (NSURL *)resourceURLForResourcePath:(NSString *)path diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.h b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.h index 0aa5845a80f3c1..9f4721be7f6dc7 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.h +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.h @@ -18,6 +18,7 @@ NS_ASSUME_NONNULL_BEGIN @class RCTFabricSurface; @class RCTHost; @class RCTModuleRegistry; +@class RCTBundleConfiguration; @class RCTDevMenuConfiguration; @protocol RCTTurboModuleManagerDelegate; @@ -65,8 +66,8 @@ typedef std::shared_ptr (^RCTHostJSEngineProv turboModuleManagerDelegate:(id)turboModuleManagerDelegate jsEngineProvider:(RCTHostJSEngineProvider)jsEngineProvider launchOptions:(nullable NSDictionary *)launchOptions - devMenuConfiguration:(RCTDevMenuConfiguration *__nullable)devMenuConfiguration - NS_DESIGNATED_INITIALIZER; + bundleConfiguration:(RCTBundleConfiguration *)bundleConfiguration + devMenuConfiguration:(RCTDevMenuConfiguration *)devMenuConfiguration NS_DESIGNATED_INITIALIZER; - (instancetype)initWithBundleURLProvider:(RCTHostBundleURLProvider)provider hostDelegate:(id)hostDelegate diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm index 5c7bf6b986a7bd..07f4c0686816fb 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm @@ -152,10 +152,6 @@ - (instancetype)initWithBundleURL:(NSURL *)bundleURL launchOptions:launchOptions]; } -/** - Host initialization should not be resource intensive. A host may be created before any intention of using React Native - has been expressed. - */ - (instancetype)initWithBundleURLProvider:(RCTHostBundleURLProvider)provider hostDelegate:(id)hostDelegate turboModuleManagerDelegate:(id)turboModuleManagerDelegate @@ -167,24 +163,32 @@ - (instancetype)initWithBundleURLProvider:(RCTHostBundleURLProvider)provider turboModuleManagerDelegate:turboModuleManagerDelegate jsEngineProvider:jsEngineProvider launchOptions:launchOptions + bundleConfiguration:[RCTBundleConfiguration defaultConfiguration] devMenuConfiguration:[RCTDevMenuConfiguration defaultConfiguration]]; } +/** + Host initialization should not be resource intensive. A host may be created before any intention of using React Native + has been expressed. + */ - (instancetype)initWithBundleURLProvider:(RCTHostBundleURLProvider)provider hostDelegate:(id)hostDelegate turboModuleManagerDelegate:(id)turboModuleManagerDelegate jsEngineProvider:(RCTHostJSEngineProvider)jsEngineProvider launchOptions:(nullable NSDictionary *)launchOptions + bundleConfiguration:(RCTBundleConfiguration *)bundleConfiguration devMenuConfiguration:(RCTDevMenuConfiguration *)devMenuConfiguration { if (self = [super init]) { _hostDelegate = hostDelegate; _turboModuleManagerDelegate = turboModuleManagerDelegate; - _bundleManager = [RCTBundleManager new]; + _bundleManager = [[RCTBundleManager alloc] initWithBundleConfig:bundleConfiguration]; _moduleRegistry = [RCTModuleRegistry new]; _jsEngineProvider = [jsEngineProvider copy]; _launchOptions = [launchOptions copy]; + [self setBundleURLProvider:provider]; + __weak RCTHost *weakSelf = self; auto bundleURLGetter = ^NSURL *() { RCTHost *strongSelf = weakSelf; @@ -450,7 +454,7 @@ - (void)_setBundleURL:(NSURL *)bundleURL // Sanitize the bundle URL _bundleURL = [RCTConvert NSURL:_bundleURL.absoluteString]; - // Update the global bundle URLq + // Update the global bundle URL RCTReloadCommandSetBundleURL(_bundleURL); }