Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77f30d6f61 | ||
|
|
8f54b8aea5 | ||
|
|
f3789e4caf | ||
|
|
cebe9dc9e2 |
@@ -246,7 +246,7 @@ export const EnvironmentConfigSchema = z.object({
|
|||||||
/**
|
/**
|
||||||
* Enable a new model for mutability and aliasing inference
|
* Enable a new model for mutability and aliasing inference
|
||||||
*/
|
*/
|
||||||
enableNewMutationAliasingModel: z.boolean().default(false),
|
enableNewMutationAliasingModel: z.boolean().default(true),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables inference of optional dependency chains. Without this flag
|
* Enables inference of optional dependency chains. Without this flag
|
||||||
|
|||||||
@@ -42,8 +42,16 @@ export default function analyseFunctions(func: HIRFunction): void {
|
|||||||
* Reset mutable range for outer inferReferenceEffects
|
* Reset mutable range for outer inferReferenceEffects
|
||||||
*/
|
*/
|
||||||
for (const operand of instr.value.loweredFunc.func.context) {
|
for (const operand of instr.value.loweredFunc.func.context) {
|
||||||
operand.identifier.mutableRange.start = makeInstructionId(0);
|
/**
|
||||||
operand.identifier.mutableRange.end = makeInstructionId(0);
|
* NOTE: inferReactiveScopeVariables makes identifiers in the scope
|
||||||
|
* point to the *same* mutableRange instance. Resetting start/end
|
||||||
|
* here is insufficient, because a later mutation of the range
|
||||||
|
* for any one identifier could affect the range for other identifiers.
|
||||||
|
*/
|
||||||
|
operand.identifier.mutableRange = {
|
||||||
|
start: makeInstructionId(0),
|
||||||
|
end: makeInstructionId(0),
|
||||||
|
};
|
||||||
operand.identifier.scope = null;
|
operand.identifier.scope = null;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -901,11 +901,36 @@ function applyEffect(
|
|||||||
console.log(prettyFormat(state.debugAbstractValue(value)));
|
console.log(prettyFormat(state.debugAbstractValue(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
const reason = getWriteErrorReason({
|
let reason: string;
|
||||||
kind: value.kind,
|
let description: string | null = null;
|
||||||
reason: value.reason,
|
|
||||||
context: new Set(),
|
if (
|
||||||
});
|
mutationKind === 'mutate-frozen' &&
|
||||||
|
context.hoistedContextDeclarations.has(
|
||||||
|
effect.value.identifier.declarationId,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
reason = `This variable is accessed before it is declared, which prevents the earlier access from updating when this value changes over time`;
|
||||||
|
if (
|
||||||
|
effect.value.identifier.name !== null &&
|
||||||
|
effect.value.identifier.name.kind === 'named'
|
||||||
|
) {
|
||||||
|
description = `Move the declaration of \`${effect.value.identifier.name.value}\` to before it is first referenced`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reason = getWriteErrorReason({
|
||||||
|
kind: value.kind,
|
||||||
|
reason: value.reason,
|
||||||
|
context: new Set(),
|
||||||
|
});
|
||||||
|
if (
|
||||||
|
effect.value.identifier.name !== null &&
|
||||||
|
effect.value.identifier.name.kind === 'named'
|
||||||
|
) {
|
||||||
|
description = `Found mutation of \`${effect.value.identifier.name.value}\``;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
effects.push({
|
effects.push({
|
||||||
kind:
|
kind:
|
||||||
value.kind === ValueKind.Frozen ? 'MutateFrozen' : 'MutateGlobal',
|
value.kind === ValueKind.Frozen ? 'MutateFrozen' : 'MutateGlobal',
|
||||||
@@ -913,11 +938,7 @@ function applyEffect(
|
|||||||
error: {
|
error: {
|
||||||
severity: ErrorSeverity.InvalidReact,
|
severity: ErrorSeverity.InvalidReact,
|
||||||
reason,
|
reason,
|
||||||
description:
|
description,
|
||||||
effect.value.identifier.name !== null &&
|
|
||||||
effect.value.identifier.name.kind === 'named'
|
|
||||||
? `Found mutation of \`${effect.value.identifier.name.value}\``
|
|
||||||
: null,
|
|
||||||
loc: effect.value.loc,
|
loc: effect.value.loc,
|
||||||
suggestions: null,
|
suggestions: null,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -175,21 +175,14 @@ import {
|
|||||||
* and mutability.
|
* and mutability.
|
||||||
*/
|
*/
|
||||||
function Component(t0) {
|
function Component(t0) {
|
||||||
const $ = _c(4);
|
const $ = _c(2);
|
||||||
const { prop } = t0;
|
const { prop } = t0;
|
||||||
let t1;
|
let t1;
|
||||||
if ($[0] !== prop) {
|
if ($[0] !== prop) {
|
||||||
const obj = shallowCopy(prop);
|
const obj = shallowCopy(prop);
|
||||||
const aliasedObj = identity(obj);
|
const aliasedObj = identity(obj);
|
||||||
let t2;
|
|
||||||
if ($[2] !== obj) {
|
const id = [obj.id];
|
||||||
t2 = [obj.id];
|
|
||||||
$[2] = obj;
|
|
||||||
$[3] = t2;
|
|
||||||
} else {
|
|
||||||
t2 = $[3];
|
|
||||||
}
|
|
||||||
const id = t2;
|
|
||||||
|
|
||||||
mutate(aliasedObj);
|
mutate(aliasedObj);
|
||||||
setPropertyByKey(aliasedObj, "id", prop.id + 1);
|
setPropertyByKey(aliasedObj, "id", prop.id + 1);
|
||||||
|
|||||||
@@ -25,17 +25,25 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
```javascript
|
```javascript
|
||||||
import { c as _c } from "react/compiler-runtime";
|
import { c as _c } from "react/compiler-runtime";
|
||||||
function bar(a) {
|
function bar(a) {
|
||||||
const $ = _c(2);
|
const $ = _c(4);
|
||||||
let y;
|
let t0;
|
||||||
if ($[0] !== a) {
|
if ($[0] !== a) {
|
||||||
const x = [a];
|
t0 = [a];
|
||||||
|
$[0] = a;
|
||||||
|
$[1] = t0;
|
||||||
|
} else {
|
||||||
|
t0 = $[1];
|
||||||
|
}
|
||||||
|
const x = t0;
|
||||||
|
let y;
|
||||||
|
if ($[2] !== x[0][1]) {
|
||||||
y = {};
|
y = {};
|
||||||
|
|
||||||
y = x[0][1];
|
y = x[0][1];
|
||||||
$[0] = a;
|
$[2] = x[0][1];
|
||||||
$[1] = y;
|
$[3] = y;
|
||||||
} else {
|
} else {
|
||||||
y = $[1];
|
y = $[3];
|
||||||
}
|
}
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,20 +29,29 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
```javascript
|
```javascript
|
||||||
import { c as _c } from "react/compiler-runtime";
|
import { c as _c } from "react/compiler-runtime";
|
||||||
function bar(a, b) {
|
function bar(a, b) {
|
||||||
const $ = _c(3);
|
const $ = _c(6);
|
||||||
let y;
|
let t0;
|
||||||
if ($[0] !== a || $[1] !== b) {
|
if ($[0] !== a || $[1] !== b) {
|
||||||
const x = [a, b];
|
t0 = [a, b];
|
||||||
|
$[0] = a;
|
||||||
|
$[1] = b;
|
||||||
|
$[2] = t0;
|
||||||
|
} else {
|
||||||
|
t0 = $[2];
|
||||||
|
}
|
||||||
|
const x = t0;
|
||||||
|
let y;
|
||||||
|
if ($[3] !== x[0][1] || $[4] !== x[1][0]) {
|
||||||
y = {};
|
y = {};
|
||||||
let t = {};
|
let t = {};
|
||||||
|
|
||||||
y = x[0][1];
|
y = x[0][1];
|
||||||
t = x[1][0];
|
t = x[1][0];
|
||||||
$[0] = a;
|
$[3] = x[0][1];
|
||||||
$[1] = b;
|
$[4] = x[1][0];
|
||||||
$[2] = y;
|
$[5] = y;
|
||||||
} else {
|
} else {
|
||||||
y = $[2];
|
y = $[5];
|
||||||
}
|
}
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,17 +25,25 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
```javascript
|
```javascript
|
||||||
import { c as _c } from "react/compiler-runtime";
|
import { c as _c } from "react/compiler-runtime";
|
||||||
function bar(a) {
|
function bar(a) {
|
||||||
const $ = _c(2);
|
const $ = _c(4);
|
||||||
let y;
|
let t0;
|
||||||
if ($[0] !== a) {
|
if ($[0] !== a) {
|
||||||
const x = [a];
|
t0 = [a];
|
||||||
|
$[0] = a;
|
||||||
|
$[1] = t0;
|
||||||
|
} else {
|
||||||
|
t0 = $[1];
|
||||||
|
}
|
||||||
|
const x = t0;
|
||||||
|
let y;
|
||||||
|
if ($[2] !== x[0].a[1]) {
|
||||||
y = {};
|
y = {};
|
||||||
|
|
||||||
y = x[0].a[1];
|
y = x[0].a[1];
|
||||||
$[0] = a;
|
$[2] = x[0].a[1];
|
||||||
$[1] = y;
|
$[3] = y;
|
||||||
} else {
|
} else {
|
||||||
y = $[1];
|
y = $[3];
|
||||||
}
|
}
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,17 +24,25 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
```javascript
|
```javascript
|
||||||
import { c as _c } from "react/compiler-runtime";
|
import { c as _c } from "react/compiler-runtime";
|
||||||
function bar(a) {
|
function bar(a) {
|
||||||
const $ = _c(2);
|
const $ = _c(4);
|
||||||
let y;
|
let t0;
|
||||||
if ($[0] !== a) {
|
if ($[0] !== a) {
|
||||||
const x = [a];
|
t0 = [a];
|
||||||
|
$[0] = a;
|
||||||
|
$[1] = t0;
|
||||||
|
} else {
|
||||||
|
t0 = $[1];
|
||||||
|
}
|
||||||
|
const x = t0;
|
||||||
|
let y;
|
||||||
|
if ($[2] !== x[0]) {
|
||||||
y = {};
|
y = {};
|
||||||
|
|
||||||
y = x[0];
|
y = x[0];
|
||||||
$[0] = a;
|
$[2] = x[0];
|
||||||
$[1] = y;
|
$[3] = y;
|
||||||
} else {
|
} else {
|
||||||
y = $[1];
|
y = $[3];
|
||||||
}
|
}
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
19 | useEffect(() => setState(2), []);
|
19 | useEffect(() => setState(2), []);
|
||||||
20 |
|
20 |
|
||||||
> 21 | const [state, setState] = useState(0);
|
> 21 | const [state, setState] = useState(0);
|
||||||
| ^^^^^^^^ InvalidReact: Updating a value used previously in an effect function or as an effect dependency is not allowed. Consider moving the mutation before calling useEffect(). Found mutation of `setState` (21:21)
|
| ^^^^^^^^ InvalidReact: This variable is accessed before it is declared, which prevents the earlier access from updating when this value changes over time. Move the declaration of `setState` to before it is first referenced (21:21)
|
||||||
22 | return <Stringify state={state} />;
|
22 | return <Stringify state={state} />;
|
||||||
23 | }
|
23 | }
|
||||||
24 |
|
24 |
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ function Component() {
|
|||||||
2 |
|
2 |
|
||||||
3 | function Component() {
|
3 | function Component() {
|
||||||
> 4 | const date = Date.now();
|
> 4 | const date = Date.now();
|
||||||
| ^^^^^^^^ InvalidReact: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent). `Date.now` is an impure function whose results may change on every call (4:4)
|
| ^^^^^^^^^^ InvalidReact: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent). `Date.now` is an impure function whose results may change on every call (4:4)
|
||||||
|
|
||||||
InvalidReact: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent). `performance.now` is an impure function whose results may change on every call (5:5)
|
InvalidReact: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent). `performance.now` is an impure function whose results may change on every call (5:5)
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ function SomeComponent() {
|
|||||||
9 | return (
|
9 | return (
|
||||||
10 | <Button
|
10 | <Button
|
||||||
> 11 | onPress={() => (sharedVal.value = Math.random())}
|
> 11 | onPress={() => (sharedVal.value = Math.random())}
|
||||||
| ^^^^^^^^^ InvalidReact: Mutating a value returned from a function whose return value should not be mutated. Found mutation of `sharedVal` (11:11)
|
| ^^^^^^^^^ InvalidReact: This mutates a variable that React considers immutable. Found mutation of `sharedVal` (11:11)
|
||||||
12 | title="Randomize"
|
12 | title="Randomize"
|
||||||
13 | />
|
13 | />
|
||||||
14 | );
|
14 | );
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ function useHook(a, b) {
|
|||||||
1 | function useHook(a, b) {
|
1 | function useHook(a, b) {
|
||||||
> 2 | b.test = 1;
|
> 2 | b.test = 1;
|
||||||
| ^ InvalidReact: Mutating component props or hook arguments is not allowed. Consider using a local variable instead (2:2)
|
| ^ InvalidReact: Mutating component props or hook arguments is not allowed. Consider using a local variable instead (2:2)
|
||||||
|
|
||||||
|
InvalidReact: Mutating component props or hook arguments is not allowed. Consider using a local variable instead (3:3)
|
||||||
3 | a.test = 2;
|
3 | a.test = 2;
|
||||||
4 | }
|
4 | }
|
||||||
5 |
|
5 |
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ function Component(props) {
|
|||||||
4 | foo(() => {
|
4 | foo(() => {
|
||||||
> 5 | x.a = 10;
|
> 5 | x.a = 10;
|
||||||
| ^ InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect (5:5)
|
| ^ InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect (5:5)
|
||||||
|
|
||||||
|
InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect (6:6)
|
||||||
6 | x.a = 20;
|
6 | x.a = 20;
|
||||||
7 | });
|
7 | });
|
||||||
8 | }
|
8 | }
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ function Component() {
|
|||||||
3 | // Cannot assign to globals
|
3 | // Cannot assign to globals
|
||||||
> 4 | someUnknownGlobal = true;
|
> 4 | someUnknownGlobal = true;
|
||||||
| ^^^^^^^^^^^^^^^^^ InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (4:4)
|
| ^^^^^^^^^^^^^^^^^ InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (4:4)
|
||||||
|
|
||||||
|
InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (5:5)
|
||||||
5 | moduleLocal = true;
|
5 | moduleLocal = true;
|
||||||
6 | };
|
6 | };
|
||||||
7 | foo();
|
7 | foo();
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ function Component() {
|
|||||||
2 | // Cannot assign to globals
|
2 | // Cannot assign to globals
|
||||||
> 3 | someUnknownGlobal = true;
|
> 3 | someUnknownGlobal = true;
|
||||||
| ^^^^^^^^^^^^^^^^^ InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (3:3)
|
| ^^^^^^^^^^^^^^^^^ InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (3:3)
|
||||||
|
|
||||||
|
InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (4:4)
|
||||||
4 | moduleLocal = true;
|
4 | moduleLocal = true;
|
||||||
5 | }
|
5 | }
|
||||||
6 |
|
6 |
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ function Component(props) {
|
|||||||
7 | return hasErrors;
|
7 | return hasErrors;
|
||||||
8 | }
|
8 | }
|
||||||
> 9 | return hasErrors();
|
> 9 | return hasErrors();
|
||||||
| ^^^^^^^^^ Invariant: [hoisting] Expected value for identifier to be initialized. hasErrors_0$15 (9:9)
|
| ^^^^^^^^^ Invariant: [InferMutationAliasingEffects] Expected value kind to be initialized. <unknown> hasErrors_0$15:TFunction (9:9)
|
||||||
10 | }
|
10 | }
|
||||||
11 |
|
11 |
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Logs
|
## Logs
|
||||||
|
|
||||||
```
|
```
|
||||||
{"kind":"CompileError","fnLoc":{"start":{"line":5,"column":0,"index":139},"end":{"line":12,"column":1,"index":384},"filename":"mutate-after-useeffect-optional-chain.ts"},"detail":{"reason":"This mutates a variable that React considers immutable","description":null,"loc":{"start":{"line":10,"column":2,"index":345},"end":{"line":10,"column":5,"index":348},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"},"suggestions":null,"severity":"InvalidReact"}}
|
{"kind":"CompileError","fnLoc":{"start":{"line":5,"column":0,"index":139},"end":{"line":12,"column":1,"index":384},"filename":"mutate-after-useeffect-optional-chain.ts"},"detail":{"reason":"Updating a value used previously in an effect function or as an effect dependency is not allowed. Consider moving the mutation before calling useEffect()","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":10,"column":2,"index":345},"end":{"line":10,"column":5,"index":348},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}}}
|
||||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":9,"column":2,"index":304},"end":{"line":9,"column":39,"index":341},"filename":"mutate-after-useeffect-optional-chain.ts"},"decorations":[{"start":{"line":9,"column":24,"index":326},"end":{"line":9,"column":27,"index":329},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}]}
|
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":9,"column":2,"index":304},"end":{"line":9,"column":39,"index":341},"filename":"mutate-after-useeffect-optional-chain.ts"},"decorations":[{"start":{"line":9,"column":24,"index":326},"end":{"line":9,"column":27,"index":329},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}]}
|
||||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":5,"column":0,"index":139},"end":{"line":12,"column":1,"index":384},"filename":"mutate-after-useeffect-optional-chain.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
{"kind":"CompileSuccess","fnLoc":{"start":{"line":5,"column":0,"index":139},"end":{"line":12,"column":1,"index":384},"filename":"mutate-after-useeffect-optional-chain.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Logs
|
## Logs
|
||||||
|
|
||||||
```
|
```
|
||||||
{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":148},"end":{"line":11,"column":1,"index":311},"filename":"mutate-after-useeffect-ref-access.ts"},"detail":{"reason":"Mutating component props or hook arguments is not allowed. Consider using a local variable instead","description":null,"loc":{"start":{"line":9,"column":2,"index":269},"end":{"line":9,"column":16,"index":283},"filename":"mutate-after-useeffect-ref-access.ts"},"suggestions":null,"severity":"InvalidReact"}}
|
{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":148},"end":{"line":11,"column":1,"index":311},"filename":"mutate-after-useeffect-ref-access.ts"},"detail":{"reason":"Mutating component props or hook arguments is not allowed. Consider using a local variable instead","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":9,"column":2,"index":269},"end":{"line":9,"column":16,"index":283},"filename":"mutate-after-useeffect-ref-access.ts"}}}
|
||||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":227},"end":{"line":8,"column":40,"index":265},"filename":"mutate-after-useeffect-ref-access.ts"},"decorations":[{"start":{"line":8,"column":24,"index":249},"end":{"line":8,"column":30,"index":255},"filename":"mutate-after-useeffect-ref-access.ts","identifierName":"arrRef"}]}
|
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":227},"end":{"line":8,"column":40,"index":265},"filename":"mutate-after-useeffect-ref-access.ts"},"decorations":[{"start":{"line":8,"column":24,"index":249},"end":{"line":8,"column":30,"index":255},"filename":"mutate-after-useeffect-ref-access.ts","identifierName":"arrRef"}]}
|
||||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":148},"end":{"line":11,"column":1,"index":311},"filename":"mutate-after-useeffect-ref-access.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
{"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":148},"end":{"line":11,"column":1,"index":311},"filename":"mutate-after-useeffect-ref-access.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Logs
|
## Logs
|
||||||
|
|
||||||
```
|
```
|
||||||
{"kind":"CompileError","fnLoc":{"start":{"line":4,"column":0,"index":101},"end":{"line":11,"column":1,"index":222},"filename":"mutate-after-useeffect.ts"},"detail":{"reason":"This mutates a variable that React considers immutable","description":null,"loc":{"start":{"line":9,"column":2,"index":194},"end":{"line":9,"column":5,"index":197},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},"suggestions":null,"severity":"InvalidReact"}}
|
{"kind":"CompileError","fnLoc":{"start":{"line":4,"column":0,"index":101},"end":{"line":11,"column":1,"index":222},"filename":"mutate-after-useeffect.ts"},"detail":{"reason":"Updating a value used previously in an effect function or as an effect dependency is not allowed. Consider moving the mutation before calling useEffect()","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":9,"column":2,"index":194},"end":{"line":9,"column":5,"index":197},"filename":"mutate-after-useeffect.ts","identifierName":"arr"}}}
|
||||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":6,"column":2,"index":149},"end":{"line":8,"column":4,"index":190},"filename":"mutate-after-useeffect.ts"},"decorations":[{"start":{"line":7,"column":4,"index":171},"end":{"line":7,"column":7,"index":174},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},{"start":{"line":7,"column":4,"index":171},"end":{"line":7,"column":7,"index":174},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},{"start":{"line":7,"column":13,"index":180},"end":{"line":7,"column":16,"index":183},"filename":"mutate-after-useeffect.ts","identifierName":"foo"}]}
|
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":6,"column":2,"index":149},"end":{"line":8,"column":4,"index":190},"filename":"mutate-after-useeffect.ts"},"decorations":[{"start":{"line":7,"column":4,"index":171},"end":{"line":7,"column":7,"index":174},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},{"start":{"line":7,"column":4,"index":171},"end":{"line":7,"column":7,"index":174},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},{"start":{"line":7,"column":13,"index":180},"end":{"line":7,"column":16,"index":183},"filename":"mutate-after-useeffect.ts","identifierName":"foo"}]}
|
||||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":4,"column":0,"index":101},"end":{"line":11,"column":1,"index":222},"filename":"mutate-after-useeffect.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
{"kind":"CompileSuccess","fnLoc":{"start":{"line":4,"column":0,"index":101},"end":{"line":11,"column":1,"index":222},"filename":"mutate-after-useeffect.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Logs
|
## Logs
|
||||||
|
|
||||||
```
|
```
|
||||||
{"kind":"CompileError","fnLoc":{"start":{"line":5,"column":0,"index":163},"end":{"line":13,"column":1,"index":357},"filename":"retry-no-emit.ts"},"detail":{"reason":"This mutates a variable that React considers immutable","description":null,"loc":{"start":{"line":11,"column":2,"index":320},"end":{"line":11,"column":6,"index":324},"filename":"retry-no-emit.ts","identifierName":"arr2"},"suggestions":null,"severity":"InvalidReact"}}
|
{"kind":"CompileError","fnLoc":{"start":{"line":5,"column":0,"index":163},"end":{"line":13,"column":1,"index":357},"filename":"retry-no-emit.ts"},"detail":{"reason":"This mutates a variable that React considers immutable","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":11,"column":2,"index":320},"end":{"line":11,"column":6,"index":324},"filename":"retry-no-emit.ts","identifierName":"arr2"}}}
|
||||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":7,"column":2,"index":216},"end":{"line":7,"column":36,"index":250},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":7,"column":31,"index":245},"end":{"line":7,"column":34,"index":248},"filename":"retry-no-emit.ts","identifierName":"arr"}]}
|
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":7,"column":2,"index":216},"end":{"line":7,"column":36,"index":250},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":7,"column":31,"index":245},"end":{"line":7,"column":34,"index":248},"filename":"retry-no-emit.ts","identifierName":"arr"}]}
|
||||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":10,"column":2,"index":274},"end":{"line":10,"column":44,"index":316},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":10,"column":25,"index":297},"end":{"line":10,"column":29,"index":301},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":10,"column":25,"index":297},"end":{"line":10,"column":29,"index":301},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":10,"column":35,"index":307},"end":{"line":10,"column":42,"index":314},"filename":"retry-no-emit.ts","identifierName":"propVal"}]}
|
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":10,"column":2,"index":274},"end":{"line":10,"column":44,"index":316},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":10,"column":25,"index":297},"end":{"line":10,"column":29,"index":301},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":10,"column":25,"index":297},"end":{"line":10,"column":29,"index":301},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":10,"column":35,"index":307},"end":{"line":10,"column":42,"index":314},"filename":"retry-no-emit.ts","identifierName":"propVal"}]}
|
||||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":5,"column":0,"index":163},"end":{"line":13,"column":1,"index":357},"filename":"retry-no-emit.ts"},"fnName":"Foo","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
{"kind":"CompileSuccess","fnLoc":{"start":{"line":5,"column":0,"index":163},"end":{"line":13,"column":1,"index":357},"filename":"retry-no-emit.ts"},"fnName":"Foo","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||||
|
|||||||
@@ -34,22 +34,28 @@ import { print } from "shared-runtime";
|
|||||||
* setState types are not enough to determine to omit from deps. Must also take reactivity into account.
|
* setState types are not enough to determine to omit from deps. Must also take reactivity into account.
|
||||||
*/
|
*/
|
||||||
function ReactiveRefInEffect(props) {
|
function ReactiveRefInEffect(props) {
|
||||||
const $ = _c(2);
|
const $ = _c(4);
|
||||||
const [, setState1] = useRef("initial value");
|
const [, setState1] = useRef("initial value");
|
||||||
const [, setState2] = useRef("initial value");
|
const [, setState2] = useRef("initial value");
|
||||||
let setState;
|
let setState;
|
||||||
if (props.foo) {
|
if ($[0] !== props.foo) {
|
||||||
setState = setState1;
|
if (props.foo) {
|
||||||
|
setState = setState1;
|
||||||
|
} else {
|
||||||
|
setState = setState2;
|
||||||
|
}
|
||||||
|
$[0] = props.foo;
|
||||||
|
$[1] = setState;
|
||||||
} else {
|
} else {
|
||||||
setState = setState2;
|
setState = $[1];
|
||||||
}
|
}
|
||||||
let t0;
|
let t0;
|
||||||
if ($[0] !== setState) {
|
if ($[2] !== setState) {
|
||||||
t0 = () => print(setState);
|
t0 = () => print(setState);
|
||||||
$[0] = setState;
|
$[2] = setState;
|
||||||
$[1] = t0;
|
$[3] = t0;
|
||||||
} else {
|
} else {
|
||||||
t0 = $[1];
|
t0 = $[3];
|
||||||
}
|
}
|
||||||
useEffect(t0, [setState]);
|
useEffect(t0, [setState]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
// @enableNewMutationAliasingModel
|
||||||
import {
|
import {
|
||||||
Stringify,
|
Stringify,
|
||||||
mutate,
|
mutate,
|
||||||
@@ -101,7 +102,7 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Code
|
## Code
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { c as _c } from "react/compiler-runtime";
|
import { c as _c } from "react/compiler-runtime"; // @enableNewMutationAliasingModel
|
||||||
import {
|
import {
|
||||||
Stringify,
|
Stringify,
|
||||||
mutate,
|
mutate,
|
||||||
@@ -175,21 +176,14 @@ import {
|
|||||||
* and mutability.
|
* and mutability.
|
||||||
*/
|
*/
|
||||||
function Component(t0) {
|
function Component(t0) {
|
||||||
const $ = _c(4);
|
const $ = _c(2);
|
||||||
const { prop } = t0;
|
const { prop } = t0;
|
||||||
let t1;
|
let t1;
|
||||||
if ($[0] !== prop) {
|
if ($[0] !== prop) {
|
||||||
const obj = shallowCopy(prop);
|
const obj = shallowCopy(prop);
|
||||||
const aliasedObj = identity(obj);
|
const aliasedObj = identity(obj);
|
||||||
let t2;
|
|
||||||
if ($[2] !== obj) {
|
const id = [obj.id];
|
||||||
t2 = [obj.id];
|
|
||||||
$[2] = obj;
|
|
||||||
$[3] = t2;
|
|
||||||
} else {
|
|
||||||
t2 = $[3];
|
|
||||||
}
|
|
||||||
const id = t2;
|
|
||||||
|
|
||||||
mutate(aliasedObj);
|
mutate(aliasedObj);
|
||||||
setPropertyByKey(aliasedObj, "id", prop.id + 1);
|
setPropertyByKey(aliasedObj, "id", prop.id + 1);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @enableNewMutationAliasingModel
|
||||||
import {
|
import {
|
||||||
Stringify,
|
Stringify,
|
||||||
mutate,
|
mutate,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
// @enableNewMutationAliasingModel
|
||||||
import {Stringify} from 'shared-runtime';
|
import {Stringify} from 'shared-runtime';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,7 +44,7 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Code
|
## Code
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { c as _c } from "react/compiler-runtime";
|
import { c as _c } from "react/compiler-runtime"; // @enableNewMutationAliasingModel
|
||||||
import { Stringify } from "shared-runtime";
|
import { Stringify } from "shared-runtime";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @enableNewMutationAliasingModel
|
||||||
import {Stringify} from 'shared-runtime';
|
import {Stringify} from 'shared-runtime';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
// @enableNewMutationAliasingModel
|
||||||
function bar(a) {
|
function bar(a) {
|
||||||
let x = [a];
|
let x = [a];
|
||||||
let y = {};
|
let y = {};
|
||||||
@@ -23,19 +24,27 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Code
|
## Code
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { c as _c } from "react/compiler-runtime";
|
import { c as _c } from "react/compiler-runtime"; // @enableNewMutationAliasingModel
|
||||||
function bar(a) {
|
function bar(a) {
|
||||||
const $ = _c(2);
|
const $ = _c(4);
|
||||||
let y;
|
let t0;
|
||||||
if ($[0] !== a) {
|
if ($[0] !== a) {
|
||||||
const x = [a];
|
t0 = [a];
|
||||||
|
$[0] = a;
|
||||||
|
$[1] = t0;
|
||||||
|
} else {
|
||||||
|
t0 = $[1];
|
||||||
|
}
|
||||||
|
const x = t0;
|
||||||
|
let y;
|
||||||
|
if ($[2] !== x[0][1]) {
|
||||||
y = {};
|
y = {};
|
||||||
|
|
||||||
y = x[0][1];
|
y = x[0][1];
|
||||||
$[0] = a;
|
$[2] = x[0][1];
|
||||||
$[1] = y;
|
$[3] = y;
|
||||||
} else {
|
} else {
|
||||||
y = $[1];
|
y = $[3];
|
||||||
}
|
}
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @enableNewMutationAliasingModel
|
||||||
function bar(a) {
|
function bar(a) {
|
||||||
let x = [a];
|
let x = [a];
|
||||||
let y = {};
|
let y = {};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
// @enableNewMutationAliasingModel
|
||||||
function bar(a, b) {
|
function bar(a, b) {
|
||||||
let x = [a, b];
|
let x = [a, b];
|
||||||
let y = {};
|
let y = {};
|
||||||
@@ -27,22 +28,31 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Code
|
## Code
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { c as _c } from "react/compiler-runtime";
|
import { c as _c } from "react/compiler-runtime"; // @enableNewMutationAliasingModel
|
||||||
function bar(a, b) {
|
function bar(a, b) {
|
||||||
const $ = _c(3);
|
const $ = _c(6);
|
||||||
let y;
|
let t0;
|
||||||
if ($[0] !== a || $[1] !== b) {
|
if ($[0] !== a || $[1] !== b) {
|
||||||
const x = [a, b];
|
t0 = [a, b];
|
||||||
|
$[0] = a;
|
||||||
|
$[1] = b;
|
||||||
|
$[2] = t0;
|
||||||
|
} else {
|
||||||
|
t0 = $[2];
|
||||||
|
}
|
||||||
|
const x = t0;
|
||||||
|
let y;
|
||||||
|
if ($[3] !== x[0][1] || $[4] !== x[1][0]) {
|
||||||
y = {};
|
y = {};
|
||||||
let t = {};
|
let t = {};
|
||||||
|
|
||||||
y = x[0][1];
|
y = x[0][1];
|
||||||
t = x[1][0];
|
t = x[1][0];
|
||||||
$[0] = a;
|
$[3] = x[0][1];
|
||||||
$[1] = b;
|
$[4] = x[1][0];
|
||||||
$[2] = y;
|
$[5] = y;
|
||||||
} else {
|
} else {
|
||||||
y = $[2];
|
y = $[5];
|
||||||
}
|
}
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @enableNewMutationAliasingModel
|
||||||
function bar(a, b) {
|
function bar(a, b) {
|
||||||
let x = [a, b];
|
let x = [a, b];
|
||||||
let y = {};
|
let y = {};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
// @enableNewMutationAliasingModel
|
||||||
function bar(a) {
|
function bar(a) {
|
||||||
let x = [a];
|
let x = [a];
|
||||||
let y = {};
|
let y = {};
|
||||||
@@ -23,19 +24,27 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Code
|
## Code
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { c as _c } from "react/compiler-runtime";
|
import { c as _c } from "react/compiler-runtime"; // @enableNewMutationAliasingModel
|
||||||
function bar(a) {
|
function bar(a) {
|
||||||
const $ = _c(2);
|
const $ = _c(4);
|
||||||
let y;
|
let t0;
|
||||||
if ($[0] !== a) {
|
if ($[0] !== a) {
|
||||||
const x = [a];
|
t0 = [a];
|
||||||
|
$[0] = a;
|
||||||
|
$[1] = t0;
|
||||||
|
} else {
|
||||||
|
t0 = $[1];
|
||||||
|
}
|
||||||
|
const x = t0;
|
||||||
|
let y;
|
||||||
|
if ($[2] !== x[0].a[1]) {
|
||||||
y = {};
|
y = {};
|
||||||
|
|
||||||
y = x[0].a[1];
|
y = x[0].a[1];
|
||||||
$[0] = a;
|
$[2] = x[0].a[1];
|
||||||
$[1] = y;
|
$[3] = y;
|
||||||
} else {
|
} else {
|
||||||
y = $[1];
|
y = $[3];
|
||||||
}
|
}
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @enableNewMutationAliasingModel
|
||||||
function bar(a) {
|
function bar(a) {
|
||||||
let x = [a];
|
let x = [a];
|
||||||
let y = {};
|
let y = {};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
// @enableNewMutationAliasingModel
|
||||||
function bar(a) {
|
function bar(a) {
|
||||||
let x = [a];
|
let x = [a];
|
||||||
let y = {};
|
let y = {};
|
||||||
@@ -22,19 +23,27 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Code
|
## Code
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { c as _c } from "react/compiler-runtime";
|
import { c as _c } from "react/compiler-runtime"; // @enableNewMutationAliasingModel
|
||||||
function bar(a) {
|
function bar(a) {
|
||||||
const $ = _c(2);
|
const $ = _c(4);
|
||||||
let y;
|
let t0;
|
||||||
if ($[0] !== a) {
|
if ($[0] !== a) {
|
||||||
const x = [a];
|
t0 = [a];
|
||||||
|
$[0] = a;
|
||||||
|
$[1] = t0;
|
||||||
|
} else {
|
||||||
|
t0 = $[1];
|
||||||
|
}
|
||||||
|
const x = t0;
|
||||||
|
let y;
|
||||||
|
if ($[2] !== x[0]) {
|
||||||
y = {};
|
y = {};
|
||||||
|
|
||||||
y = x[0];
|
y = x[0];
|
||||||
$[0] = a;
|
$[2] = x[0];
|
||||||
$[1] = y;
|
$[3] = y;
|
||||||
} else {
|
} else {
|
||||||
y = $[1];
|
y = $[3];
|
||||||
}
|
}
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @enableNewMutationAliasingModel
|
||||||
function bar(a) {
|
function bar(a) {
|
||||||
let x = [a];
|
let x = [a];
|
||||||
let y = {};
|
let y = {};
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// @validateNoImpureFunctionsInRender
|
// @validateNoImpureFunctionsInRender @enableNewMutationAliasingModel
|
||||||
|
|
||||||
function Component() {
|
function Component() {
|
||||||
const date = Date.now();
|
const date = Date.now();
|
||||||
@@ -20,7 +20,7 @@ function Component() {
|
|||||||
2 |
|
2 |
|
||||||
3 | function Component() {
|
3 | function Component() {
|
||||||
> 4 | const date = Date.now();
|
> 4 | const date = Date.now();
|
||||||
| ^^^^^^^^ InvalidReact: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent). `Date.now` is an impure function whose results may change on every call (4:4)
|
| ^^^^^^^^^^ InvalidReact: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent). `Date.now` is an impure function whose results may change on every call (4:4)
|
||||||
|
|
||||||
InvalidReact: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent). `performance.now` is an impure function whose results may change on every call (5:5)
|
InvalidReact: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent). `performance.now` is an impure function whose results may change on every call (5:5)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// @validateNoImpureFunctionsInRender
|
// @validateNoImpureFunctionsInRender @enableNewMutationAliasingModel
|
||||||
|
|
||||||
function Component() {
|
function Component() {
|
||||||
const date = Date.now();
|
const date = Date.now();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
// @enableNewMutationAliasingModel
|
||||||
function Component() {
|
function Component() {
|
||||||
let local;
|
let local;
|
||||||
|
|
||||||
@@ -41,13 +42,13 @@ function Component() {
|
|||||||
## Error
|
## Error
|
||||||
|
|
||||||
```
|
```
|
||||||
3 |
|
4 |
|
||||||
4 | const reassignLocal = newValue => {
|
5 | const reassignLocal = newValue => {
|
||||||
> 5 | local = newValue;
|
> 6 | local = newValue;
|
||||||
| ^^^^^ InvalidReact: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead. Variable `local` cannot be reassigned after render (5:5)
|
| ^^^^^ InvalidReact: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead. Variable `local` cannot be reassigned after render (6:6)
|
||||||
6 | };
|
7 | };
|
||||||
7 |
|
8 |
|
||||||
8 | const onClick = newValue => {
|
9 | const onClick = newValue => {
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @enableNewMutationAliasingModel
|
||||||
function Component() {
|
function Component() {
|
||||||
let local;
|
let local;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
|
||||||
|
## Input
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
//@flow @validatePreserveExistingMemoizationGuarantees @enableNewMutationAliasingModel
|
||||||
|
|
||||||
|
import {useCallback} from 'react';
|
||||||
|
import {useIdentity} from 'shared-runtime';
|
||||||
|
|
||||||
|
function Component({content, refetch}) {
|
||||||
|
// This callback function accesses a hoisted const as a dependency,
|
||||||
|
// but it cannot reference it as a dependency since that would be a
|
||||||
|
// TDZ violation!
|
||||||
|
const onRefetch = useCallback(() => {
|
||||||
|
refetch(data);
|
||||||
|
}, [refetch]);
|
||||||
|
|
||||||
|
// The context variable gets frozen here since it's passed to a hook
|
||||||
|
const onSubmit = useIdentity(onRefetch);
|
||||||
|
|
||||||
|
// This has to error: onRefetch needs to memoize with `content` as a
|
||||||
|
// dependency, but the dependency comes later
|
||||||
|
const {data = null} = content;
|
||||||
|
|
||||||
|
return <Foo data={data} onSubmit={onSubmit} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Error
|
||||||
|
|
||||||
|
```
|
||||||
|
17 | // This has to error: onRefetch needs to memoize with `content` as a
|
||||||
|
18 | // dependency, but the dependency comes later
|
||||||
|
> 19 | const {data = null} = content;
|
||||||
|
| ^^^^^^^^^^^ InvalidReact: This variable is accessed before it is declared, which prevents the earlier access from updating when this value changes over time. Move the declaration of `data` to before it is first referenced (19:19)
|
||||||
|
20 |
|
||||||
|
21 | return <Foo data={data} onSubmit={onSubmit} />;
|
||||||
|
22 | }
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
//@flow @validatePreserveExistingMemoizationGuarantees @enableNewMutationAliasingModel
|
||||||
|
|
||||||
|
import {useCallback} from 'react';
|
||||||
|
import {useIdentity} from 'shared-runtime';
|
||||||
|
|
||||||
|
function Component({content, refetch}) {
|
||||||
|
// This callback function accesses a hoisted const as a dependency,
|
||||||
|
// but it cannot reference it as a dependency since that would be a
|
||||||
|
// TDZ violation!
|
||||||
|
const onRefetch = useCallback(() => {
|
||||||
|
refetch(data);
|
||||||
|
}, [refetch]);
|
||||||
|
|
||||||
|
// The context variable gets frozen here since it's passed to a hook
|
||||||
|
const onSubmit = useIdentity(onRefetch);
|
||||||
|
|
||||||
|
// This has to error: onRefetch needs to memoize with `content` as a
|
||||||
|
// dependency, but the dependency comes later
|
||||||
|
const {data = null} = content;
|
||||||
|
|
||||||
|
return <Foo data={data} onSubmit={onSubmit} />;
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
// @enableNewMutationAliasingModel
|
||||||
function useHook(a, b) {
|
function useHook(a, b) {
|
||||||
b.test = 1;
|
b.test = 1;
|
||||||
a.test = 2;
|
a.test = 2;
|
||||||
@@ -13,12 +14,15 @@ function useHook(a, b) {
|
|||||||
## Error
|
## Error
|
||||||
|
|
||||||
```
|
```
|
||||||
1 | function useHook(a, b) {
|
1 | // @enableNewMutationAliasingModel
|
||||||
> 2 | b.test = 1;
|
2 | function useHook(a, b) {
|
||||||
| ^ InvalidReact: Mutating component props or hook arguments is not allowed. Consider using a local variable instead (2:2)
|
> 3 | b.test = 1;
|
||||||
3 | a.test = 2;
|
| ^ InvalidReact: Mutating component props or hook arguments is not allowed. Consider using a local variable instead (3:3)
|
||||||
4 | }
|
|
||||||
5 |
|
InvalidReact: Mutating component props or hook arguments is not allowed. Consider using a local variable instead (4:4)
|
||||||
|
4 | a.test = 2;
|
||||||
|
5 | }
|
||||||
|
6 |
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @enableNewMutationAliasingModel
|
||||||
function useHook(a, b) {
|
function useHook(a, b) {
|
||||||
b.test = 1;
|
b.test = 1;
|
||||||
a.test = 2;
|
a.test = 2;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
// @enableNewMutationAliasingModel
|
||||||
let x = {a: 42};
|
let x = {a: 42};
|
||||||
|
|
||||||
function Component(props) {
|
function Component(props) {
|
||||||
@@ -17,13 +18,15 @@ function Component(props) {
|
|||||||
## Error
|
## Error
|
||||||
|
|
||||||
```
|
```
|
||||||
3 | function Component(props) {
|
4 | function Component(props) {
|
||||||
4 | foo(() => {
|
5 | foo(() => {
|
||||||
> 5 | x.a = 10;
|
> 6 | x.a = 10;
|
||||||
| ^ InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect (5:5)
|
| ^ InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect (6:6)
|
||||||
6 | x.a = 20;
|
|
||||||
7 | });
|
InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect (7:7)
|
||||||
8 | }
|
7 | x.a = 20;
|
||||||
|
8 | });
|
||||||
|
9 | }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @enableNewMutationAliasingModel
|
||||||
let x = {a: 42};
|
let x = {a: 42};
|
||||||
|
|
||||||
function Component(props) {
|
function Component(props) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
// @enableNewMutationAliasingModel
|
||||||
function Component() {
|
function Component() {
|
||||||
const foo = () => {
|
const foo = () => {
|
||||||
// Cannot assign to globals
|
// Cannot assign to globals
|
||||||
@@ -17,13 +18,15 @@ function Component() {
|
|||||||
## Error
|
## Error
|
||||||
|
|
||||||
```
|
```
|
||||||
2 | const foo = () => {
|
3 | const foo = () => {
|
||||||
3 | // Cannot assign to globals
|
4 | // Cannot assign to globals
|
||||||
> 4 | someUnknownGlobal = true;
|
> 5 | someUnknownGlobal = true;
|
||||||
| ^^^^^^^^^^^^^^^^^ InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (4:4)
|
| ^^^^^^^^^^^^^^^^^ InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (5:5)
|
||||||
5 | moduleLocal = true;
|
|
||||||
6 | };
|
InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (6:6)
|
||||||
7 | foo();
|
6 | moduleLocal = true;
|
||||||
|
7 | };
|
||||||
|
8 | foo();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @enableNewMutationAliasingModel
|
||||||
function Component() {
|
function Component() {
|
||||||
const foo = () => {
|
const foo = () => {
|
||||||
// Cannot assign to globals
|
// Cannot assign to globals
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
// @enableNewMutationAliasingModel
|
||||||
function Component() {
|
function Component() {
|
||||||
// Cannot assign to globals
|
// Cannot assign to globals
|
||||||
someUnknownGlobal = true;
|
someUnknownGlobal = true;
|
||||||
@@ -14,13 +15,15 @@ function Component() {
|
|||||||
## Error
|
## Error
|
||||||
|
|
||||||
```
|
```
|
||||||
1 | function Component() {
|
2 | function Component() {
|
||||||
2 | // Cannot assign to globals
|
3 | // Cannot assign to globals
|
||||||
> 3 | someUnknownGlobal = true;
|
> 4 | someUnknownGlobal = true;
|
||||||
| ^^^^^^^^^^^^^^^^^ InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (3:3)
|
| ^^^^^^^^^^^^^^^^^ InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (4:4)
|
||||||
4 | moduleLocal = true;
|
|
||||||
5 | }
|
InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (5:5)
|
||||||
6 |
|
5 | moduleLocal = true;
|
||||||
|
6 | }
|
||||||
|
7 |
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @enableNewMutationAliasingModel
|
||||||
function Component() {
|
function Component() {
|
||||||
// Cannot assign to globals
|
// Cannot assign to globals
|
||||||
someUnknownGlobal = true;
|
someUnknownGlobal = true;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
// @enableNewMutationAliasingModel
|
||||||
function Component(props) {
|
function Component(props) {
|
||||||
function hasErrors() {
|
function hasErrors() {
|
||||||
let hasErrors = false;
|
let hasErrors = false;
|
||||||
@@ -19,12 +20,12 @@ function Component(props) {
|
|||||||
## Error
|
## Error
|
||||||
|
|
||||||
```
|
```
|
||||||
7 | return hasErrors;
|
8 | return hasErrors;
|
||||||
8 | }
|
9 | }
|
||||||
> 9 | return hasErrors();
|
> 10 | return hasErrors();
|
||||||
| ^^^^^^^^^ Invariant: [hoisting] Expected value for identifier to be initialized. hasErrors_0$15 (9:9)
|
| ^^^^^^^^^ Invariant: [InferMutationAliasingEffects] Expected value kind to be initialized. <unknown> hasErrors_0$15:TFunction (10:10)
|
||||||
10 | }
|
11 | }
|
||||||
11 |
|
12 |
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @enableNewMutationAliasingModel
|
||||||
function Component(props) {
|
function Component(props) {
|
||||||
function hasErrors() {
|
function hasErrors() {
|
||||||
let hasErrors = false;
|
let hasErrors = false;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
|
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
|
||||||
import {useEffect} from 'react';
|
import {useEffect} from 'react';
|
||||||
import {print} from 'shared-runtime';
|
import {print} from 'shared-runtime';
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Code
|
## Code
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
|
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { print } from "shared-runtime";
|
import { print } from "shared-runtime";
|
||||||
|
|
||||||
@@ -48,9 +48,9 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Logs
|
## Logs
|
||||||
|
|
||||||
```
|
```
|
||||||
{"kind":"CompileError","fnLoc":{"start":{"line":5,"column":0,"index":139},"end":{"line":12,"column":1,"index":384},"filename":"mutate-after-useeffect-optional-chain.ts"},"detail":{"reason":"This mutates a variable that React considers immutable","description":null,"loc":{"start":{"line":10,"column":2,"index":345},"end":{"line":10,"column":5,"index":348},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"},"suggestions":null,"severity":"InvalidReact"}}
|
{"kind":"CompileError","fnLoc":{"start":{"line":5,"column":0,"index":171},"end":{"line":12,"column":1,"index":416},"filename":"mutate-after-useeffect-optional-chain.ts"},"detail":{"reason":"Updating a value used previously in an effect function or as an effect dependency is not allowed. Consider moving the mutation before calling useEffect()","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":10,"column":2,"index":377},"end":{"line":10,"column":5,"index":380},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}}}
|
||||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":9,"column":2,"index":304},"end":{"line":9,"column":39,"index":341},"filename":"mutate-after-useeffect-optional-chain.ts"},"decorations":[{"start":{"line":9,"column":24,"index":326},"end":{"line":9,"column":27,"index":329},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}]}
|
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":9,"column":2,"index":336},"end":{"line":9,"column":39,"index":373},"filename":"mutate-after-useeffect-optional-chain.ts"},"decorations":[{"start":{"line":9,"column":24,"index":358},"end":{"line":9,"column":27,"index":361},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}]}
|
||||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":5,"column":0,"index":139},"end":{"line":12,"column":1,"index":384},"filename":"mutate-after-useeffect-optional-chain.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
{"kind":"CompileSuccess","fnLoc":{"start":{"line":5,"column":0,"index":171},"end":{"line":12,"column":1,"index":416},"filename":"mutate-after-useeffect-optional-chain.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Eval output
|
### Eval output
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
|
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
|
||||||
import {useEffect} from 'react';
|
import {useEffect} from 'react';
|
||||||
import {print} from 'shared-runtime';
|
import {print} from 'shared-runtime';
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
|
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
|
||||||
|
|
||||||
import {useEffect, useRef} from 'react';
|
import {useEffect, useRef} from 'react';
|
||||||
import {print} from 'shared-runtime';
|
import {print} from 'shared-runtime';
|
||||||
@@ -24,7 +24,7 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Code
|
## Code
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
|
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
|
||||||
|
|
||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
import { print } from "shared-runtime";
|
import { print } from "shared-runtime";
|
||||||
@@ -47,9 +47,9 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Logs
|
## Logs
|
||||||
|
|
||||||
```
|
```
|
||||||
{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":148},"end":{"line":11,"column":1,"index":311},"filename":"mutate-after-useeffect-ref-access.ts"},"detail":{"reason":"Mutating component props or hook arguments is not allowed. Consider using a local variable instead","description":null,"loc":{"start":{"line":9,"column":2,"index":269},"end":{"line":9,"column":16,"index":283},"filename":"mutate-after-useeffect-ref-access.ts"},"suggestions":null,"severity":"InvalidReact"}}
|
{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":180},"end":{"line":11,"column":1,"index":343},"filename":"mutate-after-useeffect-ref-access.ts"},"detail":{"reason":"Mutating component props or hook arguments is not allowed. Consider using a local variable instead","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":9,"column":2,"index":301},"end":{"line":9,"column":16,"index":315},"filename":"mutate-after-useeffect-ref-access.ts"}}}
|
||||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":227},"end":{"line":8,"column":40,"index":265},"filename":"mutate-after-useeffect-ref-access.ts"},"decorations":[{"start":{"line":8,"column":24,"index":249},"end":{"line":8,"column":30,"index":255},"filename":"mutate-after-useeffect-ref-access.ts","identifierName":"arrRef"}]}
|
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":259},"end":{"line":8,"column":40,"index":297},"filename":"mutate-after-useeffect-ref-access.ts"},"decorations":[{"start":{"line":8,"column":24,"index":281},"end":{"line":8,"column":30,"index":287},"filename":"mutate-after-useeffect-ref-access.ts","identifierName":"arrRef"}]}
|
||||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":148},"end":{"line":11,"column":1,"index":311},"filename":"mutate-after-useeffect-ref-access.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
{"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":180},"end":{"line":11,"column":1,"index":343},"filename":"mutate-after-useeffect-ref-access.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Eval output
|
### Eval output
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
|
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
|
||||||
|
|
||||||
import {useEffect, useRef} from 'react';
|
import {useEffect, useRef} from 'react';
|
||||||
import {print} from 'shared-runtime';
|
import {print} from 'shared-runtime';
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
|
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
|
||||||
import {useEffect} from 'react';
|
import {useEffect} from 'react';
|
||||||
|
|
||||||
function Component({foo}) {
|
function Component({foo}) {
|
||||||
@@ -24,7 +24,7 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Code
|
## Code
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
|
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
|
||||||
function Component(t0) {
|
function Component(t0) {
|
||||||
@@ -47,9 +47,9 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Logs
|
## Logs
|
||||||
|
|
||||||
```
|
```
|
||||||
{"kind":"CompileError","fnLoc":{"start":{"line":4,"column":0,"index":101},"end":{"line":11,"column":1,"index":222},"filename":"mutate-after-useeffect.ts"},"detail":{"reason":"This mutates a variable that React considers immutable","description":null,"loc":{"start":{"line":9,"column":2,"index":194},"end":{"line":9,"column":5,"index":197},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},"suggestions":null,"severity":"InvalidReact"}}
|
{"kind":"CompileError","fnLoc":{"start":{"line":4,"column":0,"index":133},"end":{"line":11,"column":1,"index":254},"filename":"mutate-after-useeffect.ts"},"detail":{"reason":"Updating a value used previously in an effect function or as an effect dependency is not allowed. Consider moving the mutation before calling useEffect()","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":9,"column":2,"index":226},"end":{"line":9,"column":5,"index":229},"filename":"mutate-after-useeffect.ts","identifierName":"arr"}}}
|
||||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":6,"column":2,"index":149},"end":{"line":8,"column":4,"index":190},"filename":"mutate-after-useeffect.ts"},"decorations":[{"start":{"line":7,"column":4,"index":171},"end":{"line":7,"column":7,"index":174},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},{"start":{"line":7,"column":4,"index":171},"end":{"line":7,"column":7,"index":174},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},{"start":{"line":7,"column":13,"index":180},"end":{"line":7,"column":16,"index":183},"filename":"mutate-after-useeffect.ts","identifierName":"foo"}]}
|
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":6,"column":2,"index":181},"end":{"line":8,"column":4,"index":222},"filename":"mutate-after-useeffect.ts"},"decorations":[{"start":{"line":7,"column":4,"index":203},"end":{"line":7,"column":7,"index":206},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},{"start":{"line":7,"column":4,"index":203},"end":{"line":7,"column":7,"index":206},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},{"start":{"line":7,"column":13,"index":212},"end":{"line":7,"column":16,"index":215},"filename":"mutate-after-useeffect.ts","identifierName":"foo"}]}
|
||||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":4,"column":0,"index":101},"end":{"line":11,"column":1,"index":222},"filename":"mutate-after-useeffect.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
{"kind":"CompileSuccess","fnLoc":{"start":{"line":4,"column":0,"index":133},"end":{"line":11,"column":1,"index":254},"filename":"mutate-after-useeffect.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Eval output
|
### Eval output
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
|
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
|
||||||
import {useEffect} from 'react';
|
import {useEffect} from 'react';
|
||||||
|
|
||||||
function Component({foo}) {
|
function Component({foo}) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
// @enableNewMutationAliasingModel
|
||||||
import {identity, mutate} from 'shared-runtime';
|
import {identity, mutate} from 'shared-runtime';
|
||||||
|
|
||||||
function Component(props) {
|
function Component(props) {
|
||||||
@@ -23,38 +24,22 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Code
|
## Code
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { c as _c } from "react/compiler-runtime";
|
import { c as _c } from "react/compiler-runtime"; // @enableNewMutationAliasingModel
|
||||||
import { identity, mutate } from "shared-runtime";
|
import { identity, mutate } from "shared-runtime";
|
||||||
|
|
||||||
function Component(props) {
|
function Component(props) {
|
||||||
const $ = _c(5);
|
const $ = _c(2);
|
||||||
let t0;
|
let context;
|
||||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
if ($[0] !== props.value) {
|
||||||
t0 = {};
|
const key = {};
|
||||||
$[0] = t0;
|
context = { [key]: identity([props.value]) };
|
||||||
} else {
|
|
||||||
t0 = $[0];
|
|
||||||
}
|
|
||||||
const key = t0;
|
|
||||||
let t1;
|
|
||||||
if ($[1] !== props.value) {
|
|
||||||
t1 = identity([props.value]);
|
|
||||||
$[1] = props.value;
|
|
||||||
$[2] = t1;
|
|
||||||
} else {
|
|
||||||
t1 = $[2];
|
|
||||||
}
|
|
||||||
let t2;
|
|
||||||
if ($[3] !== t1) {
|
|
||||||
t2 = { [key]: t1 };
|
|
||||||
$[3] = t1;
|
|
||||||
$[4] = t2;
|
|
||||||
} else {
|
|
||||||
t2 = $[4];
|
|
||||||
}
|
|
||||||
const context = t2;
|
|
||||||
|
|
||||||
mutate(key);
|
mutate(key);
|
||||||
|
$[0] = props.value;
|
||||||
|
$[1] = context;
|
||||||
|
} else {
|
||||||
|
context = $[1];
|
||||||
|
}
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @enableNewMutationAliasingModel
|
||||||
import {identity, mutate} from 'shared-runtime';
|
import {identity, mutate} from 'shared-runtime';
|
||||||
|
|
||||||
function Component(props) {
|
function Component(props) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
// @enableNewMutationAliasingModel
|
||||||
import {identity, mutate, mutateAndReturn} from 'shared-runtime';
|
import {identity, mutate, mutateAndReturn} from 'shared-runtime';
|
||||||
|
|
||||||
function Component(props) {
|
function Component(props) {
|
||||||
@@ -23,15 +24,26 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Code
|
## Code
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { c as _c } from "react/compiler-runtime";
|
import { c as _c } from "react/compiler-runtime"; // @enableNewMutationAliasingModel
|
||||||
import { identity, mutate, mutateAndReturn } from "shared-runtime";
|
import { identity, mutate, mutateAndReturn } from "shared-runtime";
|
||||||
|
|
||||||
function Component(props) {
|
function Component(props) {
|
||||||
const $ = _c(2);
|
const $ = _c(4);
|
||||||
let context;
|
let context;
|
||||||
if ($[0] !== props.value) {
|
if ($[0] !== props.value) {
|
||||||
const key = { a: "key" };
|
const key = { a: "key" };
|
||||||
context = { [key.a]: identity([props.value]) };
|
|
||||||
|
const t0 = key.a;
|
||||||
|
const t1 = identity([props.value]);
|
||||||
|
let t2;
|
||||||
|
if ($[2] !== t1) {
|
||||||
|
t2 = { [t0]: t1 };
|
||||||
|
$[2] = t1;
|
||||||
|
$[3] = t2;
|
||||||
|
} else {
|
||||||
|
t2 = $[3];
|
||||||
|
}
|
||||||
|
context = t2;
|
||||||
|
|
||||||
mutate(key);
|
mutate(key);
|
||||||
$[0] = props.value;
|
$[0] = props.value;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @enableNewMutationAliasingModel
|
||||||
import {identity, mutate, mutateAndReturn} from 'shared-runtime';
|
import {identity, mutate, mutateAndReturn} from 'shared-runtime';
|
||||||
|
|
||||||
function Component(props) {
|
function Component(props) {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// @inferEffectDependencies
|
// @inferEffectDependencies @enableNewMutationAliasingModel
|
||||||
import {useEffect, useState} from 'react';
|
import {useEffect, useState} from 'react';
|
||||||
import {print} from 'shared-runtime';
|
import {print} from 'shared-runtime';
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ function ReactiveRefInEffect(props) {
|
|||||||
## Code
|
## Code
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
|
import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies @enableNewMutationAliasingModel
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { print } from "shared-runtime";
|
import { print } from "shared-runtime";
|
||||||
|
|
||||||
@@ -34,22 +34,28 @@ import { print } from "shared-runtime";
|
|||||||
* setState types are not enough to determine to omit from deps. Must also take reactivity into account.
|
* setState types are not enough to determine to omit from deps. Must also take reactivity into account.
|
||||||
*/
|
*/
|
||||||
function ReactiveRefInEffect(props) {
|
function ReactiveRefInEffect(props) {
|
||||||
const $ = _c(2);
|
const $ = _c(4);
|
||||||
const [, setState1] = useRef("initial value");
|
const [, setState1] = useRef("initial value");
|
||||||
const [, setState2] = useRef("initial value");
|
const [, setState2] = useRef("initial value");
|
||||||
let setState;
|
let setState;
|
||||||
if (props.foo) {
|
if ($[0] !== props.foo) {
|
||||||
setState = setState1;
|
if (props.foo) {
|
||||||
|
setState = setState1;
|
||||||
|
} else {
|
||||||
|
setState = setState2;
|
||||||
|
}
|
||||||
|
$[0] = props.foo;
|
||||||
|
$[1] = setState;
|
||||||
} else {
|
} else {
|
||||||
setState = setState2;
|
setState = $[1];
|
||||||
}
|
}
|
||||||
let t0;
|
let t0;
|
||||||
if ($[0] !== setState) {
|
if ($[2] !== setState) {
|
||||||
t0 = () => print(setState);
|
t0 = () => print(setState);
|
||||||
$[0] = setState;
|
$[2] = setState;
|
||||||
$[1] = t0;
|
$[3] = t0;
|
||||||
} else {
|
} else {
|
||||||
t0 = $[1];
|
t0 = $[3];
|
||||||
}
|
}
|
||||||
useEffect(t0, [setState]);
|
useEffect(t0, [setState]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// @inferEffectDependencies
|
// @inferEffectDependencies @enableNewMutationAliasingModel
|
||||||
import {useEffect, useState} from 'react';
|
import {useEffect, useState} from 'react';
|
||||||
import {print} from 'shared-runtime';
|
import {print} from 'shared-runtime';
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
|
||||||
|
## Input
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
//@flow @validatePreserveExistingMemoizationGuarantees @enableNewMutationAliasingModel
|
||||||
|
component Component(
|
||||||
|
onAsyncSubmit?: (() => void) => void,
|
||||||
|
onClose: (isConfirmed: boolean) => void
|
||||||
|
) {
|
||||||
|
// When running inferReactiveScopeVariables,
|
||||||
|
// onAsyncSubmit and onClose update to share
|
||||||
|
// a mutableRange instance.
|
||||||
|
const onSubmit = useCallback(() => {
|
||||||
|
if (onAsyncSubmit) {
|
||||||
|
onAsyncSubmit(() => {
|
||||||
|
onClose(true);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}, [onAsyncSubmit, onClose]);
|
||||||
|
// When running inferReactiveScopeVariables here,
|
||||||
|
// first the existing range gets updated (affecting
|
||||||
|
// onAsyncSubmit) and then onClose gets assigned a
|
||||||
|
// different mutable range instance, which is the
|
||||||
|
// one reset after AnalyzeFunctions.
|
||||||
|
// The fix is to fully reset mutable ranges *instances*
|
||||||
|
// after AnalyzeFunctions visit a function expression
|
||||||
|
return <Dialog onSubmit={onSubmit} onClose={() => onClose(false)} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Code
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { c as _c } from "react/compiler-runtime";
|
||||||
|
function Component(t0) {
|
||||||
|
const $ = _c(8);
|
||||||
|
const { onAsyncSubmit, onClose } = t0;
|
||||||
|
let t1;
|
||||||
|
if ($[0] !== onAsyncSubmit || $[1] !== onClose) {
|
||||||
|
t1 = () => {
|
||||||
|
if (onAsyncSubmit) {
|
||||||
|
onAsyncSubmit(() => {
|
||||||
|
onClose(true);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
$[0] = onAsyncSubmit;
|
||||||
|
$[1] = onClose;
|
||||||
|
$[2] = t1;
|
||||||
|
} else {
|
||||||
|
t1 = $[2];
|
||||||
|
}
|
||||||
|
const onSubmit = t1;
|
||||||
|
let t2;
|
||||||
|
if ($[3] !== onClose) {
|
||||||
|
t2 = () => onClose(false);
|
||||||
|
$[3] = onClose;
|
||||||
|
$[4] = t2;
|
||||||
|
} else {
|
||||||
|
t2 = $[4];
|
||||||
|
}
|
||||||
|
let t3;
|
||||||
|
if ($[5] !== onSubmit || $[6] !== t2) {
|
||||||
|
t3 = <Dialog onSubmit={onSubmit} onClose={t2} />;
|
||||||
|
$[5] = onSubmit;
|
||||||
|
$[6] = t2;
|
||||||
|
$[7] = t3;
|
||||||
|
} else {
|
||||||
|
t3 = $[7];
|
||||||
|
}
|
||||||
|
return t3;
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Eval output
|
||||||
|
(kind: exception) Fixture not implemented
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
//@flow @validatePreserveExistingMemoizationGuarantees @enableNewMutationAliasingModel
|
||||||
|
component Component(
|
||||||
|
onAsyncSubmit?: (() => void) => void,
|
||||||
|
onClose: (isConfirmed: boolean) => void
|
||||||
|
) {
|
||||||
|
// When running inferReactiveScopeVariables,
|
||||||
|
// onAsyncSubmit and onClose update to share
|
||||||
|
// a mutableRange instance.
|
||||||
|
const onSubmit = useCallback(() => {
|
||||||
|
if (onAsyncSubmit) {
|
||||||
|
onAsyncSubmit(() => {
|
||||||
|
onClose(true);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}, [onAsyncSubmit, onClose]);
|
||||||
|
// When running inferReactiveScopeVariables here,
|
||||||
|
// first the existing range gets updated (affecting
|
||||||
|
// onAsyncSubmit) and then onClose gets assigned a
|
||||||
|
// different mutable range instance, which is the
|
||||||
|
// one reset after AnalyzeFunctions.
|
||||||
|
// The fix is to fully reset mutable ranges *instances*
|
||||||
|
// after AnalyzeFunctions visit a function expression
|
||||||
|
return <Dialog onSubmit={onSubmit} onClose={() => onClose(false)} />;
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// @inferEffectDependencies @noEmit @panicThreshold:"none" @loggerTestOnly
|
// @inferEffectDependencies @noEmit @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
|
||||||
import {print} from 'shared-runtime';
|
import {print} from 'shared-runtime';
|
||||||
import useEffectWrapper from 'useEffectWrapper';
|
import useEffectWrapper from 'useEffectWrapper';
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Code
|
## Code
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// @inferEffectDependencies @noEmit @panicThreshold:"none" @loggerTestOnly
|
// @inferEffectDependencies @noEmit @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
|
||||||
import { print } from "shared-runtime";
|
import { print } from "shared-runtime";
|
||||||
import useEffectWrapper from "useEffectWrapper";
|
import useEffectWrapper from "useEffectWrapper";
|
||||||
|
|
||||||
@@ -52,10 +52,10 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Logs
|
## Logs
|
||||||
|
|
||||||
```
|
```
|
||||||
{"kind":"CompileError","fnLoc":{"start":{"line":5,"column":0,"index":163},"end":{"line":13,"column":1,"index":357},"filename":"retry-no-emit.ts"},"detail":{"reason":"This mutates a variable that React considers immutable","description":null,"loc":{"start":{"line":11,"column":2,"index":320},"end":{"line":11,"column":6,"index":324},"filename":"retry-no-emit.ts","identifierName":"arr2"},"suggestions":null,"severity":"InvalidReact"}}
|
{"kind":"CompileError","fnLoc":{"start":{"line":5,"column":0,"index":195},"end":{"line":13,"column":1,"index":389},"filename":"retry-no-emit.ts"},"detail":{"reason":"This mutates a variable that React considers immutable","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":11,"column":2,"index":352},"end":{"line":11,"column":6,"index":356},"filename":"retry-no-emit.ts","identifierName":"arr2"}}}
|
||||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":7,"column":2,"index":216},"end":{"line":7,"column":36,"index":250},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":7,"column":31,"index":245},"end":{"line":7,"column":34,"index":248},"filename":"retry-no-emit.ts","identifierName":"arr"}]}
|
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":7,"column":2,"index":248},"end":{"line":7,"column":36,"index":282},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":7,"column":31,"index":277},"end":{"line":7,"column":34,"index":280},"filename":"retry-no-emit.ts","identifierName":"arr"}]}
|
||||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":10,"column":2,"index":274},"end":{"line":10,"column":44,"index":316},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":10,"column":25,"index":297},"end":{"line":10,"column":29,"index":301},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":10,"column":25,"index":297},"end":{"line":10,"column":29,"index":301},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":10,"column":35,"index":307},"end":{"line":10,"column":42,"index":314},"filename":"retry-no-emit.ts","identifierName":"propVal"}]}
|
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":10,"column":2,"index":306},"end":{"line":10,"column":44,"index":348},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":10,"column":25,"index":329},"end":{"line":10,"column":29,"index":333},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":10,"column":25,"index":329},"end":{"line":10,"column":29,"index":333},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":10,"column":35,"index":339},"end":{"line":10,"column":42,"index":346},"filename":"retry-no-emit.ts","identifierName":"propVal"}]}
|
||||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":5,"column":0,"index":163},"end":{"line":13,"column":1,"index":357},"filename":"retry-no-emit.ts"},"fnName":"Foo","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
{"kind":"CompileSuccess","fnLoc":{"start":{"line":5,"column":0,"index":195},"end":{"line":13,"column":1,"index":389},"filename":"retry-no-emit.ts"},"fnName":"Foo","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Eval output
|
### Eval output
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// @inferEffectDependencies @noEmit @panicThreshold:"none" @loggerTestOnly
|
// @inferEffectDependencies @noEmit @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
|
||||||
import {print} from 'shared-runtime';
|
import {print} from 'shared-runtime';
|
||||||
import useEffectWrapper from 'useEffectWrapper';
|
import useEffectWrapper from 'useEffectWrapper';
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// @enableFire
|
// @enableFire @enableNewMutationAliasingModel
|
||||||
import {fire} from 'react';
|
import {fire} from 'react';
|
||||||
|
|
||||||
function Component({bar, baz}) {
|
function Component({bar, baz}) {
|
||||||
@@ -26,7 +26,7 @@ function Component({bar, baz}) {
|
|||||||
## Code
|
## Code
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { c as _c, useFire } from "react/compiler-runtime"; // @enableFire
|
import { c as _c, useFire } from "react/compiler-runtime"; // @enableFire @enableNewMutationAliasingModel
|
||||||
import { fire } from "react";
|
import { fire } from "react";
|
||||||
|
|
||||||
function Component(t0) {
|
function Component(t0) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// @enableFire
|
// @enableFire @enableNewMutationAliasingModel
|
||||||
import {fire} from 'react';
|
import {fire} from 'react';
|
||||||
|
|
||||||
function Component({bar, baz}) {
|
function Component({bar, baz}) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
// @enableNewMutationAliasingModel
|
||||||
import {useCallback} from 'react';
|
import {useCallback} from 'react';
|
||||||
import {Stringify} from 'shared-runtime';
|
import {Stringify} from 'shared-runtime';
|
||||||
|
|
||||||
@@ -35,44 +36,51 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Code
|
## Code
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { c as _c } from "react/compiler-runtime";
|
import { c as _c } from "react/compiler-runtime"; // @enableNewMutationAliasingModel
|
||||||
import { useCallback } from "react";
|
import { useCallback } from "react";
|
||||||
import { Stringify } from "shared-runtime";
|
import { Stringify } from "shared-runtime";
|
||||||
|
|
||||||
function Foo(t0) {
|
function Foo(t0) {
|
||||||
const $ = _c(8);
|
const $ = _c(10);
|
||||||
const { arr1, arr2, foo } = t0;
|
const { arr1, arr2, foo } = t0;
|
||||||
let getVal1;
|
|
||||||
let t1;
|
let t1;
|
||||||
if ($[0] !== arr1 || $[1] !== arr2 || $[2] !== foo) {
|
if ($[0] !== arr1) {
|
||||||
const x = [arr1];
|
t1 = [arr1];
|
||||||
|
$[0] = arr1;
|
||||||
|
$[1] = t1;
|
||||||
|
} else {
|
||||||
|
t1 = $[1];
|
||||||
|
}
|
||||||
|
const x = t1;
|
||||||
|
let getVal1;
|
||||||
|
let t2;
|
||||||
|
if ($[2] !== arr2 || $[3] !== foo || $[4] !== x) {
|
||||||
let y = [];
|
let y = [];
|
||||||
|
|
||||||
getVal1 = _temp;
|
getVal1 = _temp;
|
||||||
|
|
||||||
t1 = () => [y];
|
t2 = () => [y];
|
||||||
foo ? (y = x.concat(arr2)) : y;
|
foo ? (y = x.concat(arr2)) : y;
|
||||||
$[0] = arr1;
|
$[2] = arr2;
|
||||||
$[1] = arr2;
|
$[3] = foo;
|
||||||
$[2] = foo;
|
$[4] = x;
|
||||||
$[3] = getVal1;
|
|
||||||
$[4] = t1;
|
|
||||||
} else {
|
|
||||||
getVal1 = $[3];
|
|
||||||
t1 = $[4];
|
|
||||||
}
|
|
||||||
const getVal2 = t1;
|
|
||||||
let t2;
|
|
||||||
if ($[5] !== getVal1 || $[6] !== getVal2) {
|
|
||||||
t2 = <Stringify val1={getVal1} val2={getVal2} shouldInvokeFns={true} />;
|
|
||||||
$[5] = getVal1;
|
$[5] = getVal1;
|
||||||
$[6] = getVal2;
|
$[6] = t2;
|
||||||
$[7] = t2;
|
|
||||||
} else {
|
} else {
|
||||||
t2 = $[7];
|
getVal1 = $[5];
|
||||||
|
t2 = $[6];
|
||||||
}
|
}
|
||||||
return t2;
|
const getVal2 = t2;
|
||||||
|
let t3;
|
||||||
|
if ($[7] !== getVal1 || $[8] !== getVal2) {
|
||||||
|
t3 = <Stringify val1={getVal1} val2={getVal2} shouldInvokeFns={true} />;
|
||||||
|
$[7] = getVal1;
|
||||||
|
$[8] = getVal2;
|
||||||
|
$[9] = t3;
|
||||||
|
} else {
|
||||||
|
t3 = $[9];
|
||||||
|
}
|
||||||
|
return t3;
|
||||||
}
|
}
|
||||||
function _temp() {
|
function _temp() {
|
||||||
return { x: 2 };
|
return { x: 2 };
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @enableNewMutationAliasingModel
|
||||||
import {useCallback} from 'react';
|
import {useCallback} from 'react';
|
||||||
import {Stringify} from 'shared-runtime';
|
import {Stringify} from 'shared-runtime';
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
// @enableNewMutationAliasingModel
|
||||||
import {useCallback} from 'react';
|
import {useCallback} from 'react';
|
||||||
import {Stringify} from 'shared-runtime';
|
import {Stringify} from 'shared-runtime';
|
||||||
|
|
||||||
@@ -30,37 +31,44 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Code
|
## Code
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { c as _c } from "react/compiler-runtime";
|
import { c as _c } from "react/compiler-runtime"; // @enableNewMutationAliasingModel
|
||||||
import { useCallback } from "react";
|
import { useCallback } from "react";
|
||||||
import { Stringify } from "shared-runtime";
|
import { Stringify } from "shared-runtime";
|
||||||
|
|
||||||
// We currently produce invalid output (incorrect scoping for `y` declaration)
|
// We currently produce invalid output (incorrect scoping for `y` declaration)
|
||||||
function useFoo(arr1, arr2) {
|
function useFoo(arr1, arr2) {
|
||||||
const $ = _c(5);
|
const $ = _c(7);
|
||||||
let t0;
|
let t0;
|
||||||
if ($[0] !== arr1 || $[1] !== arr2) {
|
if ($[0] !== arr1) {
|
||||||
const x = [arr1];
|
t0 = [arr1];
|
||||||
|
$[0] = arr1;
|
||||||
|
$[1] = t0;
|
||||||
|
} else {
|
||||||
|
t0 = $[1];
|
||||||
|
}
|
||||||
|
const x = t0;
|
||||||
|
let t1;
|
||||||
|
if ($[2] !== arr2 || $[3] !== x) {
|
||||||
let y;
|
let y;
|
||||||
t0 = () => ({ y });
|
t1 = () => ({ y });
|
||||||
|
|
||||||
(y = x.concat(arr2)), y;
|
(y = x.concat(arr2)), y;
|
||||||
$[0] = arr1;
|
$[2] = arr2;
|
||||||
$[1] = arr2;
|
$[3] = x;
|
||||||
$[2] = t0;
|
|
||||||
} else {
|
|
||||||
t0 = $[2];
|
|
||||||
}
|
|
||||||
const getVal = t0;
|
|
||||||
let t1;
|
|
||||||
if ($[3] !== getVal) {
|
|
||||||
t1 = <Stringify getVal={getVal} shouldInvokeFns={true} />;
|
|
||||||
$[3] = getVal;
|
|
||||||
$[4] = t1;
|
$[4] = t1;
|
||||||
} else {
|
} else {
|
||||||
t1 = $[4];
|
t1 = $[4];
|
||||||
}
|
}
|
||||||
return t1;
|
const getVal = t1;
|
||||||
|
let t2;
|
||||||
|
if ($[5] !== getVal) {
|
||||||
|
t2 = <Stringify getVal={getVal} shouldInvokeFns={true} />;
|
||||||
|
$[5] = getVal;
|
||||||
|
$[6] = t2;
|
||||||
|
} else {
|
||||||
|
t2 = $[6];
|
||||||
|
}
|
||||||
|
return t2;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FIXTURE_ENTRYPOINT = {
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @enableNewMutationAliasingModel
|
||||||
import {useCallback} from 'react';
|
import {useCallback} from 'react';
|
||||||
import {Stringify} from 'shared-runtime';
|
import {Stringify} from 'shared-runtime';
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
## Input
|
## Input
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
// @enableNewMutationAliasingModel
|
||||||
import {useMemo} from 'react';
|
import {useMemo} from 'react';
|
||||||
|
|
||||||
function useFoo(arr1, arr2) {
|
function useFoo(arr1, arr2) {
|
||||||
@@ -26,33 +27,40 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Code
|
## Code
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { c as _c } from "react/compiler-runtime";
|
import { c as _c } from "react/compiler-runtime"; // @enableNewMutationAliasingModel
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
|
|
||||||
function useFoo(arr1, arr2) {
|
function useFoo(arr1, arr2) {
|
||||||
const $ = _c(5);
|
const $ = _c(7);
|
||||||
let y;
|
|
||||||
if ($[0] !== arr1 || $[1] !== arr2) {
|
|
||||||
const x = [arr1];
|
|
||||||
|
|
||||||
(y = x.concat(arr2)), y;
|
|
||||||
$[0] = arr1;
|
|
||||||
$[1] = arr2;
|
|
||||||
$[2] = y;
|
|
||||||
} else {
|
|
||||||
y = $[2];
|
|
||||||
}
|
|
||||||
let t0;
|
let t0;
|
||||||
let t1;
|
if ($[0] !== arr1) {
|
||||||
if ($[3] !== y) {
|
t0 = [arr1];
|
||||||
t1 = { y };
|
$[0] = arr1;
|
||||||
$[3] = y;
|
$[1] = t0;
|
||||||
$[4] = t1;
|
|
||||||
} else {
|
} else {
|
||||||
t1 = $[4];
|
t0 = $[1];
|
||||||
}
|
}
|
||||||
t0 = t1;
|
const x = t0;
|
||||||
return t0;
|
let y;
|
||||||
|
if ($[2] !== arr2 || $[3] !== x) {
|
||||||
|
(y = x.concat(arr2)), y;
|
||||||
|
$[2] = arr2;
|
||||||
|
$[3] = x;
|
||||||
|
$[4] = y;
|
||||||
|
} else {
|
||||||
|
y = $[4];
|
||||||
|
}
|
||||||
|
let t1;
|
||||||
|
let t2;
|
||||||
|
if ($[5] !== y) {
|
||||||
|
t2 = { y };
|
||||||
|
$[5] = y;
|
||||||
|
$[6] = t2;
|
||||||
|
} else {
|
||||||
|
t2 = $[6];
|
||||||
|
}
|
||||||
|
t1 = t2;
|
||||||
|
return t1;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FIXTURE_ENTRYPOINT = {
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @enableNewMutationAliasingModel
|
||||||
import {useMemo} from 'react';
|
import {useMemo} from 'react';
|
||||||
|
|
||||||
function useFoo(arr1, arr2) {
|
function useFoo(arr1, arr2) {
|
||||||
|
|||||||
@@ -27,34 +27,18 @@ import { c as _c } from "react/compiler-runtime";
|
|||||||
import { identity, mutate } from "shared-runtime";
|
import { identity, mutate } from "shared-runtime";
|
||||||
|
|
||||||
function Component(props) {
|
function Component(props) {
|
||||||
const $ = _c(5);
|
const $ = _c(2);
|
||||||
let t0;
|
let context;
|
||||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
if ($[0] !== props.value) {
|
||||||
t0 = {};
|
const key = {};
|
||||||
$[0] = t0;
|
context = { [key]: identity([props.value]) };
|
||||||
} else {
|
|
||||||
t0 = $[0];
|
|
||||||
}
|
|
||||||
const key = t0;
|
|
||||||
let t1;
|
|
||||||
if ($[1] !== props.value) {
|
|
||||||
t1 = identity([props.value]);
|
|
||||||
$[1] = props.value;
|
|
||||||
$[2] = t1;
|
|
||||||
} else {
|
|
||||||
t1 = $[2];
|
|
||||||
}
|
|
||||||
let t2;
|
|
||||||
if ($[3] !== t1) {
|
|
||||||
t2 = { [key]: t1 };
|
|
||||||
$[3] = t1;
|
|
||||||
$[4] = t2;
|
|
||||||
} else {
|
|
||||||
t2 = $[4];
|
|
||||||
}
|
|
||||||
const context = t2;
|
|
||||||
|
|
||||||
mutate(key);
|
mutate(key);
|
||||||
|
$[0] = props.value;
|
||||||
|
$[1] = context;
|
||||||
|
} else {
|
||||||
|
context = $[1];
|
||||||
|
}
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,11 +27,22 @@ import { c as _c } from "react/compiler-runtime";
|
|||||||
import { identity, mutate, mutateAndReturn } from "shared-runtime";
|
import { identity, mutate, mutateAndReturn } from "shared-runtime";
|
||||||
|
|
||||||
function Component(props) {
|
function Component(props) {
|
||||||
const $ = _c(2);
|
const $ = _c(4);
|
||||||
let context;
|
let context;
|
||||||
if ($[0] !== props.value) {
|
if ($[0] !== props.value) {
|
||||||
const key = { a: "key" };
|
const key = { a: "key" };
|
||||||
context = { [key.a]: identity([props.value]) };
|
|
||||||
|
const t0 = key.a;
|
||||||
|
const t1 = identity([props.value]);
|
||||||
|
let t2;
|
||||||
|
if ($[2] !== t1) {
|
||||||
|
t2 = { [t0]: t1 };
|
||||||
|
$[2] = t1;
|
||||||
|
$[3] = t2;
|
||||||
|
} else {
|
||||||
|
t2 = $[3];
|
||||||
|
}
|
||||||
|
context = t2;
|
||||||
|
|
||||||
mutate(key);
|
mutate(key);
|
||||||
$[0] = props.value;
|
$[0] = props.value;
|
||||||
|
|||||||
@@ -40,39 +40,46 @@ import { useCallback } from "react";
|
|||||||
import { Stringify } from "shared-runtime";
|
import { Stringify } from "shared-runtime";
|
||||||
|
|
||||||
function Foo(t0) {
|
function Foo(t0) {
|
||||||
const $ = _c(8);
|
const $ = _c(10);
|
||||||
const { arr1, arr2, foo } = t0;
|
const { arr1, arr2, foo } = t0;
|
||||||
let getVal1;
|
|
||||||
let t1;
|
let t1;
|
||||||
if ($[0] !== arr1 || $[1] !== arr2 || $[2] !== foo) {
|
if ($[0] !== arr1) {
|
||||||
const x = [arr1];
|
t1 = [arr1];
|
||||||
|
$[0] = arr1;
|
||||||
|
$[1] = t1;
|
||||||
|
} else {
|
||||||
|
t1 = $[1];
|
||||||
|
}
|
||||||
|
const x = t1;
|
||||||
|
let getVal1;
|
||||||
|
let t2;
|
||||||
|
if ($[2] !== arr2 || $[3] !== foo || $[4] !== x) {
|
||||||
let y = [];
|
let y = [];
|
||||||
|
|
||||||
getVal1 = _temp;
|
getVal1 = _temp;
|
||||||
|
|
||||||
t1 = () => [y];
|
t2 = () => [y];
|
||||||
foo ? (y = x.concat(arr2)) : y;
|
foo ? (y = x.concat(arr2)) : y;
|
||||||
$[0] = arr1;
|
$[2] = arr2;
|
||||||
$[1] = arr2;
|
$[3] = foo;
|
||||||
$[2] = foo;
|
$[4] = x;
|
||||||
$[3] = getVal1;
|
|
||||||
$[4] = t1;
|
|
||||||
} else {
|
|
||||||
getVal1 = $[3];
|
|
||||||
t1 = $[4];
|
|
||||||
}
|
|
||||||
const getVal2 = t1;
|
|
||||||
let t2;
|
|
||||||
if ($[5] !== getVal1 || $[6] !== getVal2) {
|
|
||||||
t2 = <Stringify val1={getVal1} val2={getVal2} shouldInvokeFns={true} />;
|
|
||||||
$[5] = getVal1;
|
$[5] = getVal1;
|
||||||
$[6] = getVal2;
|
$[6] = t2;
|
||||||
$[7] = t2;
|
|
||||||
} else {
|
} else {
|
||||||
t2 = $[7];
|
getVal1 = $[5];
|
||||||
|
t2 = $[6];
|
||||||
}
|
}
|
||||||
return t2;
|
const getVal2 = t2;
|
||||||
|
let t3;
|
||||||
|
if ($[7] !== getVal1 || $[8] !== getVal2) {
|
||||||
|
t3 = <Stringify val1={getVal1} val2={getVal2} shouldInvokeFns={true} />;
|
||||||
|
$[7] = getVal1;
|
||||||
|
$[8] = getVal2;
|
||||||
|
$[9] = t3;
|
||||||
|
} else {
|
||||||
|
t3 = $[9];
|
||||||
|
}
|
||||||
|
return t3;
|
||||||
}
|
}
|
||||||
function _temp() {
|
function _temp() {
|
||||||
return { x: 2 };
|
return { x: 2 };
|
||||||
|
|||||||
@@ -36,31 +36,38 @@ import { Stringify } from "shared-runtime";
|
|||||||
|
|
||||||
// We currently produce invalid output (incorrect scoping for `y` declaration)
|
// We currently produce invalid output (incorrect scoping for `y` declaration)
|
||||||
function useFoo(arr1, arr2) {
|
function useFoo(arr1, arr2) {
|
||||||
const $ = _c(5);
|
const $ = _c(7);
|
||||||
let t0;
|
let t0;
|
||||||
if ($[0] !== arr1 || $[1] !== arr2) {
|
if ($[0] !== arr1) {
|
||||||
const x = [arr1];
|
t0 = [arr1];
|
||||||
|
$[0] = arr1;
|
||||||
|
$[1] = t0;
|
||||||
|
} else {
|
||||||
|
t0 = $[1];
|
||||||
|
}
|
||||||
|
const x = t0;
|
||||||
|
let t1;
|
||||||
|
if ($[2] !== arr2 || $[3] !== x) {
|
||||||
let y;
|
let y;
|
||||||
t0 = () => ({ y });
|
t1 = () => ({ y });
|
||||||
|
|
||||||
(y = x.concat(arr2)), y;
|
(y = x.concat(arr2)), y;
|
||||||
$[0] = arr1;
|
$[2] = arr2;
|
||||||
$[1] = arr2;
|
$[3] = x;
|
||||||
$[2] = t0;
|
|
||||||
} else {
|
|
||||||
t0 = $[2];
|
|
||||||
}
|
|
||||||
const getVal = t0;
|
|
||||||
let t1;
|
|
||||||
if ($[3] !== getVal) {
|
|
||||||
t1 = <Stringify getVal={getVal} shouldInvokeFns={true} />;
|
|
||||||
$[3] = getVal;
|
|
||||||
$[4] = t1;
|
$[4] = t1;
|
||||||
} else {
|
} else {
|
||||||
t1 = $[4];
|
t1 = $[4];
|
||||||
}
|
}
|
||||||
return t1;
|
const getVal = t1;
|
||||||
|
let t2;
|
||||||
|
if ($[5] !== getVal) {
|
||||||
|
t2 = <Stringify getVal={getVal} shouldInvokeFns={true} />;
|
||||||
|
$[5] = getVal;
|
||||||
|
$[6] = t2;
|
||||||
|
} else {
|
||||||
|
t2 = $[6];
|
||||||
|
}
|
||||||
|
return t2;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FIXTURE_ENTRYPOINT = {
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
|||||||
@@ -30,29 +30,36 @@ import { c as _c } from "react/compiler-runtime";
|
|||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
|
|
||||||
function useFoo(arr1, arr2) {
|
function useFoo(arr1, arr2) {
|
||||||
const $ = _c(5);
|
const $ = _c(7);
|
||||||
let y;
|
|
||||||
if ($[0] !== arr1 || $[1] !== arr2) {
|
|
||||||
const x = [arr1];
|
|
||||||
|
|
||||||
(y = x.concat(arr2)), y;
|
|
||||||
$[0] = arr1;
|
|
||||||
$[1] = arr2;
|
|
||||||
$[2] = y;
|
|
||||||
} else {
|
|
||||||
y = $[2];
|
|
||||||
}
|
|
||||||
let t0;
|
let t0;
|
||||||
let t1;
|
if ($[0] !== arr1) {
|
||||||
if ($[3] !== y) {
|
t0 = [arr1];
|
||||||
t1 = { y };
|
$[0] = arr1;
|
||||||
$[3] = y;
|
$[1] = t0;
|
||||||
$[4] = t1;
|
|
||||||
} else {
|
} else {
|
||||||
t1 = $[4];
|
t0 = $[1];
|
||||||
}
|
}
|
||||||
t0 = t1;
|
const x = t0;
|
||||||
return t0;
|
let y;
|
||||||
|
if ($[2] !== arr2 || $[3] !== x) {
|
||||||
|
(y = x.concat(arr2)), y;
|
||||||
|
$[2] = arr2;
|
||||||
|
$[3] = x;
|
||||||
|
$[4] = y;
|
||||||
|
} else {
|
||||||
|
y = $[4];
|
||||||
|
}
|
||||||
|
let t1;
|
||||||
|
let t2;
|
||||||
|
if ($[5] !== y) {
|
||||||
|
t2 = { y };
|
||||||
|
$[5] = y;
|
||||||
|
$[6] = t2;
|
||||||
|
} else {
|
||||||
|
t2 = $[6];
|
||||||
|
}
|
||||||
|
t1 = t2;
|
||||||
|
return t1;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FIXTURE_ENTRYPOINT = {
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
|||||||
Reference in New Issue
Block a user