/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "RCTAppDelegate.h" #import #import #import #import #import "RCTAppSetupUtils.h" #import "RCTLegacyInteropComponents.h" #if RCT_NEW_ARCH_ENABLED #import #import #import #import #import #import #import #import #import #if USE_HERMES #import #else #import #endif #import #import #import #import #import #import #import static NSString *const kRNConcurrentRoot = @"concurrentRoot"; @interface RCTAppDelegate () < RCTTurboModuleManagerDelegate, RCTComponentViewFactoryComponentProvider, RCTContextContainerHandling> { std::shared_ptr _reactNativeConfig; facebook::react::ContextContainer::Shared _contextContainer; } @end #endif static NSDictionary *updateInitialProps(NSDictionary *initialProps, BOOL isFabricEnabled) { #ifdef RCT_NEW_ARCH_ENABLED NSMutableDictionary *mutableProps = [initialProps mutableCopy] ?: [NSMutableDictionary new]; // Hardcoding the Concurrent Root as it it not recommended to // have the concurrentRoot turned off when Fabric is enabled. mutableProps[kRNConcurrentRoot] = @(isFabricEnabled); return mutableProps; #else return initialProps; #endif } @interface RCTAppDelegate () { std::shared_ptr _runtimeScheduler; } @end @implementation RCTAppDelegate { #if RCT_NEW_ARCH_ENABLED RCTHost *_reactHost; #endif } #if RCT_NEW_ARCH_ENABLED - (instancetype)init { if (self = [super init]) { _contextContainer = std::make_shared(); _reactNativeConfig = std::make_shared(); _contextContainer->insert("ReactNativeConfig", _reactNativeConfig); } return self; } #endif - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { BOOL enableTM = NO; BOOL enableBridgeless = NO; BOOL fabricEnabled = NO; #if RCT_NEW_ARCH_ENABLED enableTM = self.turboModuleEnabled; enableBridgeless = self.bridgelessEnabled; fabricEnabled = [self fabricEnabled]; #endif NSDictionary *initProps = updateInitialProps([self prepareInitialProps], fabricEnabled); RCTAppSetupPrepareApp(application, enableTM); UIView *rootView; if (enableBridgeless) { #if RCT_NEW_ARCH_ENABLED // Enable native view config interop only if both bridgeless mode and Fabric is enabled. RCTSetUseNativeViewConfigsInBridgelessMode(fabricEnabled); // Enable TurboModule interop by default in Bridgeless mode RCTEnableTurboModuleInterop(YES); RCTEnableTurboModuleInteropBridgeProxy(YES); [self createReactHost]; [self unstable_registerLegacyComponents]; [RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self; RCTFabricSurface *surface = [_reactHost createSurfaceWithModuleName:self.moduleName initialProperties:initProps]; RCTSurfaceHostingProxyRootView *surfaceHostingProxyRootView = [[RCTSurfaceHostingProxyRootView alloc] initWithSurface:surface sizeMeasureMode:RCTSurfaceSizeMeasureModeWidthExact | RCTSurfaceSizeMeasureModeHeightExact]; 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 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]; self.window.rootViewController = rootViewController; self.window.windowScene.delegate = self; [self.window makeKeyAndVisible]; return YES; } - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { [NSException raise:@"RCTBridgeDelegate::sourceURLForBridge not implemented" format:@"Subclasses must implement a valid sourceURLForBridge method"]; return nil; } - (NSDictionary *)prepareInitialProps { return self.initialProps; } - (RCTBridge *)createBridgeWithDelegate:(id)delegate launchOptions:(NSDictionary *)launchOptions { return [[RCTBridge alloc] initWithDelegate:delegate launchOptions:launchOptions]; } - (UIView *)createRootViewWithBridge:(RCTBridge *)bridge moduleName:(NSString *)moduleName initProps:(NSDictionary *)initProps { BOOL enableFabric = NO; #if RCT_NEW_ARCH_ENABLED enableFabric = self.fabricEnabled; #endif UIView *rootView = RCTAppSetupDefaultRootView(bridge, moduleName, initProps, enableFabric); rootView.backgroundColor = [UIColor systemBackgroundColor]; return rootView; } - (UIViewController *)createRootViewController { return [UIViewController new]; } - (void)setRootView:(UIView *)rootView toRootViewController:(UIViewController *)rootViewController { rootViewController.view = rootView; } - (BOOL)runtimeSchedulerEnabled { return YES; } #pragma mark - UISceneDelegate - (void)windowScene:(UIWindowScene *)windowScene didUpdateCoordinateSpace:(id)previousCoordinateSpace interfaceOrientation:(UIInterfaceOrientation)previousInterfaceOrientation traitCollection:(UITraitCollection *)previousTraitCollection API_AVAILABLE(ios(13.0)) { [[NSNotificationCenter defaultCenter] postNotificationName:RCTWindowFrameDidChangeNotification object:self]; } #pragma mark - RCTCxxBridgeDelegate - (std::unique_ptr)jsExecutorFactoryForBridge:(RCTBridge *)bridge { _runtimeScheduler = std::make_shared(RCTRuntimeExecutorFromBridge(bridge)); #if RCT_NEW_ARCH_ENABLED std::shared_ptr callInvoker = std::make_shared(_runtimeScheduler); RCTTurboModuleManager *turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge delegate:self jsInvoker:callInvoker]; _contextContainer->erase("RuntimeScheduler"); _contextContainer->insert("RuntimeScheduler", _runtimeScheduler); return RCTAppSetupDefaultJsExecutorFactory(bridge, turboModuleManager, _runtimeScheduler); #else return RCTAppSetupJsExecutorFactoryForOldArch(bridge, _runtimeScheduler); #endif } #if RCT_NEW_ARCH_ENABLED #pragma mark - RCTTurboModuleManagerDelegate - (Class)getModuleClassFromName:(const char *)name { return RCTCoreModulesClassProvider(name); } - (std::shared_ptr)getTurboModule:(const std::string &)name jsInvoker:(std::shared_ptr)jsInvoker { return nullptr; } - (std::shared_ptr)getTurboModule:(const std::string &)name initParams: (const facebook::react::ObjCTurboModule::InitParams &)params { return nullptr; } - (id)getModuleInstanceFromClass:(Class)moduleClass { return RCTAppSetupDefaultModuleFromClass(moduleClass); } #pragma mark - RCTComponentViewFactoryComponentProvider - (NSDictionary> *)thirdPartyFabricComponents { return @{}; } #pragma mark - New Arch Enabled settings - (BOOL)turboModuleEnabled { return YES; } - (BOOL)fabricEnabled { return YES; } - (BOOL)bridgelessEnabled { return NO; } #pragma mark - New Arch Utilities - (void)unstable_registerLegacyComponents { for (NSString *legacyComponent in [RCTLegacyInteropComponents legacyInteropComponents]) { [RCTLegacyViewManagerInteropComponentView supportLegacyViewManagerWithName:legacyComponent]; } } - (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