diff --git a/compiler/packages/babel-plugin-react-forget/src/Inference/InferMutableLifetimes.ts b/compiler/packages/babel-plugin-react-forget/src/Inference/InferMutableLifetimes.ts
index 2794d02e65..e1c4d3a762 100644
--- a/compiler/packages/babel-plugin-react-forget/src/Inference/InferMutableLifetimes.ts
+++ b/compiler/packages/babel-plugin-react-forget/src/Inference/InferMutableLifetimes.ts
@@ -5,7 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/
-import { CompilerError } from "../CompilerError";
import {
Effect,
HIRFunction,
@@ -102,22 +101,30 @@ export function inferMutableLifetimes(
): void {
for (const [_, block] of func.body.blocks) {
for (const phi of block.phis) {
- let start = Number.MAX_SAFE_INTEGER;
- let end = phi.id.mutableRange.end as number;
for (const [_, operand] of phi.operands) {
- start = Math.min(start, operand.mutableRange.start);
- end = Math.max(end, operand.mutableRange.end);
+ if (
+ operand.mutableRange.start === 0 &&
+ operand.mutableRange.end === 0
+ ) {
+ // operand's range is uninitialized, skip
+ continue;
+ } else if (
+ phi.id.mutableRange.start === 0 &&
+ phi.id.mutableRange.end === 0
+ ) {
+ // phi's range is uninitialized, take the range from the operand
+ phi.id.mutableRange.start = operand.mutableRange.start;
+ phi.id.mutableRange.end = operand.mutableRange.end;
+ } else {
+ // else join the phi and operand's range
+ phi.id.mutableRange.start = makeInstructionId(
+ Math.min(phi.id.mutableRange.start, operand.mutableRange.start)
+ );
+ phi.id.mutableRange.end = makeInstructionId(
+ Math.max(phi.id.mutableRange.end, operand.mutableRange.end)
+ );
+ }
}
- CompilerError.invariant(start !== Number.MAX_SAFE_INTEGER, {
- reason: "Expected phi to have a start range value",
- description: null,
- loc: null,
- suggestions: null,
- });
- phi.id.mutableRange = {
- start: makeInstructionId(start),
- end: makeInstructionId(end),
- };
}
for (const instr of block.instructions) {
diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/bug-repro-missing-dependency-if-within-while.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/bug-repro-missing-dependency-if-within-while.expect.md
index cacf7df91a..a1f5de135f 100644
--- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/bug-repro-missing-dependency-if-within-while.expect.md
+++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/bug-repro-missing-dependency-if-within-while.expect.md
@@ -39,11 +39,11 @@ export const FIXTURE_ENTRYPOINT = {
import { unstable_useMemoCache as useMemoCache } from "react";
const someGlobal = true;
export default function Component(props) {
- const $ = useMemoCache(1);
+ const $ = useMemoCache(4);
const { b } = props;
- let t0;
- if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
- const items = [];
+ let items;
+ if ($[0] !== b) {
+ items = [];
let i = 0;
while (i < 10) {
if (someGlobal) {
@@ -51,11 +51,18 @@ export default function Component(props) {
i++;
}
}
-
- t0 = <>{items}>;
- $[0] = t0;
+ $[0] = b;
+ $[1] = items;
} else {
- t0 = $[0];
+ items = $[1];
+ }
+ let t0;
+ if ($[2] !== items) {
+ t0 = <>{items}>;
+ $[2] = items;
+ $[3] = t0;
+ } else {
+ t0 = $[3];
}
return t0;
}
@@ -76,4 +83,13 @@ export const FIXTURE_ENTRYPOINT = {
};
```
-
\ No newline at end of file
+
+### Eval output
+(kind: ok)
0
0
0
0
0
0
0
0
0
0
+0
0
0
0
0
0
0
0
0
0
+42
42
42
42
42
42
42
42
42
42
+42
42
42
42
42
42
42
42
42
42
+0
0
0
0
0
0
0
0
0
0
+42
42
42
42
42
42
42
42
42
42
+0
0
0
0
0
0
0
0
0
0
+42
42
42
42
42
42
42
42
42
42
\ No newline at end of file
diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/for-in-statement-continue.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/for-in-statement-continue.expect.md
index 268555f8b0..213d414350 100644
--- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/for-in-statement-continue.expect.md
+++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/for-in-statement-continue.expect.md
@@ -16,7 +16,17 @@ function Component(props) {
export const FIXTURE_ENTRYPOINT = {
fn: Component,
- params: [{ value: { a: "a", continue: "skip", b: "b!" } }],
+ params: [{ value: { a: "a", continue: "skip", b: "hello!" } }],
+ sequentialRenders: [
+ { value: { a: "a", continue: "skip", b: "hello!" } },
+ { value: { a: "a", continue: "skip", b: "hello!" } },
+ { value: { a: "skip!", continue: true } },
+ { value: { a: "a", continue: "skip", b: "hello!" } },
+ { value: { a: "skip!", continue: true } },
+ { value: { a: "a", continue: "skip", b: "hello!" } },
+ { value: { a: "skip!", continue: true } },
+ { value: { a: "skip!", continue: true } },
+ ],
};
```
@@ -26,18 +36,10 @@ export const FIXTURE_ENTRYPOINT = {
```javascript
import { unstable_useMemoCache as useMemoCache } from "react";
function Component(props) {
- const $ = useMemoCache(3);
+ const $ = useMemoCache(2);
let x;
- if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
- let t0;
- if ($[1] !== props.value) {
- t0 = { ...props.value };
- $[1] = props.value;
- $[2] = t0;
- } else {
- t0 = $[2];
- }
- const object = t0;
+ if ($[0] !== props.value) {
+ const object = { ...props.value };
for (const y in object) {
if (y === "continue") {
continue;
@@ -45,19 +47,37 @@ function Component(props) {
x = object[y];
}
- $[0] = x;
+ $[0] = props.value;
+ $[1] = x;
} else {
- x = $[0];
+ x = $[1];
}
return x;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
- params: [{ value: { a: "a", continue: "skip", b: "b!" } }],
+ params: [{ value: { a: "a", continue: "skip", b: "hello!" } }],
+ sequentialRenders: [
+ { value: { a: "a", continue: "skip", b: "hello!" } },
+ { value: { a: "a", continue: "skip", b: "hello!" } },
+ { value: { a: "skip!", continue: true } },
+ { value: { a: "a", continue: "skip", b: "hello!" } },
+ { value: { a: "skip!", continue: true } },
+ { value: { a: "a", continue: "skip", b: "hello!" } },
+ { value: { a: "skip!", continue: true } },
+ { value: { a: "skip!", continue: true } },
+ ],
};
```
### Eval output
-(kind: ok) "b!"
\ No newline at end of file
+(kind: ok) "hello!"
+"hello!"
+"skip!"
+"hello!"
+"skip!"
+"hello!"
+"skip!"
+"skip!"
\ No newline at end of file
diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/for-in-statement-continue.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/for-in-statement-continue.js
index 330fbfb2ba..b74f17c773 100644
--- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/for-in-statement-continue.js
+++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/for-in-statement-continue.js
@@ -12,5 +12,15 @@ function Component(props) {
export const FIXTURE_ENTRYPOINT = {
fn: Component,
- params: [{ value: { a: "a", continue: "skip", b: "b!" } }],
+ params: [{ value: { a: "a", continue: "skip", b: "hello!" } }],
+ sequentialRenders: [
+ { value: { a: "a", continue: "skip", b: "hello!" } },
+ { value: { a: "a", continue: "skip", b: "hello!" } },
+ { value: { a: "skip!", continue: true } },
+ { value: { a: "a", continue: "skip", b: "hello!" } },
+ { value: { a: "skip!", continue: true } },
+ { value: { a: "a", continue: "skip", b: "hello!" } },
+ { value: { a: "skip!", continue: true } },
+ { value: { a: "skip!", continue: true } },
+ ],
};
diff --git a/compiler/packages/snap/src/SproutTodoFilter.ts b/compiler/packages/snap/src/SproutTodoFilter.ts
index cbc2edd572..fef339c363 100644
--- a/compiler/packages/snap/src/SproutTodoFilter.ts
+++ b/compiler/packages/snap/src/SproutTodoFilter.ts
@@ -534,7 +534,6 @@ 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",