/* * 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 "RCTAppSetupUtils.h" #import #import #import // Turbo Module #import #import #import #import #import #import #import // Fabric #import #import // jsinspector-modern #import #import "RCTDependencyProvider.h" void RCTAppSetupPrepareApp(UIApplication *application, BOOL turboModuleEnabled) { RCTEnableTurboModule(turboModuleEnabled); #if DEBUG // Disable idle timer in dev builds to avoid putting application in background and complicating // Metro reconnection logic. Users only need this when running the application using our CLI tooling. application.idleTimerDisabled = YES; #endif } UIView * RCTAppSetupDefaultRootView(RCTBridge *bridge, NSString *moduleName, NSDictionary *initialProperties, BOOL fabricEnabled) { if (fabricEnabled) { id surface = [[RCTFabricSurface alloc] initWithBridge:bridge moduleName:moduleName initialProperties:initialProperties]; UIView *rootView = [[RCTSurfaceHostingProxyRootView alloc] initWithSurface:surface]; [surface start]; return rootView; } return [[RCTRootView alloc] initWithBridge:bridge moduleName:moduleName initialProperties:initialProperties]; } id RCTAppSetupDefaultModuleFromClass(Class moduleClass, id dependencyProvider) { // private block used to filter out modules depending on protocol conformance NSArray * (^extractModuleConformingToProtocol)(RCTModuleRegistry *, Protocol *) = ^NSArray *(RCTModuleRegistry *moduleRegistry, Protocol *protocol) { NSArray *classNames = @[]; if (protocol == @protocol(RCTImageURLLoader)) { classNames = dependencyProvider ? dependencyProvider.imageURLLoaderClassNames : @[]; } else if (protocol == @protocol(RCTImageDataDecoder)) { classNames = dependencyProvider ? dependencyProvider.imageDataDecoderClassNames : @[]; } else if (protocol == @protocol(RCTURLRequestHandler)) { classNames = dependencyProvider ? dependencyProvider.URLRequestHandlerClassNames : @[]; } NSMutableArray *modules = [NSMutableArray new]; for (NSString *className in classNames) { const char *cModuleName = [className cStringUsingEncoding:NSUTF8StringEncoding]; id moduleFromLibrary = [moduleRegistry moduleForName:cModuleName]; if (![moduleFromLibrary conformsToProtocol:protocol]) { continue; } [modules addObject:moduleFromLibrary]; } return modules; }; // Set up the default RCTImageLoader and RCTNetworking modules. if (moduleClass == RCTImageLoader.class) { return [[moduleClass alloc] initWithRedirectDelegate:nil loadersProvider:^NSArray> *(RCTModuleRegistry *moduleRegistry) { NSArray *imageURLLoaderModules = extractModuleConformingToProtocol(moduleRegistry, @protocol(RCTImageURLLoader)); return [@[ [RCTBundleAssetImageLoader new] ] arrayByAddingObjectsFromArray:imageURLLoaderModules]; } decodersProvider:^NSArray> *(RCTModuleRegistry *moduleRegistry) { NSArray *imageDataDecoder = extractModuleConformingToProtocol(moduleRegistry, @protocol(RCTImageDataDecoder)); return [@[ [RCTGIFImageDecoder new] ] arrayByAddingObjectsFromArray:imageDataDecoder]; }]; } else if (moduleClass == RCTNetworking.class) { return [[moduleClass alloc] initWithHandlersProvider:^NSArray> *(RCTModuleRegistry *moduleRegistry) { NSArray *URLRequestHandlerModules = extractModuleConformingToProtocol(moduleRegistry, @protocol(RCTURLRequestHandler)); return [@[ [RCTHTTPRequestHandler new], [RCTDataRequestHandler new], [RCTFileRequestHandler new], [moduleRegistry moduleForName:"BlobModule"], ] arrayByAddingObjectsFromArray:URLRequestHandlerModules]; }]; } // No custom initializer here. return [moduleClass new]; } std::unique_ptr RCTAppSetupDefaultJsExecutorFactory( RCTBridge *bridge, RCTTurboModuleManager *turboModuleManager, const std::shared_ptr &runtimeScheduler) { // Necessary to allow NativeModules to lookup TurboModules [bridge setRCTTurboModuleRegistry:turboModuleManager]; #if RCT_DEV /** * Instantiating DevMenu has the side-effect of registering * shortcuts for CMD + d, CMD + i, and CMD + n via RCTDevMenu. * Therefore, when TurboModules are enabled, we must manually create this * NativeModule. */ [turboModuleManager moduleForName:"RCTDevMenu"]; #endif // end RCT_DEV #if USE_HERMES return std::make_unique( #else return std::make_unique( #endif // USE_HERMES facebook::react::RCTJSIExecutorRuntimeInstaller( [turboModuleManager, bridge, runtimeScheduler](facebook::jsi::Runtime &runtime) { if (!bridge || !turboModuleManager) { return; } if (runtimeScheduler) { facebook::react::RuntimeSchedulerBinding::createAndInstallIfNeeded(runtime, runtimeScheduler); } [turboModuleManager installJSBindings:runtime]; })); } std::unique_ptr RCTAppSetupJsExecutorFactoryForOldArch( RCTBridge *bridge, const std::shared_ptr &runtimeScheduler) { #if USE_HERMES return std::make_unique( #else return std::make_unique( #endif // USE_HERMES facebook::react::RCTJSIExecutorRuntimeInstaller([bridge, runtimeScheduler](facebook::jsi::Runtime &runtime) { if (!bridge) { return; } if (runtimeScheduler) { facebook::react::RuntimeSchedulerBinding::createAndInstallIfNeeded(runtime, runtimeScheduler); } })); }