diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h index b36e62f230731c..0c84edf4b93487 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h @@ -132,6 +132,14 @@ /// @return: `true` if the Fabric Renderer is enabled. Otherwise, it returns `false`. - (BOOL)fabricEnabled; +/// This method controls whether React Native's new initialization layer is enabled. +/// +/// @return: `true` if the new initialization layer is enabled. Otherwise returns `false`. +- (BOOL)bridgelessEnabled; + +/// Return the bundle URL for the main bundle. +- (NSURL *)getBundleURL; + #endif @end diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm index ecc438ca4a4f7a..b299ac72b15738 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm @@ -8,28 +8,41 @@ #import "RCTAppDelegate.h" #import #import "RCTAppSetupUtils.h" +#import "RCTLegacyInteropComponents.h" #if RCT_NEW_ARCH_ENABLED #import +#import #import #import #import +#import #import #import +#import #import #import +#import +#if USE_HERMES +#import +#else +#import +#endif +#import +#import #import +#import #import #import #import -#import "RCTLegacyInteropComponents.h" static NSString *const kRNConcurrentRoot = @"concurrentRoot"; @interface RCTAppDelegate () < RCTTurboModuleManagerDelegate, RCTCxxBridgeDelegate, - RCTComponentViewFactoryComponentProvider> { + RCTComponentViewFactoryComponentProvider, + RCTContextContainerHandling> { std::shared_ptr _reactNativeConfig; facebook::react::ContextContainer::Shared _contextContainer; std::shared_ptr _runtimeScheduler; @@ -38,7 +51,11 @@ @interface RCTAppDelegate () < #endif -@implementation RCTAppDelegate +@implementation RCTAppDelegate { +#if RCT_NEW_ARCH_ENABLED + RCTHost *_reactHost; +#endif +} #if RCT_NEW_ARCH_ENABLED - (instancetype)init @@ -55,26 +72,44 @@ - (instancetype)init - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { BOOL enableTM = NO; + BOOL enableBridgeless = NO; #if RCT_NEW_ARCH_ENABLED enableTM = self.turboModuleEnabled; + enableBridgeless = self.bridgelessEnabled; #endif + RCTAppSetupPrepareApp(application, enableTM); - if (!self.bridge) { - self.bridge = [self createBridgeWithDelegate:self launchOptions:launchOptions]; - } + UIView *rootView; + + if (enableBridgeless) { #if RCT_NEW_ARCH_ENABLED - self.bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:self.bridge - contextContainer:_contextContainer]; - self.bridge.surfacePresenter = self.bridgeAdapter.surfacePresenter; + [self createReactHost]; + RCTFabricSurface *surface = [_reactHost createSurfaceWithModuleName:self.moduleName + initialProperties:launchOptions]; - [self unstable_registerLegacyComponents]; - [RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self; -#endif + RCTSurfaceHostingProxyRootView *surfaceHostingProxyRootView = [[RCTSurfaceHostingProxyRootView alloc] + initWithSurface:surface + sizeMeasureMode:RCTSurfaceSizeMeasureModeWidthExact | RCTSurfaceSizeMeasureModeHeightExact + moduleRegistry:[_reactHost getModuleRegistry]]; - NSDictionary *initProps = [self prepareInitialProps]; - UIView *rootView = [self createRootViewWithBridge:self.bridge moduleName:self.moduleName initProps:initProps]; + rootView = (RCTRootView *)surfaceHostingProxyRootView; +#endif + } else { + if (!self.bridge) { + self.bridge = [self createBridgeWithDelegate:self launchOptions:launchOptions]; + } +#if RCT_NEW_ARCH_ENABLED + self.bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:self.bridge + contextContainer:_contextContainer]; + self.bridge.surfacePresenter = self.bridgeAdapter.surfacePresenter; + [self unstable_registerLegacyComponents]; + [RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self; +#endif + NSDictionary *initProps = [self prepareInitialProps]; + rootView = [self createRootViewWithBridge:self.bridge moduleName:self.moduleName initProps:initProps]; + } self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; UIViewController *rootViewController = [self createRootViewController]; [self setRootView:rootView toRootViewController:rootViewController]; @@ -198,6 +233,11 @@ - (BOOL)fabricEnabled return YES; } +- (BOOL)bridgelessEnabled +{ + return YES; +} + #pragma mark - New Arch Utilities - (void)unstable_registerLegacyComponents @@ -207,6 +247,43 @@ - (void)unstable_registerLegacyComponents } } +- (void)createReactHost +{ + __weak __typeof(self) weakSelf = self; + _reactHost = [[RCTHost alloc] initWithBundleURL:[self getBundleURL] + hostDelegate:nil + turboModuleManagerDelegate:self + jsEngineProvider:^std::shared_ptr() { + return [weakSelf createJSEngineInstance]; + }]; + [_reactHost setBundleURLProvider:^NSURL *() { + return [weakSelf getBundleURL]; + }]; + [_reactHost setContextContainerHandler:self]; + [_reactHost start]; +} + +- (std::shared_ptr)createJSEngineInstance +{ +#if USE_HERMES + return std::make_shared(_reactNativeConfig, nullptr); +#else + return std::make_shared(); +#endif +} + +- (void)didCreateContextContainer:(std::shared_ptr)contextContainer +{ + contextContainer->insert("ReactNativeConfig", _reactNativeConfig); +} + +- (NSURL *)getBundleURL +{ + [NSException raise:@"RCTAppDelegate::getBundleURL not implemented" + format:@"Subclasses must implement a valid getBundleURL method"]; + return nullptr; +} + #endif @end diff --git a/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec b/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec index 8df2d6a7288e46..56b015046553db 100644 --- a/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec +++ b/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec @@ -20,13 +20,14 @@ folly_flags = ' -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1' folly_compiler_flags = folly_flags + ' ' + '-Wno-comma -Wno-shorten-64-to-32' is_new_arch_enabled = ENV["RCT_NEW_ARCH_ENABLED"] == "1" +use_hermes = ENV['USE_HERMES'] == nil || ENV['USE_HERMES'] == '1' +use_frameworks = ENV['USE_FRAMEWORKS'] != nil + new_arch_enabled_flag = (is_new_arch_enabled ? " -DRCT_NEW_ARCH_ENABLED" : "") is_fabric_enabled = is_new_arch_enabled || ENV["RCT_FABRIC_ENABLED"] fabric_flag = (is_fabric_enabled ? " -DRN_FABRIC_ENABLED" : "") -other_cflags = "$(inherited)" + folly_flags + new_arch_enabled_flag + fabric_flag - -use_hermes = ENV['USE_HERMES'] == '1' -use_frameworks = ENV['USE_FRAMEWORKS'] != nil +hermes_flag = (use_hermes ? " -DUSE_HERMES" : "") +other_cflags = "$(inherited)" + folly_flags + new_arch_enabled_flag + fabric_flag + hermes_flag header_search_paths = [ "$(PODS_TARGET_SRCROOT)/../../ReactCommon", diff --git a/packages/rn-tester/RNTester/AppDelegate.mm b/packages/rn-tester/RNTester/AppDelegate.mm index 1e8616f9ad0881..35274d73bc24ad 100644 --- a/packages/rn-tester/RNTester/AppDelegate.mm +++ b/packages/rn-tester/RNTester/AppDelegate.mm @@ -123,6 +123,11 @@ - (void)application:(__unused UIApplication *)application { return @{@"RNTMyNativeView" : RNTMyNativeViewComponentView.class}; } + +- (NSURL *)getBundleURL +{ + return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"js/RNTesterApp.ios"]; +} #endif @end