@samitouri / QOS-React-2 / commits / 00abc5acf5

[be][tests] Run todo fixtures

--- Snap should compile all fixtures to record changes in results, even `todo` prefixed ones. Previously, they were skipped as we noted the correlation of `// @skip` pragmas and file naming. Now, no fixture should be skipped as our compiler pipeline should be able to handle every kind of error.

Mofei Zhang committed Nov 14, 2023 at 13:04 UTC 00abc5acf5e02fc72b1f7107d803efcdb358f441
70 files changed +1622 -23
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.bail.rules-of-hooks-279ac76f53af.expect.md new
+29
@@ -0,0 +1,29 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Unsupported input
7 +
8 +// Valid -- this is a regression test.
9 +jest.useFakeTimers();
10 +beforeEach(() => {
11 + jest.useRealTimers();
12 +});
13 +
14 +```
15 +
16 +## Code
17 +
18 +```javascript
19 +// @skip
20 +// Unsupported input
21 +
22 +// Valid -- this is a regression test.
23 +jest.useFakeTimers();
24 +beforeEach(() => {
25 + jest.useRealTimers();
26 +});
27 +
28 +```
29 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.bail.rules-of-hooks-28a78701970c.expect.md new
+40
@@ -0,0 +1,40 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Unsupported input
7 +
8 +// Valid because hooks can be used in anonymous function arguments to
9 +// React.memo.
10 +const MemoizedFunction = React.memo((props) => {
11 + useHook();
12 + return <button {...props} />;
13 +});
14 +
15 +```
16 +
17 +## Code
18 +
19 +```javascript
20 +import { unstable_useMemoCache as useMemoCache } from "react"; // @skip
21 +// Unsupported input
22 +
23 +// Valid because hooks can be used in anonymous function arguments to
24 +// React.memo.
25 +const MemoizedFunction = React.memo((props) => {
26 + const $ = useMemoCache(2);
27 + useHook();
28 + let t0;
29 + if ($[0] !== props) {
30 + t0 = <button {...props} />;
31 + $[0] = props;
32 + $[1] = t0;
33 + } else {
34 + t0 = $[1];
35 + }
36 + return t0;
37 +});
38 +
39 +```
40 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.bail.rules-of-hooks-3d692676194b.expect.md new
+52
@@ -0,0 +1,52 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Unsupported input
7 +
8 +// Invalid because it's a common misunderstanding.
9 +// We *could* make it valid but the runtime error could be confusing.
10 +const ComponentWithHookInsideCallback = React.forwardRef((props, ref) => {
11 + useEffect(() => {
12 + useHookInsideCallback();
13 + });
14 + return <button {...props} ref={ref} />;
15 +});
16 +
17 +```
18 +
19 +## Code
20 +
21 +```javascript
22 +import { unstable_useMemoCache as useMemoCache } from "react"; // @skip
23 +// Unsupported input
24 +
25 +// Invalid because it's a common misunderstanding.
26 +// We *could* make it valid but the runtime error could be confusing.
27 +const ComponentWithHookInsideCallback = React.forwardRef((props, ref) => {
28 + const $ = useMemoCache(4);
29 + let t0;
30 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
31 + t0 = () => {
32 + useHookInsideCallback();
33 + };
34 + $[0] = t0;
35 + } else {
36 + t0 = $[0];
37 + }
38 + useEffect(t0);
39 + let t1;
40 + if ($[1] !== props || $[2] !== ref) {
41 + t1 = <button {...props} ref={ref} />;
42 + $[1] = props;
43 + $[2] = ref;
44 + $[3] = t1;
45 + } else {
46 + t1 = $[3];
47 + }
48 + return t1;
49 +});
50 +
51 +```
52 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.bail.rules-of-hooks-6949b255e7eb.expect.md new
+159
@@ -0,0 +1,159 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Unsupported input
7 +
8 +// Valid because the neither the conditions before or after the hook affect the hook call
9 +// Failed prior to implementing BigInt because pathsFromStartToEnd and allPathsFromStartToEnd were too big and had rounding errors
10 +const useSomeHook = () => {};
11 +
12 +const SomeName = () => {
13 + const filler = FILLER ?? FILLER ?? FILLER;
14 + const filler2 = FILLER ?? FILLER ?? FILLER;
15 + const filler3 = FILLER ?? FILLER ?? FILLER;
16 + const filler4 = FILLER ?? FILLER ?? FILLER;
17 + const filler5 = FILLER ?? FILLER ?? FILLER;
18 + const filler6 = FILLER ?? FILLER ?? FILLER;
19 + const filler7 = FILLER ?? FILLER ?? FILLER;
20 + const filler8 = FILLER ?? FILLER ?? FILLER;
21 +
22 + useSomeHook();
23 +
24 + if (anyConditionCanEvenBeFalse) {
25 + return null;
26 + }
27 +
28 + return (
29 + <React.Fragment>
30 + {FILLER ? FILLER : FILLER}
31 + {FILLER ? FILLER : FILLER}
32 + {FILLER ? FILLER : FILLER}
33 + {FILLER ? FILLER : FILLER}
34 + {FILLER ? FILLER : FILLER}
35 + {FILLER ? FILLER : FILLER}
36 + {FILLER ? FILLER : FILLER}
37 + {FILLER ? FILLER : FILLER}
38 + {FILLER ? FILLER : FILLER}
39 + {FILLER ? FILLER : FILLER}
40 + {FILLER ? FILLER : FILLER}
41 + {FILLER ? FILLER : FILLER}
42 + {FILLER ? FILLER : FILLER}
43 + {FILLER ? FILLER : FILLER}
44 + {FILLER ? FILLER : FILLER}
45 + {FILLER ? FILLER : FILLER}
46 + {FILLER ? FILLER : FILLER}
47 + {FILLER ? FILLER : FILLER}
48 + {FILLER ? FILLER : FILLER}
49 + {FILLER ? FILLER : FILLER}
50 + {FILLER ? FILLER : FILLER}
51 + {FILLER ? FILLER : FILLER}
52 + {FILLER ? FILLER : FILLER}
53 + {FILLER ? FILLER : FILLER}
54 + {FILLER ? FILLER : FILLER}
55 + {FILLER ? FILLER : FILLER}
56 + {FILLER ? FILLER : FILLER}
57 + {FILLER ? FILLER : FILLER}
58 + {FILLER ? FILLER : FILLER}
59 + {FILLER ? FILLER : FILLER}
60 + {FILLER ? FILLER : FILLER}
61 + {FILLER ? FILLER : FILLER}
62 + {FILLER ? FILLER : FILLER}
63 + {FILLER ? FILLER : FILLER}
64 + {FILLER ? FILLER : FILLER}
65 + {FILLER ? FILLER : FILLER}
66 + {FILLER ? FILLER : FILLER}
67 + {FILLER ? FILLER : FILLER}
68 + {FILLER ? FILLER : FILLER}
69 + {FILLER ? FILLER : FILLER}
70 + {FILLER ? FILLER : FILLER}
71 + {FILLER ? FILLER : FILLER}
72 + </React.Fragment>
73 + );
74 +};
75 +
76 +```
77 +
78 +## Code
79 +
80 +```javascript
81 +import { unstable_useMemoCache as useMemoCache } from "react"; // @skip
82 +// Unsupported input
83 +
84 +// Valid because the neither the conditions before or after the hook affect the hook call
85 +// Failed prior to implementing BigInt because pathsFromStartToEnd and allPathsFromStartToEnd were too big and had rounding errors
86 +const useSomeHook = () => {};
87 +
88 +const SomeName = () => {
89 + const $ = useMemoCache(1);
90 + (FILLER ?? FILLER, FILLER) ?? FILLER;
91 + (FILLER ?? FILLER, FILLER) ?? FILLER;
92 + (FILLER ?? FILLER, FILLER) ?? FILLER;
93 + (FILLER ?? FILLER, FILLER) ?? FILLER;
94 + (FILLER ?? FILLER, FILLER) ?? FILLER;
95 + (FILLER ?? FILLER, FILLER) ?? FILLER;
96 + (FILLER ?? FILLER, FILLER) ?? FILLER;
97 + (FILLER ?? FILLER, FILLER) ?? FILLER;
98 +
99 + useSomeHook();
100 + if (anyConditionCanEvenBeFalse) {
101 + return null;
102 + }
103 + let t0;
104 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
105 + t0 = (
106 + <React.Fragment>
107 + {FILLER ? FILLER : FILLER}
108 + {FILLER ? FILLER : FILLER}
109 + {FILLER ? FILLER : FILLER}
110 + {FILLER ? FILLER : FILLER}
111 + {FILLER ? FILLER : FILLER}
112 + {FILLER ? FILLER : FILLER}
113 + {FILLER ? FILLER : FILLER}
114 + {FILLER ? FILLER : FILLER}
115 + {FILLER ? FILLER : FILLER}
116 + {FILLER ? FILLER : FILLER}
117 + {FILLER ? FILLER : FILLER}
118 + {FILLER ? FILLER : FILLER}
119 + {FILLER ? FILLER : FILLER}
120 + {FILLER ? FILLER : FILLER}
121 + {FILLER ? FILLER : FILLER}
122 + {FILLER ? FILLER : FILLER}
123 + {FILLER ? FILLER : FILLER}
124 + {FILLER ? FILLER : FILLER}
125 + {FILLER ? FILLER : FILLER}
126 + {FILLER ? FILLER : FILLER}
127 + {FILLER ? FILLER : FILLER}
128 + {FILLER ? FILLER : FILLER}
129 + {FILLER ? FILLER : FILLER}
130 + {FILLER ? FILLER : FILLER}
131 + {FILLER ? FILLER : FILLER}
132 + {FILLER ? FILLER : FILLER}
133 + {FILLER ? FILLER : FILLER}
134 + {FILLER ? FILLER : FILLER}
135 + {FILLER ? FILLER : FILLER}
136 + {FILLER ? FILLER : FILLER}
137 + {FILLER ? FILLER : FILLER}
138 + {FILLER ? FILLER : FILLER}
139 + {FILLER ? FILLER : FILLER}
140 + {FILLER ? FILLER : FILLER}
141 + {FILLER ? FILLER : FILLER}
142 + {FILLER ? FILLER : FILLER}
143 + {FILLER ? FILLER : FILLER}
144 + {FILLER ? FILLER : FILLER}
145 + {FILLER ? FILLER : FILLER}
146 + {FILLER ? FILLER : FILLER}
147 + {FILLER ? FILLER : FILLER}
148 + {FILLER ? FILLER : FILLER}
149 + </React.Fragment>
150 + );
151 + $[0] = t0;
152 + } else {
153 + t0 = $[0];
154 + }
155 + return t0;
156 +};
157 +
158 +```
159 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.bail.rules-of-hooks-8503ca76d6f8.expect.md new
+51
@@ -0,0 +1,51 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Unsupported input
7 +
8 +// Invalid because it's a common misunderstanding.
9 +// We *could* make it valid but the runtime error could be confusing.
10 +const ComponentWithHookInsideCallback = React.memo((props) => {
11 + useEffect(() => {
12 + useHookInsideCallback();
13 + });
14 + return <button {...props} />;
15 +});
16 +
17 +```
18 +
19 +## Code
20 +
21 +```javascript
22 +import { unstable_useMemoCache as useMemoCache } from "react"; // @skip
23 +// Unsupported input
24 +
25 +// Invalid because it's a common misunderstanding.
26 +// We *could* make it valid but the runtime error could be confusing.
27 +const ComponentWithHookInsideCallback = React.memo((props) => {
28 + const $ = useMemoCache(3);
29 + let t0;
30 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
31 + t0 = () => {
32 + useHookInsideCallback();
33 + };
34 + $[0] = t0;
35 + } else {
36 + t0 = $[0];
37 + }
38 + useEffect(t0);
39 + let t1;
40 + if ($[1] !== props) {
41 + t1 = <button {...props} />;
42 + $[1] = props;
43 + $[2] = t1;
44 + } else {
45 + t1 = $[2];
46 + }
47 + return t1;
48 +});
49 +
50 +```
51 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.bail.rules-of-hooks-e0a5db3ae21e.expect.md new
+99
@@ -0,0 +1,99 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Unsupported input
7 +
8 +// Valid because hooks can call hooks.
9 +function useHook() {
10 + useState();
11 +}
12 +const whatever = function useHook() {
13 + useState();
14 +};
15 +const useHook1 = () => {
16 + useState();
17 +};
18 +let useHook2 = () => useState();
19 +useHook2 = () => {
20 + useState();
21 +};
22 +({
23 + useHook: () => {
24 + useState();
25 + },
26 +});
27 +({
28 + useHook() {
29 + useState();
30 + },
31 +});
32 +const {
33 + useHook3 = () => {
34 + useState();
35 + },
36 +} = {};
37 +({
38 + useHook = () => {
39 + useState();
40 + },
41 +} = {});
42 +Namespace.useHook = () => {
43 + useState();
44 +};
45 +
46 +```
47 +
48 +## Code
49 +
50 +```javascript
51 +// @skip
52 +// Unsupported input
53 +
54 +// Valid because hooks can call hooks.
55 +function useHook() {
56 + useState();
57 +}
58 +
59 +const whatever = function useHook() {
60 + useState();
61 +};
62 +
63 +const useHook1 = () => {
64 + useState();
65 +};
66 +
67 +let useHook2 = () => {
68 + return useState();
69 +};
70 +useHook2 = () => {
71 + useState();
72 +};
73 +
74 +({
75 + useHook: () => {
76 + useState();
77 + },
78 +});
79 +({
80 + useHook() {
81 + useState();
82 + },
83 +});
84 +const {
85 + useHook3 = () => {
86 + useState();
87 + },
88 +} = {};
89 +({
90 + useHook = () => {
91 + useState();
92 + },
93 +} = {});
94 +Namespace.useHook = () => {
95 + useState();
96 +};
97 +
98 +```
99 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.bail.rules-of-hooks-e9f9bac89f8f.expect.md new
+41
@@ -0,0 +1,41 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Unsupported input
7 +
8 +// Valid because hooks can be used in anonymous arrow-function arguments
9 +// to forwardRef.
10 +const FancyButton = React.forwardRef((props, ref) => {
11 + useHook();
12 + return <button {...props} ref={ref} />;
13 +});
14 +
15 +```
16 +
17 +## Code
18 +
19 +```javascript
20 +import { unstable_useMemoCache as useMemoCache } from "react"; // @skip
21 +// Unsupported input
22 +
23 +// Valid because hooks can be used in anonymous arrow-function arguments
24 +// to forwardRef.
25 +const FancyButton = React.forwardRef((props, ref) => {
26 + const $ = useMemoCache(3);
27 + useHook();
28 + let t0;
29 + if ($[0] !== props || $[1] !== ref) {
30 + t0 = <button {...props} ref={ref} />;
31 + $[0] = props;
32 + $[1] = ref;
33 + $[2] = t0;
34 + } else {
35 + t0 = $[2];
36 + }
37 + return t0;
38 +});
39 +
40 +```
41 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.bail.rules-of-hooks-fadd52c1e460.expect.md new
+101
@@ -0,0 +1,101 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Unsupported input
7 +
8 +// Currently invalid.
9 +// These are variations capturing the current heuristic--
10 +// we only allow hooks in PascalCase or useFoo functions.
11 +// We *could* make some of these valid. But before doing it,
12 +// consider specific cases documented above that contain reasoning.
13 +function a() {
14 + useState();
15 +}
16 +const whatever = function b() {
17 + useState();
18 +};
19 +const c = () => {
20 + useState();
21 +};
22 +let d = () => useState();
23 +e = () => {
24 + useState();
25 +};
26 +({
27 + f: () => {
28 + useState();
29 + },
30 +});
31 +({
32 + g() {
33 + useState();
34 + },
35 +});
36 +const {
37 + j = () => {
38 + useState();
39 + },
40 +} = {};
41 +({
42 + k = () => {
43 + useState();
44 + },
45 +} = {});
46 +
47 +```
48 +
49 +## Code
50 +
51 +```javascript
52 +// @skip
53 +// Unsupported input
54 +
55 +// Currently invalid.
56 +// These are variations capturing the current heuristic--
57 +// we only allow hooks in PascalCase or useFoo functions.
58 +// We *could* make some of these valid. But before doing it,
59 +// consider specific cases documented above that contain reasoning.
60 +function a() {
61 + useState();
62 +}
63 +
64 +const whatever = function b() {
65 + useState();
66 +};
67 +
68 +const c = () => {
69 + useState();
70 +};
71 +
72 +let d = () => {
73 + return useState();
74 +};
75 +e = () => {
76 + useState();
77 +};
78 +
79 +({
80 + f: () => {
81 + useState();
82 + },
83 +});
84 +({
85 + g() {
86 + useState();
87 + },
88 +});
89 +const {
90 + j = () => {
91 + useState();
92 + },
93 +} = {};
94 +({
95 + k = () => {
96 + useState();
97 + },
98 +} = {});
99 +
100 +```
101 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.invalid-rules-of-hooks-368024110a58.expect.md new
+26
@@ -0,0 +1,26 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +// Invalid because it's dangerous and might not warn otherwise.
9 +// This *must* be invalid.
10 +const FancyButton = forwardRef(function (props, ref) {
11 + if (props.fancy) {
12 + useCustomHook();
13 + }
14 + return <button ref={ref}>{props.children}</button>;
15 +});
16 +
17 +```
18 +
19 +
20 +## Error
21 +
22 +```
23 +[ReactForget] InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (8:8)
24 +```
25 +
26 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.invalid-rules-of-hooks-8566f9a360e2.expect.md new
+26
@@ -0,0 +1,26 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +// Invalid because it's dangerous and might not warn otherwise.
9 +// This *must* be invalid.
10 +const MemoizedButton = memo(function (props) {
11 + if (props.fancy) {
12 + useCustomHook();
13 + }
14 + return <button>{props.children}</button>;
15 +});
16 +
17 +```
18 +
19 +
20 +## Error
21 +
22 +```
23 +[ReactForget] InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (8:8)
24 +```
25 +
26 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.invalid-rules-of-hooks-a0058f0b446d.expect.md new
+25
@@ -0,0 +1,25 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +// Invalid because it's dangerous and might not warn otherwise.
9 +// This *must* be invalid.
10 +function ComponentWithConditionalHook() {
11 + if (cond) {
12 + Namespace.useConditionalHook();
13 + }
14 +}
15 +
16 +```
17 +
18 +
19 +## Error
20 +
21 +```
22 +[ReactForget] InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (8:8)
23 +```
24 +
25 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.rules-of-hooks-27c18dc8dad2.expect.md new
+26
@@ -0,0 +1,26 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Unsupported input
7 +
8 +// Invalid because it's dangerous and might not warn otherwise.
9 +// This *must* be invalid.
10 +const FancyButton = React.forwardRef((props, ref) => {
11 + if (props.fancy) {
12 + useCustomHook();
13 + }
14 + return <button ref={ref}>{props.children}</button>;
15 +});
16 +
17 +```
18 +
19 +
20 +## Error
21 +
22 +```
23 +[ReactForget] InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (8:8)
24 +```
25 +
26 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.rules-of-hooks-27c18dc8dad2.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.rules-of-hooks-69521d94fa03.expect.md new
+28
@@ -0,0 +1,28 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Unsupported input
7 +
8 +// Valid because the neither the condition nor the loop affect the hook call.
9 +function App(props) {
10 + const someObject = { propA: true };
11 + for (const propName in someObject) {
12 + if (propName === true) {
13 + } else {
14 + }
15 + }
16 + const [myState, setMyState] = useState(null);
17 +}
18 +
19 +```
20 +
21 +
22 +## Error
23 +
24 +```
25 +[ReactForget] InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (12:12)
26 +```
27 +
28 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.rules-of-hooks-69521d94fa03.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.rules-of-hooks-93dc5d5e538a.expect.md new
+27
@@ -0,0 +1,27 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Unsupported input
7 +
8 +// Valid because the loop doesn't change the order of hooks calls.
9 +function RegressionTest() {
10 + const res = [];
11 + const additionalCond = true;
12 + for (let i = 0; i !== 10 && additionalCond; ++i) {
13 + res.push(i);
14 + }
15 + React.useLayoutEffect(() => {});
16 +}
17 +
18 +```
19 +
20 +
21 +## Error
22 +
23 +```
24 +[ReactForget] InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (11:11)
25 +```
26 +
27 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.rules-of-hooks-93dc5d5e538a.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.rules-of-hooks-d0935abedc42.expect.md new
+25
@@ -0,0 +1,25 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Unsupported input
7 +
8 +// This is valid because "use"-prefixed functions called in
9 +// unnamed function arguments are not assumed to be hooks.
10 +React.unknownFunction((foo, bar) => {
11 + if (foo) {
12 + useNotAHook(bar);
13 + }
14 +});
15 +
16 +```
17 +
18 +
19 +## Error
20 +
21 +```
22 +[ReactForget] InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (8:8)
23 +```
24 +
25 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.rules-of-hooks-d0935abedc42.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.rules-of-hooks-e29c874aa913.expect.md new
+26
@@ -0,0 +1,26 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Unsupported input
7 +
8 +// Invalid because it's dangerous and might not warn otherwise.
9 +// This *must* be invalid.
10 +function useHook() {
11 + try {
12 + f();
13 + useState();
14 + } catch {}
15 +}
16 +
17 +```
18 +
19 +
20 +## Error
21 +
22 +```
23 +[ReactForget] InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (9:9)
24 +```
25 +
26 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.rules-of-hooks-e29c874aa913.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-0a1dbff27ba0.expect.md new
+45
@@ -0,0 +1,45 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +// Invalid because it's dangerous and might not warn otherwise.
9 +// This *must* be invalid.
10 +function createHook() {
11 + return function useHookWithConditionalHook() {
12 + if (cond) {
13 + useConditionalHook();
14 + }
15 + };
16 +}
17 +
18 +```
19 +
20 +## Code
21 +
22 +```javascript
23 +import { unstable_useMemoCache as useMemoCache } from "react"; // @skip
24 +// Passed but should have failed
25 +
26 +// Invalid because it's dangerous and might not warn otherwise.
27 +// This *must* be invalid.
28 +function createHook() {
29 + const $ = useMemoCache(1);
30 + let t0;
31 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
32 + t0 = function useHookWithConditionalHook() {
33 + if (cond) {
34 + useConditionalHook();
35 + }
36 + };
37 + $[0] = t0;
38 + } else {
39 + t0 = $[0];
40 + }
41 + return t0;
42 +}
43 +
44 +```
45 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-0a1dbff27ba0.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-0de1224ce64b.expect.md new
+45
@@ -0,0 +1,45 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +// Invalid because it's a common misunderstanding.
9 +// We *could* make it valid but the runtime error could be confusing.
10 +function createComponent() {
11 + return function ComponentWithHookInsideCallback() {
12 + useEffect(() => {
13 + useHookInsideCallback();
14 + });
15 + };
16 +}
17 +
18 +```
19 +
20 +## Code
21 +
22 +```javascript
23 +import { unstable_useMemoCache as useMemoCache } from "react"; // @skip
24 +// Passed but should have failed
25 +
26 +// Invalid because it's a common misunderstanding.
27 +// We *could* make it valid but the runtime error could be confusing.
28 +function createComponent() {
29 + const $ = useMemoCache(1);
30 + let t0;
31 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
32 + t0 = function ComponentWithHookInsideCallback() {
33 + useEffect(() => {
34 + useHookInsideCallback();
35 + });
36 + };
37 + $[0] = t0;
38 + } else {
39 + t0 = $[0];
40 + }
41 + return t0;
42 +}
43 +
44 +```
45 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-0de1224ce64b.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-191029ac48c8.expect.md new
+41
@@ -0,0 +1,41 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +// Invalid because it's dangerous.
9 +// Normally, this would crash, but not if you use inline requires.
10 +// This *must* be invalid.
11 +// It's expected to have some false positives, but arguably
12 +// they are confusing anyway due to the use*() convention
13 +// already being associated with Hooks.
14 +useState();
15 +if (foo) {
16 + const foo = React.useCallback(() => {});
17 +}
18 +useCustomHook();
19 +
20 +```
21 +
22 +## Code
23 +
24 +```javascript
25 +// @skip
26 +// Passed but should have failed
27 +
28 +// Invalid because it's dangerous.
29 +// Normally, this would crash, but not if you use inline requires.
30 +// This *must* be invalid.
31 +// It's expected to have some false positives, but arguably
32 +// they are confusing anyway due to the use*() convention
33 +// already being associated with Hooks.
34 +useState();
35 +if (foo) {
36 + const foo = React.useCallback(() => {});
37 +}
38 +useCustomHook();
39 +
40 +```
41 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-191029ac48c8.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-206e2811c87c.expect.md new
+37
@@ -0,0 +1,37 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +// This is a false positive (it's valid) that unfortunately
9 +// we cannot avoid. Prefer to rename it to not start with "use"
10 +class Foo extends Component {
11 + render() {
12 + if (cond) {
13 + FooStore.useFeatureFlag();
14 + }
15 + }
16 +}
17 +
18 +```
19 +
20 +## Code
21 +
22 +```javascript
23 +// @skip
24 +// Passed but should have failed
25 +
26 +// This is a false positive (it's valid) that unfortunately
27 +// we cannot avoid. Prefer to rename it to not start with "use"
28 +class Foo extends Component {
29 + render() {
30 + if (cond) {
31 + FooStore.useFeatureFlag();
32 + }
33 + }
34 +}
35 +
36 +```
37 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-206e2811c87c.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-28a7111f56a7.expect.md new
+43
@@ -0,0 +1,43 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +// Technically this is a false positive.
9 +// We *could* make it valid (and it used to be).
10 +//
11 +// However, top-level Hook-like calls can be very dangerous
12 +// in environments with inline requires because they can mask
13 +// the runtime error by accident.
14 +// So we prefer to disallow it despite the false positive.
15 +
16 +const { createHistory, useBasename } = require("history-2.1.2");
17 +const browserHistory = useBasename(createHistory)({
18 + basename: "/",
19 +});
20 +
21 +```
22 +
23 +## Code
24 +
25 +```javascript
26 +// @skip
27 +// Passed but should have failed
28 +
29 +// Technically this is a false positive.
30 +// We *could* make it valid (and it used to be).
31 +//
32 +// However, top-level Hook-like calls can be very dangerous
33 +// in environments with inline requires because they can mask
34 +// the runtime error by accident.
35 +// So we prefer to disallow it despite the false positive.
36 +
37 +const { createHistory, useBasename } = require("history-2.1.2");
38 +const browserHistory = useBasename(createHistory)({
39 + basename: "/",
40 +});
41 +
42 +```
43 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-28a7111f56a7.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-2c51251df67a.expect.md new
+29
@@ -0,0 +1,29 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +(class {
9 + useHook() {
10 + useState();
11 + }
12 +});
13 +
14 +```
15 +
16 +## Code
17 +
18 +```javascript
19 +// @skip
20 +// Passed but should have failed
21 +
22 +(class {
23 + useHook() {
24 + useState();
25 + }
26 +});
27 +
28 +```
29 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-2c51251df67a.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-449a37146a83.expect.md new
+41
@@ -0,0 +1,41 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +// Invalid because it's a common misunderstanding.
9 +// We *could* make it valid but the runtime error could be confusing.
10 +function createComponent() {
11 + return function ComponentWithHookInsideCallback() {
12 + function handleClick() {
13 + useState();
14 + }
15 + };
16 +}
17 +
18 +```
19 +
20 +## Code
21 +
22 +```javascript
23 +import { unstable_useMemoCache as useMemoCache } from "react"; // @skip
24 +// Passed but should have failed
25 +
26 +// Invalid because it's a common misunderstanding.
27 +// We *could* make it valid but the runtime error could be confusing.
28 +function createComponent() {
29 + const $ = useMemoCache(1);
30 + let t0;
31 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
32 + t0 = function ComponentWithHookInsideCallback() {};
33 + $[0] = t0;
34 + } else {
35 + t0 = $[0];
36 + }
37 + return t0;
38 +}
39 +
40 +```
41 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-449a37146a83.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-5a7ac9a6e8fa.expect.md new
+34
@@ -0,0 +1,34 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +// These are neither functions nor hooks.
9 +function _normalFunctionWithHook() {
10 + useHookInsideNormalFunction();
11 +}
12 +function _useNotAHook() {
13 + useHookInsideNormalFunction();
14 +}
15 +
16 +```
17 +
18 +## Code
19 +
20 +```javascript
21 +// @skip
22 +// Passed but should have failed
23 +
24 +// These are neither functions nor hooks.
25 +function _normalFunctionWithHook() {
26 + useHookInsideNormalFunction();
27 +}
28 +
29 +function _useNotAHook() {
30 + useHookInsideNormalFunction();
31 +}
32 +
33 +```
34 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-5a7ac9a6e8fa.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-76a74b4666e9.expect.md new
+29
@@ -0,0 +1,29 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +// Invalid because it's a common misunderstanding.
9 +// We *could* make it valid but the runtime error could be confusing.
10 +function ComponentWithHookInsideCallback() {
11 + function handleClick() {
12 + useState();
13 + }
14 +}
15 +
16 +```
17 +
18 +## Code
19 +
20 +```javascript
21 +// @skip
22 +// Passed but should have failed
23 +
24 +// Invalid because it's a common misunderstanding.
25 +// We *could* make it valid but the runtime error could be confusing.
26 +function ComponentWithHookInsideCallback() {}
27 +
28 +```
29 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-76a74b4666e9.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-8303403b8e4c.expect.md new
+29
@@ -0,0 +1,29 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +class ClassComponentWithHook extends React.Component {
9 + render() {
10 + React.useState();
11 + }
12 +}
13 +
14 +```
15 +
16 +## Code
17 +
18 +```javascript
19 +// @skip
20 +// Passed but should have failed
21 +
22 +class ClassComponentWithHook extends React.Component {
23 + render() {
24 + React.useState();
25 + }
26 +}
27 +
28 +```
29 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-8303403b8e4c.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-99b5c750d1d1.expect.md new
+33
@@ -0,0 +1,33 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +class ClassComponentWithFeatureFlag extends React.Component {
9 + render() {
10 + if (foo) {
11 + useFeatureFlag();
12 + }
13 + }
14 +}
15 +
16 +```
17 +
18 +## Code
19 +
20 +```javascript
21 +// @skip
22 +// Passed but should have failed
23 +
24 +class ClassComponentWithFeatureFlag extends React.Component {
25 + render() {
26 + if (foo) {
27 + useFeatureFlag();
28 + }
29 + }
30 +}
31 +
32 +```
33 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-99b5c750d1d1.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-9c79feec4b9b.expect.md new
+29
@@ -0,0 +1,29 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +(class {
9 + h = () => {
10 + useState();
11 + };
12 +});
13 +
14 +```
15 +
16 +## Code
17 +
18 +```javascript
19 +// @skip
20 +// Passed but should have failed
21 +
22 +(class {
23 + h = () => {
24 + useState();
25 + };
26 +});
27 +
28 +```
29 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-9c79feec4b9b.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-a63fd4f9dcc0.expect.md new
+29
@@ -0,0 +1,29 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +// This is invalid because "use"-prefixed functions used in named
9 +// functions are assumed to be hooks.
10 +React.unknownFunction(function notAComponent(foo, bar) {
11 + useProbablyAHook(bar);
12 +});
13 +
14 +```
15 +
16 +## Code
17 +
18 +```javascript
19 +// @skip
20 +// Passed but should have failed
21 +
22 +// This is invalid because "use"-prefixed functions used in named
23 +// functions are assumed to be hooks.
24 +React.unknownFunction(function notAComponent(foo, bar) {
25 + useProbablyAHook(bar);
26 +});
27 +
28 +```
29 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-a63fd4f9dcc0.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-acb56658fe7e.expect.md new
+31
@@ -0,0 +1,31 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +class C {
9 + m() {
10 + This.useHook();
11 + Super.useHook();
12 + }
13 +}
14 +
15 +```
16 +
17 +## Code
18 +
19 +```javascript
20 +// @skip
21 +// Passed but should have failed
22 +
23 +class C {
24 + m() {
25 + This.useHook();
26 + Super.useHook();
27 + }
28 +}
29 +
30 +```
31 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-acb56658fe7e.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-c59788ef5676.expect.md new
+33
@@ -0,0 +1,33 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +// Currently invalid because it violates the convention and removes the "taint"
9 +// from a hook. We *could* make it valid to avoid some false positives but let's
10 +// ensure that we don't break the "renderItem" and "normalFunctionWithConditionalHook"
11 +// cases which must remain invalid.
12 +function normalFunctionWithHook() {
13 + useHookInsideNormalFunction();
14 +}
15 +
16 +```
17 +
18 +## Code
19 +
20 +```javascript
21 +// @skip
22 +// Passed but should have failed
23 +
24 +// Currently invalid because it violates the convention and removes the "taint"
25 +// from a hook. We *could* make it valid to avoid some false positives but let's
26 +// ensure that we don't break the "renderItem" and "normalFunctionWithConditionalHook"
27 +// cases which must remain invalid.
28 +function normalFunctionWithHook() {
29 + useHookInsideNormalFunction();
30 +}
31 +
32 +```
33 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-c59788ef5676.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-d842d36db450.expect.md new
+45
@@ -0,0 +1,45 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +// Invalid because it's dangerous and might not warn otherwise.
9 +// This *must* be invalid.
10 +function createComponent() {
11 + return function ComponentWithConditionalHook() {
12 + if (cond) {
13 + useConditionalHook();
14 + }
15 + };
16 +}
17 +
18 +```
19 +
20 +## Code
21 +
22 +```javascript
23 +import { unstable_useMemoCache as useMemoCache } from "react"; // @skip
24 +// Passed but should have failed
25 +
26 +// Invalid because it's dangerous and might not warn otherwise.
27 +// This *must* be invalid.
28 +function createComponent() {
29 + const $ = useMemoCache(1);
30 + let t0;
31 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
32 + t0 = function ComponentWithConditionalHook() {
33 + if (cond) {
34 + useConditionalHook();
35 + }
36 + };
37 + $[0] = t0;
38 + } else {
39 + t0 = $[0];
40 + }
41 + return t0;
42 +}
43 +
44 +```
45 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-d842d36db450.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-d952b82c2597.expect.md new
+41
@@ -0,0 +1,41 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +// Invalid because it's a common misunderstanding.
9 +// We *could* make it valid but the runtime error could be confusing.
10 +function ComponentWithHookInsideCallback() {
11 + useEffect(() => {
12 + useHookInsideCallback();
13 + });
14 +}
15 +
16 +```
17 +
18 +## Code
19 +
20 +```javascript
21 +import { unstable_useMemoCache as useMemoCache } from "react"; // @skip
22 +// Passed but should have failed
23 +
24 +// Invalid because it's a common misunderstanding.
25 +// We *could* make it valid but the runtime error could be confusing.
26 +function ComponentWithHookInsideCallback() {
27 + const $ = useMemoCache(1);
28 + let t0;
29 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
30 + t0 = () => {
31 + useHookInsideCallback();
32 + };
33 + $[0] = t0;
34 + } else {
35 + t0 = $[0];
36 + }
37 + useEffect(t0);
38 +}
39 +
40 +```
41 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-d952b82c2597.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-ddeca9708b63.expect.md new
+29
@@ -0,0 +1,29 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +(class {
9 + i() {
10 + useState();
11 + }
12 +});
13 +
14 +```
15 +
16 +## Code
17 +
18 +```javascript
19 +// @skip
20 +// Passed but should have failed
21 +
22 +(class {
23 + i() {
24 + useState();
25 + }
26 +});
27 +
28 +```
29 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-ddeca9708b63.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-e675f0a672d8.expect.md new
+46
@@ -0,0 +1,46 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +// Invalid because it's dangerous and might not warn otherwise.
9 +// This *must* be invalid.
10 +function renderItem() {
11 + useState();
12 +}
13 +
14 +function List(props) {
15 + return props.items.map(renderItem);
16 +}
17 +
18 +```
19 +
20 +## Code
21 +
22 +```javascript
23 +import { unstable_useMemoCache as useMemoCache } from "react"; // @skip
24 +// Passed but should have failed
25 +
26 +// Invalid because it's dangerous and might not warn otherwise.
27 +// This *must* be invalid.
28 +function renderItem() {
29 + useState();
30 +}
31 +
32 +function List(props) {
33 + const $ = useMemoCache(2);
34 + let t0;
35 + if ($[0] !== props.items) {
36 + t0 = props.items.map(renderItem);
37 + $[0] = props.items;
38 + $[1] = t0;
39 + } else {
40 + t0 = $[1];
41 + }
42 + return t0;
43 +}
44 +
45 +```
46 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-e675f0a672d8.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-e69ffce323c3.expect.md new
+29
@@ -0,0 +1,29 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @skip
6 +// Passed but should have failed
7 +
8 +(class {
9 + useHook = () => {
10 + useState();
11 + };
12 +});
13 +
14 +```
15 +
16 +## Code
17 +
18 +```javascript
19 +// @skip
20 +// Passed but should have failed
21 +
22 +(class {
23 + useHook = () => {
24 + useState();
25 + };
26 +});
27 +
28 +```
29 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-e69ffce323c3.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-f6f37b63b2d4 renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/todo.error.object-pattern-computed-key.expect.md new
+27
@@ -0,0 +1,27 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +import { identity } from "shared-runtime";
6 +
7 +const SCALE = 2;
8 +function Component(props) {
9 + const { [props.name]: value } = props;
10 + return value;
11 +}
12 +
13 +export const FIXTURE_ENTRYPOINT = {
14 + fn: Component,
15 + params: [{ name: "Sathya" }],
16 +};
17 +
18 +```
19 +
20 +
21 +## Error
22 +
23 +```
24 +[ReactForget] Todo: (BuildHIR::lowerAssignment) Handle computed properties in ObjectPattern (5:5)
25 +```
26 +
27 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/todo.error.object-pattern-computed-key.js renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/todo.unnecessary-lambda-memoization.expect.md
+2 -4
@@ -26,9 +26,8 @@ import { unstable_useMemoCache as useMemoCache } from "react";
26 function Component(props) {
27 const $ = useMemoCache(5);
28 const data = useFreeze();
29 - const c_0 = $[0] !== data.items;
29 let t1;
31 - if (c_0) {
30 + if ($[0] !== data.items) {
31 let t0;
32 if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
33 t0 = (item) => <Item item={item} />;
@@ -43,9 +42,8 @@ function Component(props) {
42 t1 = $[1];
43 }
44 const items = t1;
46 - const c_3 = $[3] !== items;
45 let t2;
48 - if (c_3) {
46 + if ($[3] !== items) {
47 t2 = <div>{items}</div>;
48 $[3] = items;
49 $[4] = t2;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/todo.useContext-mutate-context-in-callback.expect.md new
+46
@@ -0,0 +1,46 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function Component(props) {
6 + const FooContext = useContext(Foo);
7 + // This function should be memoized, but its mutable range is entangled
8 + // with the useContext call. We can't memoize hooks, therefore the
9 + // reactive scope around the hook + callback is pruned and we're left
10 + // w no memoization of the callback.
11 + //
12 + // Ideally we'd determine that this isn't called during render and can
13 + // therefore be considered "immutable" or otherwise safe to memoize
14 + // independently
15 + const onClick = () => {
16 + FooContext.current = true;
17 + };
18 + return <div onClick={onClick} />;
19 +}
20 +
21 +```
22 +
23 +## Code
24 +
25 +```javascript
26 +import { unstable_useMemoCache as useMemoCache } from "react";
27 +function Component(props) {
28 + const $ = useMemoCache(2);
29 + const FooContext = useContext(Foo);
30 +
31 + const onClick = () => {
32 + FooContext.current = true;
33 + };
34 + let t0;
35 + if ($[0] !== onClick) {
36 + t0 = <div onClick={onClick} />;
37 + $[0] = onClick;
38 + $[1] = t0;
39 + } else {
40 + t0 = $[1];
41 + }
42 + return t0;
43 +}
44 +
45 +```
46 +
\ No newline at end of file
compiler/packages/fixture-test-utils/src/fixture-utils.ts
+3 -11
@@ -42,11 +42,7 @@ function stripExtension(filename: string, extensions: Array<string>): string {
42 return filename;
43 }
44
45 -function shouldSkip(
46 - filter: TestFilter | null,
47 - filterId: string,
48 - filename: string
49 -) {
45 +function shouldSkip(filter: TestFilter | null, filterId: string) {
46 if (filter) {
47 if (filter.kind === "only" && filter.paths.indexOf(filterId) === -1) {
48 return true;
@@ -56,8 +52,6 @@ function shouldSkip(
52 ) {
53 return true;
54 }
59 - } else if (filename.startsWith("todo.")) {
60 - return true;
55 }
56 return false;
57 }
@@ -117,10 +111,9 @@ export function getFixtures(
111 });
112 const fixtures: Map<string, TestFixture> = new Map();
113 for (const filePath of inputFiles) {
120 - const filename = path.basename(filePath);
114 // Do not include extensions in unique identifier for fixture
115 const partialPath = stripExtension(filePath, INPUT_EXTENSIONS);
123 - if (shouldSkip(filter, partialPath, filename)) {
116 + if (shouldSkip(filter, partialPath)) {
117 continue;
118 }
119
@@ -145,10 +138,9 @@ export function getFixtures(
138 cwd: FIXTURES_PATH,
139 });
140 for (const filePath of outputFiles) {
148 - const filename = path.basename(filePath);
141 // Do not include extensions in unique identifier for fixture
142 const partialPath = stripExtension(filePath, [OUTPUT_EXTENSION]);
151 - if (shouldSkip(filter, partialPath, filename)) {
143 + if (shouldSkip(filter, partialPath)) {
144 continue;
145 }
146
compiler/packages/snap/src/compiler-worker.ts
+3 -3
@@ -53,8 +53,7 @@ export async function compile(
53 clearRequireCache();
54 }
55 version = compilerVersion;
56 - const { inputPath, outputPath, outputExists, basename } =
57 - fixture;
56 + const { inputPath, outputPath, outputExists, basename } = fixture;
57 const input = inputPath != null ? await fs.readFile(inputPath, "utf8") : null;
58 const expected = outputExists ? await fs.readFile(outputPath, "utf8") : null;
59
@@ -109,7 +108,8 @@ export async function compile(
108 }
109
110 const output = writeOutputToString(input, code, error);
112 - const expectError = basename.startsWith("error.");
111 + const expectError =
112 + basename.startsWith("error.") || basename.startsWith("todo.error");
113 let unexpectedError: string | null = null;
114 if (expectError) {
115 if (error === null) {
compiler/packages/sprout/src/SproutTodoFilter.ts
+31
@@ -477,6 +477,37 @@ const skipFilter = new Set([
477
478 // nothing to compile/run
479 "repro-no-gating-import-without-compiled-functions",
480 +
481 + // TODOs
482 + "rules-of-hooks/todo.bail.rules-of-hooks-279ac76f53af",
483 + "rules-of-hooks/todo.bail.rules-of-hooks-28a78701970c",
484 + "rules-of-hooks/todo.bail.rules-of-hooks-3d692676194b",
485 + "rules-of-hooks/todo.bail.rules-of-hooks-6949b255e7eb",
486 + "rules-of-hooks/todo.bail.rules-of-hooks-8503ca76d6f8",
487 + "rules-of-hooks/todo.bail.rules-of-hooks-e0a5db3ae21e",
488 + "rules-of-hooks/todo.bail.rules-of-hooks-e9f9bac89f8f",
489 + "rules-of-hooks/todo.bail.rules-of-hooks-fadd52c1e460",
490 + "rules-of-hooks/todo.invalid.invalid-rules-of-hooks-0a1dbff27ba0",
491 + "rules-of-hooks/todo.invalid.invalid-rules-of-hooks-0de1224ce64b",
492 + "rules-of-hooks/todo.invalid.invalid-rules-of-hooks-191029ac48c8",
493 + "rules-of-hooks/todo.invalid.invalid-rules-of-hooks-206e2811c87c",
494 + "rules-of-hooks/todo.invalid.invalid-rules-of-hooks-28a7111f56a7",
495 + "rules-of-hooks/todo.invalid.invalid-rules-of-hooks-2c51251df67a",
496 + "rules-of-hooks/todo.invalid.invalid-rules-of-hooks-449a37146a83",
497 + "rules-of-hooks/todo.invalid.invalid-rules-of-hooks-5a7ac9a6e8fa",
498 + "rules-of-hooks/todo.invalid.invalid-rules-of-hooks-76a74b4666e9",
499 + "rules-of-hooks/todo.invalid.invalid-rules-of-hooks-8303403b8e4c",
500 + "rules-of-hooks/todo.invalid.invalid-rules-of-hooks-99b5c750d1d1",
501 + "rules-of-hooks/todo.invalid.invalid-rules-of-hooks-9c79feec4b9b",
502 + "rules-of-hooks/todo.invalid.invalid-rules-of-hooks-a63fd4f9dcc0",
503 + "rules-of-hooks/todo.invalid.invalid-rules-of-hooks-acb56658fe7e",
504 + "rules-of-hooks/todo.invalid.invalid-rules-of-hooks-c59788ef5676",
505 + "rules-of-hooks/todo.invalid.invalid-rules-of-hooks-d842d36db450",
506 + "rules-of-hooks/todo.invalid.invalid-rules-of-hooks-d952b82c2597",
507 + "rules-of-hooks/todo.invalid.invalid-rules-of-hooks-ddeca9708b63",
508 + "rules-of-hooks/todo.invalid.invalid-rules-of-hooks-e675f0a672d8",
509 + "rules-of-hooks/todo.invalid.invalid-rules-of-hooks-e69ffce323c3",
510 + "todo.unnecessary-lambda-memoization",
511 ]);
512
513 export default skipFilter;
compiler/packages/sprout/src/runner.ts
+11 -5
@@ -6,16 +6,19 @@
6 */
7
8 import chalk from "chalk";
9 -import { TestFixture } from "fixture-test-utils";
10 -import { getFixtures, readTestFilter } from "fixture-test-utils";
9 +import {
10 + FILTER_FILENAME,
11 + TestFixture,
12 + getFixtures,
13 + readTestFilter,
14 +} from "fixture-test-utils";
15 import { Worker } from "jest-worker";
16 import process from "process";
17 import * as readline from "readline";
14 -import * as RunnerWorker from "./runner-worker";
18 import yargs from "yargs";
19 import { hideBin } from "yargs/helpers";
20 import SproutTodoFilter from "./SproutTodoFilter";
18 -import { FILTER_FILENAME } from "fixture-test-utils";
21 +import * as RunnerWorker from "./runner-worker";
22
23 const WORKER_PATH = require.resolve("./runner-worker");
24 readline.emitKeypressEvents(process.stdin);
@@ -186,7 +189,10 @@ export async function main(opts: RunnerOptions): Promise<void> {
189
190 const validFixtures = new Map();
191 for (const [name, fixture] of allFixtures) {
189 - if (fixture.basename.startsWith("error.")) {
192 + if (
193 + fixture.basename.startsWith("error.") ||
194 + fixture.basename.startsWith("todo.error.")
195 + ) {
196 // skip
197 continue;
198 }