Skip to content

[compiler] Repro for imprecise memo due to closure capturing changes #33180

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
bfff07b
[compiler] Repro for imprecise memo due to closure capturing changes
josephsavona May 12, 2025
b0b09a7
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona May 13, 2025
f5cd556
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona May 22, 2025
c26195e
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona May 23, 2025
fc0f220
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona May 27, 2025
8c9a80b
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona May 27, 2025
980e9a8
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona May 28, 2025
8b7b36c
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona May 28, 2025
c2927f5
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona May 29, 2025
4386170
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona May 29, 2025
9dd5492
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona May 30, 2025
2bb42a3
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona May 30, 2025
bdcad8b
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona May 30, 2025
3b04069
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona May 30, 2025
01fc1f5
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona Jun 2, 2025
38c2e4c
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona Jun 3, 2025
546d61f
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona Jun 3, 2025
38d9253
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona Jun 3, 2025
ac6e029
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona Jun 4, 2025
1d6202a
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona Jun 5, 2025
7e01403
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona Jun 5, 2025
5df62a2
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona Jun 5, 2025
8f9226e
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona Jun 6, 2025
2771221
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona Jun 6, 2025
9f3327d
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona Jun 6, 2025
87cce08
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona Jun 6, 2025
7458959
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona Jun 7, 2025
726dd8b
Update on "[compiler] Repro for imprecise memo due to closure capturi…
josephsavona Jun 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@

## Input

```javascript
import {ValidateMemoization} from 'shared-runtime';

const Codes = {
en: {name: 'English'},
ja: {name: 'Japanese'},
ko: {name: 'Korean'},
zh: {name: 'Chinese'},
};

function Component(a) {
let keys;
if (a) {
keys = Object.keys(Codes);
} else {
return null;
}
const options = keys.map(code => {
const country = Codes[code];
return {
name: country.name,
code,
};
});
return (
<>
<ValidateMemoization inputs={[]} output={keys} onlyCheckCompiled={true} />
<ValidateMemoization
inputs={[]}
output={options}
onlyCheckCompiled={true}
/>
</>
);
}

export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{a: false}],
sequentialRenders: [
{a: false},
{a: true},
{a: true},
{a: false},
{a: true},
{a: false},
],
};

```

## Code

```javascript
import { c as _c } from "react/compiler-runtime";
import { ValidateMemoization } from "shared-runtime";

const Codes = {
en: { name: "English" },
ja: { name: "Japanese" },
ko: { name: "Korean" },
zh: { name: "Chinese" },
};

function Component(a) {
const $ = _c(13);
let keys;
let t0;
let t1;
if ($[0] !== a) {
t1 = Symbol.for("react.early_return_sentinel");
bb0: {
if (a) {
keys = Object.keys(Codes);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

W the changes in this stack, we aren't able to independently memoize this call separately from the keys.map() call below. We infer the callback as mutating its parameter and therefore the callback doesn't meet the "non mutating params" criteria to get independently memoized.

} else {
t1 = null;
break bb0;
}

t0 = keys.map(_temp);
}
$[0] = a;
$[1] = t0;
$[2] = t1;
$[3] = keys;
} else {
t0 = $[1];
t1 = $[2];
keys = $[3];
}
if (t1 !== Symbol.for("react.early_return_sentinel")) {
return t1;
}
const options = t0;
let t2;
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
t2 = [];
$[4] = t2;
} else {
t2 = $[4];
}
let t3;
if ($[5] !== keys) {
t3 = (
<ValidateMemoization inputs={t2} output={keys} onlyCheckCompiled={true} />
);
$[5] = keys;
$[6] = t3;
} else {
t3 = $[6];
}
let t4;
if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
t4 = [];
$[7] = t4;
} else {
t4 = $[7];
}
let t5;
if ($[8] !== options) {
t5 = (
<ValidateMemoization
inputs={t4}
output={options}
onlyCheckCompiled={true}
/>
);
$[8] = options;
$[9] = t5;
} else {
t5 = $[9];
}
let t6;
if ($[10] !== t3 || $[11] !== t5) {
t6 = (
<>
{t3}
{t5}
</>
);
$[10] = t3;
$[11] = t5;
$[12] = t6;
} else {
t6 = $[12];
}
return t6;
}
function _temp(code) {
const country = Codes[code];
return { name: country.name, code };
}

export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ a: false }],
sequentialRenders: [
{ a: false },
{ a: true },
{ a: true },
{ a: false },
{ a: true },
{ a: false },
],
};

```

Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import {ValidateMemoization} from 'shared-runtime';

const Codes = {
en: {name: 'English'},
ja: {name: 'Japanese'},
ko: {name: 'Korean'},
zh: {name: 'Chinese'},
};

function Component(a) {
let keys;
if (a) {
keys = Object.keys(Codes);
} else {
return null;
}
const options = keys.map(code => {
const country = Codes[code];
return {
name: country.name,
code,
};
});
return (
<>
<ValidateMemoization inputs={[]} output={keys} onlyCheckCompiled={true} />
<ValidateMemoization
inputs={[]}
output={options}
onlyCheckCompiled={true}
/>
</>
);
}

export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{a: false}],
sequentialRenders: [
{a: false},
{a: true},
{a: true},
{a: false},
{a: true},
{a: false},
],
};
1 change: 1 addition & 0 deletions compiler/packages/snap/src/SproutTodoFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,7 @@ const skipFilter = new Set([
'todo.lower-context-access-array-destructuring',
'lower-context-selector-simple',
'lower-context-acess-multiple',
'bug-separate-memoization-due-to-callback-capturing',
]);

export default skipFilter;
Loading