test(react_compiler): default validatePreserveExistingMemoizationGuarantees off, matching snap runner (#24134)

## Root cause

The `new-mutability/` fixtures (and several others across the corpus)
that set
`// @enablePreserveExistingMemoizationGuarantees:false` bailed with a
spurious

```
[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved
```

diagnostic and emitted `No changes.`, whereas the fork compiles them.

This is **not** a compiler bug — it is a test-harness config mismatch.
The
upstream `snap` runner (`packages/snap/src/compiler.ts`,
`makePluginOptions`)
runs the entire fixture corpus with
`validatePreserveExistingMemoizationGuarantees` **off**, enabling it
only when a
fixture's first line contains
`@validatePreserveExistingMemoizationGuarantees`
(it keys off substring presence, ignoring any `:value`):

```ts
let validatePreserveExistingMemoizationGuarantees = false;
if (firstLine.includes('@validatePreserveExistingMemoizationGuarantees')) {
  validatePreserveExistingMemoizationGuarantees = true;
}
```

oxc's `snapshot.rs` instead used the `EnvironmentConfig` schema default
(`true`). The `ValidatePreservedManualMemoization` pass is gated on
`enable_preserve || validate_preserve`, so with `enable_preserve:false`
but
`validate_preserve` left at its default `true`, the pass ran and fired
the error
where the fork skips validation entirely.

I confirmed with a `debugLogIRs` dump of the fork under the *real* snap
config
that oxc's `InferMutationAliasingEffects` /
`InferMutationAliasingRanges` /
reactive-scope output is byte-identical to the fork; the only divergence
was
whether the validation pass runs. (The fork also errors on these
fixtures when
`validatePreserveExistingMemoizationGuarantees` is forced on.)

## Fix

Replicate the snap runner exactly in `parse_pragma` — after the
directive loop,
unconditionally set `validate_preserve_existing_memoization_guarantees`
to
whether the first line contains the
`@validatePreserveExistingMemoizationGuarantees`
substring. This is the same class of harness alignment as #24118.

## Fixtures changed

26 snapshots, **all** moving from a spurious `PreserveManualMemo` bail
(or, for
`useMemo-named-function`, an over-eager diagnostic) to compiled code
that
matches the fork:

- 11 in `new-mutability/` (the batch): `mutate-through-identity`,
  `mutate-through-identity-function-expression`,
`todo-transitivity-createfrom-capture-lambda`,
`transitivity-capture-createfrom`,
`transitivity-capture-createfrom-lambda`,
`transitivity-add-captured-array-to-itself`,
`transitivity-phi-assign-or-capture`,
`todo-control-flow-sensitive-mutation`,
  `useCallback-reordering-deplist-controlflow`,
`useCallback-reordering-depslist-assignment`,
`useMemo-reordering-depslist-assignment`
- 15 elsewhere (`preserve-memo-validation/*`,
`useMemo-*`/`useCallback-*-dont-preserve-*`,
`repro-*`, `allow-modify-global-in-callback-jsx`,
`context-variable-as-jsx-element-tag`,
  `existing-variables-with-c-name`).

Every changed snapshot was verified to have the **same `_c(N)` cache
size and
memoization structure as the fork** (differences reduce to codegen
whitespace:
redundant parens around assignments, JSX/array line-wrapping, trailing
commas).
No snapshot regressed (none went code→error/bail).

### new-mutability batch outcome (54 fixtures)

- **35** exact structural matches with the fork.
- **6** codegen-formatting-only diffs (identical cache size /
memoization):
  `array-filter`, `array-map-named-callback-cross-context`,
`todo-control-flow-sensitive-mutation`,
`useCallback-reordering-deplist-controlflow`,
`useCallback-reordering-depslist-assignment`,
`useMemo-reordering-depslist-assignment`.
- **9** `error.*` fixtures already emit diagnostics matching the fork's
error intent
  (unaffected by this change).
- **0** fixtures where oxc errors but the fork compiles (was 11).

## Remaining work (out of scope, distinct root causes)

- `transitivity-add-captured-array-to-itself` (`_c(18)` vs `_c(19)`) and
`transitivity-phi-assign-or-capture` (`_c(9)` vs `_c(11)`) now compile
but with
coarser memoization. Root cause: the harness does not supply the
shared-runtime
`typedCapture` / `typedCreateFrom` / `typedMutate` **aliasing**
signatures that
`makeSharedRuntimeTypeProvider` gives the fork, so oxc falls back to
conservative
call effects. Fixing this needs a broader `moduleTypeProvider` addition
and its own
  corpus-wide verification.
- `ssa-renaming-ternary-destruction` emits an empty `function useFoo()
{}` — a
pre-existing SSA/phi/alias-group bug (the fixture's own comment flags
the case as
  unresolved), unrelated to memoization validation.
- `error.todo-repro-named-function-with-shadowed-local-same-name` raises
an internal
  `Invariant` instead of a clean error — a separate pre-existing issue.
This commit is contained in:
Boshen authored and GitHub committed 2026-07-04 11:00:36 +08:00
1 parent c59f2fe031
commit f693a473ce
27 files changed
+1338 -151

No files matched your search

@@ -173,6 +173,20 @@ fn parse_pragma(source: &str) -> (SourceType, PluginOptions) {
}
}
// Mirror the snap runner (`packages/snap/src/compiler.ts`): the fixture corpus runs
// with `validatePreserveExistingMemoizationGuarantees` OFF by default — most fixtures
// care about compilation output, not whether manual memoization is preserved — and it
// is turned on only when the fixture's first line opts in via the directive. Snap keys
// off substring presence alone (ignoring any `:value`), so replicate that exactly and
// let it override whatever the directive loop parsed. Without this, fixtures that set
// `@enablePreserveExistingMemoizationGuarantees:false` still hit `ValidatePreservedManual-
// Memoization` and bail with a spurious "memoization could not be preserved" error.
options.environment.validate_preserve_existing_memoization_guarantees = source
.lines()
.next()
.unwrap_or("")
.contains("@validatePreserveExistingMemoizationGuarantees");
// Upstream parses every (non-Flow) fixture with the TypeScript + JSX plugins,
// regardless of extension, and as a module unless `@script` — so injected runtime
// imports are `import`, not `require`. Flow fixtures are excluded (no oxc parser).
@@ -2,8 +2,42 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/allow-modify-global-in-callback-jsx.js
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing manual memoization"), span: SourceSpan { offset: SourceOffset(275), length: 71 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `onClick`, but the source dependencies were []. Inferred dependency not present in source"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
import { useMemo } from "react";
const someGlobal = { value: 0 };
function Component(t0) {
const $ = _c(4);
const { value } = t0;
let t1;
if ($[0] !== value) {
t1 = () => {
someGlobal.value = value;
};
$[0] = value;
$[1] = t1;
} else {
t1 = $[1];
}
const onClick = t1;
let t2;
if ($[2] !== onClick) {
t2 = <div onClick={onClick}>{someGlobal.value}</div>;
$[2] = onClick;
$[3] = t2;
} else {
t2 = $[3];
}
return t2;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ value: 0 }],
sequentialRenders: [
{ value: 1 },
{ value: 1 },
{ value: 42 },
{ value: 42 },
{ value: 0 }
]
};
@@ -2,9 +2,32 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/context-variable-as-jsx-element-tag.js
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("This dependency may be modified later"), span: SourceSpan { offset: SourceOffset(244), length: 9 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing memoization"), span: SourceSpan { offset: SourceOffset(200), length: 55 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enablePreserveExistingMemoizationGuarantees:false
import { useMemo } from "react";
import { Stringify } from "shared-runtime";
function Component(props) {
const $ = _c(3);
let Component;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
Component = Stringify;
Component;
Component = Component;
$[0] = Component;
} else {
Component = $[0];
}
let t0;
if ($[1] !== props) {
t0 = <Component {...props} />;
$[1] = props;
$[2] = t0;
} else {
t0 = $[2];
}
return t0;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ name: "Sathya" }]
};
@@ -2,8 +2,52 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/existing-variables-with-c-name.js
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing manual memoization"), span: SourceSpan { offset: SourceOffset(408), length: 10 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `$c`, but the source dependencies were [state]. Inferred different dependency than source"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c2 } from "react/compiler-runtime";
// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
import { useMemo, useState } from "react";
import { ValidateMemoization } from "shared-runtime";
function Component(props) {
const $ = _c2(7);
const [state] = useState(0);
const c = state;
const _c = c;
const __c = _c;
const c1 = __c;
const $c = c1;
let t0;
if ($[0] !== $c) {
t0 = [$c];
$[0] = $c;
$[1] = t0;
} else {
t0 = $[1];
}
const array = t0;
let t1;
if ($[2] !== state) {
t1 = [state];
$[2] = state;
$[3] = t1;
} else {
t1 = $[3];
}
let t2;
if ($[4] !== array || $[5] !== t1) {
t2 = <ValidateMemoization inputs={t1} output={array} />;
$[4] = array;
$[5] = t1;
$[6] = t2;
} else {
t2 = $[6];
}
return t2;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{}],
sequentialRenders: [
{},
{},
{}
]
};
@@ -2,8 +2,67 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/new-mutability/mutate-through-identity-function-expression.js
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing memoization"), span: SourceSpan { offset: SourceOffset(238), length: 28 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
import { useMemo } from "react";
import { identity, ValidateMemoization } from "shared-runtime";
function Component(t0) {
const $ = _c(9);
const { a, b } = t0;
let x;
if ($[0] !== a || $[1] !== b) {
x = { a };
const f = () => identity(x);
const x2 = f();
x2.b = b;
$[0] = a;
$[1] = b;
$[2] = x;
} else {
x = $[2];
}
let t1;
if ($[3] !== a || $[4] !== b) {
t1 = [a, b];
$[3] = a;
$[4] = b;
$[5] = t1;
} else {
t1 = $[5];
}
let t2;
if ($[6] !== t1 || $[7] !== x) {
t2 = <ValidateMemoization inputs={t1} output={x} />;
$[6] = t1;
$[7] = x;
$[8] = t2;
} else {
t2 = $[8];
}
return t2;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{
a: 0,
b: 0
}],
sequentialRenders: [
{
a: 0,
b: 0
},
{
a: 0,
b: 1
},
{
a: 1,
b: 1
},
{
a: 0,
b: 0
}
]
};
@@ -2,8 +2,66 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/new-mutability/mutate-through-identity.js
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing memoization"), span: SourceSpan { offset: SourceOffset(238), length: 28 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
import { useMemo } from "react";
import { identity, ValidateMemoization } from "shared-runtime";
function Component(t0) {
const $ = _c(9);
const { a, b } = t0;
let x;
if ($[0] !== a || $[1] !== b) {
x = { a };
const x2 = identity(x);
x2.b = b;
$[0] = a;
$[1] = b;
$[2] = x;
} else {
x = $[2];
}
let t1;
if ($[3] !== a || $[4] !== b) {
t1 = [a, b];
$[3] = a;
$[4] = b;
$[5] = t1;
} else {
t1 = $[5];
}
let t2;
if ($[6] !== t1 || $[7] !== x) {
t2 = <ValidateMemoization inputs={t1} output={x} />;
$[6] = t1;
$[7] = x;
$[8] = t2;
} else {
t2 = $[8];
}
return t2;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{
a: 0,
b: 0
}],
sequentialRenders: [
{
a: 0,
b: 0
},
{
a: 0,
b: 1
},
{
a: 1,
b: 1
},
{
a: 0,
b: 0
}
]
};
@@ -2,8 +2,127 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/new-mutability/todo-control-flow-sensitive-mutation.tsx
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing memoization"), span: SourceSpan { offset: SourceOffset(331), length: 38 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
import { useMemo } from "react";
import { mutate, typedCapture, typedCreateFrom, typedMutate, ValidateMemoization } from "shared-runtime";
function Component(t0) {
const $ = _c(21);
const { a, b, c } = t0;
let x;
if ($[0] !== a || $[1] !== b || $[2] !== c) {
x = [{ value: a }];
if (b === 0) {
x.push({ value: c });
} else {
mutate(x);
}
$[0] = a;
$[1] = b;
$[2] = c;
$[3] = x;
} else {
x = $[3];
}
let t1;
if ($[4] !== a || $[5] !== b || $[6] !== c) {
t1 = [
a,
b,
c
];
$[4] = a;
$[5] = b;
$[6] = c;
$[7] = t1;
} else {
t1 = $[7];
}
let t2;
if ($[8] !== t1 || $[9] !== x) {
t2 = <ValidateMemoization inputs={t1} output={x} />;
$[8] = t1;
$[9] = x;
$[10] = t2;
} else {
t2 = $[10];
}
let t3;
if ($[11] !== a || $[12] !== b || $[13] !== c) {
t3 = [
a,
b,
c
];
$[11] = a;
$[12] = b;
$[13] = c;
$[14] = t3;
} else {
t3 = $[14];
}
let t4;
if ($[15] !== t3 || $[16] !== x[0]) {
t4 = <ValidateMemoization inputs={t3} output={x[0]} />;
$[15] = t3;
$[16] = x[0];
$[17] = t4;
} else {
t4 = $[17];
}
let t5;
if ($[18] !== t2 || $[19] !== t4) {
t5 = <>{t2};{t4};</>;
$[18] = t2;
$[19] = t4;
$[20] = t5;
} else {
t5 = $[20];
}
return t5;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{
a: 0,
b: 0,
c: 0
}],
sequentialRenders: [
{
a: 0,
b: 0,
c: 0
},
{
a: 0,
b: 1,
c: 0
},
{
a: 1,
b: 1,
c: 0
},
{
a: 1,
b: 1,
c: 1
},
{
a: 1,
b: 1,
c: 0
},
{
a: 1,
b: 0,
c: 0
},
{
a: 0,
b: 0,
c: 0
}
]
};
@@ -2,8 +2,71 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/new-mutability/todo-transitivity-createfrom-capture-lambda.tsx
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing memoization"), span: SourceSpan { offset: SourceOffset(234), length: 25 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enablePreserveExistingMemoizationGuarantees:false
import { useMemo } from "react";
import { typedCapture, typedCreateFrom, typedMutate, ValidateMemoization } from "shared-runtime";
function Component(t0) {
const $ = _c(9);
const { a, b } = t0;
let x;
if ($[0] !== a || $[1] !== b) {
x = [{ a }];
const f = () => {
const y = typedCreateFrom(x);
const z = typedCapture(y);
return z;
};
const z_0 = f();
typedMutate(z_0, b);
$[0] = a;
$[1] = b;
$[2] = x;
} else {
x = $[2];
}
let t1;
if ($[3] !== a || $[4] !== b) {
t1 = [a, b];
$[3] = a;
$[4] = b;
$[5] = t1;
} else {
t1 = $[5];
}
let t2;
if ($[6] !== t1 || $[7] !== x) {
t2 = <ValidateMemoization inputs={t1} output={x} />;
$[6] = t1;
$[7] = x;
$[8] = t2;
} else {
t2 = $[8];
}
return t2;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{
a: 0,
b: 0
}],
sequentialRenders: [
{
a: 0,
b: 0
},
{
a: 0,
b: 1
},
{
a: 1,
b: 1
},
{
a: 0,
b: 0
}
]
};
@@ -2,10 +2,98 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/new-mutability/transitivity-add-captured-array-to-itself.tsx
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing memoization"), span: SourceSpan { offset: SourceOffset(288), length: 25 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("This dependency may be modified later"), span: SourceSpan { offset: SourceOffset(359), length: 1 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing memoization"), span: SourceSpan { offset: SourceOffset(339), length: 26 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
import { useMemo } from "react";
import { typedCapture, typedCreateFrom, typedMutate, ValidateMemoization } from "shared-runtime";
function Component(t0) {
const $ = _c(18);
const { a, b } = t0;
let o;
let x;
if ($[0] !== a || $[1] !== b) {
o = { a };
x = [o];
const y = typedCapture(x);
const z = typedCapture(y);
x.push(z);
x.push(b);
$[0] = a;
$[1] = b;
$[2] = o;
$[3] = x;
} else {
o = $[2];
x = $[3];
}
let t1;
if ($[4] !== a) {
t1 = [a];
$[4] = a;
$[5] = t1;
} else {
t1 = $[5];
}
let t2;
if ($[6] !== o || $[7] !== t1) {
t2 = <ValidateMemoization inputs={t1} output={o} />;
$[6] = o;
$[7] = t1;
$[8] = t2;
} else {
t2 = $[8];
}
let t3;
if ($[9] !== a || $[10] !== b) {
t3 = [a, b];
$[9] = a;
$[10] = b;
$[11] = t3;
} else {
t3 = $[11];
}
let t4;
if ($[12] !== t3 || $[13] !== x) {
t4 = <ValidateMemoization inputs={t3} output={x} />;
$[12] = t3;
$[13] = x;
$[14] = t4;
} else {
t4 = $[14];
}
let t5;
if ($[15] !== t2 || $[16] !== t4) {
t5 = <>{t2};{t4};</>;
$[15] = t2;
$[16] = t4;
$[17] = t5;
} else {
t5 = $[17];
}
return t5;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{
a: 0,
b: 0
}],
sequentialRenders: [
{
a: 0,
b: 0
},
{
a: 0,
b: 1
},
{
a: 1,
b: 1
},
{
a: 0,
b: 0
}
]
};
@@ -2,8 +2,71 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/new-mutability/transitivity-capture-createfrom-lambda.tsx
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing memoization"), span: SourceSpan { offset: SourceOffset(307), length: 28 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
import { useMemo } from "react";
import { typedCapture, typedCreateFrom, typedMutate, ValidateMemoization } from "shared-runtime";
function Component(t0) {
const $ = _c(9);
const { a, b } = t0;
let x;
if ($[0] !== a || $[1] !== b) {
x = { a };
const f = () => {
const y = typedCapture(x);
const z = typedCreateFrom(y);
return z;
};
const z_0 = f();
typedMutate(z_0, b);
$[0] = a;
$[1] = b;
$[2] = x;
} else {
x = $[2];
}
let t1;
if ($[3] !== a || $[4] !== b) {
t1 = [a, b];
$[3] = a;
$[4] = b;
$[5] = t1;
} else {
t1 = $[5];
}
let t2;
if ($[6] !== t1 || $[7] !== x) {
t2 = <ValidateMemoization inputs={t1} output={x} />;
$[6] = t1;
$[7] = x;
$[8] = t2;
} else {
t2 = $[8];
}
return t2;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{
a: 0,
b: 0
}],
sequentialRenders: [
{
a: 0,
b: 0
},
{
a: 0,
b: 1
},
{
a: 1,
b: 1
},
{
a: 0,
b: 0
}
]
};
@@ -2,8 +2,67 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/new-mutability/transitivity-capture-createfrom.tsx
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing memoization"), span: SourceSpan { offset: SourceOffset(307), length: 28 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
import { useMemo } from "react";
import { typedCapture, typedCreateFrom, typedMutate, ValidateMemoization } from "shared-runtime";
function Component(t0) {
const $ = _c(9);
const { a, b } = t0;
let x;
if ($[0] !== a || $[1] !== b) {
x = { a };
const y = typedCapture(x);
const z = typedCreateFrom(y);
typedMutate(z, b);
$[0] = a;
$[1] = b;
$[2] = x;
} else {
x = $[2];
}
let t1;
if ($[3] !== a || $[4] !== b) {
t1 = [a, b];
$[3] = a;
$[4] = b;
$[5] = t1;
} else {
t1 = $[5];
}
let t2;
if ($[6] !== t1 || $[7] !== x) {
t2 = <ValidateMemoization inputs={t1} output={x} />;
$[6] = t1;
$[7] = x;
$[8] = t2;
} else {
t2 = $[8];
}
return t2;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{
a: 0,
b: 0
}],
sequentialRenders: [
{
a: 0,
b: 0
},
{
a: 0,
b: 1
},
{
a: 1,
b: 1
},
{
a: 0,
b: 0
}
]
};
@@ -2,8 +2,71 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/new-mutability/transitivity-phi-assign-or-capture.tsx
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing memoization"), span: SourceSpan { offset: SourceOffset(283), length: 28 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
import { useMemo } from "react";
import { typedCapture, typedCreateFrom, typedMutate, ValidateMemoization } from "shared-runtime";
function Component(t0) {
const $ = _c(9);
const { a, b } = t0;
let x;
if ($[0] !== a || $[1] !== b) {
x = [{ a }];
let z;
if (b) {
z = x;
} else {
z = typedCapture(x);
}
typedMutate(z, b);
$[0] = a;
$[1] = b;
$[2] = x;
} else {
x = $[2];
}
let t1;
if ($[3] !== a || $[4] !== b) {
t1 = [a, b];
$[3] = a;
$[4] = b;
$[5] = t1;
} else {
t1 = $[5];
}
let t2;
if ($[6] !== t1 || $[7] !== x) {
t2 = <ValidateMemoization inputs={t1} output={x} />;
$[6] = t1;
$[7] = x;
$[8] = t2;
} else {
t2 = $[8];
}
return t2;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{
a: 0,
b: 0
}],
sequentialRenders: [
{
a: 0,
b: 0
},
{
a: 0,
b: 1
},
{
a: 1,
b: 1
},
{
a: 0,
b: 0
}
]
};
@@ -2,11 +2,67 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/new-mutability/useCallback-reordering-deplist-controlflow.tsx
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("This dependency may be modified later"), span: SourceSpan { offset: SourceOffset(440), length: 1 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing manual memoization"), span: SourceSpan { offset: SourceOffset(381), length: 27 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `foo`, but the source dependencies were [y]. Inferred different dependency than source"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing manual memoization"), span: SourceSpan { offset: SourceOffset(381), length: 27 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `x`, but the source dependencies were [y]. Inferred different dependency than source"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing manual memoization"), span: SourceSpan { offset: SourceOffset(381), length: 27 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `arr2`, but the source dependencies were [y]. Inferred different dependency than source"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enableNewMutationAliasingModel @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
import { useCallback } from "react";
import { Stringify } from "shared-runtime";
function Foo(t0) {
const $ = _c(10);
const { arr1, arr2, foo } = t0;
let t1;
if ($[0] !== arr1) {
t1 = [arr1];
$[0] = arr1;
$[1] = t1;
} else {
t1 = $[1];
}
const x = t1;
let getVal1;
let t2;
if ($[2] !== arr2 || $[3] !== foo || $[4] !== x) {
let y = [];
getVal1 = _temp;
t2 = () => [y];
foo ? y = x.concat(arr2) : y;
$[2] = arr2;
$[3] = foo;
$[4] = x;
$[5] = getVal1;
$[6] = t2;
} else {
getVal1 = $[5];
t2 = $[6];
}
const getVal2 = t2;
let t3;
if ($[7] !== getVal1 || $[8] !== getVal2) {
t3 = <Stringify val1={getVal1} val2={getVal2} shouldInvokeFns={true} />;
$[7] = getVal1;
$[8] = getVal2;
$[9] = t3;
} else {
t3 = $[9];
}
return t3;
}
function _temp() {
return { x: 2 };
}
export const FIXTURE_ENTRYPOINT = {
fn: Foo,
params: [{
arr1: [1, 2],
arr2: [3, 4],
foo: true
}],
sequentialRenders: [{
arr1: [1, 2],
arr2: [3, 4],
foo: true
}, {
arr1: [1, 2],
arr2: [3, 4],
foo: false
}]
};
@@ -2,10 +2,45 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/new-mutability/useCallback-reordering-depslist-assignment.tsx
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("This dependency may be modified later"), span: SourceSpan { offset: SourceOffset(434), length: 1 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing manual memoization"), span: SourceSpan { offset: SourceOffset(381), length: 27 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `x`, but the source dependencies were [y]. Inferred different dependency than source"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing manual memoization"), span: SourceSpan { offset: SourceOffset(381), length: 27 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `arr2`, but the source dependencies were [y]. Inferred different dependency than source"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enableNewMutationAliasingModel @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
import { useCallback } from "react";
import { Stringify } from "shared-runtime";
// We currently produce invalid output (incorrect scoping for `y` declaration)
function useFoo(arr1, arr2) {
const $ = _c(7);
let t0;
if ($[0] !== arr1) {
t0 = [arr1];
$[0] = arr1;
$[1] = t0;
} else {
t0 = $[1];
}
const x = t0;
let t1;
if ($[2] !== arr2 || $[3] !== x) {
let y;
t1 = () => ({ y });
y = x.concat(arr2), y;
$[2] = arr2;
$[3] = x;
$[4] = t1;
} else {
t1 = $[4];
}
const getVal = t1;
let t2;
if ($[5] !== getVal) {
t2 = <Stringify getVal={getVal} shouldInvokeFns={true} />;
$[5] = getVal;
$[6] = t2;
} else {
t2 = $[6];
}
return t2;
}
export const FIXTURE_ENTRYPOINT = {
fn: useFoo,
params: [[1, 2], [3, 4]]
};
@@ -2,10 +2,40 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/new-mutability/useMemo-reordering-depslist-assignment.ts
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("This dependency may be modified later"), span: SourceSpan { offset: SourceOffset(297), length: 1 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing manual memoization"), span: SourceSpan { offset: SourceOffset(244), length: 27 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `x`, but the source dependencies were [y]. Inferred different dependency than source"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing manual memoization"), span: SourceSpan { offset: SourceOffset(244), length: 27 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `arr2`, but the source dependencies were [y]. Inferred different dependency than source"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enableNewMutationAliasingModel @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
import { useMemo } from "react";
function useFoo(arr1, arr2) {
const $ = _c(7);
let t0;
if ($[0] !== arr1) {
t0 = [arr1];
$[0] = arr1;
$[1] = t0;
} else {
t0 = $[1];
}
const x = t0;
let y;
if ($[2] !== arr2 || $[3] !== x) {
y = x.concat(arr2), y;
$[2] = arr2;
$[3] = x;
$[4] = y;
} else {
y = $[4];
}
let t1;
if ($[5] !== y) {
t1 = { y };
$[5] = y;
$[6] = t1;
} else {
t1 = $[6];
}
return t1;
}
export const FIXTURE_ENTRYPOINT = {
fn: useFoo,
params: [[1, 2], [3, 4]]
};
@@ -2,11 +2,67 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/preserve-memo-validation/useCallback-reordering-deplist-controlflow.tsx
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("This dependency may be modified later"), span: SourceSpan { offset: SourceOffset(408), length: 1 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing manual memoization"), span: SourceSpan { offset: SourceOffset(349), length: 27 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `foo`, but the source dependencies were [y]. Inferred different dependency than source"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing manual memoization"), span: SourceSpan { offset: SourceOffset(349), length: 27 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `x`, but the source dependencies were [y]. Inferred different dependency than source"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing manual memoization"), span: SourceSpan { offset: SourceOffset(349), length: 27 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `arr2`, but the source dependencies were [y]. Inferred different dependency than source"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
import { useCallback } from "react";
import { Stringify } from "shared-runtime";
function Foo(t0) {
const $ = _c(10);
const { arr1, arr2, foo } = t0;
let t1;
if ($[0] !== arr1) {
t1 = [arr1];
$[0] = arr1;
$[1] = t1;
} else {
t1 = $[1];
}
const x = t1;
let getVal1;
let t2;
if ($[2] !== arr2 || $[3] !== foo || $[4] !== x) {
let y = [];
getVal1 = _temp;
t2 = () => [y];
foo ? y = x.concat(arr2) : y;
$[2] = arr2;
$[3] = foo;
$[4] = x;
$[5] = getVal1;
$[6] = t2;
} else {
getVal1 = $[5];
t2 = $[6];
}
const getVal2 = t2;
let t3;
if ($[7] !== getVal1 || $[8] !== getVal2) {
t3 = <Stringify val1={getVal1} val2={getVal2} shouldInvokeFns={true} />;
$[7] = getVal1;
$[8] = getVal2;
$[9] = t3;
} else {
t3 = $[9];
}
return t3;
}
function _temp() {
return { x: 2 };
}
export const FIXTURE_ENTRYPOINT = {
fn: Foo,
params: [{
arr1: [1, 2],
arr2: [3, 4],
foo: true
}],
sequentialRenders: [{
arr1: [1, 2],
arr2: [3, 4],
foo: true
}, {
arr1: [1, 2],
arr2: [3, 4],
foo: false
}]
};
@@ -2,10 +2,45 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/preserve-memo-validation/useCallback-reordering-depslist-assignment.tsx
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("This dependency may be modified later"), span: SourceSpan { offset: SourceOffset(402), length: 1 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing manual memoization"), span: SourceSpan { offset: SourceOffset(349), length: 27 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `x`, but the source dependencies were [y]. Inferred different dependency than source"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing manual memoization"), span: SourceSpan { offset: SourceOffset(349), length: 27 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `arr2`, but the source dependencies were [y]. Inferred different dependency than source"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
import { useCallback } from "react";
import { Stringify } from "shared-runtime";
// We currently produce invalid output (incorrect scoping for `y` declaration)
function useFoo(arr1, arr2) {
const $ = _c(7);
let t0;
if ($[0] !== arr1) {
t0 = [arr1];
$[0] = arr1;
$[1] = t0;
} else {
t0 = $[1];
}
const x = t0;
let t1;
if ($[2] !== arr2 || $[3] !== x) {
let y;
t1 = () => ({ y });
y = x.concat(arr2), y;
$[2] = arr2;
$[3] = x;
$[4] = t1;
} else {
t1 = $[4];
}
const getVal = t1;
let t2;
if ($[5] !== getVal) {
t2 = <Stringify getVal={getVal} shouldInvokeFns={true} />;
$[5] = getVal;
$[6] = t2;
} else {
t2 = $[6];
}
return t2;
}
export const FIXTURE_ENTRYPOINT = {
fn: useFoo,
params: [[1, 2], [3, 4]]
};
@@ -2,10 +2,40 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/preserve-memo-validation/useMemo-reordering-depslist-assignment.ts
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("This dependency may be modified later"), span: SourceSpan { offset: SourceOffset(265), length: 1 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing manual memoization"), span: SourceSpan { offset: SourceOffset(212), length: 27 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `x`, but the source dependencies were [y]. Inferred different dependency than source"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing manual memoization"), span: SourceSpan { offset: SourceOffset(212), length: 27 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `arr2`, but the source dependencies were [y]. Inferred different dependency than source"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
import { useMemo } from "react";
function useFoo(arr1, arr2) {
const $ = _c(7);
let t0;
if ($[0] !== arr1) {
t0 = [arr1];
$[0] = arr1;
$[1] = t0;
} else {
t0 = $[1];
}
const x = t0;
let y;
if ($[2] !== arr2 || $[3] !== x) {
y = x.concat(arr2), y;
$[2] = arr2;
$[3] = x;
$[4] = y;
} else {
y = $[4];
}
let t1;
if ($[5] !== y) {
t1 = { y };
$[5] = y;
$[6] = t1;
} else {
t1 = $[6];
}
return t1;
}
export const FIXTURE_ENTRYPOINT = {
fn: useFoo,
params: [[1, 2], [3, 4]]
};
@@ -2,11 +2,63 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/preserve-memo-validation/useMemo-reordering-depslist-controlflow.tsx
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("This dependency may be modified later"), span: SourceSpan { offset: SourceOffset(390), length: 1 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing manual memoization"), span: SourceSpan { offset: SourceOffset(331), length: 27 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `arr1`, but the source dependencies were [y]. Inferred different dependency than source"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing manual memoization"), span: SourceSpan { offset: SourceOffset(331), length: 27 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `foo`, but the source dependencies were [y]. Inferred different dependency than source"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing manual memoization"), span: SourceSpan { offset: SourceOffset(331), length: 27 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `arr2`, but the source dependencies were [y]. Inferred different dependency than source"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
import { useMemo } from "react";
import { Stringify } from "shared-runtime";
function Foo(t0) {
const $ = _c(9);
const { arr1, arr2, foo } = t0;
let t1;
let val1;
if ($[0] !== arr1 || $[1] !== arr2 || $[2] !== foo) {
const x = [arr1];
let y = [];
let t2;
if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
t2 = { x: 2 };
$[5] = t2;
} else {
t2 = $[5];
}
val1 = t2;
foo ? y = x.concat(arr2) : y;
t1 = (() => [y])();
$[0] = arr1;
$[1] = arr2;
$[2] = foo;
$[3] = t1;
$[4] = val1;
} else {
t1 = $[3];
val1 = $[4];
}
const val2 = t1;
let t2;
if ($[6] !== val1 || $[7] !== val2) {
t2 = <Stringify val1={val1} val2={val2} />;
$[6] = val1;
$[7] = val2;
$[8] = t2;
} else {
t2 = $[8];
}
return t2;
}
export const FIXTURE_ENTRYPOINT = {
fn: Foo,
params: [{
arr1: [1, 2],
arr2: [3, 4],
foo: true
}],
sequentialRenders: [{
arr1: [1, 2],
arr2: [3, 4],
foo: true
}, {
arr1: [1, 2],
arr2: [3, 4],
foo: false
}]
};
@@ -2,8 +2,55 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/repro-no-declarations-in-reactive-scope-with-early-return.js
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing memoization"), span: SourceSpan { offset: SourceOffset(260), length: 110 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
function Component() {
const $ = _c(6);
const items = useItems();
let t0;
let t1;
if ($[0] !== items) {
t1 = Symbol.for("react.early_return_sentinel");
bb0: {
const filteredItems = items.filter(_temp);
if (filteredItems.length === 0) {
let t2;
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
t2 = <div><span /></div>;
$[3] = t2;
} else {
t2 = $[3];
}
t1 = t2;
break bb0;
}
t0 = filteredItems.map(_temp2);
}
$[0] = items;
$[1] = t0;
$[2] = t1;
} else {
t0 = $[1];
t1 = $[2];
}
if (t1 !== Symbol.for("react.early_return_sentinel")) {
return t1;
}
let t2;
if ($[4] !== t0) {
t2 = <>{t0}</>;
$[4] = t0;
$[5] = t2;
} else {
t2 = $[5];
}
return t2;
}
function _temp2(t0) {
const [item_0] = t0;
return <Stringify item={item_0} />;
}
function _temp(t0) {
const [item] = t0;
return item.name != null;
}
@@ -2,8 +2,70 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/repro-renaming-conflicting-decls.js
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing memoization"), span: SourceSpan { offset: SourceOffset(207), length: 37 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enablePreserveExistingMemoizationGuarantees:false
import { Stringify, identity, makeArray, toJSON } from "shared-runtime";
import { useMemo } from "react";
function Component(props) {
const $ = _c(10);
let t0;
let t1;
if ($[0] !== props) {
t1 = Symbol.for("react.early_return_sentinel");
bb0: {
const propsString = toJSON(props);
if (propsString.length <= 2) {
t1 = null;
break bb0;
}
t0 = identity(propsString);
}
$[0] = props;
$[1] = t0;
$[2] = t1;
} else {
t0 = $[1];
t1 = $[2];
}
if (t1 !== Symbol.for("react.early_return_sentinel")) {
return t1;
}
let t2;
if ($[3] !== t0) {
const linkProps = { url: t0 };
const x = {};
let t3;
let t4;
let t5;
let t6;
let t7;
if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
t3 = [1];
t4 = [2];
t5 = [3];
t6 = [4];
t7 = [5];
$[5] = t3;
$[6] = t4;
$[7] = t5;
$[8] = t6;
$[9] = t7;
} else {
t3 = $[5];
t4 = $[6];
t5 = $[7];
t6 = $[8];
t7 = $[9];
}
t2 = <Stringify link={linkProps} val1={t3} val2={t4} val3={t5} val4={t6} val5={t7}>{makeArray(x, 2)}</Stringify>;
$[3] = t0;
$[4] = t2;
} else {
t2 = $[4];
}
return t2;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ val: 2 }]
};
@@ -2,9 +2,32 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/useCallback-call-second-function-which-captures-maybe-mutable-value-dont-preserve-memoization.js
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("This dependency may be modified later"), span: SourceSpan { offset: SourceOffset(425), length: 3 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing memoization"), span: SourceSpan { offset: SourceOffset(400), length: 22 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enablePreserveExistingMemoizationGuarantees:false @enableTransitivelyFreezeFunctionExpressions:false
import { useCallback } from "react";
import { identity, logValue, makeObject_Primitives, useHook } from "shared-runtime";
function Component(props) {
const $ = _c(2);
const object = makeObject_Primitives();
useHook();
const log = () => {
logValue(object);
};
const onClick = () => {
log();
};
identity(object);
let t0;
if ($[0] !== onClick) {
t0 = <div onClick={onClick} />;
$[0] = onClick;
$[1] = t0;
} else {
t0 = $[1];
}
return t0;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{}]
};
@@ -2,8 +2,23 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/useCallback-maybe-modify-free-variable-dont-preserve-memoization-guarantee.js
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing memoization"), span: SourceSpan { offset: SourceOffset(400), length: 104 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
import { useCallback } from "react";
import { identity, makeObject_Primitives, mutate, useHook } from "shared-runtime";
function Component(props) {
const free = makeObject_Primitives();
const free2 = makeObject_Primitives();
const part = free2.part;
useHook();
const callback = () => {
const x = makeObject_Primitives();
x.value = props.value;
mutate(x, free, part);
};
mutate(free, part);
return callback;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ value: 42 }]
};
@@ -2,8 +2,23 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/useMemo-mabye-modified-free-variable-dont-preserve-memoization-guarantees.js
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing memoization"), span: SourceSpan { offset: SourceOffset(596), length: 142 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
import { useMemo } from "react";
import { identity, makeObject_Primitives, mutate, useHook } from "shared-runtime";
function Component(props) {
const free = makeObject_Primitives();
const free2 = makeObject_Primitives();
const part = free2.part;
useHook();
const x = makeObject_Primitives();
x.value = props.value;
mutate(x, free, part);
const object = x;
identity(free);
identity(part);
return object;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ value: 42 }]
};
@@ -2,8 +2,23 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/useMemo-maybe-modified-later-dont-preserve-memoization-guarantees.js
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing memoization"), span: SourceSpan { offset: SourceOffset(203), length: 42 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enablePreserveExistingMemoizationGuarantees:false
import { useMemo } from "react";
import { identity, makeObject_Primitives, mutate } from "shared-runtime";
function Component(props) {
const $ = _c(1);
let object;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
object = makeObject_Primitives();
identity(object);
$[0] = object;
} else {
object = $[0];
}
return object;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{}]
};
@@ -2,8 +2,23 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/useMemo-named-function.ts
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] UseMemo: Expected the first argument to be an inline function expression", labels: One([LabeledSpan { label: Some("Expected the first argument to be an inline function expression"), span: SourceSpan { offset: SourceOffset(205), length: 9 }, primary: false }]), help: Some("Expected the first argument to be an inline function expression"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @validateNoSetStateInRender:false @enablePreserveExistingMemoizationGuarantees:false
import { useMemo } from "react";
import { makeArray } from "shared-runtime";
function Component() {
const $ = _c(1);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = makeArray();
$[0] = t0;
} else {
t0 = $[0];
}
const x = t0;
return x;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{}]
};
@@ -2,8 +2,22 @@
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/useMemo-with-optional.js
---
Diagnostics:
OxcDiagnostic { inner: OxcDiagnosticInner { message: "[ReactCompiler] PreserveManualMemo: Existing memoization could not be preserved", labels: One([LabeledSpan { label: Some("Could not preserve existing memoization"), span: SourceSpan { offset: SourceOffset(177), length: 50 }, primary: false }]), help: Some("React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output"), note: None, severity: Error, code: OxcCode { scope: None, number: None }, url: None } }
No changes.
import { c as _c } from "react/compiler-runtime";
// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false
import { useMemo } from "react";
function Component(props) {
const $ = _c(2);
let t0;
if ($[0] !== props.value) {
t0 = (() => [props.value])() || [];
$[0] = props.value;
$[1] = t0;
} else {
t0 = $[1];
}
return t0;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ value: 1 }]
};