Closes the migration tracked in #23043.
The new builder API (methods on the AST types themselves) has been in place for a while, all Oxc crates are migrated, and every crate which uses `AstBuilder` already enables `disable_old_builder` in its tests. The module docs said "after a few weeks, we will remove `AstBuilder`'s own methods entirely" — this does that.
## What's removed
- `crates/oxc_ast/src/generated/ast_builder.rs` and `builder/methods.rs` — `AstBuilder`'s own node and primitive constructors.
- `AstBuilderGenerator`, which produced the former.
- The `disable_old_builder` Cargo feature, plus the dev-dependency hacks it required across 33 manifests. Eight crates depended on `oxc_ast` *purely* to turn the feature on; those deps and their `cargo-shear` ignore entries are gone too.
## One thing worth reviewing
`AstBuilderGenerator` owned the `#[builder(default)]` / `#[builder(skip)]` attr registration that `BuilderMethodsGenerator` only *reads* — its doc comment said as much. Deleting it naively would have silently dropped `skip`/`default` handling for the 12 AST types using those attrs, so `attrs()` and `parse_attr()` move to `BuilderMethodsGenerator`.
The evidence this was faithful: after regenerating, `builder_methods.rs` and every other generated file are **byte-identical**. The only generated change in the diff is the deletion.
## Breaking changes
- `AstBuilder`'s own methods are gone. Use the AST type methods: `Statement::new_expression_statement(span, expr, &builder)` instead of `builder.statement_expression(span, expr)`.
- `AstBuilder` is no longer `Copy`/`Clone`, and its `allocator` field is private — use the `allocator` method from `GetAllocator`.
- `AstBuilder` and `NONE` are no longer re-exported from the crate root; import them from `oxc_ast::builder`. (The `disable_old_builder` feature already gated these off, so nothing in-tree used the root path.)
- The `disable_old_builder` feature no longer exists — remove it from any manifest that sets it.
A migration note covering all of the above is in `crates/oxc_ast/src/builder/mod.rs`.
---
Implemented with AI assistance (Claude Code); design, review, and verification driven by the author per the repo AI-usage policy.
Part of #23043.
We don't enable `oxc_ast`'s `disable_old_builder` Cargo feature in any of our published crates, or crates that are depended on by published crates.
Tasks are private to the repo, so enable this feature on them, to ensure no usage of legacy `AstBuilder` methods sneak in during the transition period before we delete these methods.
Rework the pipeline benchmark to run the full compilation through the
`oxc` root crate's `Compiler`/`CompilerInterface` instead of hand-wiring
each `oxc_*` stage.
- A `PipelineCompiler` implements `CompilerInterface`, overriding the
option hooks with common options:
- **transform**: `esnext` target
- **define**: `process.env.NODE_ENV` → `'production'`
- **inject**: `Buffer` from `node:buffer`
- **compress**: `CompressOptions::smallest()`, plus default mangle and
codegen
- The bench body just calls `compiler.compile(...)`, so parse → semantic
→ transform → define → inject → minify → mangle → codegen is driven by
the interface.
- `Cargo.toml`: added `oxc` (with `full` feature) to the `compiler`
feature and to `cargo-shear` ignored list.
The CI matrix maps the `pipeline` component to the `compiler` feature,
which now includes `oxc`, so no workflow changes are needed.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Closes https://github.com/oxc-project/oxc/issues/10048
Integrates the Rust port of the React Compiler ([facebook/react#36173](https://github.com/facebook/react/pull/36173)) into oxc.
## Notes (resolved)
- Published crates can't reference Git URLs, so using this from Rolldown needs the React Compiler crates on crates.io. ✅ Published as a fork at https://crates.io/crates/forked_react_compiler; this PR depends on those `forked_react_compiler*` crates so people can get earlier access.
- The React Compiler crates had no license field. ✅ The published fork carries `license = "MIT"` (per the React repo's MIT license), so Cargo Deny and Security Analysis pass.
## Benchmark
**Wall-clock overhead vs plain transform** (release `transformSync`, same `jsx: automatic`, toggling only `reactCompiler`):
| fixture | without | with | overhead |
| --- | --- | --- | --- |
| RadixUIAdoptionSection.jsx (2.5 KiB) | 0.03 ms | 1.81 ms | +1.8 ms |
| excalidraw `App.tsx` (406 KiB) | 4.09 ms | 14.49 ms | +10.4 ms (3.5×) |
So roughly a fixed ~1.8 ms floor per file plus a per-size cost — about **3.5× the transform time** on a large real-world component.
## Binary size
Linking the React Compiler pulls the whole compiler pipeline (HIR, lowering, inference, SSA, optimization, reactive scopes, validation) plus the oxc⇄Babel AST conversion into the binding. Release build of the napi transform addon (`transform.darwin-arm64.node`, `--release`, stripped), darwin-arm64:
| build | size |
| --- | --- |
| baseline (`main`) | 3.51 MiB |
| with React Compiler | 8.66 MiB |
| **delta** | **+5.14 MiB (+146%, 2.46×)** |
Add benchmarks for:
1. Parsing with tokens.
2. Serializing tokens to ESTree-style JSON.
Neither of these benchmarks needs to be kept indefinitely, but they'll be useful while working on the tokens code. There's a lot of room for optimization.
Since the update of
[cargo-shear](https://github.com/Boshen/cargo-shear/releases/tag/v1.6.6),
there are more unused dependencies be found in latest version of it, it
prevents the git commits and this PR applies the fix from latest cargo
shear to fix it
Improve the source text cleaner in lexer benchmark to do less string cloning and allocations. Does not affect the benchmark itself, only makes the setup more efficient.
closes https://github.com/oxc-project/oxc/issues/14007
- Replace 8 individual benchmark features with 2: compiler and linter
- Update matrix script to return objects with component and feature
fields
- Simplify workflow to use cargo codspeed build/run with feature mapping
🤖 Generated with [Claude Code](https://claude.ai/code)
This balances build speed and cache size, it was saving 7 separate
caches of 280MB each component + 400MB for the linter, it's now
200-300MB for the "compiler".
Co-authored-by: Claude <noreply@anthropic.com>
part of #13646
## Summary
This PR converts the Control Flow Graph (CFG) functionality in `oxc_semantic` from runtime checks to a compile-time cargo feature, eliminating runtime overhead when CFG is not needed.
## Changes
- Added `cfg` cargo feature to `oxc_semantic/Cargo.toml` with `oxc_cfg` as optional dependency
- Feature-gated all CFG-related code using `#[cfg(feature = "cfg")]`
- Updated `oxc_linter` to enable the `cfg` feature (since it requires CFG)
- Made the `control_flow!` macro work correctly with and without the feature
## Benefits
- **Performance**: Eliminates runtime `Option<CFG>` checks when feature is disabled
- **Binary size**: Smaller binaries for crates that don't need CFG
- **Cleaner API**: CFG methods only available when feature is enabled
## Test Plan
- [x] All existing tests pass with `cargo test -p oxc_semantic --features cfg`
- [x] `oxc_linter` builds and works correctly (it enables the feature)
- [x] Feature is backward compatible - existing code continues to work
🤖 Generated with [Claude Code](https://claude.ai/code)
The benchmark jobs take too long to run, change them to a minimal set.
This set of files are smaller but should provide basic coverage to real
world examples.
this PR moves all of the config resolution for a single file into the `ConfigStore` structure, rather than half existing in `oxc_linter` and half in `oxlint` crates
Part of #5068, suggested by @ematipico and @MichaReiser, where @leaysgur
and I explored using biome formatter as the base and made a success. All
credits to the old Rome and the new Biome team.
This PR is in a boilerplate state where some of the functions are marked
as `todo!()`.
I also made the following changes:
* changed the base to be less generic, removed the `Language` and
`Context` generics
* expanded the formatter lifetime to include an `'ast` lifetime
* added access to the source text and comments
* added a mechanism for tracking and accessing parent ast nodes (done by
our codegen)
* removed most of the unit tests because they no longer compile
* removed the `oxc_prettier` crate
* Fix `cargo benchmark` - previous it failed with an error.
* Add `just benchmark-one` to run a single benchmark e.g. `just
benchmark-one parser`.
* Simplify `default` feature in `tasks/benchmark/Cargo.toml`.
The lexer benchmarks had a problem. The lexer alone cannot make sense of regexp literals, template literals, or JSX text elements - it needs the parser "driving" it.
So lexer was producing plenty of errors on some benchmarks. This is unrealistic - when driven by the parser, the lexer produces no errors. Generating diagnostics is relatively expensive, so this was skewing the benchmarks somewhat.
Solve this by cleaning up the input source text to replace these syntaxes with string literals prior to running the benchmarks.
Unfortunately lexer benchmarks don't exercise the code paths for these syntaxes, but there isn't much we can do about that. We can judge by the parser benchmarks, which are the more important ones anyway.
Minifier benchmark currently includes the time to run parser and semantic as well as the minifier itself. Similar to transformer benchmark, only measure the minifier itself in the benchmark.
This will give us a clearer picture of performance changes, and should also reduce variance in the benchmarks.
We no longer need to build semantic data inside the transformer.
The caller should be responsible for handling semantic data and its
errors.
The best way to achieve this in via `CompilerInterface`.
closes#3565
After studying google closure compiler, I'm leaning towards a multi-ast-pass infrastructure for the minifier.
This is one of the few places where we are going to trade maintainability over performance, given the goal of the minifier is compression size not performance.
All of the terminologies and separation of concerns are aligned with google closure compiler.
Infrastructure of `terser` and `esbuild` are not suitable for us to study nor pursuit. Their code are so tightly coupled - I failed to comprehend any of them every time I try to walk through a piece of optmization. Google closure compiler despite being written in Java, it's actually the most readable minifier out there.
To improve performance between ast passes, I envision a change detection system over a portion of the code.
The benchmark will demonstrate the performance regression of running 5 ast passes instead of 2.
To complete this PR, I need to figure out "fix-point" and order of these ast passes.
This PR builds on #3201 to further speed up the benchmarks and reduce CI
time.
* Build and run each benchmark as separate job (like before).
* But now each bench is only built with the dependencies it needs.
* For linter benchmarks, build benchmark in 1 job (like #3201 does).
* Run each linter fixture in a separate job as they're slow.
This reduces total time to complete benchmarks from between 6m-7m to
~4m40s.
All the individual jobs complete in under 1m30s, except for building
linter benchmark which takes 2m30s. So there won't be the problem of
blocking the CI queue that there was before.
NB: I did try this before, and didn't see a benefit. But I realized
today what I was doing wrong - it only works once the caches are
populated by a previous run on main branch.
So the CI times in this PR won't look good, but once it's merged to
main, it will take effect. Here it is running on main branch of my fork:
https://github.com/overlookmotel/oxc/actions/runs/9030511348
I also added a step to delete the temp artefacts which aren't needed
once the run has completed.
The sourcemap implement port from
[rust-sourcemap](https://github.com/getsentry/rust-sourcemap), but has
some different with it.
- Encode sourcemap at parallel, including quote `sourceContent` and
encode token to `vlq` mappings.
- Avoid `Sourcemap` some methods overhead, like `SourceMap::tokens()`
caused extra overhead at common cases. Here using `SourceViewToken` to
instead of it.
The `parser_napi` pseudo-benchmark does not depend on any Oxc crates, so
remove all dependencies for this benchmark. This reduces build time of
this benchmark on CI by ~1 minute.
After #2780, NAPI parser benchmark sometimes took the longest of all the
benchmarks, so making it faster reduces time to complete the benchmarks
overall.
Add NodeJS parser to benchmarks.
Previous attempt #2724 did not work due CodSpeed producing very
inaccurate results (https://github.com/CodSpeedHQ/action/issues/96).
This version runs the actual benchmarks without CodSpeed's
instrumentation. Then another faux-benchmark runs within Codspeed's
instrumented action and just performs meaningless calculations in a loop
for as long as is required to take same amount of time as the original
uninstrumented benchmarks took.
It's unfortunate that we therefore don't get flame graphs on CodSpeed,
but this seems to be the best we can do for now.