Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,12 @@ extern "C" {

Class<RCTComponentViewProtocol> RCTThirdPartyFabricComponentsProvider(const char *name);

#ifndef RCT_DYNAMIC_FRAMEWORKS

${lookupFuncs}

#endif

#ifdef __cplusplus
}
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ const FileTemplate = ({lookupMap}: {lookupMap: string}) => `

Class<RCTComponentViewProtocol> RCTThirdPartyFabricComponentsProvider(const char *name) {
static std::unordered_map<std::string, Class (*)(void)> sFabricComponentsClassMap = {
#ifndef RCT_DYNAMIC_FRAMEWORKS
${lookupMap}
#endif
};

auto p = sFabricComponentsClassMap.find(name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ extern \\"C\\" {

Class<RCTComponentViewProtocol> RCTThirdPartyFabricComponentsProvider(const char *name);

#ifndef RCT_DYNAMIC_FRAMEWORKS

Class<RCTComponentViewProtocol> NoPropsNoEventsComponentCls(void) __attribute__((used)); // NO_PROPS_NO_EVENTS
Class<RCTComponentViewProtocol> InterfaceOnlyComponentCls(void) __attribute__((used)); // INTERFACE_ONLY
Class<RCTComponentViewProtocol> BooleanPropNativeComponentCls(void) __attribute__((used)); // BOOLEAN_PROP
Expand Down Expand Up @@ -55,6 +57,8 @@ Class<RCTComponentViewProtocol> ExcludedAndroidComponentCls(void) __attribute__(

Class<RCTComponentViewProtocol> MultiFileIncludedNativeComponentCls(void) __attribute__((used)); // EXCLUDE_IOS_TWO_COMPONENTS_DIFFERENT_FILES

#endif

#ifdef __cplusplus
}
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Map {

Class<RCTComponentViewProtocol> RCTThirdPartyFabricComponentsProvider(const char *name) {
static std::unordered_map<std::string, Class (*)(void)> sFabricComponentsClassMap = {
#ifndef RCT_DYNAMIC_FRAMEWORKS

{\\"NoPropsNoEventsComponent\\", NoPropsNoEventsComponentCls}, // NO_PROPS_NO_EVENTS

Expand Down Expand Up @@ -80,6 +81,7 @@ Class<RCTComponentViewProtocol> RCTThirdPartyFabricComponentsProvider(const char


{\\"MultiFileIncludedNativeComponent\\", MultiFileIncludedNativeComponentCls}, // EXCLUDE_IOS_TWO_COMPONENTS_DIFFERENT_FILES
#endif
};

auto p = sFabricComponentsClassMap.find(name);
Expand Down
9 changes: 9 additions & 0 deletions packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#import <React/RCTBridgeDelegate.h>
#import <UIKit/UIKit.h>

@protocol RCTComponentViewProtocol;
@class RCTSurfacePresenterBridgeAdapter;

/**
Expand Down Expand Up @@ -96,6 +97,14 @@
#if RCT_NEW_ARCH_ENABLED
@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).
Expand Down
15 changes: 14 additions & 1 deletion packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

#if RCT_NEW_ARCH_ENABLED
#import <React/CoreModulesPlugins.h>
#import <React/RCTComponentViewFactory.h>
#import <React/RCTComponentViewProtocol.h>
#import <React/RCTCxxBridgeDelegate.h>
#import <React/RCTFabricSurfaceHostingProxyRootView.h>
#import <React/RCTLegacyViewManagerInteropComponentView.h>
Expand All @@ -24,7 +26,10 @@

static NSString *const kRNConcurrentRoot = @"concurrentRoot";

@interface RCTAppDelegate () <RCTTurboModuleManagerDelegate, RCTCxxBridgeDelegate> {
@interface RCTAppDelegate () <
RCTTurboModuleManagerDelegate,
RCTCxxBridgeDelegate,
RCTComponentViewFactoryComponentProvider> {
std::shared_ptr<const facebook::react::ReactNativeConfig> _reactNativeConfig;
facebook::react::ContextContainer::Shared _contextContainer;
std::shared_ptr<facebook::react::RuntimeScheduler> _runtimeScheduler;
Expand Down Expand Up @@ -64,6 +69,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
self.bridge.surfacePresenter = self.bridgeAdapter.surfacePresenter;

[self unstable_registerLegacyComponents];
[RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self;
#endif

NSDictionary *initProps = [self prepareInitialProps];
Expand Down Expand Up @@ -163,6 +169,13 @@ - (Class)getModuleClassFromName:(const char *)name
return RCTAppSetupDefaultModuleFromClass(moduleClass);
}

#pragma mark - RCTComponentViewFactoryComponentProvider

- (NSDictionary<NSString *, Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents
{
return @{};
}

#pragma mark - New Arch Enabled settings

- (BOOL)turboModuleEnabled
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
#import <react/renderer/components/view/ViewEventEmitter.h>
#import <react/renderer/components/view/ViewProps.h>

#ifdef RCT_DYNAMIC_FRAMEWORKS
#import <React/RCTComponentViewFactory.h>
#endif

using namespace facebook::react;

@implementation RCTViewComponentView {
Expand All @@ -30,6 +34,13 @@ @implementation RCTViewComponentView {
NSSet<NSString *> *_Nullable _propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN;
}

#ifdef RCT_DYNAMIC_FRAMEWORKS
+ (void)load
{
[RCTComponentViewFactory.currentComponentViewFactory registerComponentViewClass:self];
}
#endif

- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,28 @@ NS_ASSUME_NONNULL_BEGIN

void RCTInstallNativeComponentRegistryBinding(facebook::jsi::Runtime &runtime);

/**
* Protocol that can be implemented to provide some 3rd party components to Fabric.
* Fabric will check in this map whether there are some components that need to be registered.
*/
@protocol RCTComponentViewFactoryComponentProvider <NSObject>

/**
* Return a dictionary of third party components where the `key` is the Component Handler and the `value` is a Class
* that conforms to `RCTComponentViewProtocol`.
*/
- (NSDictionary<NSString *, Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents;

@end

/**
* Registry of supported component view classes that can instantiate
* view component instances by given component handle.
*/
@interface RCTComponentViewFactory : NSObject

@property (nonatomic, weak) id<RCTComponentViewFactoryComponentProvider> thirdPartyFabricComponentsProvider;

/**
* Constructs and returns an instance of the class with a bunch of already registered standard components.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,19 @@ - (BOOL)registerComponentIfPossible:(std::string const &)name
return YES;
}

// Fallback 2: Try to use Paper Interop.
// Fallback 2: Ask the provider and check in the dictionary provided
if (self.thirdPartyFabricComponentsProvider) {
// Test whether a provider has been passed to avoid potentially expensive conversions
// between C++ and ObjC strings.
NSString *objcName = [NSString stringWithCString:name.c_str() encoding:NSUTF8StringEncoding];
klass = self.thirdPartyFabricComponentsProvider.thirdPartyFabricComponents[objcName];
if (klass) {
[self registerComponentViewClass:klass];
return YES;
}
}

// Fallback 3: Try to use Paper Interop.
NSString *componentNameString = RCTNSStringFromString(name);
if ([RCTLegacyViewManagerInteropComponentView isSupported:componentNameString]) {
RCTLogNewArchitectureValidation(
Expand All @@ -136,7 +148,7 @@ - (BOOL)registerComponentIfPossible:(std::string const &)name
return YES;
}

// Fallback 3: use <UnimplementedView> if component doesn't exist.
// Fallback 4: use <UnimplementedView> if component doesn't exist.
auto flavor = std::make_shared<std::string const>(name);
auto componentName = ComponentName{flavor->c_str()};
auto componentHandle = reinterpret_cast<ComponentHandle>(componentName);
Expand Down
10 changes: 10 additions & 0 deletions packages/react-native/scripts/cocoapods/new_architecture.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ def self.modify_flags_for_new_architecture(installer, is_new_arch_enabled)
end
end

# Set "RCT_DYNAMIC_FRAMEWORKS=1" if pod are installed with USE_FRAMEWORKS=dynamic
# This helps with backward compatibility.
if pod_name == 'React-RCTFabric' && ENV['USE_FRAMEWORKS'] == 'dynamic'
rct_dynamic_framework_flag = " -DRCT_DYNAMIC_FRAMEWORKS=1"
target_installation_result.native_target.build_configurations.each do |config|
prev_build_settings = config.build_settings['OTHER_CPLUSPLUSFLAGS'] != nil ? config.build_settings['OTHER_CPLUSPLUSFLAGS'] : "$(inherithed)"
config.build_settings['OTHER_CPLUSPLUSFLAGS'] = prev_build_settings + rct_dynamic_framework_flag
end
end

target_installation_result.native_target.build_configurations.each do |config|
if config.name == "Release"
current_flags = config.build_settings['OTHER_CPLUSPLUSFLAGS'] != nil ? config.build_settings['OTHER_CPLUSPLUSFLAGS'] : "$(inherited)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ + (ComponentDescriptorProvider)componentDescriptorProvider
return concreteComponentDescriptorProvider<RNTMyNativeViewComponentDescriptor>();
}

// Load is not invoked if it is not defined, therefore, we must ask to update this.
// See the Apple documentation: https://developer.apple.com/documentation/objectivec/nsobject/1418815-load?language=objc
// "[...] but only if the newly loaded class or category implements a method that can respond."
+ (void)load
{
[super load];
}

- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
Expand Down
24 changes: 24 additions & 0 deletions packages/rn-tester/RNTester/AppDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#endif

#ifdef RN_FABRIC_ENABLED
#import <React/RCTComponentViewFactory.h>
#import <React/RCTFabricSurfaceHostingProxyRootView.h>
#import <React/RCTSurfacePresenter.h>
#import <React/RCTSurfacePresenterBridgeAdapter.h>
Expand All @@ -60,6 +61,10 @@
#import <react/renderer/runtimescheduler/RuntimeSchedulerCallInvoker.h>
#endif

#if RCT_NEW_ARCH_ENABLED
#import <RNTMyNativeViewComponentView.h>
#endif

#if DEBUG
#ifdef FB_SONARKIT_ENABLED
#import <FlipperKit/FlipperClient.h>
Expand All @@ -85,6 +90,12 @@ @interface AppDelegate () <RCTCxxBridgeDelegate, RCTTurboModuleManagerDelegate>
}
@end

#if RCT_NEW_ARCH_ENABLED
/// Declare conformance to `RCTComponentViewFactoryComponentProvider`
@interface AppDelegate () <RCTComponentViewFactoryComponentProvider>
@end
#endif

static NSString *const kRNConcurrentRoot = @"concurrentRoot";

@implementation AppDelegate
Expand All @@ -110,6 +121,10 @@ - (BOOL)application:(__unused UIApplication *)application didFinishLaunchingWith
// 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];

Expand Down Expand Up @@ -333,4 +348,13 @@ - (void)application:(__unused UIApplication *)application

#endif

#pragma mark - RCTComponentViewFactoryComponentProvider

#if RCT_NEW_ARCH_ENABLED
- (nonnull NSDictionary<NSString *, Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents
{
return @{@"RNTMyNativeView" : RNTMyNativeViewComponentView.class};
}
#endif

@end