Skip to content

Commit 3afa03c

Browse files
committed
feat: Implement RCTRootViewFactory
1 parent c2c5791 commit 3afa03c

File tree

8 files changed

+454
-201
lines changed

8 files changed

+454
-201
lines changed

packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#import <React/RCTBridgeDelegate.h>
99
#import <UIKit/UIKit.h>
10+
#import "RCTRootViewFactory.h"
1011

1112
@class RCTBridge;
1213
@protocol RCTBridgeDelegate;
@@ -58,9 +59,9 @@ NS_ASSUME_NONNULL_BEGIN
5859

5960
/// The window object, used to render the UViewControllers
6061
@property (nonatomic, strong, nonnull) UIWindow *window;
61-
@property (nonatomic, strong, nullable) RCTBridge *bridge;
6262
@property (nonatomic, strong, nullable) NSString *moduleName;
6363
@property (nonatomic, strong, nullable) NSDictionary *initialProps;
64+
@property (nonatomic, strong) RCTRootViewFactory* rootViewFactory;
6465

6566
/**
6667
* It creates a `RCTBridge` using a delegate and some launch options.
@@ -127,13 +128,6 @@ NS_ASSUME_NONNULL_BEGIN
127128
*/
128129
- (void)setRootView:(UIView *)rootView toRootViewController:(UIViewController *)rootViewController;
129130

130-
/// This method controls whether the App will use RuntimeScheduler. Only applicable in the legacy architecture.
131-
///
132-
/// @return: `YES` to use RuntimeScheduler, `NO` to use JavaScript scheduler. The default value is `YES`.
133-
- (BOOL)runtimeSchedulerEnabled;
134-
135-
@property (nonatomic, strong) RCTSurfacePresenterBridgeAdapter *bridgeAdapter;
136-
137131
/// This method returns a map of Component Descriptors and Components classes that needs to be registered in the
138132
/// new renderer. The Component Descriptor is a string which represent the name used in JS to refer to the native
139133
/// component. The default implementation returns an empty dictionary. Subclasses can override this method to register

packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm

Lines changed: 41 additions & 186 deletions
Original file line numberDiff line numberDiff line change
@@ -39,54 +39,47 @@
3939
#import <react/renderer/runtimescheduler/RuntimeSchedulerCallInvoker.h>
4040
#import <react/runtime/JSRuntimeFactory.h>
4141

42-
static NSString *const kRNConcurrentRoot = @"concurrentRoot";
43-
44-
@interface RCTAppDelegate () <
45-
RCTTurboModuleManagerDelegate,
46-
RCTComponentViewFactoryComponentProvider,
47-
RCTContextContainerHandling> {
48-
std::shared_ptr<const facebook::react::ReactNativeConfig> _reactNativeConfig;
49-
facebook::react::ContextContainer::Shared _contextContainer;
50-
}
51-
@end
52-
53-
static NSDictionary *updateInitialProps(NSDictionary *initialProps, BOOL isFabricEnabled)
54-
{
55-
NSMutableDictionary *mutableProps = [initialProps mutableCopy] ?: [NSMutableDictionary new];
56-
// Hardcoding the Concurrent Root as it it not recommended to
57-
// have the concurrentRoot turned off when Fabric is enabled.
58-
mutableProps[kRNConcurrentRoot] = @(isFabricEnabled);
59-
return mutableProps;
60-
}
61-
62-
@interface RCTAppDelegate () <RCTCxxBridgeDelegate> {
63-
std::shared_ptr<facebook::react::RuntimeScheduler> _runtimeScheduler;
64-
}
42+
@interface RCTAppDelegate () <RCTComponentViewFactoryComponentProvider>
6543
@end
6644

67-
@implementation RCTAppDelegate {
68-
RCTHost *_reactHost;
69-
}
70-
71-
- (instancetype)init
72-
{
73-
if (self = [super init]) {
74-
_contextContainer = std::make_shared<facebook::react::ContextContainer const>();
75-
_reactNativeConfig = std::make_shared<facebook::react::EmptyReactNativeConfig const>();
76-
_contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
77-
}
78-
return self;
79-
}
45+
@implementation RCTAppDelegate
8046

8147
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
8248
{
8349
RCTSetNewArchEnabled([self newArchEnabled]);
8450
BOOL enableTM = self.turboModuleEnabled;
85-
86-
RCTAppSetupPrepareApp(application, enableTM, *_reactNativeConfig);
8751

88-
UIView *rootView = [self viewWithModuleName:self.moduleName initialProperties:[self prepareInitialProps] launchOptions:launchOptions];
89-
52+
#pragma clang diagnostic push
53+
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
54+
RCTAppSetupPrepareApp(application, enableTM);
55+
#pragma clang diagnostic pop
56+
57+
RCTRootViewFactoryConfiguration *configuration = [[RCTRootViewFactoryConfiguration alloc] initWithBundleURL:self.bundleURL];
58+
configuration.fabricEnabled = self.fabricEnabled;
59+
configuration.turboModuleEnabled = self.turboModuleEnabled;
60+
configuration.bridgelessEnabled = self.bridgelessEnabled;
61+
62+
__weak __typeof(self) weakSelf = self;
63+
configuration.createRootViewWithBridge = ^UIView* (RCTBridge *bridge, NSString *moduleName, NSDictionary *initProps) {
64+
return [weakSelf createRootViewWithBridge:bridge moduleName:moduleName initProps:initProps];
65+
};
66+
67+
configuration.createBridgeWithDelegate = ^RCTBridge* (id<RCTBridgeDelegate> delegate, NSDictionary* launchOptions) {
68+
return [weakSelf createBridgeWithDelegate:delegate launchOptions:launchOptions];
69+
};
70+
71+
self.rootViewFactory = [[RCTRootViewFactory alloc] initWithConfiguration:configuration];
72+
73+
UIView *rootView = [self.rootViewFactory viewWithModuleName:self.moduleName
74+
initialProperties:self.initialProps
75+
launchOptions:launchOptions];
76+
77+
if (self.newArchEnabled || self.bridgelessEnabled) {
78+
[RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self;
79+
}
80+
81+
[self customizeRootView:(RCTRootView* )rootView];
82+
9083
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
9184
UIViewController *rootViewController = [self createRootViewController];
9285
[self setRootView:rootView toRootViewController:rootViewController];
@@ -97,55 +90,6 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
9790
return YES;
9891
}
9992

100-
- (UIView *)viewWithModuleName:(NSString *)moduleName
101-
initialProperties:(NSDictionary *)initialProperties
102-
launchOptions:(NSDictionary *)launchOptions {
103-
BOOL fabricEnabled = self.fabricEnabled;
104-
BOOL enableBridgeless = self.bridgelessEnabled;
105-
106-
NSDictionary *initProps = updateInitialProps(initialProperties, fabricEnabled);
107-
108-
UIView *rootView;
109-
if (enableBridgeless) {
110-
// Enable native view config interop only if both bridgeless mode and Fabric is enabled.
111-
RCTSetUseNativeViewConfigsInBridgelessMode(fabricEnabled);
112-
113-
// Enable TurboModule interop by default in Bridgeless mode
114-
RCTEnableTurboModuleInterop(YES);
115-
RCTEnableTurboModuleInteropBridgeProxy(YES);
116-
117-
if (!_reactHost) {
118-
[self createReactHost];
119-
}
120-
121-
[RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self;
122-
RCTFabricSurface *surface = [_reactHost createSurfaceWithModuleName:self.moduleName initialProperties:initProps];
123-
124-
RCTSurfaceHostingProxyRootView *surfaceHostingProxyRootView = [[RCTSurfaceHostingProxyRootView alloc]
125-
initWithSurface:surface
126-
sizeMeasureMode:RCTSurfaceSizeMeasureModeWidthExact | RCTSurfaceSizeMeasureModeHeightExact];
127-
128-
rootView = (RCTRootView *)surfaceHostingProxyRootView;
129-
} else {
130-
if (!self.bridge) {
131-
self.bridge = [self createBridgeWithDelegate:self launchOptions:launchOptions];
132-
}
133-
if ([self newArchEnabled]) {
134-
if (!self.bridgeAdapter) {
135-
self.bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:self.bridge
136-
contextContainer:_contextContainer];
137-
self.bridge.surfacePresenter = self.bridgeAdapter.surfacePresenter;
138-
139-
[RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self;
140-
}
141-
}
142-
rootView = [self createRootViewWithBridge:self.bridge moduleName:self.moduleName initProps:initProps];
143-
}
144-
[self customizeRootView:(RCTRootView *)rootView];
145-
146-
return rootView;
147-
}
148-
14993
- (void)applicationDidEnterBackground:(UIApplication *)application
15094
{
15195
// Noop
@@ -158,21 +102,11 @@ - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
158102
return nil;
159103
}
160104

161-
- (NSDictionary *)prepareInitialProps
162-
{
163-
return self.initialProps;
164-
}
165-
166105
- (RCTBridge *)createBridgeWithDelegate:(id<RCTBridgeDelegate>)delegate launchOptions:(NSDictionary *)launchOptions
167106
{
168107
return [[RCTBridge alloc] initWithDelegate:delegate launchOptions:launchOptions];
169108
}
170109

171-
- (void)customizeRootView:(RCTRootView *)rootView
172-
{
173-
// Override point for customization after application launch.
174-
}
175-
176110
- (UIView *)createRootViewWithBridge:(RCTBridge *)bridge
177111
moduleName:(NSString *)moduleName
178112
initProps:(NSDictionary *)initProps
@@ -211,9 +145,9 @@ - (void)setRootView:(UIView *)rootView toRootViewController:(UIViewController *)
211145
rootViewController.view = rootView;
212146
}
213147

214-
- (BOOL)runtimeSchedulerEnabled
148+
- (void)customizeRootView:(RCTRootView *)rootView
215149
{
216-
return YES;
150+
// Override point for customization after application launch.
217151
}
218152

219153
#pragma mark - UISceneDelegate
@@ -225,24 +159,6 @@ - (void)windowScene:(UIWindowScene *)windowScene
225159
[[NSNotificationCenter defaultCenter] postNotificationName:RCTWindowFrameDidChangeNotification object:self];
226160
}
227161

228-
#pragma mark - RCTCxxBridgeDelegate
229-
- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge
230-
{
231-
_runtimeScheduler = std::make_shared<facebook::react::RuntimeScheduler>(RCTRuntimeExecutorFromBridge(bridge));
232-
if ([self newArchEnabled]) {
233-
std::shared_ptr<facebook::react::CallInvoker> callInvoker =
234-
std::make_shared<facebook::react::RuntimeSchedulerCallInvoker>(_runtimeScheduler);
235-
RCTTurboModuleManager *turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge
236-
delegate:self
237-
jsInvoker:callInvoker];
238-
_contextContainer->erase("RuntimeScheduler");
239-
_contextContainer->insert("RuntimeScheduler", _runtimeScheduler);
240-
return RCTAppSetupDefaultJsExecutorFactory(bridge, turboModuleManager, _runtimeScheduler);
241-
} else {
242-
return RCTAppSetupJsExecutorFactoryForOldArch(bridge, _runtimeScheduler);
243-
}
244-
}
245-
246162
#pragma mark - New Arch Enabled settings
247163

248164
- (BOOL)newArchEnabled
@@ -269,79 +185,18 @@ - (BOOL)bridgelessEnabled
269185
return NO;
270186
}
271187

272-
#pragma mark - RCTComponentViewFactoryComponentProvider
273-
274-
- (NSDictionary<NSString *, Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents
275-
{
276-
return @{};
277-
}
278-
279-
#pragma mark - RCTTurboModuleManagerDelegate
280-
281-
- (Class)getModuleClassFromName:(const char *)name
282-
{
283-
#if RN_DISABLE_OSS_PLUGIN_HEADER
284-
return RCTTurboModulePluginClassProvider(name);
285-
#else
286-
return RCTCoreModulesClassProvider(name);
287-
#endif
288-
}
289-
290-
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
291-
jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
292-
{
293-
return nullptr;
294-
}
295-
296-
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
297-
initParams:
298-
(const facebook::react::ObjCTurboModule::InitParams &)params
299-
{
188+
- (NSURL *)bundleURL {
189+
[NSException raise:@"RCTAppDelegate::bundleURL not implemented"
190+
format:@"Subclasses must implement a valid getBundleURL method"];
300191
return nullptr;
301192
}
302193

303-
- (id<RCTTurboModule>)getModuleInstanceFromClass:(Class)moduleClass
304-
{
305-
return RCTAppSetupDefaultModuleFromClass(moduleClass);
306-
}
307-
308-
#pragma mark - New Arch Utilities
309-
310-
- (void)createReactHost
311-
{
312-
__weak __typeof(self) weakSelf = self;
313-
_reactHost = [[RCTHost alloc] initWithBundleURL:[self bundleURL]
314-
hostDelegate:nil
315-
turboModuleManagerDelegate:self
316-
jsEngineProvider:^std::shared_ptr<facebook::react::JSRuntimeFactory>() {
317-
return [weakSelf createJSRuntimeFactory];
318-
}];
319-
[_reactHost setBundleURLProvider:^NSURL *() {
320-
return [weakSelf bundleURL];
321-
}];
322-
[_reactHost setContextContainerHandler:self];
323-
[_reactHost start];
324-
}
325-
326-
- (std::shared_ptr<facebook::react::JSRuntimeFactory>)createJSRuntimeFactory
327-
{
328-
#if USE_HERMES
329-
return std::make_shared<facebook::react::RCTHermesInstance>(_reactNativeConfig, nullptr);
330-
#else
331-
return std::make_shared<facebook::react::RCTJscInstance>();
332-
#endif
333-
}
334194

335-
- (void)didCreateContextContainer:(std::shared_ptr<facebook::react::ContextContainer>)contextContainer
336-
{
337-
contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
338-
}
195+
#pragma mark - RCTComponentViewFactoryComponentProvider
339196

340-
- (NSURL *)bundleURL
197+
- (NSDictionary<NSString *, Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents
341198
{
342-
[NSException raise:@"RCTAppDelegate::bundleURL not implemented"
343-
format:@"Subclasses must implement a valid getBundleURL method"];
344-
return nullptr;
199+
return @{};
345200
}
346201

347202
@end

packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ void RCTAppSetupPrepareApp(
5151
BOOL turboModuleEnabled,
5252
const facebook::react::ReactNativeConfig &reactNativeConfig);
5353

54+
void RCTAppSetupPrepareConfig(const facebook::react::ReactNativeConfig &reactNativeConfig);
55+
5456
#endif // __cplusplus
5557

5658
RCT_EXTERN_C_BEGIN

packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.mm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@ void RCTAppSetupPrepareApp(
4747
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
4848
RCTAppSetupPrepareApp(application, turboModuleEnabled);
4949
#pragma clang diagnostic pop
50+
RCTAppSetupPrepareConfig(reactNativeConfig);
51+
}
5052

53+
void RCTAppSetupPrepareConfig(const facebook::react::ReactNativeConfig &reactNativeConfig)
54+
{
5155
auto &inspectorFlags = facebook::react::jsinspector_modern::InspectorFlags::getInstance();
5256
inspectorFlags.initFromConfig(reactNativeConfig);
5357
}

0 commit comments

Comments
 (0)