mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
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:
+79
@@ -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 },
|
||||
],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
+28
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user