Restore legacy semantics of modulesConformingToProtocol (#51381)

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

Changelog: [General][Fixed] Fixed codegen breaking when a subset of `modulesConformingToProtocol` fields was specified or when the value was string

D70822061 introduced a new way of defininf modules and components in codegen, but accidentally introduced two breaking changes to the legacy syntax:
- before that diff, in case of 1:1 mapping, the value of the fileds could be a string, while after, it required it to be an array
- before that diff, not all of the fields on `modulesConformingToProtocol` had to be defined in `package.json`, while after, it required all fields to be defined even if unused

Reviewed By: cipolleschi

Differential Revision: D74875251

fbshipit-source-id: 610103b508f1462b4de01725f9b0a87341571197
This commit is contained in:
Jakub Piasecki
2025-05-16 05:59:05 -07:00
committed by Facebook GitHub Bot
parent 82279bd981
commit e4ef685dd7
4 changed files with 626 additions and 104 deletions
@@ -0,0 +1,37 @@
{
"name": "test-app-legacy",
"version": "0.0.0",
"private": true,
"scripts": {
},
"dependencies": {
},
"devDependencies": {
},
"codegenConfig": {
"name": "TestAppConfig",
"type": "all",
"android": {
"javaPackageName": "com.testApp"
},
"ios": {
"modulesConformingToProtocol": {
"RCTImageURLLoader": "RCTTestAppDeprecatedImageURLLoader",
"RCTURLRequestHandler": "RCTTestAppDeprecatedURLRequestHandler"
},
"modulesProvider": {
"TestAppDeprecatedImageURLLoader": "RCTTestAppDeprecatedImageURLLoader",
"TestAppDeprecatedURLRequestHandler": "RCTTestAppDeprecatedURLRequestHandler",
"TestAppDeprecatedImageDataDecoder": "RCTTestAppDeprecatedImageDataDecoder"
},
"componentProvider": {
"TestAppDeprecatedComponent": "RCTTestAppDeprecatedComponentClass"
},
"unstableModulesRequiringMainQueueSetup": [
"RCTTestAppDeprecatedImageURLLoader",
"RCTTestAppDeprecatedURLRequestHandler",
"RCTTestAppDeprecatedImageDataDecoder"
]
}
}
}
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`execute "RCTAppDependencyProvider.h" should match snapshot 1`] = `
exports[`execute test-app "RCTAppDependencyProvider.h" should match snapshot 1`] = `
"/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
@@ -29,7 +29,7 @@ NS_ASSUME_NONNULL_END
"
`;
exports[`execute "RCTAppDependencyProvider.mm" should match snapshot 1`] = `
exports[`execute test-app "RCTAppDependencyProvider.mm" should match snapshot 1`] = `
"/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
@@ -73,7 +73,7 @@ exports[`execute "RCTAppDependencyProvider.mm" should match snapshot 1`] = `
"
`;
exports[`execute "RCTModuleProviders.h" should match snapshot 1`] = `
exports[`execute test-app "RCTModuleProviders.h" should match snapshot 1`] = `
"/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
@@ -93,7 +93,7 @@ exports[`execute "RCTModuleProviders.h" should match snapshot 1`] = `
"
`;
exports[`execute "RCTModuleProviders.mm" should match snapshot 1`] = `
exports[`execute test-app "RCTModuleProviders.mm" should match snapshot 1`] = `
"/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
@@ -159,7 +159,7 @@ exports[`execute "RCTModuleProviders.mm" should match snapshot 1`] = `
"
`;
exports[`execute "RCTModulesConformingToProtocolsProvider.h" should match snapshot 1`] = `
exports[`execute test-app "RCTModulesConformingToProtocolsProvider.h" should match snapshot 1`] = `
"/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
@@ -181,7 +181,7 @@ exports[`execute "RCTModulesConformingToProtocolsProvider.h" should match snapsh
"
`;
exports[`execute "RCTModulesConformingToProtocolsProvider.mm" should match snapshot 1`] = `
exports[`execute test-app "RCTModulesConformingToProtocolsProvider.mm" should match snapshot 1`] = `
"/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
@@ -248,7 +248,7 @@ exports[`execute "RCTModulesConformingToProtocolsProvider.mm" should match snaps
"
`;
exports[`execute "RCTThirdPartyComponentsProvider.h" should match snapshot 1`] = `
exports[`execute test-app "RCTThirdPartyComponentsProvider.h" should match snapshot 1`] = `
"/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
@@ -268,7 +268,7 @@ exports[`execute "RCTThirdPartyComponentsProvider.h" should match snapshot 1`] =
"
`;
exports[`execute "RCTThirdPartyComponentsProvider.mm" should match snapshot 1`] = `
exports[`execute test-app "RCTThirdPartyComponentsProvider.mm" should match snapshot 1`] = `
"/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
@@ -305,7 +305,7 @@ exports[`execute "RCTThirdPartyComponentsProvider.mm" should match snapshot 1`]
"
`;
exports[`execute "RCTUnstableModulesRequiringMainQueueSetupProvider.h" should match snapshot 1`] = `
exports[`execute test-app "RCTUnstableModulesRequiringMainQueueSetupProvider.h" should match snapshot 1`] = `
"/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
@@ -323,7 +323,7 @@ exports[`execute "RCTUnstableModulesRequiringMainQueueSetupProvider.h" should ma
"
`;
exports[`execute "RCTUnstableModulesRequiringMainQueueSetupProvider.mm" should match snapshot 1`] = `
exports[`execute test-app "RCTUnstableModulesRequiringMainQueueSetupProvider.mm" should match snapshot 1`] = `
"/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
@@ -357,7 +357,7 @@ exports[`execute "RCTUnstableModulesRequiringMainQueueSetupProvider.mm" should m
"
`;
exports[`execute "ReactAppDependencyProvider.podspec" should match snapshot 1`] = `
exports[`execute test-app "ReactAppDependencyProvider.podspec" should match snapshot 1`] = `
"# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
@@ -395,7 +395,482 @@ end
"
`;
exports[`execute "ReactCodegen.podspec" should match snapshot 1`] = `
exports[`execute test-app "ReactCodegen.podspec" should match snapshot 1`] = `
"# 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.
version = \\"1000.0.0\\"
source = { :git => 'https://github.com/facebook/react-native.git' }
if version == '1000.0.0'
# This is an unpublished version, use the latest commit hash of the react-native repo, which were presumably in.
source[:commit] = \`git rev-parse HEAD\`.strip if system(\\"git rev-parse --git-dir > /dev/null 2>&1\\")
else
source[:tag] = \\"v#{version}\\"
end
use_frameworks = ENV['USE_FRAMEWORKS'] != nil
folly_compiler_flags = Helpers::Constants.folly_config[:compiler_flags]
boost_compiler_flags = Helpers::Constants.boost_config[:compiler_flags]
header_search_paths = [
\\"\\\\\\"$(PODS_ROOT)/ReactNativeDependencies\\\\\\"\\",
\\"\\\\\\"\${PODS_ROOT}/Headers/Public/ReactCodegen/react/renderer/components\\\\\\"\\",
\\"\\\\\\"$(PODS_ROOT)/Headers/Private/React-Fabric\\\\\\"\\",
\\"\\\\\\"$(PODS_ROOT)/Headers/Private/React-RCTFabric\\\\\\"\\",
\\"\\\\\\"$(PODS_ROOT)/Headers/Private/Yoga\\\\\\"\\",
\\"\\\\\\"$(PODS_TARGET_SRCROOT)\\\\\\"\\",
]
framework_search_paths = []
if use_frameworks
ReactNativePodsUtils.create_header_search_path_for_frameworks(\\"PODS_CONFIGURATION_BUILD_DIR\\", \\"React-Fabric\\", \\"React_Fabric\\", [\\"react/renderer/components/view/platform/cxx\\"])
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks(\\"PODS_CONFIGURATION_BUILD_DIR\\", \\"React-FabricImage\\", \\"React_FabricImage\\", []))
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks(\\"PODS_CONFIGURATION_BUILD_DIR\\", \\"React-graphics\\", \\"React_graphics\\", [\\"react/renderer/graphics/platform/ios\\"]))
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks(\\"PODS_CONFIGURATION_BUILD_DIR\\", \\"ReactCommon\\", \\"ReactCommon\\", [\\"react/nativemodule/core\\"]))
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks(\\"PODS_CONFIGURATION_BUILD_DIR\\", \\"React-NativeModulesApple\\", \\"React_NativeModulesApple\\", []))
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks(\\"PODS_CONFIGURATION_BUILD_DIR\\", \\"React-RCTFabric\\", \\"RCTFabric\\", []))
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks(\\"PODS_CONFIGURATION_BUILD_DIR\\", \\"React-debug\\", \\"React_debug\\", []))
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks(\\"PODS_CONFIGURATION_BUILD_DIR\\", \\"React-rendererdebug\\", \\"React_rendererdebug\\", []))
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks(\\"PODS_CONFIGURATION_BUILD_DIR\\", \\"React-utils\\", \\"React_utils\\", []))
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks(\\"PODS_CONFIGURATION_BUILD_DIR\\", \\"React-featureflags\\", \\"React_featureflags\\", []))
.each { |search_path|
header_search_paths << \\"\\\\\\"#{search_path}\\\\\\"\\"
}
end
Pod::Spec.new do |s|
s.name = \\"ReactCodegen\\"
s.version = version
s.summary = 'Temp pod for generated files for React Native'
s.homepage = 'https://facebook.com/'
s.license = 'Unlicense'
s.authors = 'Facebook'
s.compiler_flags = \\"#{folly_compiler_flags} #{boost_compiler_flags} -Wno-nullability-completeness -std=c++20\\"
s.source = { :git => '' }
s.header_mappings_dir = './'
s.platforms = min_supported_versions
s.source_files = \\"**/*.{h,mm,cpp}\\"
s.exclude_files = \\"RCTAppDependencyProvider.{h,mm}\\" # these files are generated in the same codegen path but needs to belong to a different pod
s.pod_target_xcconfig = {
\\"HEADER_SEARCH_PATHS\\" => header_search_paths.join(' '),
\\"FRAMEWORK_SEARCH_PATHS\\" => framework_search_paths,
\\"OTHER_CPLUSPLUSFLAGS\\" => \\"$(inherited) #{folly_compiler_flags} #{boost_compiler_flags}\\"
}
s.dependency \\"React-jsiexecutor\\"
s.dependency \\"RCTRequired\\"
s.dependency \\"RCTTypeSafety\\"
s.dependency \\"React-Core\\"
s.dependency \\"React-jsi\\"
s.dependency \\"ReactCommon/turbomodule/bridging\\"
s.dependency \\"ReactCommon/turbomodule/core\\"
s.dependency \\"React-NativeModulesApple\\"
s.dependency 'React-graphics'
s.dependency 'React-rendererdebug'
s.dependency 'React-Fabric'
s.dependency 'React-FabricImage'
s.dependency 'React-debug'
s.dependency 'React-utils'
s.dependency 'React-featureflags'
s.dependency 'React-RCTAppDelegate'
depend_on_js_engine(s)
add_rn_third_party_dependencies(s)
s.script_phases = {
'name' => 'Generate Specs',
'execution_position' => :before_compile,
'input_files' => [],
'show_env_vars_in_log' => true,
'output_files' => [\\"\${DERIVED_FILE_DIR}/react-codegen.log\\"],
'script': <<-SCRIPT
pushd \\"$PODS_ROOT/../\\" > /dev/null
RCT_SCRIPT_POD_INSTALLATION_ROOT=$(pwd)
popd >/dev/null
export RCT_SCRIPT_RN_DIR=\\"$RCT_SCRIPT_POD_INSTALLATION_ROOT/../../../../..\\"
export RCT_SCRIPT_APP_PATH=\\"$RCT_SCRIPT_POD_INSTALLATION_ROOT/..\\"
export RCT_SCRIPT_OUTPUT_DIR=\\"$RCT_SCRIPT_POD_INSTALLATION_ROOT\\"
export RCT_SCRIPT_TYPE=\\"withCodegenDiscovery\\"
SCRIPT_PHASES_SCRIPT=\\"$RCT_SCRIPT_RN_DIR/scripts/react_native_pods_utils/script_phases.sh\\"
WITH_ENVIRONMENT=\\"$RCT_SCRIPT_RN_DIR/scripts/xcode/with-environment.sh\\"
/bin/sh -c \\"$WITH_ENVIRONMENT $SCRIPT_PHASES_SCRIPT\\"
SCRIPT
}
end
"
`;
exports[`execute test-app-legacy "RCTAppDependencyProvider.h" should match snapshot 1`] = `
"/*
* 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
"
`;
exports[`execute test-app-legacy "RCTAppDependencyProvider.mm" should match snapshot 1`] = `
"/*
* 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 <ReactCodegen/RCTModulesConformingToProtocolsProvider.h>
#import <ReactCodegen/RCTThirdPartyComponentsProvider.h>
#import <ReactCodegen/RCTUnstableModulesRequiringMainQueueSetupProvider.h>
#import <ReactCodegen/RCTModuleProviders.h>
@implementation RCTAppDependencyProvider
- (nonnull NSArray<NSString *> *)URLRequestHandlerClassNames {
return RCTModulesConformingToProtocolsProvider.URLRequestHandlerClassNames;
}
- (nonnull NSArray<NSString *> *)imageDataDecoderClassNames {
return RCTModulesConformingToProtocolsProvider.imageDataDecoderClassNames;
}
- (nonnull NSArray<NSString *> *)imageURLLoaderClassNames {
return RCTModulesConformingToProtocolsProvider.imageURLLoaderClassNames;
}
- (nonnull NSArray<NSString *> *)unstableModulesRequiringMainQueueSetup {
return RCTUnstableModulesRequiringMainQueueSetupProvider.modules;
}
- (nonnull NSDictionary<NSString *,Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents {
return RCTThirdPartyComponentsProvider.thirdPartyFabricComponents;
}
- (nonnull NSDictionary<NSString *, id<RCTModuleProvider>> *)moduleProviders {
return RCTModuleProviders.moduleProviders;
}
@end
"
`;
exports[`execute test-app-legacy "RCTModuleProviders.h" should match snapshot 1`] = `
"/*
* 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 RCTModuleProvider;
@interface RCTModuleProviders: NSObject
+ (NSDictionary<NSString *, id<RCTModuleProvider>> *)moduleProviders;
@end
"
`;
exports[`execute test-app-legacy "RCTModuleProviders.mm" should match snapshot 1`] = `
"/*
* 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>
#import \\"RCTModuleProviders.h\\"
#import <ReactCommon/RCTTurboModule.h>
#import <React/RCTLog.h>
@implementation RCTModuleProviders
+ (NSDictionary<NSString *, id<RCTModuleProvider>> *)moduleProviders
{
static NSDictionary<NSString *, id<RCTModuleProvider>> *providers = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSDictionary<NSString *, NSString *> * moduleMapping = @{
@\\"TestAppDeprecatedImageURLLoader\\": @\\"RCTTestAppDeprecatedImageURLLoader\\", // test-app-legacy
@\\"TestAppDeprecatedURLRequestHandler\\": @\\"RCTTestAppDeprecatedURLRequestHandler\\", // test-app-legacy
@\\"TestAppDeprecatedImageDataDecoder\\": @\\"RCTTestAppDeprecatedImageDataDecoder\\", // test-app-legacy
};
NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:moduleMapping.count];
for (NSString *key in moduleMapping) {
NSString * moduleProviderName = moduleMapping[key];
Class klass = NSClassFromString(moduleProviderName);
if (!klass) {
RCTLogError(@\\"Module provider %@ cannot be found in the runtime\\", moduleProviderName);
continue;
}
id instance = [klass new];
if (![instance respondsToSelector:@selector(getTurboModule:)]) {
RCTLogError(@\\"Module provider %@ does not conform to RCTModuleProvider\\", moduleProviderName);
continue;
}
[dict setObject:instance forKey:key];
}
providers = dict;
});
return providers;
}
@end
"
`;
exports[`execute test-app-legacy "RCTModulesConformingToProtocolsProvider.h" should match snapshot 1`] = `
"/*
* 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>
@interface RCTModulesConformingToProtocolsProvider: NSObject
+(NSArray<NSString *> *)imageURLLoaderClassNames;
+(NSArray<NSString *> *)imageDataDecoderClassNames;
+(NSArray<NSString *> *)URLRequestHandlerClassNames;
@end
"
`;
exports[`execute test-app-legacy "RCTModulesConformingToProtocolsProvider.mm" should match snapshot 1`] = `
"/*
* 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 \\"RCTModulesConformingToProtocolsProvider.h\\"
@implementation RCTModulesConformingToProtocolsProvider
+(NSArray<NSString *> *)imageURLLoaderClassNames
{
static NSArray<NSString *> *classNames = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
classNames = @[
@\\"RCTTestAppDeprecatedImageURLLoader\\"
];
});
return classNames;
}
+(NSArray<NSString *> *)imageDataDecoderClassNames
{
static NSArray<NSString *> *classNames = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
classNames = @[
];
});
return classNames;
}
+(NSArray<NSString *> *)URLRequestHandlerClassNames
{
static NSArray<NSString *> *classNames = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
classNames = @[
@\\"RCTTestAppDeprecatedURLRequestHandler\\"
];
});
return classNames;
}
@end
"
`;
exports[`execute test-app-legacy "RCTThirdPartyComponentsProvider.h" should match snapshot 1`] = `
"/*
* 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;
@interface RCTThirdPartyComponentsProvider: NSObject
+ (NSDictionary<NSString *, Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents;
@end
"
`;
exports[`execute test-app-legacy "RCTThirdPartyComponentsProvider.mm" should match snapshot 1`] = `
"/*
* 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>
#import \\"RCTThirdPartyComponentsProvider.h\\"
#import <React/RCTComponentViewProtocol.h>
@implementation RCTThirdPartyComponentsProvider
+ (NSDictionary<NSString *, Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents
{
static NSDictionary<NSString *, Class<RCTComponentViewProtocol>> *thirdPartyComponents = nil;
static dispatch_once_t nativeComponentsToken;
dispatch_once(&nativeComponentsToken, ^{
thirdPartyComponents = @{
};
});
return thirdPartyComponents;
}
@end
"
`;
exports[`execute test-app-legacy "RCTUnstableModulesRequiringMainQueueSetupProvider.h" should match snapshot 1`] = `
"/*
* 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>
@interface RCTUnstableModulesRequiringMainQueueSetupProvider: NSObject
+(NSArray<NSString *> *)modules;
@end
"
`;
exports[`execute test-app-legacy "RCTUnstableModulesRequiringMainQueueSetupProvider.mm" should match snapshot 1`] = `
"/*
* 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 \\"RCTUnstableModulesRequiringMainQueueSetupProvider.h\\"
@implementation RCTUnstableModulesRequiringMainQueueSetupProvider
+(NSArray<NSString *> *)modules
{
return @[
@\\"RCTTestAppDeprecatedImageURLLoader\\",
@\\"RCTTestAppDeprecatedURLRequestHandler\\",
@\\"RCTTestAppDeprecatedImageDataDecoder\\"
];
}
@end
"
`;
exports[`execute test-app-legacy "ReactAppDependencyProvider.podspec" should match snapshot 1`] = `
"# 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.
version = \\"1000.0.0\\"
source = { :git => 'https://github.com/facebook/react-native.git' }
if version == '1000.0.0'
# This is an unpublished version, use the latest commit hash of the react-native repo, which were presumably in.
source[:commit] = \`git rev-parse HEAD\`.strip if system(\\"git rev-parse --git-dir > /dev/null 2>&1\\")
else
source[:tag] = \\"v#{version}\\"
end
Pod::Spec.new do |s|
s.name = \\"ReactAppDependencyProvider\\"
s.version = version
s.summary = \\"The third party dependency provider for the app\\"
s.homepage = \\"https://reactnative.dev/\\"
s.documentation_url = \\"https://reactnative.dev/\\"
s.license = \\"MIT\\"
s.author = \\"Meta Platforms, Inc. and its affiliates\\"
s.platforms = min_supported_versions
s.source = source
s.source_files = \\"**/RCTAppDependencyProvider.{h,mm}\\"
# This guard prevent to install the dependencies when we run \`pod install\` in the old architecture.
s.pod_target_xcconfig = {
\\"CLANG_CXX_LANGUAGE_STANDARD\\" => rct_cxx_language_standard(),
\\"DEFINES_MODULE\\" => \\"YES\\"
}
s.dependency \\"ReactCodegen\\"
end
"
`;
exports[`execute test-app-legacy "ReactCodegen.podspec" should match snapshot 1`] = `
"# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
@@ -28,105 +28,107 @@ const packageJson = JSON.stringify({
name: 'react-native',
});
describe('execute', () => {
const appDir = path.join(__dirname, '../__fixtures__/test-app');
const outputDir = path.join(appDir, 'temp');
['test-app', 'test-app-legacy'].forEach(appName => {
describe(`execute ${appName}`, () => {
const appDir = path.join(__dirname, '../__fixtures__', appName);
const outputDir = path.join(appDir, 'temp');
beforeAll(() => {
execute(appDir, 'ios', outputDir, 'app', false);
});
afterAll(() => {
fs.rmdirSync(outputDir, {recursive: true});
});
[
'RCTAppDependencyProvider.h',
'RCTAppDependencyProvider.mm',
'RCTModuleProviders.h',
'RCTModuleProviders.mm',
'RCTModulesConformingToProtocolsProvider.h',
'RCTModulesConformingToProtocolsProvider.mm',
'RCTThirdPartyComponentsProvider.h',
'RCTThirdPartyComponentsProvider.mm',
'ReactAppDependencyProvider.podspec',
'ReactCodegen.podspec',
'RCTUnstableModulesRequiringMainQueueSetupProvider.h',
'RCTUnstableModulesRequiringMainQueueSetupProvider.mm',
].forEach(file => {
it(`"${file}" should match snapshot`, () => {
const generatedFileDir = path.join(outputDir, 'build/generated/ios');
const generatedFile = path.join(generatedFileDir, file);
expect(fs.existsSync(generatedFile)).toBe(true);
expect(fs.readFileSync(generatedFile, 'utf8')).toMatchSnapshot();
beforeAll(() => {
execute(appDir, 'ios', outputDir, 'app', false);
});
});
});
describe('extractLibrariesFromJSON', () => {
it('extracts a single dependency when config has no libraries', () => {
let configFile = fixtures.noLibrariesConfigFile;
let libraries = extractLibrariesFromJSON(configFile, '.');
expect(libraries.length).toBe(1);
expect(libraries[0]).toEqual({
config: {
name: 'AppModules',
type: 'all',
jsSrcsDir: '.',
},
libraryPath: '.',
afterAll(() => {
fs.rmdirSync(outputDir, {recursive: true});
});
[
'RCTAppDependencyProvider.h',
'RCTAppDependencyProvider.mm',
'RCTModuleProviders.h',
'RCTModuleProviders.mm',
'RCTModulesConformingToProtocolsProvider.h',
'RCTModulesConformingToProtocolsProvider.mm',
'RCTThirdPartyComponentsProvider.h',
'RCTThirdPartyComponentsProvider.mm',
'ReactAppDependencyProvider.podspec',
'ReactCodegen.podspec',
'RCTUnstableModulesRequiringMainQueueSetupProvider.h',
'RCTUnstableModulesRequiringMainQueueSetupProvider.mm',
].forEach(file => {
it(`"${file}" should match snapshot`, () => {
const generatedFileDir = path.join(outputDir, 'build/generated/ios');
const generatedFile = path.join(generatedFileDir, file);
expect(fs.existsSync(generatedFile)).toBe(true);
expect(fs.readFileSync(generatedFile, 'utf8')).toMatchSnapshot();
});
});
});
it("doesn't extract libraries when they are present but empty", () => {
const configFile = {codegenConfig: {libraries: []}};
let libraries = extractLibrariesFromJSON(configFile, rootPath);
expect(libraries.length).toBe(0);
});
describe('extractLibrariesFromJSON', () => {
it('extracts a single dependency when config has no libraries', () => {
let configFile = fixtures.noLibrariesConfigFile;
let libraries = extractLibrariesFromJSON(configFile, '.');
expect(libraries.length).toBe(1);
expect(libraries[0]).toEqual({
config: {
name: 'AppModules',
type: 'all',
jsSrcsDir: '.',
},
libraryPath: '.',
});
});
it('extracts libraries when they are present and not empty', () => {
const configFile = fixtures.singleLibraryCodegenConfig;
let libraries = extractLibrariesFromJSON(configFile, rootPath);
expect(libraries.length).toBe(1);
expect(libraries[0]).toEqual({
config: {
name: 'react-native',
type: 'all',
jsSrcsDir: '.',
},
libraryPath: rootPath,
it("doesn't extract libraries when they are present but empty", () => {
const configFile = {codegenConfig: {libraries: []}};
let libraries = extractLibrariesFromJSON(configFile, rootPath);
expect(libraries.length).toBe(0);
});
});
it('extract codegenConfig with multiple dependencies', () => {
const configFile = fixtures.multipleLibrariesCodegenConfig;
const myDependency = 'my-dependency';
const myDependencyPath = path.join(__dirname, myDependency);
let libraries = extractLibrariesFromJSON(configFile, myDependencyPath);
expect(libraries.length).toBe(3);
expect(libraries[0]).toEqual({
config: {
name: 'react-native',
type: 'all',
jsSrcsDir: '.',
},
libraryPath: myDependencyPath,
it('extracts libraries when they are present and not empty', () => {
const configFile = fixtures.singleLibraryCodegenConfig;
let libraries = extractLibrariesFromJSON(configFile, rootPath);
expect(libraries.length).toBe(1);
expect(libraries[0]).toEqual({
config: {
name: 'react-native',
type: 'all',
jsSrcsDir: '.',
},
libraryPath: rootPath,
});
});
expect(libraries[1]).toEqual({
config: {
name: 'my-component',
type: 'components',
jsSrcsDir: 'component/js',
},
libraryPath: myDependencyPath,
});
expect(libraries[2]).toEqual({
config: {
name: 'my-module',
type: 'module',
jsSrcsDir: 'module/js',
},
libraryPath: myDependencyPath,
it('extract codegenConfig with multiple dependencies', () => {
const configFile = fixtures.multipleLibrariesCodegenConfig;
const myDependency = 'my-dependency';
const myDependencyPath = path.join(__dirname, myDependency);
let libraries = extractLibrariesFromJSON(configFile, myDependencyPath);
expect(libraries.length).toBe(3);
expect(libraries[0]).toEqual({
config: {
name: 'react-native',
type: 'all',
jsSrcsDir: '.',
},
libraryPath: myDependencyPath,
});
expect(libraries[1]).toEqual({
config: {
name: 'my-component',
type: 'components',
jsSrcsDir: 'component/js',
},
libraryPath: myDependencyPath,
});
expect(libraries[2]).toEqual({
config: {
name: 'my-module',
type: 'module',
jsSrcsDir: 'module/js',
},
libraryPath: myDependencyPath,
});
});
});
});
@@ -30,6 +30,8 @@ function generateCustomURLHandlers(libraries, outputDir) {
const imageDataDecoderModules = new Set();
const urlRequestHandlersModules = new Set();
const wrapInArrayIfNecessary = value =>
Array.isArray(value) || value == null ? value : [value];
// Old API
for (const library of libraries) {
const modulesConformingToProtocol =
@@ -38,13 +40,19 @@ function generateCustomURLHandlers(libraries, outputDir) {
continue;
}
modulesConformingToProtocol.RCTImageURLLoader.forEach(moduleName => {
wrapInArrayIfNecessary(
modulesConformingToProtocol.RCTImageURLLoader,
)?.forEach(moduleName => {
imageURLLoaderModules.add(moduleName);
});
modulesConformingToProtocol.RCTImageDataDecoder.forEach(moduleName => {
wrapInArrayIfNecessary(
modulesConformingToProtocol.RCTImageDataDecoder,
)?.forEach(moduleName => {
imageDataDecoderModules.add(moduleName);
});
modulesConformingToProtocol.RCTURLRequestHandler.forEach(moduleName => {
wrapInArrayIfNecessary(
modulesConformingToProtocol.RCTURLRequestHandler,
)?.forEach(moduleName => {
urlRequestHandlersModules.add(moduleName);
});
}