mirror of
https://github.com/oxc-project/oxc.git
synced 2026-09-14 19:36:11 +08:00
3ae8317299
## 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)
34 lines
885 B
Plaintext
34 lines
885 B
Plaintext
---
|
|
source: crates/oxc_react_compiler/tests/snapshot.rs
|
|
input_file: crates/oxc_react_compiler/fixtures/using-declaration-skips-only-that-function.tsx
|
|
---
|
|
import { c as _c } from "react/compiler-runtime";
|
|
// `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) {
|
|
const $ = _c(5);
|
|
let t0;
|
|
if ($[0] !== props) {
|
|
t0 = () => props.onClick();
|
|
$[0] = props;
|
|
$[1] = t0;
|
|
} else {
|
|
t0 = $[1];
|
|
}
|
|
let t1;
|
|
if ($[2] !== props.text || $[3] !== t0) {
|
|
t1 = <div onClick={t0}>{props.text}</div>;
|
|
$[2] = props.text;
|
|
$[3] = t0;
|
|
$[4] = t1;
|
|
} else {
|
|
t1 = $[4];
|
|
}
|
|
return t1;
|
|
}
|