forked from facebook/react-native
-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e6c1b21
commit e8f630f
Showing
7 changed files
with
397 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
packages/react-native/Libraries/AppDelegate/RCTReactController.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
#import <React/RCTBridgeDelegate.h> | ||
#import <UIKit/UIKit.h> | ||
|
||
@class RCTBridge; | ||
@protocol RCTBridgeDelegate; | ||
@protocol RCTComponentViewProtocol; | ||
@class RCTRootView; | ||
@class RCTSurfacePresenterBridgeAdapter; | ||
|
||
@protocol RCTAppControllerDelegate<RCTBridgeDelegate> | ||
|
||
- (NSURL *)bundleURL; | ||
|
||
@end | ||
|
||
@interface RCTReactController : UIViewController<RCTAppControllerDelegate> | ||
|
||
@property (nonatomic, strong) RCTBridge *bridge; | ||
@property (nonatomic, strong) NSString *moduleName; | ||
@property (nonatomic, strong) NSDictionary *initialProps; | ||
@property (nonatomic, weak) id<RCTBridgeDelegate> delegate; | ||
|
||
- (instancetype)initWithModuleName:(NSString*) moduleName; | ||
|
||
/// This method controls whether the App will use RuntimeScheduler. Only applicable in the legacy architecture. | ||
/// | ||
/// @return: `YES` to use RuntimeScheduler, `NO` to use JavaScript scheduler. The default value is `YES`. | ||
- (BOOL)runtimeSchedulerEnabled; | ||
|
||
@property (nonatomic, strong) RCTSurfacePresenterBridgeAdapter *bridgeAdapter; | ||
|
||
/// This method returns a map of Component Descriptors and Components classes that needs to be registered in the | ||
/// new renderer. The Component Descriptor is a string which represent the name used in JS to refer to the native | ||
/// component. The default implementation returns an empty dictionary. Subclasses can override this method to register | ||
/// the required components. | ||
/// | ||
/// @return a dictionary that associate a component for the new renderer with his descriptor. | ||
- (NSDictionary<NSString *, Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents; | ||
|
||
/// This method controls whether the `turboModules` feature of the New Architecture is turned on or off. | ||
/// | ||
/// @note: This is required to be rendering on Fabric (i.e. on the New Architecture). | ||
/// @return: `true` if the Turbo Native Module are enabled. Otherwise, it returns `false`. | ||
- (BOOL)turboModuleEnabled; | ||
|
||
/// This method controls whether the App will use the Fabric renderer of the New Architecture or not. | ||
/// | ||
/// @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; | ||
|
||
@end |
273 changes: 273 additions & 0 deletions
273
packages/react-native/Libraries/AppDelegate/RCTReactController.mm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,273 @@ | ||
#import "RCTReactController.h" | ||
#import <React/RCTCxxBridgeDelegate.h> | ||
#import <React/RCTLog.h> | ||
#import <React/RCTRootView.h> | ||
#import <React/RCTSurfacePresenterBridgeAdapter.h> | ||
#import <React/RCTUtils.h> | ||
#import <react/renderer/runtimescheduler/RuntimeScheduler.h> | ||
#import "RCTAppSetupUtils.h" | ||
#import <React/RCTUtils.h> | ||
|
||
#if RN_DISABLE_OSS_PLUGIN_HEADER | ||
#import <RCTTurboModulePlugin/RCTTurboModulePlugin.h> | ||
#else | ||
#import <React/CoreModulesPlugins.h> | ||
#endif | ||
#import <React/RCTBundleURLProvider.h> | ||
#import <React/RCTComponentViewFactory.h> | ||
#import <React/RCTComponentViewProtocol.h> | ||
#import <React/RCTFabricSurface.h> | ||
#import <React/RCTSurfaceHostingProxyRootView.h> | ||
#import <React/RCTSurfacePresenter.h> | ||
#import <ReactCommon/RCTContextContainerHandling.h> | ||
#if USE_HERMES | ||
#import <ReactCommon/RCTHermesInstance.h> | ||
#else | ||
#import <ReactCommon/RCTJscInstance.h> | ||
#endif | ||
#import <ReactCommon/RCTHost+Internal.h> | ||
#import <ReactCommon/RCTHost.h> | ||
#import <ReactCommon/RCTTurboModuleManager.h> | ||
#import <react/config/ReactNativeConfig.h> | ||
#import <react/renderer/runtimescheduler/RuntimeScheduler.h> | ||
#import <react/renderer/runtimescheduler/RuntimeSchedulerCallInvoker.h> | ||
#import <react/runtime/JSRuntimeFactory.h> | ||
|
||
static NSString *kBundlePath = @"js/RNTesterApp.ios"; | ||
|
||
static NSString *const kRNConcurrentRoot = @"concurrentRoot"; | ||
|
||
static NSDictionary *updateInitialProps(NSDictionary *initialProps, BOOL isFabricEnabled) | ||
{ | ||
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; | ||
} | ||
|
||
@interface RCTReactController () < | ||
RCTTurboModuleManagerDelegate, | ||
RCTComponentViewFactoryComponentProvider, | ||
RCTContextContainerHandling> { | ||
std::shared_ptr<const facebook::react::ReactNativeConfig> _reactNativeConfig; | ||
facebook::react::ContextContainer::Shared _contextContainer; | ||
} | ||
@end | ||
|
||
@interface RCTReactController () <RCTCxxBridgeDelegate> { | ||
std::shared_ptr<facebook::react::RuntimeScheduler> _runtimeScheduler; | ||
} | ||
@end | ||
|
||
@implementation RCTReactController { | ||
RCTHost *_reactHost; | ||
} | ||
|
||
|
||
- (instancetype)initWithModuleName:(NSString *)moduleName { | ||
if (self = [super init]) { | ||
_moduleName = moduleName; | ||
_contextContainer = std::make_shared<facebook::react::ContextContainer const>(); | ||
_reactNativeConfig = std::make_shared<facebook::react::EmptyReactNativeConfig const>(); | ||
_contextContainer->insert("ReactNativeConfig", _reactNativeConfig); | ||
} | ||
return self; | ||
} | ||
|
||
- (void)loadView { | ||
RCTSetNewArchEnabled([self newArchEnabled]); | ||
BOOL enableTM = self.turboModuleEnabled; | ||
BOOL fabricEnabled = self.fabricEnabled; | ||
BOOL enableBridgeless = self.bridgelessEnabled; | ||
|
||
NSDictionary *initProps = updateInitialProps([self prepareInitialProps], fabricEnabled); | ||
|
||
RCTAppSetupPrepareApp(nil, enableTM, *_reactNativeConfig); | ||
|
||
UIView *rootView; | ||
if (enableBridgeless) { | ||
// 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]; | ||
[RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self; | ||
RCTFabricSurface *surface = [_reactHost createSurfaceWithModuleName:self.moduleName initialProperties:initProps]; | ||
|
||
RCTSurfaceHostingProxyRootView *surfaceHostingProxyRootView = [[RCTSurfaceHostingProxyRootView alloc] | ||
initWithSurface:surface | ||
sizeMeasureMode:RCTSurfaceSizeMeasureModeWidthExact | RCTSurfaceSizeMeasureModeHeightExact]; | ||
|
||
rootView = (RCTRootView *)surfaceHostingProxyRootView; | ||
} else { | ||
if (!self.bridge) { | ||
self.bridge = [self createBridgeWithDelegate:self launchOptions:@{}]; | ||
} | ||
if ([self newArchEnabled]) { | ||
self.bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:self.bridge | ||
contextContainer:_contextContainer]; | ||
self.bridge.surfacePresenter = self.bridgeAdapter.surfacePresenter; | ||
|
||
[RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self; | ||
} | ||
rootView = [self createRootViewWithBridge:self.bridge moduleName:self.moduleName initProps:initProps]; | ||
} | ||
|
||
// Set rootView to the main of this view controller. | ||
self.view = rootView; | ||
} | ||
|
||
- (RCTBridge *)createBridgeWithDelegate:(id<RCTBridgeDelegate>)delegate launchOptions:(NSDictionary *)launchOptions | ||
{ | ||
return [[RCTBridge alloc] initWithDelegate:delegate launchOptions:launchOptions]; | ||
} | ||
|
||
- (UIView *)createRootViewWithBridge:(RCTBridge *)bridge | ||
moduleName:(NSString *)moduleName | ||
initProps:(NSDictionary *)initProps | ||
{ | ||
BOOL enableFabric = self.fabricEnabled; | ||
UIView *rootView = RCTAppSetupDefaultRootView(bridge, moduleName, initProps, enableFabric); | ||
|
||
rootView.backgroundColor = [UIColor systemBackgroundColor]; | ||
|
||
return rootView; | ||
} | ||
|
||
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { | ||
return [self.delegate sourceURLForBridge:bridge]; | ||
} | ||
|
||
- (BOOL)runtimeSchedulerEnabled | ||
{ | ||
return YES; | ||
} | ||
|
||
- (NSDictionary *)prepareInitialProps | ||
{ | ||
return self.initialProps; | ||
} | ||
|
||
#pragma mark - RCTCxxBridgeDelegate | ||
- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge | ||
{ | ||
_runtimeScheduler = std::make_shared<facebook::react::RuntimeScheduler>(RCTRuntimeExecutorFromBridge(bridge)); | ||
if ([self newArchEnabled]) { | ||
std::shared_ptr<facebook::react::CallInvoker> callInvoker = | ||
std::make_shared<facebook::react::RuntimeSchedulerCallInvoker>(_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); | ||
} | ||
} | ||
|
||
#pragma mark - New Arch Enabled settings | ||
|
||
- (BOOL)newArchEnabled | ||
{ | ||
#if USE_NEW_ARCH | ||
return YES; | ||
#else | ||
return NO; | ||
#endif | ||
} | ||
|
||
- (BOOL)turboModuleEnabled | ||
{ | ||
return [self newArchEnabled]; | ||
} | ||
|
||
- (BOOL)fabricEnabled | ||
{ | ||
return [self newArchEnabled]; | ||
} | ||
|
||
- (BOOL)bridgelessEnabled | ||
{ | ||
return NO; | ||
} | ||
|
||
#pragma mark - RCTComponentViewFactoryComponentProvider | ||
|
||
- (NSDictionary<NSString *, Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents | ||
{ | ||
return @{}; | ||
} | ||
|
||
#pragma mark - RCTTurboModuleManagerDelegate | ||
|
||
- (Class)getModuleClassFromName:(const char *)name | ||
{ | ||
#if RN_DISABLE_OSS_PLUGIN_HEADER | ||
return RCTTurboModulePluginClassProvider(name); | ||
#else | ||
return RCTCoreModulesClassProvider(name); | ||
#endif | ||
} | ||
|
||
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name | ||
jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker | ||
{ | ||
return nullptr; | ||
} | ||
|
||
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name | ||
initParams: | ||
(const facebook::react::ObjCTurboModule::InitParams &)params | ||
{ | ||
return nullptr; | ||
} | ||
|
||
- (id<RCTTurboModule>)getModuleInstanceFromClass:(Class)moduleClass | ||
{ | ||
return RCTAppSetupDefaultModuleFromClass(moduleClass); | ||
} | ||
|
||
#pragma mark - New Arch Utilities | ||
|
||
- (void)createReactHost | ||
{ | ||
__weak __typeof(self) weakSelf = self; | ||
_reactHost = [[RCTHost alloc] initWithBundleURL:[self bundleURL] | ||
hostDelegate:nil | ||
turboModuleManagerDelegate:self | ||
jsEngineProvider:^std::shared_ptr<facebook::react::JSRuntimeFactory>() { | ||
return [weakSelf createJSRuntimeFactory]; | ||
}]; | ||
[_reactHost setBundleURLProvider:^NSURL *() { | ||
return [weakSelf bundleURL]; | ||
}]; | ||
[_reactHost setContextContainerHandler:self]; | ||
[_reactHost start]; | ||
} | ||
|
||
- (std::shared_ptr<facebook::react::JSRuntimeFactory>)createJSRuntimeFactory | ||
{ | ||
#if USE_HERMES | ||
return std::make_shared<facebook::react::RCTHermesInstance>(_reactNativeConfig, nullptr); | ||
#else | ||
return std::make_shared<facebook::react::RCTJscInstance>(); | ||
#endif | ||
} | ||
|
||
- (void)didCreateContextContainer:(std::shared_ptr<facebook::react::ContextContainer>)contextContainer | ||
{ | ||
contextContainer->insert("ReactNativeConfig", _reactNativeConfig); | ||
} | ||
|
||
- (NSURL *)bundleURL | ||
{ | ||
return nullptr; | ||
// return [self.delegate ]; | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.