Make RNTester use RCTAppDelegate (#37572)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/37572

Currently, RNTester was using a completely custom AppDelegate and not leveraging the RCTAppDelegate we use in the OSS. This resulted in a misalignment between the two setups and duplicated work to test stuff internally furst and then in the OSS, with some more time needed to understand why one setup was working and the other wasn't.

With this change, we are aligning the two, bringing RNTester closer to the OSS setup. There are still small differences, but we can iterate over those.

## Changelog:
[iOS][Changed] - Make RNTester use RCTAppDelegate

Reviewed By: cortinico

Differential Revision: D46182888

fbshipit-source-id: 7c55b06de1a317b1f2d4ad0d18a390dc4d3356a4
This commit is contained in:
Riccardo Cipolleschi
2023-05-30 04:10:17 -07:00
committed by Facebook GitHub Bot
parent 551bbbc234
commit 680cbe757b
7 changed files with 21 additions and 337 deletions
@@ -1,3 +1,4 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
@@ -11,7 +12,7 @@
+ (NSArray<NSString *> *)legacyInteropComponents
{
return @[];
return @[ @"RNTMyLegacyNativeView" ];
}
@end
+2 -6
View File
@@ -5,13 +5,9 @@
* LICENSE file in the root directory of this source tree.
*/
#import <RCTAppDelegate.h>
#import <UIKit/UIKit.h>
@class RCTBridge;
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (nonatomic, strong) UIWindow *window;
@property (nonatomic, readonly) RCTBridge *bridge;
@interface AppDelegate : RCTAppDelegate
@end
+16 -255
View File
@@ -7,161 +7,30 @@
#import "AppDelegate.h"
#ifndef RCT_USE_HERMES
#if __has_include(<reacthermes/HermesExecutorFactory.h>)
#define RCT_USE_HERMES 1
#else
#define RCT_USE_HERMES 0
#endif
#endif
#ifdef RCT_NEW_ARCH_ENABLED
#ifndef RN_FABRIC_ENABLED
#define RN_FABRIC_ENABLED
#endif
#endif
#if RCT_USE_HERMES
#import <reacthermes/HermesExecutorFactory.h>
#else
#import <React/JSCExecutorFactory.h>
#endif
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTCxxBridgeDelegate.h>
#import <React/RCTDataRequestHandler.h>
#import <React/RCTFileRequestHandler.h>
#import <React/RCTGIFImageDecoder.h>
#import <React/RCTHTTPRequestHandler.h>
#import <React/RCTImageLoader.h>
#import <React/RCTJSIExecutorRuntimeInstaller.h>
#import <React/RCTJavaScriptLoader.h>
#import <React/RCTLinkingManager.h>
#import <React/RCTLocalAssetImageLoader.h>
#import <React/RCTNetworking.h>
#import <React/RCTRootView.h>
#import <React/RCTRuntimeExecutorFromBridge.h>
#import <ReactCommon/RuntimeExecutor.h>
#import <react/renderer/runtimescheduler/RuntimeScheduler.h>
#import <react/renderer/runtimescheduler/RuntimeSchedulerBinding.h>
#import <cxxreact/JSExecutor.h>
#import <ReactCommon/RCTSampleTurboModule.h>
#import <ReactCommon/SampleTurboCxxModule.h>
#if !TARGET_OS_TV && !TARGET_OS_UIKITFORMAC
#import <React/RCTPushNotificationManager.h>
#endif
#ifdef RN_FABRIC_ENABLED
#import <React/RCTComponentViewFactory.h>
#import <React/RCTFabricSurfaceHostingProxyRootView.h>
#import <React/RCTSurfacePresenter.h>
#import <React/RCTSurfacePresenterBridgeAdapter.h>
#import <React/RCTLegacyViewManagerInteropComponentView.h>
#import <react/config/ReactNativeConfig.h>
#import <react/renderer/runtimescheduler/RuntimeSchedulerCallInvoker.h>
#endif
#if RCT_NEW_ARCH_ENABLED
#import <NativeCxxModuleExample/NativeCxxModuleExample.h>
#import <RNTMyNativeViewComponentView.h>
#endif
#if DEBUG
#ifdef FB_SONARKIT_ENABLED
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitLayoutPlugin/SKDescriptorMapper.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#endif
#endif
#import <ReactCommon/RCTTurboModuleManager.h>
#import "RNTesterTurboModuleProvider.h"
@interface RCTBridge ()
- (std::shared_ptr<facebook::react::MessageQueueThread>)jsMessageThread;
- (void)invokeAsync:(std::function<void()> &&)func;
@end
using namespace facebook::react;
@interface AppDelegate () <RCTCxxBridgeDelegate, RCTTurboModuleManagerDelegate> {
std::shared_ptr<facebook::react::RuntimeScheduler> _runtimeScheduler;
#ifdef RN_FABRIC_ENABLED
RCTSurfacePresenterBridgeAdapter *_bridgeAdapter;
std::shared_ptr<const facebook::react::ReactNativeConfig> _reactNativeConfig;
facebook::react::ContextContainer::Shared _contextContainer;
#endif
}
@end
#if RCT_NEW_ARCH_ENABLED
/// Declare conformance to `RCTComponentViewFactoryComponentProvider`
@interface AppDelegate () <RCTComponentViewFactoryComponentProvider>
@end
#endif
static NSString *const kRNConcurrentRoot = @"concurrentRoot";
@implementation AppDelegate
#ifdef RN_FABRIC_ENABLED
- (instancetype)init
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if (self = [super init]) {
_contextContainer = std::make_shared<facebook::react::ContextContainer const>();
_reactNativeConfig = std::make_shared<facebook::react::EmptyReactNativeConfig const>();
_contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
}
return self;
}
#endif
self.moduleName = @"RNTesterApp";
// You can add your custom initial props in the dictionary below.
// They will be passed down to the ViewController used by React Native.
self.initialProps = [self prepareInitialProps];
- (BOOL)application:(__unused UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
RCTEnableTurboModule(YES);
_bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
// Appetizer.io params check
NSDictionary *initProps = [self prepareInitialProps];
#if RCT_NEW_ARCH_ENABLED
[RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self;
#endif
#ifdef RN_FABRIC_ENABLED
_bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:_bridge contextContainer:_contextContainer];
_bridge.surfacePresenter = _bridgeAdapter.surfacePresenter;
UIView *rootView = [[RCTFabricSurfaceHostingProxyRootView alloc] initWithBridge:_bridge
moduleName:@"RNTesterApp"
initialProperties:initProps];
[self registerPaperComponents:@[ @"RNTMyLegacyNativeView" ]];
#else
UIView *rootView = [[RCTRootView alloc] initWithBridge:_bridge moduleName:@"RNTesterApp" initialProperties:initProps];
#endif
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
[self initializeFlipper:application];
return YES;
}
- (BOOL)concurrentRootEnabled
{
// Switch this bool to turn on and off the concurrent root
return true;
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
- (NSDictionary *)prepareInitialProps
@@ -173,34 +42,14 @@ static NSString *const kRNConcurrentRoot = @"concurrentRoot";
initProps[@"exampleFromAppetizeParams"] = [NSString stringWithFormat:@"rntester://example/%@Example", _routeUri];
}
#ifdef RN_FABRIC_ENABLED
initProps[kRNConcurrentRoot] = @([self concurrentRootEnabled]);
#endif
return initProps;
}
- (NSURL *)sourceURLForBridge:(__unused RCTBridge *)bridge
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"js/RNTesterApp.ios"];
}
- (void)initializeFlipper:(UIApplication *)application
{
#if DEBUG
#ifdef FB_SONARKIT_ENABLED
FlipperClient *client = [FlipperClient sharedClient];
SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
[client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application
withDescriptorMapper:layoutDescriptorMapper]];
[client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
[client addPlugin:[FlipperKitReactPlugin new]];
[client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
[client start];
#endif
#endif
}
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
@@ -215,108 +64,20 @@ static NSString *const kRNConcurrentRoot = @"concurrentRoot";
[RCTJavaScriptLoader loadBundleAtURL:[self sourceURLForBridge:bridge] onProgress:onProgress onComplete:loadCallback];
}
#pragma mark - RCTCxxBridgeDelegate
// This function is called during
// `[[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];`
- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge
{
std::shared_ptr<facebook::react::CallInvoker> callInvoker = bridge.jsCallInvoker;
_runtimeScheduler = std::make_shared<facebook::react::RuntimeScheduler>(RCTRuntimeExecutorFromBridge(bridge));
#ifdef RN_FABRIC_ENABLED
_contextContainer->erase("RuntimeScheduler");
_contextContainer->insert("RuntimeScheduler", _runtimeScheduler);
callInvoker = std::make_shared<facebook::react::RuntimeSchedulerCallInvoker>(_runtimeScheduler);
#endif
RCTTurboModuleManager *turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge
delegate:self
jsInvoker:callInvoker];
[bridge setRCTTurboModuleRegistry:turboModuleManager];
#if RCT_DEV
/**
* Eagerly initialize RCTDevMenu so CMD + d, CMD + i, and CMD + r work.
* This is a stop gap until we have a system to eagerly init Turbo Modules.
*/
[turboModuleManager moduleForName:"RCTDevMenu"];
#endif
__weak __typeof(self) weakSelf = self;
#if RCT_USE_HERMES
return std::make_unique<facebook::react::HermesExecutorFactory>(
#else
return std::make_unique<facebook::react::JSCExecutorFactory>(
#endif
facebook::react::RCTJSIExecutorRuntimeInstaller([weakSelf, bridge, turboModuleManager](
facebook::jsi::Runtime &runtime) {
if (!bridge) {
return;
}
__typeof(self) strongSelf = weakSelf;
if (strongSelf && strongSelf->_runtimeScheduler) {
facebook::react::RuntimeSchedulerBinding::createAndInstallIfNeeded(runtime, strongSelf->_runtimeScheduler);
}
facebook::react::RuntimeExecutor syncRuntimeExecutor =
[&](std::function<void(facebook::jsi::Runtime & runtime_)> &&callback) { callback(runtime); };
[turboModuleManager installJSBindingWithRuntimeExecutor:syncRuntimeExecutor];
}));
}
#pragma mark - RCTTurboModuleManagerDelegate
- (Class)getModuleClassFromName:(const char *)name
{
return facebook::react::RNTesterTurboModuleClassProvider(name);
}
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
{
return facebook::react::RNTesterTurboModuleProvider(name, jsInvoker);
}
- (id<RCTTurboModule>)getModuleInstanceFromClass:(Class)moduleClass
{
// Set up the default RCTImageLoader and RCTNetworking modules.
if (moduleClass == RCTImageLoader.class) {
return [[moduleClass alloc] initWithRedirectDelegate:nil
loadersProvider:^NSArray<id<RCTImageURLLoader>> *(RCTModuleRegistry *) {
return @[ [RCTLocalAssetImageLoader new] ];
}
decodersProvider:^NSArray<id<RCTImageDataDecoder>> *(RCTModuleRegistry *) {
return @[ [RCTGIFImageDecoder new] ];
}];
} else if (moduleClass == RCTNetworking.class) {
return [[moduleClass alloc] initWithHandlersProvider:^NSArray<id<RCTURLRequestHandler>> *(RCTModuleRegistry *) {
return @[
[RCTHTTPRequestHandler new],
[RCTDataRequestHandler new],
[RCTFileRequestHandler new],
];
}];
if (name == std::string([@"SampleTurboCxxModule" UTF8String])) {
return std::make_shared<facebook::react::SampleTurboCxxModule>(jsInvoker);
}
// No custom initializer here.
return [moduleClass new];
}
#pragma mark - Interop layer
- (void)registerPaperComponents:(NSArray<NSString *> *)components
{
#if RCT_NEW_ARCH_ENABLED
for (NSString *component in components) {
[RCTLegacyViewManagerInteropComponentView supportLegacyViewManagerWithName:component];
#ifdef RCT_NEW_ARCH_ENABLED
if (name == std::string([@"NativeCxxModuleExampleCxx" UTF8String])) {
return std::make_shared<facebook::react::NativeCxxModuleExample>(jsInvoker);
}
#endif
return nullptr;
}
#pragma mark - Push Notifications
#if !TARGET_OS_TV && !TARGET_OS_UIKITFORMAC
// Required to register for notifications
@@ -1,26 +0,0 @@
/*
* 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 <ReactCommon/RCTTurboModule.h>
namespace facebook {
namespace react {
/**
* Provide the TurboModule class for the given name.
*/
Class RNTesterTurboModuleClassProvider(const char *name);
/**
* Provide a pure C++ instance of a TurboModule, specific to this app.
*/
std::shared_ptr<TurboModule> RNTesterTurboModuleProvider(
const std::string &name,
std::shared_ptr<CallInvoker> jsInvoker);
} // namespace react
} // namespace facebook
@@ -1,43 +0,0 @@
/*
* 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 "RNTesterTurboModuleProvider.h"
#ifdef RCT_NEW_ARCH_ENABLED
#import <NativeCxxModuleExample/NativeCxxModuleExample.h>
#endif
#import <React/CoreModulesPlugins.h>
#import <ReactCommon/RCTSampleTurboModule.h>
#import <ReactCommon/SampleTurboCxxModule.h>
// NOTE: This entire file should be codegen'ed.
namespace facebook {
namespace react {
Class RNTesterTurboModuleClassProvider(const char *name)
{
return RCTCoreModulesClassProvider(name);
}
std::shared_ptr<TurboModule> RNTesterTurboModuleProvider(
const std::string &name,
std::shared_ptr<CallInvoker> jsInvoker)
{
if (name == "SampleTurboCxxModule") {
return std::make_shared<SampleTurboCxxModule>(jsInvoker);
}
#ifdef RCT_NEW_ARCH_ENABLED
if (name == "NativeCxxModuleExampleCxx") {
return std::make_shared<NativeCxxModuleExample>(jsInvoker);
}
#endif
return nullptr;
}
} // namespace react
} // namespace facebook
@@ -15,7 +15,6 @@
383889DA23A7398900D06C3E /* RCTConvert_UIColorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 383889D923A7398900D06C3E /* RCTConvert_UIColorTests.m */; };
3D2AFAF51D646CF80089D1A3 /* legacy_image@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3D2AFAF41D646CF80089D1A3 /* legacy_image@2x.png */; };
5C60EB1C226440DB0018C04F /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C60EB1B226440DB0018C04F /* AppDelegate.mm */; };
5CB07C9B226467E60039471C /* RNTesterTurboModuleProvider.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5CB07C99226467E60039471C /* RNTesterTurboModuleProvider.mm */; };
8145AE06241172D900A3F8DA /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8145AE05241172D900A3F8DA /* LaunchScreen.storyboard */; };
953D44E0A849F5064163EA24 /* libPods-RNTesterIntegrationTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4F4A7C4C85AB0198A25D51E4 /* libPods-RNTesterIntegrationTests.a */; };
BE3BEE3556275C62F33864C8 /* libPods-RNTesterUnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6144DEEE56C6C17B301A90E4 /* libPods-RNTesterUnitTests.a */; };
@@ -96,8 +95,6 @@
3D2AFAF41D646CF80089D1A3 /* legacy_image@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "legacy_image@2x.png"; path = "RNTester/legacy_image@2x.png"; sourceTree = "<group>"; };
4F4A7C4C85AB0198A25D51E4 /* libPods-RNTesterIntegrationTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTesterIntegrationTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
5C60EB1B226440DB0018C04F /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = RNTester/AppDelegate.mm; sourceTree = "<group>"; };
5CB07C99226467E60039471C /* RNTesterTurboModuleProvider.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RNTesterTurboModuleProvider.mm; path = RNTester/RNTesterTurboModuleProvider.mm; sourceTree = "<group>"; };
5CB07C9A226467E60039471C /* RNTesterTurboModuleProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNTesterTurboModuleProvider.h; path = RNTester/RNTesterTurboModuleProvider.h; sourceTree = "<group>"; };
6144DEEE56C6C17B301A90E4 /* libPods-RNTesterUnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTesterUnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
7FC437025B5EE3899315628B /* Pods-RNTester.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTester.release.xcconfig"; path = "Target Support Files/Pods-RNTester/Pods-RNTester.release.xcconfig"; sourceTree = "<group>"; };
8145AE05241172D900A3F8DA /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = RNTester/LaunchScreen.storyboard; sourceTree = "<group>"; };
@@ -230,8 +227,6 @@
E771AEEA22B44E3100EA1189 /* Info.plist */,
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
5C60EB1B226440DB0018C04F /* AppDelegate.mm */,
5CB07C9A226467E60039471C /* RNTesterTurboModuleProvider.h */,
5CB07C99226467E60039471C /* RNTesterTurboModuleProvider.mm */,
13B07FB71A68108700A75B9A /* main.m */,
2DDEF00F1F84BF7B00DBDF73 /* Images.xcassets */,
8145AE05241172D900A3F8DA /* LaunchScreen.storyboard */,
@@ -762,7 +757,6 @@
buildActionMask = 2147483647;
files = (
272E6B3F1BEA849E001FCF37 /* UpdatePropertiesExampleView.m in Sources */,
5CB07C9B226467E60039471C /* RNTesterTurboModuleProvider.mm in Sources */,
27F441EC1BEBE5030039B79C /* FlexibleSizeExampleView.m in Sources */,
5C60EB1C226440DB0018C04F /* AppDelegate.mm in Sources */,
13B07FC11A68108700A75B9A /* main.m in Sources */,
@@ -28,6 +28,7 @@ module.exports = {
project: {
ios: {
sourceDir: '.',
unstable_reactLegacyComponentNames: ['RNTMyLegacyNativeView'],
},
android: {
sourceDir: '../../',