Repro for missing dep with while/if using externally declared "index" variable

What happens here is that the phi node for `i` has its mutable range set to 
start at 0, because it has a back edge and we haven't initialized the mutable 
ranges of all its operands yet when we iterate the operands and set range.start 
= min(start of operand starts). 

Then the corresponding scope has its range set to start at 0 too. When 
PropagateScopeDeps runs it sees that `b` is from instruction 1, which is after 
the start of the scope (0), so it thinks `b` isn't a valid dependency. 

The fix is in InferMutableRanges, where we need to make sure that phis ignore 
their operand's ranges until those ranges are initialized.
This commit is contained in:
Joe Savona
2024-03-22 21:49:39 -07:00
parent db7e7c7fae
commit 2ce112dbf2
3 changed files with 108 additions and 0 deletions
@@ -0,0 +1,79 @@
## Input
```javascript
const someGlobal = true;
export default function Component(props) {
const { b } = props;
const items = [];
let i = 0;
while (i < 10) {
if (someGlobal) {
items.push(<div key={i}>{b}</div>);
i++;
}
}
return <>{items}</>;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ b: 42 }],
sequentialRenders: [
{ b: 0 },
{ b: 0 },
{ b: 42 },
{ b: 42 },
{ b: 0 },
{ b: 42 },
{ b: 0 },
{ b: 42 },
],
};
```
## Code
```javascript
import { unstable_useMemoCache as useMemoCache } from "react";
const someGlobal = true;
export default function Component(props) {
const $ = useMemoCache(1);
const { b } = props;
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
const items = [];
let i = 0;
while (i < 10) {
if (someGlobal) {
items.push(<div key={i}>{b}</div>);
i++;
}
}
t0 = <>{items}</>;
$[0] = t0;
} else {
t0 = $[0];
}
return t0;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ b: 42 }],
sequentialRenders: [
{ b: 0 },
{ b: 0 },
{ b: 42 },
{ b: 42 },
{ b: 0 },
{ b: 42 },
{ b: 0 },
{ b: 42 },
],
};
```
@@ -0,0 +1,28 @@
const someGlobal = true;
export default function Component(props) {
const { b } = props;
const items = [];
let i = 0;
while (i < 10) {
if (someGlobal) {
items.push(<div key={i}>{b}</div>);
i++;
}
}
return <>{items}</>;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ b: 42 }],
sequentialRenders: [
{ b: 0 },
{ b: 0 },
{ b: 42 },
{ b: 42 },
{ b: 0 },
{ b: 42 },
{ b: 0 },
{ b: 42 },
],
};
@@ -534,6 +534,7 @@ const skipFilter = new Set([
// bugs
"bug-reduce-reactive-deps-return-in-scope",
"bug-reduce-reactive-deps-break-in-scope",
"bug-repro-missing-dependency-if-within-while",
// 'react-forget-runtime' not yet supported
"flag-enable-emit-hook-guards",