Skip to content

Commit 17726e1

Browse files
davidaurelioFacebook Github Bot 6
authored andcommitted
Improve constant inlining, add process.platform
Reviewed By: bestander Differential Revision: D3235716 fb-gh-sync-id: f9019ec0042827e409fa84ba74f4c426ccad1519 fbshipit-source-id: f9019ec0042827e409fa84ba74f4c426ccad1519
1 parent cc538b9 commit 17726e1

2 files changed

Lines changed: 91 additions & 21 deletions

File tree

react-packager/src/JSTransformer/worker/__tests__/inline-test.js

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ describe('inline constants', () => {
3535
var a = __DEV__ ? 1 : 2;
3636
var b = a.__DEV__;
3737
var c = function __DEV__(__DEV__) {};
38-
}`
38+
}`;
3939
const {ast} = inline('arbitrary.js', {code}, {dev: true});
4040
expect(toString(ast)).toEqual(normalize(code.replace(/__DEV__/, 'true')));
4141
});
@@ -44,7 +44,7 @@ describe('inline constants', () => {
4444
const code = `function a() {
4545
var a = Platform.OS;
4646
var b = a.Platform.OS;
47-
}`
47+
}`;
4848
const {ast} = inline('arbitrary.js', {code}, {platform: 'ios'});
4949
expect(toString(ast)).toEqual(normalize(code.replace(/Platform\.OS/, '"ios"')));
5050
});
@@ -55,7 +55,18 @@ describe('inline constants', () => {
5555
function a() {
5656
if (Platform.OS === 'android') a = function() {};
5757
var b = a.Platform.OS;
58-
}`
58+
}`;
59+
const {ast} = inline('arbitrary.js', {code}, {platform: 'ios'});
60+
expect(toString(ast)).toEqual(normalize(code.replace(/Platform\.OS/, '"ios"')));
61+
});
62+
63+
it('replaces Platform.OS in the code if Platform is a top level import from react-native', () => {
64+
const code = `
65+
var Platform = require('react-native').Platform;
66+
function a() {
67+
if (Platform.OS === 'android') a = function() {};
68+
var b = a.Platform.OS;
69+
}`;
5970
const {ast} = inline('arbitrary.js', {code}, {platform: 'ios'});
6071
expect(toString(ast)).toEqual(normalize(code.replace(/Platform\.OS/, '"ios"')));
6172
});
@@ -64,7 +75,7 @@ describe('inline constants', () => {
6475
const code = `function a() {
6576
var a = require('Platform').OS;
6677
var b = a.require('Platform').OS;
67-
}`
78+
}`;
6879
const {ast} = inline('arbitrary.js', {code}, {platform: 'android'});
6980
expect(toString(ast)).toEqual(
7081
normalize(code.replace(/require\('Platform'\)\.OS/, '"android"')));
@@ -74,18 +85,27 @@ describe('inline constants', () => {
7485
const code = `function a() {
7586
var a = React.Platform.OS;
7687
var b = a.React.Platform.OS;
77-
}`
88+
}`;
7889
const {ast} = inline('arbitrary.js', {code}, {platform: 'ios'});
7990
expect(toString(ast)).toEqual(normalize(code.replace(/React\.Platform\.OS/, '"ios"')));
8091
});
8192

93+
it('replaces ReactNative.Platform.OS in the code if ReactNative is a global', () => {
94+
const code = `function a() {
95+
var a = ReactNative.Platform.OS;
96+
var b = a.ReactNative.Platform.OS;
97+
}`;
98+
const {ast} = inline('arbitrary.js', {code}, {platform: 'ios'});
99+
expect(toString(ast)).toEqual(normalize(code.replace(/ReactNative\.Platform\.OS/, '"ios"')));
100+
});
101+
82102
it('replaces React.Platform.OS in the code if React is a top level import', () => {
83103
const code = `
84104
var React = require('React');
85105
function a() {
86106
if (React.Platform.OS === 'android') a = function() {};
87107
var b = a.React.Platform.OS;
88-
}`
108+
}`;
89109
const {ast} = inline('arbitrary.js', {code}, {platform: 'ios'});
90110
expect(toString(ast)).toEqual(normalize(code.replace(/React.Platform\.OS/, '"ios"')));
91111
});
@@ -94,19 +114,40 @@ describe('inline constants', () => {
94114
const code = `function a() {
95115
var a = require('React').Platform.OS;
96116
var b = a.require('React').Platform.OS;
97-
}`
117+
}`;
98118
const {ast} = inline('arbitrary.js', {code}, {platform: 'android'});
99119
expect(toString(ast)).toEqual(
100120
normalize(code.replace(/require\('React'\)\.Platform\.OS/, '"android"')));
101121
});
102122

123+
it('replaces ReactNative.Platform.OS in the code if ReactNative is a top level import', () => {
124+
const code = `
125+
var ReactNative = require('react-native');
126+
function a() {
127+
if (ReactNative.Platform.OS === 'android') a = function() {};
128+
var b = a.ReactNative.Platform.OS;
129+
}`;
130+
const {ast} = inline('arbitrary.js', {code}, {platform: 'android'});
131+
expect(toString(ast)).toEqual(normalize(code.replace(/ReactNative.Platform\.OS/, '"android"')));
132+
});
133+
134+
it('replaces require("react-native").Platform.OS in the code', () => {
135+
const code = `function a() {
136+
var a = require('react-native').Platform.OS;
137+
var b = a.require('react-native').Platform.OS;
138+
}`;
139+
const {ast} = inline('arbitrary.js', {code}, {platform: 'android'});
140+
expect(toString(ast)).toEqual(
141+
normalize(code.replace(/require\('react-native'\)\.Platform\.OS/, '"android"')));
142+
});
143+
103144
it('replaces process.env.NODE_ENV in the code', () => {
104145
const code = `function a() {
105146
if (process.env.NODE_ENV === 'production') {
106147
return require('Prod');
107148
}
108149
return require('Dev');
109-
}`
150+
}`;
110151
const {ast} = inline('arbitrary.js', {code}, {dev: false});
111152
expect(toString(ast)).toEqual(
112153
normalize(code.replace(/process\.env\.NODE_ENV/, '"production"')));
@@ -118,16 +159,28 @@ describe('inline constants', () => {
118159
return require('Prod');
119160
}
120161
return require('Dev');
121-
}`
162+
}`;
122163
const {ast} = inline('arbitrary.js', {code}, {dev: true});
123164
expect(toString(ast)).toEqual(
124165
normalize(code.replace(/process\.env\.NODE_ENV/, '"development"')));
125166
});
126167

168+
it('replaces process.platform in the code', () => {
169+
const code = `function a() {
170+
if (process.platform === 'android') {
171+
return require('./android');
172+
}
173+
return require('./ios');
174+
}`;
175+
const {ast} = inline('arbitrary.js', {code}, {platform: 'ios'});
176+
expect(toString(ast)).toEqual(
177+
normalize(code.replace(/process\.platform\b/, '"ios"')));
178+
});
179+
127180
it('accepts an AST as input', function() {
128-
const code = `function ifDev(a,b){return __DEV__?a:b;}`;
181+
const code = 'function ifDev(a,b){return __DEV__?a:b;}';
129182
const {ast} = inline('arbitrary.hs', {ast: toAst(code)}, {dev: false});
130-
expect(toString(ast)).toEqual(code.replace(/__DEV__/, 'false'))
183+
expect(toString(ast)).toEqual(code.replace(/__DEV__/, 'false'));
131184
});
132185
});
133186

react-packager/src/JSTransformer/worker/inline.js

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,21 @@
1111
const babel = require('babel-core');
1212
const t = babel.types;
1313

14-
const react = {name: 'React'};
14+
const React = {name: 'React'};
15+
const ReactNative = {name: 'ReactNative'};
1516
const platform = {name: 'Platform'};
1617
const os = {name: 'OS'};
1718
const requirePattern = {name: 'require'};
1819

1920
const env = {name: 'env'};
2021
const nodeEnv = {name: 'NODE_ENV'};
2122
const processId = {name: 'process'};
23+
const platformId = {name: 'platform'};
2224

2325
const dev = {name: '__DEV__'};
2426

27+
const importMap = new Map([['ReactNative', 'react-native']]);
28+
2529
const isGlobal = (binding) => !binding;
2630

2731
const isToplevelBinding = (binding) => isGlobal(binding) || !binding.scope.parent;
@@ -31,20 +35,27 @@ const isRequireCall = (node, dependencyId, scope) =>
3135
t.isIdentifier(node.callee, requirePattern) &&
3236
t.isStringLiteral(node.arguments[0], t.stringLiteral(dependencyId));
3337

34-
const isImport = (node, scope, pattern) =>
35-
t.isIdentifier(node, pattern) &&
36-
isToplevelBinding(scope.getBinding(pattern.name)) ||
37-
isRequireCall(node, pattern.name, scope);
38+
const isImport = (node, scope, patterns) =>
39+
patterns.some(pattern => {
40+
const importName = importMap.get(pattern.name) || pattern.name;
41+
return isRequireCall(node, importName, scope);
42+
});
43+
44+
function isImportOrGlobal(node, scope, patterns) {
45+
const identifier = patterns.find(pattern => t.isIdentifier(node, pattern));
46+
return identifier && isToplevelBinding(scope.getBinding(identifier.name)) ||
47+
isImport(node, scope, patterns);
48+
}
3849

3950
const isPlatformOS = (node, scope) =>
4051
t.isIdentifier(node.property, os) &&
41-
isImport(node.object, scope, platform);
52+
isImportOrGlobal(node.object, scope, [platform]);
4253

4354
const isReactPlatformOS = (node, scope) =>
4455
t.isIdentifier(node.property, os) &&
4556
t.isMemberExpression(node.object) &&
4657
t.isIdentifier(node.object.property, platform) &&
47-
isImport(node.object.object, scope, react);
58+
isImportOrGlobal(node.object.object, scope, [React, ReactNative]);
4859

4960
const isProcessEnvNodeEnv = (node, scope) =>
5061
t.isIdentifier(node.property, nodeEnv) &&
@@ -53,6 +64,11 @@ const isProcessEnvNodeEnv = (node, scope) =>
5364
t.isIdentifier(node.object.object, processId) &&
5465
isGlobal(scope.getBinding(processId.name));
5566

67+
const isProcessPlatform = (node, scope) =>
68+
t.isIdentifier(node.property, platformId) &&
69+
t.isIdentifier(node.object, processId) &&
70+
isGlobal(scope.getBinding(processId.name));
71+
5672
const isDev = (node, parent, scope) =>
5773
t.isIdentifier(node, dev) &&
5874
isGlobal(scope.getBinding(dev.name)) &&
@@ -71,11 +87,12 @@ const inlinePlugin = {
7187

7288
if (isPlatformOS(node, scope) || isReactPlatformOS(node, scope)) {
7389
path.replaceWith(t.stringLiteral(state.opts.platform));
74-
}
75-
76-
if(isProcessEnvNodeEnv(node, scope)) {
90+
} else if (isProcessEnvNodeEnv(node, scope)) {
7791
path.replaceWith(
7892
t.stringLiteral(state.opts.dev ? 'development' : 'production'));
93+
} else if (isProcessPlatform(node, scope)) {
94+
path.replaceWith(
95+
t.stringLiteral(state.opts.platform));
7996
}
8097
},
8198
},

0 commit comments

Comments
 (0)