Fix invariant on mutable context values
ghstack-source-id: cb105318bf66d876a546b1c52e28286839d30032 Pull Request resolved: https://github.com/facebook/react-forget/pull/2904
Joe Savona committed
Apr 25, 2024 at 08:00 UTC
0a7f4427f13d70cd4cafe0388eb7d6b44ef1832e
4 files changed
+79
-62
compiler/packages/babel-plugin-react-forget/src/Inference/InferReferenceEffects.ts
-11
@@ -1640,17 +1640,6 @@ function inferBlock(
1640
const lvalue = instr.lvalue;
1641
lvalue.effect = Effect.ConditionallyMutate;
1642
const valueKind = state.kind(instrValue.place);
1643
- CompilerError.invariant(
1644
- valueKind.kind === ValueKind.Mutable ||
1645
- valueKind.kind === ValueKind.Context,
1646
- {
1647
- reason:
1648
- "[InferReferenceEffects] Context variables are always mutable.",
1649
- description: null,
1650
- loc: instrValue.loc,
1651
- suggestions: null,
1652
- }
1653
- );
1643
state.initialize(instrValue, valueKind);
1644
state.define(lvalue, instrValue);
1645
continue;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-multiple-calls-to-hoisted-callback-from-other-callback.expect.md
deleted
-46
@@ -1,46 +0,0 @@
1
-
2
-## Input
3
-
4
-```javascript
5
-// @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions
6
-function Component(props) {
7
- const [_state, setState] = useState();
8
- const a = () => {
9
- return b();
10
- };
11
- const b = () => {
12
- return (
13
- <>
14
- <div onClick={() => onClick(true)} />
15
- <div onClick={() => onClick(false)} />
16
- </>
17
- );
18
- };
19
- const onClick = (value) => {
20
- setState(value);
21
- };
22
-
23
- return <div>{a()}</div>;
24
-}
25
-
26
-export const FIXTURE_ENTRYPONT = {
27
- fn: Component,
28
- props: [{}],
29
-};
30
-
31
-```
32
-
33
-
34
-## Error
35
-
36
-```
37
- 9 | <>
38
- 10 | <div onClick={() => onClick(true)} />
39
-> 11 | <div onClick={() => onClick(false)} />
40
- | ^^^^^^^ Invariant: [InferReferenceEffects] Context variables are always mutable. (11:11)
41
- 12 | </>
42
- 13 | );
43
- 14 | };
44
-```
45
-
46
-
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/multiple-calls-to-hoisted-callback-from-other-callback.expect.md
new
+73
@@ -0,0 +1,73 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+import { useState } from "react";
6
+
7
+function Component(props) {
8
+ const [_state, setState] = useState();
9
+ const a = () => {
10
+ return b();
11
+ };
12
+ const b = () => {
13
+ return (
14
+ <>
15
+ <div onClick={() => onClick(true)}>a</div>
16
+ <div onClick={() => onClick(false)}>b</div>
17
+ </>
18
+ );
19
+ };
20
+ const onClick = (value) => {
21
+ setState(value);
22
+ };
23
+
24
+ return <div>{a()}</div>;
25
+}
26
+
27
+export const FIXTURE_ENTRYPOINT = {
28
+ fn: Component,
29
+ params: [{}],
30
+};
31
+
32
+```
33
+
34
+## Code
35
+
36
+```javascript
37
+import { useState, unstable_useMemoCache as useMemoCache } from "react";
38
+
39
+function Component(props) {
40
+ const $ = useMemoCache(1);
41
+ const [_state, setState] = useState();
42
+ let t0;
43
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
44
+ const a = () => b();
45
+
46
+ const b = () => (
47
+ <>
48
+ <div onClick={() => onClick(true)}>a</div>
49
+ <div onClick={() => onClick(false)}>b</div>
50
+ </>
51
+ );
52
+
53
+ const onClick = (value) => {
54
+ setState(value);
55
+ };
56
+
57
+ t0 = <div>{a()}</div>;
58
+ $[0] = t0;
59
+ } else {
60
+ t0 = $[0];
61
+ }
62
+ return t0;
63
+}
64
+
65
+export const FIXTURE_ENTRYPOINT = {
66
+ fn: Component,
67
+ params: [{}],
68
+};
69
+
70
+```
71
+
72
+### Eval output
73
+(kind: ok) <div><div>a</div><div>b</div></div>
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/multiple-calls-to-hoisted-callback-from-other-callback.js
renamed
+6
-5
@@ -1,4 +1,5 @@
1
-// @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions
1
+import { useState } from "react";
2
+
3
function Component(props) {
4
const [_state, setState] = useState();
5
const a = () => {
@@ -7,8 +8,8 @@ function Component(props) {
8
const b = () => {
9
return (
10
<>
10
- <div onClick={() => onClick(true)} />
11
- <div onClick={() => onClick(false)} />
11
+ <div onClick={() => onClick(true)}>a</div>
12
+ <div onClick={() => onClick(false)}>b</div>
13
</>
14
);
15
};
@@ -19,7 +20,7 @@ function Component(props) {
20
return <div>{a()}</div>;
21
}
22
22
-export const FIXTURE_ENTRYPONT = {
23
+export const FIXTURE_ENTRYPOINT = {
24
fn: Component,
24
- props: [{}],
25
+ params: [{}],
26
};