Fix invariant on mutable context values

ghstack-source-id: cb105318bf66d876a546b1c52e28286839d30032
Pull Request resolved: https://github.com/facebook/react-forget/pull/2904
This commit is contained in:
Joe Savona
2024-04-25 08:00:56 -07:00
parent 59e37b088b
commit 0a7f4427f1
4 changed files with 79 additions and 62 deletions
@@ -1640,17 +1640,6 @@ function inferBlock(
const lvalue = instr.lvalue;
lvalue.effect = Effect.ConditionallyMutate;
const valueKind = state.kind(instrValue.place);
CompilerError.invariant(
valueKind.kind === ValueKind.Mutable ||
valueKind.kind === ValueKind.Context,
{
reason:
"[InferReferenceEffects] Context variables are always mutable.",
description: null,
loc: instrValue.loc,
suggestions: null,
}
);
state.initialize(instrValue, valueKind);
state.define(lvalue, instrValue);
continue;
@@ -1,46 +0,0 @@
## Input
```javascript
// @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions
function Component(props) {
const [_state, setState] = useState();
const a = () => {
return b();
};
const b = () => {
return (
<>
<div onClick={() => onClick(true)} />
<div onClick={() => onClick(false)} />
</>
);
};
const onClick = (value) => {
setState(value);
};
return <div>{a()}</div>;
}
export const FIXTURE_ENTRYPONT = {
fn: Component,
props: [{}],
};
```
## Error
```
9 | <>
10 | <div onClick={() => onClick(true)} />
> 11 | <div onClick={() => onClick(false)} />
| ^^^^^^^ Invariant: [InferReferenceEffects] Context variables are always mutable. (11:11)
12 | </>
13 | );
14 | };
```
@@ -0,0 +1,73 @@
## Input
```javascript
import { useState } from "react";
function Component(props) {
const [_state, setState] = useState();
const a = () => {
return b();
};
const b = () => {
return (
<>
<div onClick={() => onClick(true)}>a</div>
<div onClick={() => onClick(false)}>b</div>
</>
);
};
const onClick = (value) => {
setState(value);
};
return <div>{a()}</div>;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{}],
};
```
## Code
```javascript
import { useState, unstable_useMemoCache as useMemoCache } from "react";
function Component(props) {
const $ = useMemoCache(1);
const [_state, setState] = useState();
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
const a = () => b();
const b = () => (
<>
<div onClick={() => onClick(true)}>a</div>
<div onClick={() => onClick(false)}>b</div>
</>
);
const onClick = (value) => {
setState(value);
};
t0 = <div>{a()}</div>;
$[0] = t0;
} else {
t0 = $[0];
}
return t0;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{}],
};
```
### Eval output
(kind: ok) <div><div>a</div><div>b</div></div>
@@ -1,4 +1,5 @@
// @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions
import { useState } from "react";
function Component(props) {
const [_state, setState] = useState();
const a = () => {
@@ -7,8 +8,8 @@ function Component(props) {
const b = () => {
return (
<>
<div onClick={() => onClick(true)} />
<div onClick={() => onClick(false)} />
<div onClick={() => onClick(true)}>a</div>
<div onClick={() => onClick(false)}>b</div>
</>
);
};
@@ -19,7 +20,7 @@ function Component(props) {
return <div>{a()}</div>;
}
export const FIXTURE_ENTRYPONT = {
export const FIXTURE_ENTRYPOINT = {
fn: Component,
props: [{}],
params: [{}],
};