[babel] Ensure only adding import specifier to non-namespace
Missed this in the previous PR Test plan: P706162189 (some babel errors) before this PR, P706255523 has no errors
Lauren Tan committed
Apr 26, 2023 at 15:16 UTC
b1eaf88c61dfaf3fedf4f58e45fad4cf519e8049
3 files changed
+133
-9
compiler/forget/src/Babel/BabelPlugin.ts
+18
-9
@@ -233,14 +233,7 @@ export default function ReactForgetBabelPlugin(
233
}
234
},
235
ImportDeclaration(importDeclPath) {
236
- // Matches `import { /* ... */ } from 'react';`
237
- // but not `import * as React from 'react';`
238
- if (
239
- importDeclPath.get("source").node.value === "react" &&
240
- importDeclPath
241
- .get("specifiers")
242
- .every((specifier) => specifier.isImportSpecifier())
243
- ) {
236
+ if (isNonNamespacedImportOfReact(importDeclPath)) {
237
hasExistingReactImport = true;
238
}
239
},
@@ -253,7 +246,7 @@ export default function ReactForgetBabelPlugin(
246
let didUpdateImport = false;
247
path.traverse({
248
ImportDeclaration(importDeclPath) {
256
- if (importDeclPath.get("source").node.value === "react") {
249
+ if (isNonNamespacedImportOfReact(importDeclPath)) {
250
importDeclPath.pushContainer(
251
"specifiers",
252
t.importSpecifier(
@@ -262,6 +255,7 @@ export default function ReactForgetBabelPlugin(
255
)
256
);
257
didUpdateImport = true;
258
+ path.stop();
259
}
260
},
261
});
@@ -440,3 +434,18 @@ function buildImportForGatingModule(
434
function buildSpecifierIdent(gating: GatingOptions): t.Identifier {
435
return t.identifier(gating.importSpecifierName);
436
}
437
+
438
+/**
439
+ * Matches `import { ... } from 'react';`
440
+ * but not `import * as React from 'react';`
441
+ */
442
+function isNonNamespacedImportOfReact(
443
+ importDeclPath: BabelCore.NodePath<t.ImportDeclaration>
444
+): boolean {
445
+ return (
446
+ importDeclPath.get("source").node.value === "react" &&
447
+ importDeclPath
448
+ .get("specifiers")
449
+ .every((specifier) => specifier.isImportSpecifier())
450
+ );
451
+}
compiler/forget/src/__tests__/fixtures/compiler/babel-existing-react-kitchensink-import.expect.md
new
+99
@@ -0,0 +1,99 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+import * as React from "react";
6
+import { useState } from "react";
7
+
8
+function Component(props) {
9
+ const [x] = useState(0);
10
+ const expensiveNumber = React.useMemo(() => calculateExpensiveNumber(x), [x]);
11
+
12
+ return <div>{expensiveNumber}</div>;
13
+}
14
+
15
+function Component2(props) {
16
+ const [x] = useState(0);
17
+ const expensiveNumber = React.useMemo(() => calculateExpensiveNumber(x), [x]);
18
+
19
+ return <div>{expensiveNumber}</div>;
20
+}
21
+
22
+```
23
+
24
+## Code
25
+
26
+```javascript
27
+import * as React from "react";
28
+import { useState, unstable_useMemoCache as useMemoCache } from "react";
29
+
30
+function Component(props) {
31
+ const $ = useMemoCache(6);
32
+ const [x] = useState(0);
33
+ const c_0 = $[0] !== x;
34
+ let t1;
35
+ if (c_0) {
36
+ const c_2 = $[2] !== x;
37
+ let t0;
38
+ if (c_2) {
39
+ t0 = () => calculateExpensiveNumber(x);
40
+ $[2] = x;
41
+ $[3] = t0;
42
+ } else {
43
+ t0 = $[3];
44
+ }
45
+ t1 = React.useMemo(t0, [x]);
46
+ $[0] = x;
47
+ $[1] = t1;
48
+ } else {
49
+ t1 = $[1];
50
+ }
51
+ const expensiveNumber = t1;
52
+ const c_4 = $[4] !== expensiveNumber;
53
+ let t2;
54
+ if (c_4) {
55
+ t2 = <div>{expensiveNumber}</div>;
56
+ $[4] = expensiveNumber;
57
+ $[5] = t2;
58
+ } else {
59
+ t2 = $[5];
60
+ }
61
+ return t2;
62
+}
63
+
64
+function Component2(props) {
65
+ const $ = useMemoCache(6);
66
+ const [x] = useState(0);
67
+ const c_0 = $[0] !== x;
68
+ let t1;
69
+ if (c_0) {
70
+ const c_2 = $[2] !== x;
71
+ let t0;
72
+ if (c_2) {
73
+ t0 = () => calculateExpensiveNumber(x);
74
+ $[2] = x;
75
+ $[3] = t0;
76
+ } else {
77
+ t0 = $[3];
78
+ }
79
+ t1 = React.useMemo(t0, [x]);
80
+ $[0] = x;
81
+ $[1] = t1;
82
+ } else {
83
+ t1 = $[1];
84
+ }
85
+ const expensiveNumber = t1;
86
+ const c_4 = $[4] !== expensiveNumber;
87
+ let t2;
88
+ if (c_4) {
89
+ t2 = <div>{expensiveNumber}</div>;
90
+ $[4] = expensiveNumber;
91
+ $[5] = t2;
92
+ } else {
93
+ t2 = $[5];
94
+ }
95
+ return t2;
96
+}
97
+
98
+```
99
+
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/babel-existing-react-kitchensink-import.js
new
+16
@@ -0,0 +1,16 @@
1
+import * as React from "react";
2
+import { useState } from "react";
3
+
4
+function Component(props) {
5
+ const [x] = useState(0);
6
+ const expensiveNumber = React.useMemo(() => calculateExpensiveNumber(x), [x]);
7
+
8
+ return <div>{expensiveNumber}</div>;
9
+}
10
+
11
+function Component2(props) {
12
+ const [x] = useState(0);
13
+ const expensiveNumber = React.useMemo(() => calculateExpensiveNumber(x), [x]);
14
+
15
+ return <div>{expensiveNumber}</div>;
16
+}