Merge 53cc92d2d2 into sapling-pr-archive-mofeiZ

This commit is contained in:
mofeiZ
2025-05-21 14:51:24 -04:00
committed by GitHub
8 changed files with 258 additions and 11 deletions
@@ -0,0 +1,58 @@
## Input
```javascript
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
import {useEffect} from 'react';
import {print} from 'shared-runtime';
function Component({foo}) {
const arr = [];
// Taking either arr[0].value or arr as a dependency is reasonable
// as long as developers know what to expect.
useEffect(() => print(arr[0]?.value));
arr.push({value: foo});
return arr;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{foo: 1}],
};
```
## Code
```javascript
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
import { useEffect } from "react";
import { print } from "shared-runtime";
function Component(t0) {
const { foo } = t0;
const arr = [];
useEffect(() => print(arr[0]?.value), [arr[0]?.value]);
arr.push({ value: foo });
return arr;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ foo: 1 }],
};
```
## 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":"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}
```
### Eval output
(kind: ok) [{"value":1}]
logs: [1]
@@ -0,0 +1,17 @@
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
import {useEffect} from 'react';
import {print} from 'shared-runtime';
function Component({foo}) {
const arr = [];
// Taking either arr[0].value or arr as a dependency is reasonable
// as long as developers know what to expect.
useEffect(() => print(arr[0]?.value));
arr.push({value: foo});
return arr;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{foo: 1}],
};
@@ -2,7 +2,7 @@
## Input
```javascript
// @inferEffectDependencies @panicThreshold:"none"
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
import {useEffect, useRef} from 'react';
import {print} from 'shared-runtime';
@@ -14,12 +14,17 @@ function Component({arrRef}) {
return arrRef;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{arrRef: {current: {val: 'initial ref value'}}}],
};
```
## Code
```javascript
// @inferEffectDependencies @panicThreshold:"none"
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
import { useEffect, useRef } from "react";
import { print } from "shared-runtime";
@@ -32,7 +37,21 @@ function Component(t0) {
return arrRef;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ arrRef: { current: { val: "initial ref value" } } }],
};
```
## 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":"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}
```
### Eval output
(kind: exception) Fixture not implemented
(kind: ok) {"current":{"val":2}}
logs: [{ val: 2 }]
@@ -1,4 +1,4 @@
// @inferEffectDependencies @panicThreshold:"none"
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
import {useEffect, useRef} from 'react';
import {print} from 'shared-runtime';
@@ -9,3 +9,8 @@ function Component({arrRef}) {
arrRef.current.val = 2;
return arrRef;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{arrRef: {current: {val: 'initial ref value'}}}],
};
@@ -2,33 +2,55 @@
## Input
```javascript
// @inferEffectDependencies @panicThreshold:"none"
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
import {useEffect} from 'react';
function Component({foo}) {
const arr = [];
useEffect(() => arr.push(foo));
useEffect(() => {
arr.push(foo);
});
arr.push(2);
return arr;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{foo: 1}],
};
```
## Code
```javascript
// @inferEffectDependencies @panicThreshold:"none"
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
import { useEffect } from "react";
function Component(t0) {
const { foo } = t0;
const arr = [];
useEffect(() => arr.push(foo), [arr, foo]);
useEffect(() => {
arr.push(foo);
}, [arr, foo]);
arr.push(2);
return arr;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ foo: 1 }],
};
```
## 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":"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}
```
### Eval output
(kind: exception) Fixture not implemented
(kind: ok) [2]
@@ -1,9 +1,16 @@
// @inferEffectDependencies @panicThreshold:"none"
// @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
import {useEffect} from 'react';
function Component({foo}) {
const arr = [];
useEffect(() => arr.push(foo));
useEffect(() => {
arr.push(foo);
});
arr.push(2);
return arr;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{foo: 1}],
};
@@ -0,0 +1,101 @@
## Input
```javascript
// @inferEffectDependencies
import {useEffect} from 'react';
import {print, shallowCopy} from 'shared-runtime';
// TODO: take optional chains as dependencies
function ReactiveMemberExpr({cond, propVal}) {
const obj = {a: cond ? {b: propVal} : null, c: null};
const other = shallowCopy({a: {b: {c: {d: {e: {f: propVal + 1}}}}}});
const primitive = shallowCopy(propVal);
useEffect(() =>
print(obj.a?.b, other?.a?.b?.c?.d?.e.f, primitive.a?.b.c?.d?.e.f)
);
}
export const FIXTURE_ENTRYPOINT = {
fn: ReactiveMemberExpr,
params: [{cond: true, propVal: 1}],
};
```
## Code
```javascript
import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
import { useEffect } from "react";
import { print, shallowCopy } from "shared-runtime";
// TODO: take optional chains as dependencies
function ReactiveMemberExpr(t0) {
const $ = _c(13);
const { cond, propVal } = t0;
let t1;
if ($[0] !== cond || $[1] !== propVal) {
t1 = cond ? { b: propVal } : null;
$[0] = cond;
$[1] = propVal;
$[2] = t1;
} else {
t1 = $[2];
}
let t2;
if ($[3] !== t1) {
t2 = { a: t1, c: null };
$[3] = t1;
$[4] = t2;
} else {
t2 = $[4];
}
const obj = t2;
const t3 = propVal + 1;
let t4;
if ($[5] !== t3) {
t4 = shallowCopy({ a: { b: { c: { d: { e: { f: t3 } } } } } });
$[5] = t3;
$[6] = t4;
} else {
t4 = $[6];
}
const other = t4;
let t5;
if ($[7] !== propVal) {
t5 = shallowCopy(propVal);
$[7] = propVal;
$[8] = t5;
} else {
t5 = $[8];
}
const primitive = t5;
let t6;
if (
$[9] !== obj.a?.b ||
$[10] !== other?.a?.b?.c?.d?.e.f ||
$[11] !== primitive.a?.b.c?.d?.e.f
) {
t6 = () =>
print(obj.a?.b, other?.a?.b?.c?.d?.e.f, primitive.a?.b.c?.d?.e.f);
$[9] = obj.a?.b;
$[10] = other?.a?.b?.c?.d?.e.f;
$[11] = primitive.a?.b.c?.d?.e.f;
$[12] = t6;
} else {
t6 = $[12];
}
useEffect(t6, [obj.a?.b, other?.a?.b?.c?.d?.e.f, primitive.a?.b.c?.d?.e.f]);
}
export const FIXTURE_ENTRYPOINT = {
fn: ReactiveMemberExpr,
params: [{ cond: true, propVal: 1 }],
};
```
### Eval output
(kind: ok)
logs: [1,2,undefined]
@@ -0,0 +1,18 @@
// @inferEffectDependencies
import {useEffect} from 'react';
import {print, shallowCopy} from 'shared-runtime';
// TODO: take optional chains as dependencies
function ReactiveMemberExpr({cond, propVal}) {
const obj = {a: cond ? {b: propVal} : null, c: null};
const other = shallowCopy({a: {b: {c: {d: {e: {f: propVal + 1}}}}}});
const primitive = shallowCopy(propVal);
useEffect(() =>
print(obj.a?.b, other?.a?.b?.c?.d?.e.f, primitive.a?.b.c?.d?.e.f)
);
}
export const FIXTURE_ENTRYPOINT = {
fn: ReactiveMemberExpr,
params: [{cond: true, propVal: 1}],
};