Files
oxc-project__oxc/crates/oxc_react_compiler/tests/snapshots/useMemo-named-function.snap
Boshen f693a473ce 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.
2026-07-04 11:00:36 +08:00

25 lines
611 B
Plaintext

---
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/useMemo-named-function.ts
---
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: [{}]
};