Files
oxc-project__oxc/crates/oxc_react_compiler/fixtures/using-declaration-skips-only-that-function.tsx
Boshen 3ae8317299 refactor(react_compiler): skip only functions that use using instead of the whole file (#24217)
## Summary

`using`/`await using` disposal semantics aren't preserved by the React Compiler yet, so any file containing them was skipped entirely by a whole-program `ResourceManagementVisitor` pre-pass — a `using` *anywhere* in the file dropped *every* component in it.

This detects `using` during lowering instead. `lower_variable_declaration` already visits every variable declaration (including those in nested closures), so it sets a `skip_compilation` flag on the `Environment`; `compile_fn` checks it after lowering and returns `Ok(None)` — a silent, per-function skip with no diagnostic — so sibling functions still compile.

## Details

- Removes `ResourceManagementVisitor` and the whole-file gate in `compile()`; reuses the existing lowering traversal rather than adding a new visitor.
- The skip is silent (no diagnostic), unlike a `record_error` bail.
- Top-level `using` is untouched: the compiler only rewrites function bodies, so a module-scope `using` is preserved verbatim while the file's components still compile.
- Adds a fixture where a `using`-containing component is emitted unchanged and a structurally identical sibling component is memoized.

Before: any `using` → whole file skipped. After: only the enclosing function is skipped.

## Performance

CodSpeed reports a large regression on `react_compiler[kitchen-sink.tsx]` (19ms → 429ms) and `linter[kitchen-sink.tsx]` (166ms → 542ms). This reflects correct behavior, not a code inefficiency:

- `kitchen-sink.tsx` is a ~21k-line file with ~90 React components, and it contains `using`/`await using` in two small **non-React** helper functions (`exerciseUsing`/`exerciseAwaitUsing`).
- On `main` the whole-program pre-pass saw that `using` and skipped the **entire file**, so the benchmark was measuring parse + semantic + skip — it never actually compiled anything.
- With this PR the 90 components compile normally (the 429ms is their real cost). The two `using` helpers aren't even compile candidates in the default `infer` mode, so the per-function skip never fires for them here.

Files that do **not** contain `using` are unaffected — identical performance. The regression is confined to files that mix `using` with React components (a rare combination), which now correctly compile instead of being discarded wholesale.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-07-06 11:27:55 +00:00

12 lines
433 B
TypeScript

// `using`/`await using` disposal semantics aren't preserved yet, so `WithUsing` is
// skipped and emitted unchanged, while the structurally identical `Clean` component
// in the same file is still compiled.
function WithUsing(props) {
using resource = props.acquire();
return <div onClick={() => props.onClick()}>{props.text}</div>;
}
function Clean(props) {
return <div onClick={() => props.onClick()}>{props.text}</div>;
}