Skip to content

Commit 07c29e3

Browse files
huntiefacebook-github-bot
authored andcommitted
Expose 'react-native/setup-env' to replace InitializeCore (#57461)
Summary: Replace `'react-native/Libraries/Core/InitializeCore'` with an explicit `'react-native/setup-env'` secondary export. This was previously a special-case path excluded from our ESLint warnings. It is now formalised. **Changes** - Add new `src/setup-env.js` entry point and `package.json` mapping. - Replace references in `packages/metro-config/` and `packages/community-cli-plugin/`. - Update `warn-on-deep-imports` ESLint rule. Changelog: [General][Added] - Add `'react-native/setup-env'` entry point. This replaces the previous side-effectful `'react-native/Libraries/Core/InitializeCore'`. [General][Deprecated] - Deprecate `'react-native/Libraries/Core/InitializeCore'`. Use `'react-native/setup-env'` instead. Reviewed By: rubennorte Differential Revision: D110890810
1 parent 58ffd18 commit 07c29e3

14 files changed

Lines changed: 108 additions & 50 deletions

File tree

.flowconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ experimental.multi_platform.extensions=.android
5656
munge_underscores=true
5757

5858
module.name_mapper='^react-native$' -> '<PROJECT_ROOT>/packages/react-native/index.js'
59+
module.name_mapper='^react-native/setup-env$' -> '<PROJECT_ROOT>/packages/react-native/src/setup-env.js'
5960
module.name_mapper='^react-native/\(.*\)$' -> '<PROJECT_ROOT>/packages/react-native/\1'
6061
module.name_mapper='^@react-native/dev-middleware$' -> '<PROJECT_ROOT>/packages/dev-middleware'
6162
module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\|xml\|ktx\|heic\|heif\)$' -> '<PROJECT_ROOT>/packages/react-native/Libraries/Image/RelativeImageStub'

packages/community-cli-plugin/src/utils/loadMetroConfig.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,17 @@ function getCommunityCliDefaultConfig(
6060
return {
6161
resolver,
6262
serializer: {
63-
// We can include multiple copies of InitializeCore here because metro will
63+
// We can include multiple copies of setup-env here because Metro will
6464
// only add ones that are already part of the bundle
6565
getModulesRunBeforeMainModule: () => [
66-
require.resolve(
67-
path.join(ctx.reactNativePath, 'Libraries/Core/InitializeCore'),
68-
{paths: [ctx.root]},
69-
),
66+
// NOTE: ctx.reactNativePath is an absolute path, therefore we need to
67+
// reference setup-env.js here by exact path specifier.
68+
require.resolve(path.join(ctx.reactNativePath, 'src/setup-env.js'), {
69+
paths: [ctx.root],
70+
}),
7071
...outOfTreePlatforms.map(platform =>
7172
require.resolve(
72-
`${ctx.platforms[platform].npmPackageName}/Libraries/Core/InitializeCore`,
73+
`${ctx.platforms[platform].npmPackageName}/setup-env`,
7374
{paths: [ctx.root]},
7475
),
7576
),

packages/eslint-plugin-react-native/__tests__/no-deep-imports-test.js

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ eslintTester.run('../no-deep-imports', rule, {
2929
"import Foo from 'react-native-foo';",
3030
"import Foo from 'react-native-foo/Foo';",
3131
"import Foo from 'react/native/Foo';",
32-
"import 'react-native/Libraries/Core/InitializeCore';",
33-
"require('react-native/Libraries/Core/InitializeCore');",
3432
"import Foo from 'react-native/src/fb_internal/Foo'",
3533
"require('react-native/src/fb_internal/Foo')",
34+
"import 'react-native/setup-env';",
35+
"require('react-native/setup-env');",
3636
],
3737
invalid: [
3838
{
@@ -125,5 +125,31 @@ eslintTester.run('../no-deep-imports', rule, {
125125
],
126126
output: null,
127127
},
128+
{
129+
code: "import 'react-native/Libraries/Core/InitializeCore';",
130+
errors: [
131+
{
132+
messageId: 'useReplacementSource',
133+
data: {
134+
importPath: 'react-native/Libraries/Core/InitializeCore',
135+
replacementSource: 'react-native/setup-env',
136+
},
137+
},
138+
],
139+
output: "import 'react-native/setup-env';",
140+
},
141+
{
142+
code: "require('react-native/Libraries/Core/InitializeCore');",
143+
errors: [
144+
{
145+
messageId: 'useReplacementSource',
146+
data: {
147+
importPath: 'react-native/Libraries/Core/InitializeCore',
148+
replacementSource: 'react-native/setup-env',
149+
},
150+
},
151+
],
152+
output: "require('react-native/setup-env');",
153+
},
128154
],
129155
});

packages/eslint-plugin-react-native/no-deep-imports.js

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ module.exports = {
2121
messages: {
2222
deepImport:
2323
"'{{importPath}}' React Native deep imports are deprecated. Please use the top level import instead.",
24+
useReplacementSource:
25+
"'{{importPath}}' is deprecated. Please import '{{replacementSource}}' instead.",
2426
},
2527
schema: [],
2628
fixable: 'code',
@@ -31,12 +33,14 @@ module.exports = {
3133
ImportDeclaration(node) {
3234
if (
3335
!isDeepReactNativeImport(node.source) ||
34-
isInitializeCoreImport(node.source) ||
3536
isSecondaryEntryPoint(node.source) ||
3637
isFbInternalImport(node.source)
3738
) {
3839
return;
3940
}
41+
if (reportReplacementSource(node.source)) {
42+
return;
43+
}
4044
if (isDefaultImport(node)) {
4145
const reactNativeSource = node.source.value.slice(
4246
'react-native/'.length,
@@ -88,13 +92,16 @@ module.exports = {
8892
CallExpression(node) {
8993
if (
9094
!isDeepRequire(node) ||
91-
isInitializeCoreImport(node.arguments[0]) ||
9295
isSecondaryEntryPoint(node.arguments[0]) ||
9396
isFbInternalImport(node.arguments[0])
9497
) {
9598
return;
9699
}
97100

101+
if (reportReplacementSource(node.arguments[0])) {
102+
return;
103+
}
104+
98105
const parent = node.parent;
99106
const importPath = node.arguments[0].value;
100107

@@ -123,6 +130,26 @@ module.exports = {
123130
},
124131
};
125132

133+
function reportReplacementSource(source) {
134+
const reactNativeSource = source.value.slice('react-native/'.length);
135+
const mapping = publicAPIMapping[reactNativeSource];
136+
if (!mapping || !mapping.replacementSource) {
137+
return false;
138+
}
139+
context.report({
140+
node: source,
141+
messageId: 'useReplacementSource',
142+
data: {
143+
importPath: source.value,
144+
replacementSource: mapping.replacementSource,
145+
},
146+
fix(fixer) {
147+
return fixer.replaceText(source, `'${mapping.replacementSource}'`);
148+
},
149+
});
150+
return true;
151+
}
152+
126153
function getStandardReport(source) {
127154
return {
128155
node: source,
@@ -167,20 +194,15 @@ module.exports = {
167194
return parts.length > 1 && parts[0] === 'react-native';
168195
}
169196

170-
function isInitializeCoreImport(source) {
171-
if (source.type !== 'Literal' || typeof source.value !== 'string') {
172-
return false;
173-
}
174-
175-
return source.value === 'react-native/Libraries/Core/InitializeCore';
176-
}
177-
178197
function isSecondaryEntryPoint(source) {
179198
if (source.type !== 'Literal' || typeof source.value !== 'string') {
180199
return false;
181200
}
182201

183-
return source.value === 'react-native/asset-registry';
202+
return (
203+
source.value === 'react-native/asset-registry' ||
204+
source.value === 'react-native/setup-env'
205+
);
184206
}
185207

186208
function isFbInternalImport(source) {

packages/eslint-plugin-react-native/utils.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ const publicAPIMapping = {
3737
default: 'experimental_LayoutConformance',
3838
types: ['LayoutConformanceProps'],
3939
},
40+
'Libraries/Core/InitializeCore': {
41+
// `InitializeCore` has no public named export; the deep import must be
42+
// swapped for the `react-native/setup-env` entry point entirely.
43+
default: null,
44+
types: null,
45+
replacementSource: 'react-native/setup-env',
46+
},
4047
'Libraries/Lists/FlatList': {
4148
default: 'FlatList',
4249
types: ['FlatListProps'],

packages/jest-preset/jest/setup.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ mock(
133133
'm#react-native/Libraries/Core/InitializeCore',
134134
'm#./mocks/InitializeCore',
135135
);
136+
mock('m#react-native/setup-env', 'm#./mocks/InitializeCore');
136137
mock('m#react-native/Libraries/Core/NativeExceptionsManager');
137138
mock('m#react-native/Libraries/Image/Image', 'm#./mocks/Image');
138139
mock(

packages/metro-config/src/index.flow.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export function getDefaultConfig(projectRoot: string): ConfigT {
6161
serializer: {
6262
// Note: This option is overridden in cli-plugin-metro (getOverrideConfig)
6363
getModulesRunBeforeMainModule: () => [
64-
require.resolve('react-native/Libraries/Core/InitializeCore'),
64+
require.resolve('react-native/setup-env'),
6565
],
6666
getPolyfills: () => require('@react-native/js-polyfills')(),
6767
isThirdPartyModule({path: modulePath}: Readonly<{path: string, ...}>) {

packages/react-native-babel-preset/src/__tests__/plugin-warn-on-deep-imports-test.js

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,3 @@ test('import from other package', () => {
8282
`"import { foo } from 'react-native-foo';"`,
8383
);
8484
});
85-
86-
test('import react-native/Libraries/Core/InitializeCore', () => {
87-
const code = `
88-
import 'react-native/Libraries/Core/InitializeCore';
89-
require('react-native/Libraries/Core/InitializeCore');
90-
export * from 'react-native/Libraries/Core/InitializeCore';
91-
`;
92-
93-
expect(transform(code, [rnDeepImportsWarningPlugin])).toMatchInlineSnapshot(`
94-
"import 'react-native/Libraries/Core/InitializeCore';
95-
require('react-native/Libraries/Core/InitializeCore');
96-
export * from 'react-native/Libraries/Core/InitializeCore';"
97-
`);
98-
});

packages/react-native-babel-preset/src/plugin-warn-on-deep-imports.js

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,6 @@ function isDeepReactNativeImport(source) {
3838
return parts.length > 1 && parts[0] === 'react-native';
3939
}
4040

41-
function isInitializeCoreImport(source) {
42-
return source === 'react-native/Libraries/Core/InitializeCore';
43-
}
44-
4541
function withLocation(node, loc) {
4642
if (!node.loc) {
4743
return {...node, loc};
@@ -55,7 +51,7 @@ module.exports = ({types: t}) => ({
5551
ImportDeclaration(path, state) {
5652
const source = path.node.source.value;
5753

58-
if (isDeepReactNativeImport(source) && !isInitializeCoreImport(source)) {
54+
if (isDeepReactNativeImport(source)) {
5955
const loc = path.node.loc;
6056
state.import.push({source, loc});
6157
}
@@ -71,10 +67,7 @@ module.exports = ({types: t}) => ({
7167
) {
7268
const source =
7369
args[0].node.type === 'StringLiteral' ? args[0].node.value : '';
74-
if (
75-
isDeepReactNativeImport(source) &&
76-
!isInitializeCoreImport(source)
77-
) {
70+
if (isDeepReactNativeImport(source)) {
7871
const loc = path.node.loc;
7972
state.require.push({source, loc});
8073
}
@@ -83,11 +76,7 @@ module.exports = ({types: t}) => ({
8376
ExportNamedDeclaration(path, state) {
8477
const source = path.node.source;
8578

86-
if (
87-
source &&
88-
isDeepReactNativeImport(source.value) &&
89-
!isInitializeCoreImport(source)
90-
) {
79+
if (source && isDeepReactNativeImport(source.value)) {
9180
const loc = path.node.loc;
9281
state.export.push({source: source.value, loc});
9382
}

packages/react-native/Libraries/Core/InitializeCore.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
* 1. Require system.
2323
* 2. Bridged modules.
2424
*
25+
* @deprecated Since 0.87. Use `'react-native/setup-env'` instead.
2526
*/
2627

2728
'use strict';

0 commit comments

Comments
 (0)