Skip to content

Commit be8595b

Browse files
ismarbesicfacebook-github-bot
authored andcommitted
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. ## Changelog: [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 04ab28f commit be8595b

File tree

2 files changed

+51
-16
lines changed
  • packages/react-native/scripts/codegen/generate-artifacts-executor

2 files changed

+51
-16
lines changed

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

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@ const {
3535
cleanupEmptyFilesAndFolders,
3636
codegenLog,
3737
findCodegenEnabledLibraries,
38+
findDisabledLibrariesByPlatform,
3839
pkgJsonIncludesGeneratedCode,
3940
readPkgJsonInDirectory,
41+
readReactNativeConfig,
4042
} = require('./utils');
4143
const path = require('path');
4244

@@ -83,9 +85,14 @@ function execute(
8385
buildCodegenIfNeeded();
8486
}
8587

86-
const libraries = findCodegenEnabledLibraries(pkgJson, projectRoot);
88+
const reactNativeConfig = readReactNativeConfig(projectRoot);
89+
const codegenEnabledLibraries = findCodegenEnabledLibraries(
90+
pkgJson,
91+
projectRoot,
92+
reactNativeConfig,
93+
);
8794

88-
if (libraries.length === 0) {
95+
if (codegenEnabledLibraries.length === 0) {
8996
codegenLog('No codegen-enabled libraries found.', true);
9097
return;
9198
}
@@ -94,6 +101,18 @@ function execute(
94101
targetPlatform === 'all' ? supportedPlatforms : [targetPlatform];
95102

96103
for (const platform of platforms) {
104+
const disabledLibraries = findDisabledLibrariesByPlatform(
105+
reactNativeConfig,
106+
platform,
107+
);
108+
const libraries = codegenEnabledLibraries.filter(
109+
({name}) => !disabledLibraries.includes(name),
110+
);
111+
112+
if (!libraries.length) {
113+
continue;
114+
}
115+
97116
const outputPath = computeOutputPath(
98117
projectRoot,
99118
baseOutputPath,

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

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -94,18 +94,28 @@ function cleanupEmptyFilesAndFolders(filepath) {
9494
}
9595
}
9696

97+
function readReactNativeConfig(projectRoot) {
98+
const rnConfigFilePath = path.resolve(projectRoot, 'react-native.config.js');
99+
100+
if (!fs.existsSync(rnConfigFilePath)) {
101+
return {};
102+
}
103+
104+
return require(rnConfigFilePath);
105+
}
106+
97107
/**
98108
* Finding libraries!
99109
*/
100-
function findCodegenEnabledLibraries(pkgJson, projectRoot) {
110+
function findCodegenEnabledLibraries(pkgJson, projectRoot, reactNativeConfig) {
101111
const projectLibraries = findProjectRootLibraries(pkgJson, projectRoot);
102112
if (pkgJsonIncludesGeneratedCode(pkgJson)) {
103113
return projectLibraries;
104114
} else {
105115
return [
106116
...projectLibraries,
107117
...findExternalLibraries(pkgJson, projectRoot),
108-
...findLibrariesFromReactNativeConfig(projectRoot),
118+
...findLibrariesFromReactNativeConfig(projectRoot, reactNativeConfig),
109119
];
110120
}
111121
}
@@ -128,22 +138,13 @@ function findProjectRootLibraries(pkgJson, projectRoot) {
128138
return extractLibrariesFromJSON(pkgJson, projectRoot);
129139
}
130140

131-
function findLibrariesFromReactNativeConfig(projectRoot) {
132-
const rnConfigFileName = 'react-native.config.js';
133-
141+
function findLibrariesFromReactNativeConfig(projectRoot, rnConfig) {
134142
codegenLog(
135-
`Searching for codegen-enabled libraries in ${rnConfigFileName}`,
143+
`Searching for codegen-enabled libraries in react-native.config.js`,
136144
true,
137145
);
138146

139-
const rnConfigFilePath = path.resolve(projectRoot, rnConfigFileName);
140-
141-
if (!fs.existsSync(rnConfigFilePath)) {
142-
return [];
143-
}
144-
const rnConfig = require(rnConfigFilePath);
145-
146-
if (rnConfig.dependencies == null) {
147+
if (!rnConfig.dependencies) {
147148
return [];
148149
}
149150
return Object.keys(rnConfig.dependencies).flatMap(name => {
@@ -366,6 +367,19 @@ function getLibraryName(library) {
366367
).name;
367368
}
368369

370+
/**
371+
* Finds all disabled libraries by platform based the react native config.
372+
*
373+
* This is needed when selectively disabling libraries in react-native.config.js since codegen should exclude those libraries as well.
374+
*/
375+
function findDisabledLibrariesByPlatform(reactNativeConfig, platform) {
376+
const dependencies = reactNativeConfig.dependencies ?? {};
377+
378+
return Object.keys(dependencies).filter(
379+
dependency => dependencies[dependency].platforms?.[platform] === null,
380+
);
381+
}
382+
369383
module.exports = {
370384
buildCodegenIfNeeded,
371385
pkgJsonIncludesGeneratedCode,
@@ -377,4 +391,6 @@ module.exports = {
377391
findProjectRootLibraries,
378392
extractLibrariesFromJSON,
379393
parseiOSAnnotations,
394+
readReactNativeConfig,
395+
findDisabledLibrariesByPlatform,
380396
};

0 commit comments

Comments
 (0)