Fix gating mode hoisting check to skip type references
ghstack-source-id: f83e9e28c1cdf31dba718e62db12aaa3a5f9ddab Pull Request resolved: https://github.com/facebook/react-forget/pull/2876
Joe Savona committed
Apr 19, 2024 at 15:16 UTC
9f9f4a9f1138eabdc466cc10544d6b0727dca027
5 files changed
+59
-33
compiler/packages/babel-plugin-react-forget/src/Entrypoint/Program.ts
+12
@@ -758,6 +758,18 @@ function checkFunctionReferencedBeforeDeclarationAtTopLevel(
758
const errors = new CompilerError();
759
760
program.traverse({
761
+ TypeAnnotation(path) {
762
+ path.skip();
763
+ },
764
+ TSTypeAnnotation(path) {
765
+ path.skip();
766
+ },
767
+ TypeAlias(path) {
768
+ path.skip();
769
+ },
770
+ TSTypeAliasDeclaration(path) {
771
+ path.skip();
772
+ },
773
Identifier(id) {
774
const fn = fnNames.get(id.node.name);
775
// We're not tracking this identifier.
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-gating-with-react-memo.flow.expect.md
deleted
-32
@@ -1,32 +0,0 @@
1
-
2
-## Input
3
-
4
-```javascript
5
-// @flow @gating
6
-import { memo } from "react";
7
-
8
-// TODO: this appears as a hoisted reference to Component, but it's a type not runtime reference!
9
-type Props = React.ElementConfig<typeof Component>;
10
-
11
-component Component(value: string) {
12
- return <div>{value}</div>;
13
-}
14
-
15
-export default memo<Props>(Component);
16
-
17
-```
18
-
19
-
20
-## Error
21
-
22
-```
23
- 5 | type Props = React.ElementConfig<typeof Component>;
24
- 6 |
25
-> 7 | component Component(value: string) {
26
- | ^^^^^^^^^ Invariant: Encountered a function used before its declaration, which breaks Forget's gating codegen due to hoisting. Rewrite the reference to Component to not rely on hoisting to fix this issue (7:7)
27
- 8 | return <div>{value}</div>;
28
- 9 | }
29
- 10 |
30
-```
31
-
32
-
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/gating-with-hoisted-type-reference.flow.expect.md
new
+46
@@ -0,0 +1,46 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+// @flow @gating
6
+import { memo } from "react";
7
+
8
+type Props = React.ElementConfig<typeof Component>;
9
+
10
+component Component(value: string) {
11
+ return <div>{value}</div>;
12
+}
13
+
14
+export default memo<Props>(Component);
15
+
16
+```
17
+
18
+## Code
19
+
20
+```javascript
21
+import { isForgetEnabled_Fixtures } from "ReactForgetFeatureFlag";
22
+import { memo, unstable_useMemoCache as useMemoCache } from "react";
23
+
24
+type Props = React.ElementConfig<typeof Component>;
25
+const Component = isForgetEnabled_Fixtures()
26
+ ? function Component(t0) {
27
+ const $ = useMemoCache(2);
28
+ const { value } = t0;
29
+ let t1;
30
+ if ($[0] !== value) {
31
+ t1 = <div>{value}</div>;
32
+ $[0] = value;
33
+ $[1] = t1;
34
+ } else {
35
+ t1 = $[1];
36
+ }
37
+ return t1;
38
+ }
39
+ : function Component({ value }: $ReadOnly<{ value: string }>) {
40
+ return <div>{value}</div>;
41
+ };
42
+
43
+export default memo<Props>(Component);
44
+
45
+```
46
+
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/gating-with-hoisted-type-reference.flow.js
renamed
-1
@@ -1,7 +1,6 @@
1
// @flow @gating
2
import { memo } from "react";
3
4
-// TODO: this appears as a hoisted reference to Component, but it's a type not runtime reference!
4
type Props = React.ElementConfig<typeof Component>;
5
6
component Component(value: string) {
compiler/packages/snap/src/SproutTodoFilter.ts
+1
@@ -375,6 +375,7 @@ const skipFilter = new Set([
375
"gating-test-export-function-and-default",
376
"gating-test-export-function",
377
"gating-test",
378
+ "gating-with-hoisted-type-reference.flow",
379
"hook-call",
380
"hooks-freeze-arguments",
381
"hooks-freeze-possibly-mutable-arguments",