Skip to content

Commit 63c8f7e

Browse files
committed
Exclude selectively disabled libraries from codegen generation (#51078)
Summary: Selectively disabling autolinking of a native dependency with components registered in the codegen configuration in react-native.config.js causes builds to crash upon launch on iOS. This is because the generated `RCTThirdPartyComponentsProvider.mm` file contains references to the excluded library using `NSClassFromString` causing the returned NSDictionary from `+[RCTThirdPartyComponentsProvider thirdPartyFabricComponents]` to be populated with nil values and therefore crashing the app. This has been confirmed in 0.78.2 and 0.79.2 but probably exists in 0.77.x as well. The issue has been further described in #51077. [IOS][FIXED] - Skip codegen for selectively disabled libraries in react-native.config.js Pull Request resolved: #51078 Test Plan: 1. Install a library that has the componentProvider field set in the codegen config (see reproducer) and install the iOS pods. 2. Build the app. 3. App should run successfully without any crashes. Reviewed By: cortinico Differential Revision: D74248371 Pulled By: cipolleschi fbshipit-source-id: 1ff7b477ed3d94ca45616ae243d3d2d30bd897db
1 parent 58a4c2f commit 63c8f7e

1 file changed

Lines changed: 47 additions & 16 deletions

File tree

packages/react-native/scripts/codegen/generate-artifacts-executor.js

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -324,22 +324,13 @@ function findExternalLibraries(pkgJson, projectRoot) {
324324
});
325325
}
326326

327-
function findLibrariesFromReactNativeConfig(projectRoot) {
328-
const rnConfigFileName = 'react-native.config.js';
329-
327+
function findLibrariesFromReactNativeConfig(projectRoot, rnConfig) {
330328
codegenLog(
331-
`Searching for codegen-enabled libraries in ${rnConfigFileName}`,
329+
`Searching for codegen-enabled libraries in react-native.config.js`,
332330
true,
333331
);
334332

335-
const rnConfigFilePath = path.resolve(projectRoot, rnConfigFileName);
336-
337-
if (!fs.existsSync(rnConfigFilePath)) {
338-
return [];
339-
}
340-
const rnConfig = require(rnConfigFilePath);
341-
342-
if (rnConfig.dependencies == null) {
333+
if (!rnConfig.dependencies) {
343334
return [];
344335
}
345336
return Object.keys(rnConfig.dependencies).flatMap(name => {
@@ -591,15 +582,15 @@ function mustGenerateNativeCode(includeLibraryPath, schemaInfo) {
591582
);
592583
}
593584

594-
function findCodegenEnabledLibraries(pkgJson, projectRoot) {
585+
function findCodegenEnabledLibraries(pkgJson, projectRoot, reactNativeConfig) {
595586
const projectLibraries = findProjectRootLibraries(pkgJson, projectRoot);
596587
if (pkgJsonIncludesGeneratedCode(pkgJson)) {
597588
return projectLibraries;
598589
} else {
599590
return [
600591
...projectLibraries,
601592
...findExternalLibraries(pkgJson, projectRoot),
602-
...findLibrariesFromReactNativeConfig(projectRoot),
593+
...findLibrariesFromReactNativeConfig(projectRoot, reactNativeConfig),
603594
];
604595
}
605596
}
@@ -924,9 +915,14 @@ function execute(projectRoot, targetPlatform, baseOutputPath, source) {
924915

925916
buildCodegenIfNeeded();
926917

927-
const libraries = findCodegenEnabledLibraries(pkgJson, projectRoot);
918+
const reactNativeConfig = readReactNativeConfig(projectRoot);
919+
const codegenEnabledLibraries = findCodegenEnabledLibraries(
920+
pkgJson,
921+
projectRoot,
922+
reactNativeConfig,
923+
);
928924

929-
if (libraries.length === 0) {
925+
if (codegenEnabledLibraries.length === 0) {
930926
codegenLog('No codegen-enabled libraries found.', true);
931927
return;
932928
}
@@ -935,6 +931,18 @@ function execute(projectRoot, targetPlatform, baseOutputPath, source) {
935931
targetPlatform === 'all' ? supportedPlatforms : [targetPlatform];
936932

937933
for (const platform of platforms) {
934+
const disabledLibraries = findDisabledLibrariesByPlatform(
935+
reactNativeConfig,
936+
platform,
937+
);
938+
const libraries = codegenEnabledLibraries.filter(
939+
({name}) => !disabledLibraries.includes(name),
940+
);
941+
942+
if (!libraries.length) {
943+
continue;
944+
}
945+
938946
const outputPath = computeOutputPath(
939947
projectRoot,
940948
baseOutputPath,
@@ -970,6 +978,29 @@ function execute(projectRoot, targetPlatform, baseOutputPath, source) {
970978
return;
971979
}
972980

981+
/**
982+
* Finds all disabled libraries by platform based the react native config.
983+
*
984+
* This is needed when selectively disabling libraries in react-native.config.js since codegen should exclude those libraries as well.
985+
*/
986+
function findDisabledLibrariesByPlatform(reactNativeConfig, platform) {
987+
const dependencies = reactNativeConfig.dependencies ?? {};
988+
989+
return Object.keys(dependencies).filter(
990+
dependency => dependencies[dependency].platforms?.[platform] === null,
991+
);
992+
}
993+
994+
function readReactNativeConfig(projectRoot) {
995+
const rnConfigFilePath = path.resolve(projectRoot, 'react-native.config.js');
996+
997+
if (!fs.existsSync(rnConfigFilePath)) {
998+
return {};
999+
}
1000+
1001+
return require(rnConfigFilePath);
1002+
}
1003+
9731004
module.exports = {
9741005
execute,
9751006
generateRNCoreComponentsIOS,

0 commit comments

Comments
 (0)