@samitouri / QOS-React / commits / 9f9f4a9f11

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",