Skip to content

Generate RCTAppDependencyProvider for apps #47650

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
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
2 changes: 2 additions & 0 deletions packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
@protocol RCTComponentViewProtocol;
@class RCTRootView;
@class RCTSurfacePresenterBridgeAdapter;
@protocol RCTDependencyProvider;

NS_ASSUME_NONNULL_BEGIN

Expand Down Expand Up @@ -70,6 +71,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, strong, nullable) NSString *moduleName;
@property (nonatomic, strong, nullable) NSDictionary *initialProps;
@property (nonatomic, strong, nonnull) RCTRootViewFactory *rootViewFactory;
@property (nonatomic, strong) id<RCTDependencyProvider> dependencyProvider;

/// If `automaticallyLoadReactNativeWindow` is set to `true`, the React Native window will be loaded automatically.
@property (nonatomic, assign) BOOL automaticallyLoadReactNativeWindow;
Expand Down
17 changes: 3 additions & 14 deletions packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#import <react/renderer/graphics/ColorComponents.h>
#import "RCTAppDelegate+Protected.h"
#import "RCTAppSetupUtils.h"
#import "RCTDependencyProvider.h"

#if RN_DISABLE_OSS_PLUGIN_HEADER
#import <RCTTurboModulePlugin/RCTTurboModulePlugin.h>
Expand All @@ -34,14 +35,6 @@
#endif
#import <react/nativemodule/defaults/DefaultTurboModules.h>

#if __has_include(<ReactCodegen/RCTThirdPartyComponentsProvider.h>)
#define USE_OSS_CODEGEN 1
#import <ReactCodegen/RCTThirdPartyComponentsProvider.h>
#else
// Meta internal system do not generate the RCTModulesConformingToProtocolsProvider.h file
#define USE_OSS_CODEGEN 0
#endif

using namespace facebook::react;

@interface RCTAppDelegate () <RCTComponentViewFactoryComponentProvider, RCTHostDelegate>
Expand Down Expand Up @@ -236,18 +229,14 @@ - (Class)getModuleClassFromName:(const char *)name

- (id<RCTTurboModule>)getModuleInstanceFromClass:(Class)moduleClass
{
return RCTAppSetupDefaultModuleFromClass(moduleClass);
return RCTAppSetupDefaultModuleFromClass(moduleClass, self.dependencyProvider);
}

#pragma mark - RCTComponentViewFactoryComponentProvider

- (NSDictionary<NSString *, Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents
{
#if USE_OSS_CODEGEN
return [RCTThirdPartyComponentsProvider thirdPartyFabricComponents];
#else
return @{};
#endif
return self.dependencyProvider ? self.dependencyProvider.thirdPartyFabricComponents : @{};
}

- (RCTRootViewFactory *)createRCTRootViewFactory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,16 @@

#import <ReactCommon/RCTTurboModuleManager.h>

@protocol RCTDependencyProvider;

// Forward declaration to decrease compilation coupling
namespace facebook::react {
class RuntimeScheduler;
}

RCT_EXTERN id<RCTTurboModule> RCTAppSetupDefaultModuleFromClass(Class moduleClass);
RCT_EXTERN id<RCTTurboModule> RCTAppSetupDefaultModuleFromClass(
Class moduleClass,
id<RCTDependencyProvider> dependencyProvider);

std::unique_ptr<facebook::react::JSExecutorFactory> RCTAppSetupDefaultJsExecutorFactory(
RCTBridge *bridge,
Expand Down
18 changes: 5 additions & 13 deletions packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.mm
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,7 @@
// jsinspector-modern
#import <jsinspector-modern/InspectorFlags.h>

#if __has_include(<ReactCodegen/RCTModulesConformingToProtocolsProvider.h>)
#define USE_OSS_CODEGEN 1
#import <ReactCodegen/RCTModulesConformingToProtocolsProvider.h>
#else
// Meta internal system do not generate the RCTModulesConformingToProtocolsProvider.h file
#define USE_OSS_CODEGEN 0
#endif
#import "RCTDependencyProvider.h"

void RCTAppSetupPrepareApp(UIApplication *application, BOOL turboModuleEnabled)
{
Expand All @@ -60,22 +54,20 @@ void RCTAppSetupPrepareApp(UIApplication *application, BOOL turboModuleEnabled)
return [[RCTRootView alloc] initWithBridge:bridge moduleName:moduleName initialProperties:initialProperties];
}

id<RCTTurboModule> RCTAppSetupDefaultModuleFromClass(Class moduleClass)
id<RCTTurboModule> RCTAppSetupDefaultModuleFromClass(Class moduleClass, id<RCTDependencyProvider> dependencyProvider)
{
// private block used to filter out modules depending on protocol conformance
NSArray * (^extractModuleConformingToProtocol)(RCTModuleRegistry *, Protocol *) =
^NSArray *(RCTModuleRegistry *moduleRegistry, Protocol *protocol) {
NSArray<NSString *> *classNames = @[];

#if USE_OSS_CODEGEN
if (protocol == @protocol(RCTImageURLLoader)) {
classNames = [RCTModulesConformingToProtocolsProvider imageURLLoaderClassNames];
classNames = dependencyProvider ? dependencyProvider.imageURLLoaderClassNames : @[];
} else if (protocol == @protocol(RCTImageDataDecoder)) {
classNames = [RCTModulesConformingToProtocolsProvider imageDataDecoderClassNames];
classNames = dependencyProvider ? dependencyProvider.imageDataDecoderClassNames : @[];
} else if (protocol == @protocol(RCTURLRequestHandler)) {
classNames = [RCTModulesConformingToProtocolsProvider URLRequestHandlerClassNames];
classNames = dependencyProvider ? dependencyProvider.URLRequestHandlerClassNames : @[];
}
#endif

NSMutableArray *modules = [NSMutableArray new];

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* 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 <Foundation/Foundation.h>

@protocol RCTComponentViewProtocol;

NS_ASSUME_NONNULL_BEGIN

@protocol RCTDependencyProvider <NSObject>

- (NSArray<NSString *> *)imageURLLoaderClassNames;

- (NSArray<NSString *> *)imageDataDecoderClassNames;

- (NSArray<NSString *> *)URLRequestHandlerClassNames;

- (NSDictionary<NSString *, Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents;

@end

NS_ASSUME_NONNULL_END
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ Pod::Spec.new do |s|
s.dependency "React-nativeconfig"
s.dependency "React-RCTFBReactNativeSpec"
s.dependency "React-defaultsnativemodule"
s.dependency "ReactCodegen"

add_dependency(s, "ReactCommon", :subspec => "turbomodule/core", :additional_framework_paths => ["react/nativemodule/core"])
add_dependency(s, "React-NativeModulesApple")
Expand Down
1 change: 1 addition & 0 deletions packages/react-native/scripts/cocoapods/codegen_utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ def get_react_codegen_spec(package_json_file, folly_version: get_folly_config()[
'React-debug': [],
'React-utils': [],
'React-featureflags': [],
'React-RCTAppDelegate': [],
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,22 @@ const THIRD_PARTY_COMPONENTS_MM_TEMPLATE_PATH = path.join(
'RCTThirdPartyComponentsProviderMM.template',
);

const APP_DEPENDENCY_PROVIDER_H_TEMPLATE_PATH = path.join(
REACT_NATIVE_PACKAGE_ROOT_FOLDER,
'scripts',
'codegen',
'templates',
'RCTAppDependencyProviderH.template',
);

const APP_DEPENDENCY_PROVIDER_MM_TEMPLATE_PATH = path.join(
REACT_NATIVE_PACKAGE_ROOT_FOLDER,
'scripts',
'codegen',
'templates',
'RCTAppDependencyProviderMM.template',
);

const codegenLog = (text, info = false) => {
// ANSI escape codes for colors and formatting
const reset = '\x1b[0m';
Expand Down Expand Up @@ -628,6 +644,27 @@ function generateCustomURLHandlers(libraries, outputDir) {
);
}

function generateAppDependencyProvider(outputDir) {
fs.mkdirSync(outputDir, {recursive: true});
codegenLog('Generating RCTAppDependencyProvider');

const templateH = fs.readFileSync(
APP_DEPENDENCY_PROVIDER_H_TEMPLATE_PATH,
'utf8',
);
const finalPathH = path.join(outputDir, 'RCTAppDependencyProvider.h');
fs.writeFileSync(finalPathH, templateH);
codegenLog(`Generated artifact: ${finalPathH}`);

const templateMM = fs.readFileSync(
APP_DEPENDENCY_PROVIDER_MM_TEMPLATE_PATH,
'utf8',
);
const finalPathMM = path.join(outputDir, 'RCTAppDependencyProvider.mm');
fs.writeFileSync(finalPathMM, templateMM);
codegenLog(`Generated artifact: ${finalPathMM}`);
}

function generateRCTThirdPartyComponents(libraries, outputDir) {
fs.mkdirSync(outputDir, {recursive: true});
// Generate Header File
Expand Down Expand Up @@ -886,6 +923,7 @@ function execute(projectRoot, targetPlatform, baseOutputPath) {

generateRCTThirdPartyComponents(libraries, outputPath);
generateCustomURLHandlers(libraries, outputPath);
generateAppDependencyProvider(outputPath);

cleanupEmptyFilesAndFolders(outputPath);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* 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 <Foundation/Foundation.h>

#if __has_include(<React-RCTAppDelegate/RCTDependencyProvider.h>)
#import <React-RCTAppDelegate/RCTDependencyProvider.h>
#elif __has_include(<React_RCTAppDelegate/RCTDependencyProvider.h>)
#import <React_RCTAppDelegate/RCTDependencyProvider.h>
#else
#import "RCTDependencyProvider.h"
#endif

NS_ASSUME_NONNULL_BEGIN

@interface RCTAppDependencyProvider : NSObject <RCTDependencyProvider>

@end

NS_ASSUME_NONNULL_END
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* 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 "RCTAppDependencyProvider.h"
#import "RCTModulesConformingToProtocolsProvider.h"
#import "RCTThirdPartyComponentsProvider.h"

@implementation RCTAppDependencyProvider {
NSArray<NSString *> * _URLRequestHandlerClassNames;
NSArray<NSString *> * _imageDataDecoderClassNames;
NSArray<NSString *> * _imageURLLoaderClassNames;
NSDictionary<NSString *,Class<RCTComponentViewProtocol>> * _thirdPartyFabricComponents;
}

- (nonnull NSArray<NSString *> *)URLRequestHandlerClassNames {
static dispatch_once_t requestUrlToken;
dispatch_once(&requestUrlToken, ^{
self->_URLRequestHandlerClassNames = RCTModulesConformingToProtocolsProvider.URLRequestHandlerClassNames;
});

return _URLRequestHandlerClassNames;
}

- (nonnull NSArray<NSString *> *)imageDataDecoderClassNames {
static dispatch_once_t dataDecoderToken;
dispatch_once(&dataDecoderToken, ^{
_imageDataDecoderClassNames = RCTModulesConformingToProtocolsProvider.imageDataDecoderClassNames;
});

return _imageDataDecoderClassNames;
}

- (nonnull NSArray<NSString *> *)imageURLLoaderClassNames {
static dispatch_once_t urlLoaderToken;
dispatch_once(&urlLoaderToken, ^{
_imageURLLoaderClassNames = RCTModulesConformingToProtocolsProvider.imageURLLoaderClassNames;
});

return _imageURLLoaderClassNames;
}

- (nonnull NSDictionary<NSString *,Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents {
static dispatch_once_t nativeComponentsToken;
dispatch_once(&nativeComponentsToken, ^{
_thirdPartyFabricComponents = RCTThirdPartyComponentsProvider.thirdPartyFabricComponents;
});

return _thirdPartyFabricComponents;
}

@end
Loading