Files
oxc-project__oxc/crates/oxc_react_compiler/tests/snapshots/valid-setState-in-effect-from-ref-arithmetic.snap
Boshen 5771982655 fix(react_compiler): render unchanged programs as source in fixture snapshots (#24129)
## Root cause

The `oxc_react_compiler` snapshot harness (`tests/snapshot.rs`) rendered a clean no-op compile as the literal `No changes.` marker:

```rust
if result.changed {
    out.push_str(&Codegen::new().build(&program).code);
} else {
    out.push_str("No changes.");
}
```

Upstream's `snap` runner instead **always** re-emits the program as `## Code`, and only replaces it with `## Error` on a hard error. So for every fixture where oxc "bails" with `No changes.`, the fork's golden shows the reprinted source — a permanent, opaque diff.

Investigating the **rules-of-hooks** batch showed this is purely a harness-representation gap, not a compiler bug:

- All 17 "bailing" rules-of-hooks fixtures carry `@expectNothingCompiled` (e.g. top-level statements, classes, or `@compilationMode:"infer"` functions that aren't components/hooks). oxc correctly compiles nothing — matching the fork, which also compiles nothing and just reprints the source.
- Every rules-of-hooks **error** fixture already matches the fork on category, message text, and source location (Rules-of-Hooks validation is a complete port).
- Every rules-of-hooks **compiling** fixture already matches the fork structurally; residual diffs are pure codegen formatting (trailing commas, JSX paren-wrapping) which are out of scope.

## Fix

Test-only change. On a clean no-op (no parse errors **and** no compile diagnostics), codegen the unchanged program instead of the marker, mirroring the upstream runner. The marker is kept when an error was reported, since upstream emits `## Error` with no code there — and reprinting a parse-recovered AST would be misleading.

```rust
let clean = parsed.diagnostics.is_empty() && result.diagnostics.as_slice().is_empty();
if result.changed || clean {
    out.push_str(&Codegen::new().build(&program).code);
} else {
    out.push_str("No changes.");
}
```

No compiler source is touched, so there is no risk to the compiler, napi bindings, or other consumers. The snapshot test still catches any future behavior change.

## Fixtures changed

54 snapshots that previously said `No changes.` now render the reprinted source:

- **17 rules-of-hooks** (this batch) — all `@expectNothingCompiled`; now match the fork's `## Code` modulo whitespace.
- **37 elsewhere** (guarded corpus-wide no-ops: `infer-*`, `use-no-forget-*`, `use-no-memo-*`, `gating/*`, `effect-derived-computations/*`, `valid-setState-*`, etc.).

52 of the 54 match the fork's `## Code` modulo formatting. The 11 parse-error fixtures (`error.todo-*`) keep the marker as intended.

## Remaining work

Two of the changed snapshots move **closer** to the fork but retain **pre-existing, out-of-batch** compiler gaps (unchanged by this PR, now just more visible):

- `ignore-use-no-forget.js` — oxc doesn't implement the `@ignoreUseNoForget` plugin option, so it honors the `'use no forget'` opt-out and skips; the fork ignores the opt-out and fully compiles.
- `valid-setState-in-effect-from-ref-function-call.js` — in `@outputMode:"lint"` the fork reprints with an SSA-renamed shadowed param (`ref` → `ref_0`); oxc leaves the source unchanged.

Both are separate from Rules-of-Hooks and left to their respective batches.
2026-07-04 01:22:38 +00:00

19 lines
581 B
Plaintext

---
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/valid-setState-in-effect-from-ref-arithmetic.js
---
// @validateNoSetStateInEffects @enableAllowSetStateFromRefsInEffects @outputMode:"lint"
import { useState, useRef, useLayoutEffect } from "react";
function Component() {
const ref = useRef({ size: 5 });
const [computedSize, setComputedSize] = useState(0);
useLayoutEffect(() => {
setComputedSize(ref.current.size * 10);
}, []);
return computedSize;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: []
};