Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
@class RCTBridge;
@protocol RCTComponentViewProtocol;
@class RCTSurfacePresenterBridgeAdapter;
@class RCTCustomBundleConfiguration;
@class RCTDevMenuConfiguration;

NS_ASSUME_NONNULL_BEGIN
Expand Down Expand Up @@ -117,6 +118,8 @@ typedef NS_ENUM(NSInteger, RCTReleaseLevel) { Canary, Experimental, Stable };

@property (nonatomic, weak) id<RCTReactNativeFactoryDelegate> delegate;

@property (nonatomic, nullable) RCTCustomBundleConfiguration *customBundleConfiguration;

@property (nonatomic, nullable) RCTDevMenuConfiguration *devMenuConfiguration;

@end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

#import "RCTReactNativeFactory.h"
#import <React/RCTBundleManager.h>
#import <React/RCTColorSpaceUtils.h>
#import <React/RCTDevMenu.h>
#import <React/RCTLog.h>
Expand Down Expand Up @@ -59,6 +60,8 @@ - (instancetype)initWithDelegate:(id<RCTReactNativeFactoryDelegate>)delegate rel
self.rootViewFactory = [self createRCTRootViewFactory];

[RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self;

self.customBundleConfiguration = [[RCTCustomBundleConfiguration alloc] init];
}

return self;
Expand All @@ -84,6 +87,7 @@ - (void)startReactNativeWithModuleName:(NSString *)moduleName
UIView *rootView = [self.rootViewFactory viewWithModuleName:moduleName
initialProperties:initialProperties
launchOptions:launchOptions
customBundleConfiguration:self.customBundleConfiguration
devMenuConfiguration:self.devMenuConfiguration];
UIViewController *rootViewController = [_delegate createRootViewController];
[_delegate setRootView:rootView toRootViewController:rootViewController];
Expand Down
12 changes: 9 additions & 3 deletions packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
@class RCTHost;
@class RCTRootView;
@class RCTSurfacePresenterBridgeAdapter;
@class RCTCustomBundleConfiguration;
@class RCTDevMenuConfiguration;

NS_ASSUME_NONNULL_BEGIN
Expand Down Expand Up @@ -202,11 +203,13 @@ 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: customBundleConfiguration - 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
customBundleConfiguration:(RCTCustomBundleConfiguration *__nullable)customBundleConfiguration
devMenuConfiguration:(RCTDevMenuConfiguration *__nullable)devMenuConfiguration;

- (UIView *_Nonnull)viewWithModuleName:(NSString *)moduleName
Expand All @@ -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: customBundleConfiguration - a configuration for custom bundle source URL.
* @parameter: devMenuConfiguration - a configuration for enabling/disabling dev menu.
*/
- (void)initializeReactHostWithLaunchOptions:(NSDictionary *__nullable)launchOptions
customBundleConfiguration:(RCTCustomBundleConfiguration *__nullable)customBundleConfiguration
devMenuConfiguration:(RCTDevMenuConfiguration *)devMenuConfiguration;

- (RCTHost *)createReactHost:(NSDictionary *__nullable)launchOptions;

- (RCTHost *)createReactHost:(NSDictionary *__nullable)launchOptions
devMenuConfiguration:(RCTDevMenuConfiguration *__nullable)devMenuConfiguration;
customBundleConfiguration:(RCTCustomBundleConfiguration *__nullable)customBundleConfiguration
devMenuConfiguration:(RCTDevMenuConfiguration *)devMenuConfiguration;

- (RCTHost *)createReactHost:(NSDictionary *__nullable)launchOptions;

@end

Expand Down
28 changes: 22 additions & 6 deletions packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
#else
#import <React/CoreModulesPlugins.h>
#endif
#import <React/RCTBundleURLProvider.h>
#import <React/RCTComponentViewFactory.h>
#import <React/RCTComponentViewProtocol.h>
#import <React/RCTFabricSurface.h>
Expand Down Expand Up @@ -137,6 +136,7 @@ - (UIView *)viewWithModuleName:(NSString *)moduleName initialProperties:(NSDicti
return [self viewWithModuleName:moduleName
initialProperties:initialProperties
launchOptions:nil
customBundleConfiguration:nil
devMenuConfiguration:[RCTDevMenuConfiguration defaultConfiguration]];
}

Expand All @@ -145,17 +145,21 @@ - (UIView *)viewWithModuleName:(NSString *)moduleName
return [self viewWithModuleName:moduleName
initialProperties:nil
launchOptions:nil
customBundleConfiguration:nil
devMenuConfiguration:[RCTDevMenuConfiguration defaultConfiguration]];
}

- (void)initializeReactHostWithLaunchOptions:(NSDictionary *)launchOptions
customBundleConfiguration:(RCTCustomBundleConfiguration *)customBundleConfiguration
devMenuConfiguration:(RCTDevMenuConfiguration *)devMenuConfiguration
{
// Enable TurboModule interop by default in Bridgeless mode
RCTEnableTurboModuleInterop(YES);
RCTEnableTurboModuleInteropBridgeProxy(YES);

[self createReactHostIfNeeded:launchOptions devMenuConfiguration:devMenuConfiguration];
[self createReactHostIfNeeded:launchOptions
customBundleConfiguration:customBundleConfiguration
devMenuConfiguration:devMenuConfiguration];
return;
}

Expand All @@ -166,15 +170,19 @@ - (UIView *)viewWithModuleName:(NSString *)moduleName
return [self viewWithModuleName:moduleName
initialProperties:initialProperties
launchOptions:launchOptions
customBundleConfiguration:nil
devMenuConfiguration:[RCTDevMenuConfiguration defaultConfiguration]];
}

- (UIView *)viewWithModuleName:(NSString *)moduleName
initialProperties:(NSDictionary *)initProps
launchOptions:(NSDictionary *)launchOptions
customBundleConfiguration:(RCTCustomBundleConfiguration *)customBundleConfiguration
devMenuConfiguration:(RCTDevMenuConfiguration *)devMenuConfiguration
{
[self initializeReactHostWithLaunchOptions:launchOptions devMenuConfiguration:devMenuConfiguration];
[self initializeReactHostWithLaunchOptions:launchOptions
customBundleConfiguration:customBundleConfiguration
devMenuConfiguration:devMenuConfiguration];

RCTFabricSurface *surface = [self.reactHost createSurfaceWithModuleName:moduleName
initialProperties:initProps ? initProps : @{}];
Expand Down Expand Up @@ -245,21 +253,28 @@ - (void)createBridgeAdapterIfNeeded
#pragma mark - New Arch Utilities

- (void)createReactHostIfNeeded:(NSDictionary *)launchOptions
customBundleConfiguration:(RCTCustomBundleConfiguration *)customBundleConfiguration
devMenuConfiguration:(RCTDevMenuConfiguration *)devMenuConfiguration
{
if (self.reactHost) {
return;
}
self.reactHost = [self createReactHost:launchOptions devMenuConfiguration:devMenuConfiguration];

self.reactHost = [self createReactHost:launchOptions
customBundleConfiguration:customBundleConfiguration
devMenuConfiguration:devMenuConfiguration];
}

- (RCTHost *)createReactHost:(NSDictionary *)launchOptions
{
return [self createReactHost:launchOptions devMenuConfiguration:[RCTDevMenuConfiguration defaultConfiguration]];
return [self createReactHost:launchOptions
customBundleConfiguration:nil
devMenuConfiguration:[RCTDevMenuConfiguration defaultConfiguration]];
}

- (RCTHost *)createReactHost:(NSDictionary *)launchOptions
devMenuConfiguration:(RCTDevMenuConfiguration *)devMenuConfiguration
customBundleConfiguration:(RCTCustomBundleConfiguration *)customBundleConfiguration
devMenuConfiguration:(RCTDevMenuConfiguration *)devMenuConfiguration
{
__weak __typeof(self) weakSelf = self;
RCTHost *reactHost =
Expand All @@ -270,6 +285,7 @@ - (RCTHost *)createReactHost:(NSDictionary *)launchOptions
return [weakSelf createJSRuntimeFactory];
}
launchOptions:launchOptions
customBundleConfiguration:customBundleConfiguration
devMenuConfiguration:devMenuConfiguration];
[reactHost setBundleURLProvider:^NSURL *() {
return [weakSelf bundleURL];
Expand Down
42 changes: 42 additions & 0 deletions packages/react-native/React/Base/RCTBundleManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,47 @@
typedef NSURL * (^RCTBridgelessBundleURLGetter)(void);
typedef void (^RCTBridgelessBundleURLSetter)(NSURL *bundleURL);

/**
* Configuration class for setting up custom bundle locations
*/
@interface RCTCustomBundleConfiguration : NSObject

/**
* 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;

/**
* The relative path to the bundle.
*/
@property (nonatomic, readonly, nullable) NSString *bundlePath;

- (instancetype)initWithBundleFilePath:(NSURL *)bundleFilePath;

- (instancetype)initWithPackagerServerScheme:(NSString *)packagerServerScheme
packagerServerHost:(NSString *)packagerServerHost
bundlePath:(NSString *)bundlePath;

- (NSURL *)getBundleURL:(NSURL *__nullable (^)(void))fallbackURLProvider;

- (NSString *)getPackagerServerScheme;

- (NSString *)getPackagerServerHost;

- (void)clean;

@end

/**
* A class that allows NativeModules/TurboModules to read/write the bundleURL, with or without the bridge.
*/
Expand All @@ -24,4 +65,5 @@ typedef void (^RCTBridgelessBundleURLSetter)(NSURL *bundleURL);
andDefaultGetter:(RCTBridgelessBundleURLGetter)defaultGetter;
- (void)resetBundleURL;
@property NSURL *bundleURL;
@property (nonatomic, nullable) RCTCustomBundleConfiguration *customBundleConfig;
@end
80 changes: 80 additions & 0 deletions packages/react-native/React/Base/RCTBundleManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,88 @@
*/

#import "RCTBundleManager.h"
#import <React/RCTBundleURLProvider.h>
#import "RCTAssert.h"
#import "RCTBridge+Private.h"
#import "RCTBridge.h"
#import "RCTLog.h"

@implementation RCTCustomBundleConfiguration

- (instancetype)initWithBundleFilePath:(NSURL *)bundleFilePath
{
if (self = [super init]) {
_bundleFilePath = bundleFilePath;
}

return self;
}

- (instancetype)initWithPackagerServerScheme:(NSString *)packagerServerScheme
packagerServerHost:(NSString *)packagerServerHost
bundlePath:(NSString *)bundlePath
{
if (self = [super init]) {
_packagerServerScheme = packagerServerScheme;
_packagerServerHost = packagerServerHost;
_bundlePath = bundlePath;
}

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<NSURLQueryItem *> *jsBundleURLQuery =
[[RCTBundleURLProvider sharedSettings] createJSBundleURLQuery:_packagerServerHost
packagerScheme:_packagerServerScheme];

NSString *path = [NSString stringWithFormat:@"/%@.bundle", _bundlePath];
return [[RCTBundleURLProvider class] resourceURLForResourcePath:path
packagerHost:_packagerServerHost
scheme:_packagerServerScheme
queryItems:jsBundleURLQuery];
}

if (_bundleFilePath) {
if (!_bundleFilePath.fileURL) {
RCTLogError(@"Bundle file path must be a file URL");
return nil;
}

return _bundleFilePath;
}

return fallbackURLProvider();
}

- (void)clean
{
_packagerServerHost = nil;
_packagerServerScheme = nil;
_bundleFilePath = nil;
}

@end

@implementation RCTBundleManager {
#ifndef RCT_REMOVE_LEGACY_ARCH
Expand All @@ -18,6 +97,7 @@ @implementation RCTBundleManager {
RCTBridgelessBundleURLSetter _bridgelessBundleURLSetter;
RCTBridgelessBundleURLGetter _bridgelessBundleURLDefaultGetter;
}
@synthesize customBundleConfig;

#ifndef RCT_REMOVE_LEGACY_ARCH
- (void)setBridge:(RCTBridge *)bridge
Expand Down
13 changes: 13 additions & 0 deletions packages/react-native/React/Base/RCTBundleURLProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,19 @@ NS_ASSUME_NONNULL_BEGIN
resourceExtension:(NSString *)extension
offlineBundle:(NSBundle *)offlineBundle;

- (NSArray<NSURLQueryItem *> *)createJSBundleURLQuery:(NSString *)packagerHost
packagerScheme:(NSString *__nullable)scheme;

+ (NSArray<NSURLQueryItem *> *)createJSBundleURLQuery:(NSString *)packagerHost
packagerScheme:(NSString *__nullable)scheme
enableDev:(BOOL)enableDev
enableMinification:(BOOL)enableMinification
inlineSourceMap:(BOOL)inlineSourceMap
modulesOnly:(BOOL)modulesOnly
runModule:(BOOL)runModule
additionalOptions:(NSDictionary<NSString *, NSString *>
*__nullable)additionalOptions;

/**
* The IP address or hostname of the packager.
*/
Expand Down
Loading
Loading