mirror of
https://github.com/oxc-project/oxc.git
synced 2026-09-14 19:36:11 +08:00
codex/comment-attachments
43 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
1645d93cfb |
fix(react_compiler): preserve source spans (#25462)
React Compiler rebuilt source-derived AST nodes with empty spans, so compiled function bodies had no useful source mappings. Preserve retained HIR and reactive spans during codegen while keeping synthetic memoization scaffolding unmapped. AI-assisted: implementation used Codex; the author remains responsible for review. |
||
|
|
4a6542bfda |
chore(react_compiler): configure package publishing (#25389)
Prevents the internal `oxc_react_compiler` and `oxc_transform_react_napi` Rust crates from being published while including the `oxc-transform-react` npm package in workspace releases. Validated with `taplo lint`, Cargo metadata, and `just ready`. AI assistance was used for this change. |
||
|
|
45a17c25d1 |
release(crates): oxc v0.143.0 (#25250)
### 💥 BREAKING CHANGES - |
||
|
|
fc702c1fa9 |
release(crates): oxc v0.142.0 (#24977)
### 💥 BREAKING CHANGES - |
||
|
|
33a97da760 |
chore(oxc_react_compiler): exclude testonly files from published crate (#24932)
Adds explicit includes for `oxc_react_compiler` to omit 2.2MB of files (49% of total) under `/tests` and `/fixtures` from the published package. I included the examples directory, but that can also be excluded if desired [The full list of removed files are included in this text file](https://github.com/user-attachments/files/30380492/oxc_react_removed.txt). Today I learned there is a size limit in GitHub PR descriptions For the record, I checked all other published crates in the workspace, and none of them included any extraneous files 😃 |
||
|
|
baf022d74d |
refactor(ast)!: remove old AstBuilder methods (#24563)
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. |
||
|
|
14533a3dc1 |
release(crates): oxc v0.141.0 (#24714)
### 💥 BREAKING CHANGES - |
||
|
|
bfecb1a3f8 |
refactor(react_compiler): back HIR ordered maps with Vec + FxHashMap (#24666)
The HIR's insertion-ordered CFG containers were `indexmap`-based: - `HIR.blocks: FxIndexMap<BlockId, BasicBlock>` — iteration order is reverse-postorder, which is load-bearing (forward dataflow visits each block after its predecessors). - `BasicBlock.preds: FxIndexSet<BlockId>` — predecessor order sets phi-operand order. - `Phi.operands: FxIndexMap<BlockId, Place>` — one operand per predecessor, in that order. `indexmap` has no arena-allocator variant, which blocks moving the HIR into an arena. `Vec` and hash maps do (`oxc_allocator::Vec` / `oxc_allocator::HashMap`), so this replaces those three fields with `OrderedMap` / `OrderedSet` — ordered containers backed by `Vec<(K, V)>` plus an `FxHashMap<K, usize>` index. They mirror the subset of the `IndexMap` / `IndexSet` API the HIR uses (`get`/`get_mut`/`insert`/`shift_remove`/`retain`/`drain`/`keys`/`values`/`iter[_mut]`/`get_index_of`, `IntoIterator`, `Index`, `DoubleEndedIterator`), preserving insertion order and O(1) lookup, so call sites are unchanged. This is a preparatory step: the three fields are now composed of arena-convertible primitives, so the eventual arena move is a mechanical `Vec` -> `Vec<'a>` / `FxHashMap` -> arena `HashMap` swap rather than an impossible `indexmap` port. The `SymbolId`-keyed builder maps and `StabilizeBlockIds`' scratch set stay `FxIndexMap` / `FxIndexSet` — they are pass-local working data, not HIR CFG structures. Pure internal change: the fixtures snapshot is byte-identical; new unit tests cover the `shift_remove` / `retain` / `drain` reindexing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> |
||
|
|
b6850625af |
perf(react_compiler): keep small hot-path collections inline (#24514)
## What Two kinds of small, hot collections in the react-compiler pass get heap-allocated on every use: - The HIR operand/lvalue visitors (`each_instruction_value_operand`, `each_terminal_operand`, and friends) build a fresh `Vec<Place>` for every instruction they're called on, and nearly every pass calls them in a loop. The lists almost always hold one to four entries. - The aliasing fixpoint allocates a successor list per block visit (`terminal_successors`) and an args/captures list per interned effect (`EffectKey`). ## Change - The visitors now return `PlaceList = SmallVec<[Place; 4]>`; element order and contents are unchanged. - `terminal_successors` returns a `SmallVec<[BlockId; 2]>`, and `EffectKey::Apply` args / `CreateFunction` captures are inline small vectors, so building a typical key no longer allocates. - Adds `smallvec` to the crate (already a workspace dependency). Numbers from the stock release profile (fat LTO), linting cal.com with `react/react-compiler` as the only enabled rule, `--threads=1`: | | before | after | delta | | ------------ | -------------: | -------------: | ------------------: | | instructions | 18,085,644,607 | 17,200,052,223 | −4.9% | | wall time | 2.787 s | 2.754 s | −1.2% | ## Verification - Lint output is byte-identical to main on cal.com and excalidraw, with `reportAllBailouts` both on and off (full stdout/stderr and exit codes, single-threaded). - Transform output is identical on all 1,438 tsx/jsx files across the two corpora, with no exit-code changes. - `cargo test -p oxc_react_compiler` (including the fixture snapshot suite), clippy, and rustfmt are all clean. This PR was assisted by Claude Code. |
||
|
|
3a36f2a67c |
perf(react_compiler): store AbstractValue reasons as a u16 bitmask (#24480)
Follow-up to #24476. Profiling the mutation-aliasing pass after that PR showed the `SmallVec<[ValueReason; 4]>` I introduced for `AbstractValue.reason` at **~7% of compile self-time** — it no longer allocates, but it's still copied on every `AbstractValue` clone, which happens once per entry on every `InferenceState` clone in the fixpoint. There are only 12 `ValueReason` variants, so the whole set fits in a `u16` bitmask. `ReasonSet` — and therefore `AbstractValue` — becomes `Copy`, so copying it is a register move instead of a memcpy, and membership / union / superset collapse to single bitwise ops. The one behavioral wrinkle is `primary_reason`, which returns the first non-`Other` reason: it now iterates in `ValueReason` declaration order rather than insertion order. The full snapshot suite (`tests/snapshot.rs`, the ~1288 upstream fixtures) is **unchanged**, confirming the ordering difference is not observable in output. ### Results Real-world React component files (from `bluesky-social/social-app`), compile pass only: | File | before | after | | --- | ---: | ---: | | Explore.tsx (35 KB) | 23.1 ms | **21.2 ms** (−8%) | | MessageItem.tsx (30 KB) | 21.3 ms | **20.5 ms** (−4%) | | Drawer.tsx (21 KB) | 8.6 ms | 8.7 ms (noise; few reasons) | Allocation count is unchanged — the `SmallVec` was already inline, so this is purely a copy/`memcpy` win. 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
8e0ed2ebb9 |
release(crates): oxc v0.140.0 (#24453)
### 🚀 Features - |
||
|
|
1e3e626831 |
perf(react_compiler): reduce allocations in reactive-places and mutation-aliasing passes (#24476)
Two allocation-focused optimizations to the React Compiler's two hottest passes. Both are behavior-preserving — the full snapshot suite (`tests/snapshot.rs`, the ~1288 upstream fixtures) is unchanged, and no snapshots were regenerated. Profiling the compiler on real component files showed ~99% of compile time is the compiler core (parse/semantic/codegen are <1% combined), and the core is allocation-bound: compiling a 35 KB file did ~1.2M heap allocations. These two changes remove most of that. ### 1. Memoize post-dominator frontiers (`infer_reactive_places`) `is_reactive_controlled_block` recomputed each block's post-dominator frontier — a reverse-CFG walk that allocates several sets — on every call, which happens once per block and once per phi operand on every fixpoint iteration. The frontier depends only on the CFG, which is invariant across the fixpoint, so it is now computed once per block up front and looked up. ### 2. Inline `SmallVec` for `AbstractValue.reason` (`infer_mutation_aliasing_effects`) `AbstractValue.reason` was an `FxIndexSet<ValueReason>`, which heap-allocates on every clone. During inference these values are cloned constantly (once per entry on every `InferenceState` clone), so the reason sets dominated allocation in the pass. The sets are tiny — usually a single element, never more than one per `ValueReason` variant — so they are now backed by an inline, insertion-ordered `SmallVec`: clones no longer allocate, and `primary_reason` (first non-`Other` reason) keeps its ordering. ### Results Measured on real-world React component files (from `bluesky-social/social-app`), compile pass only, system allocator: | File | before | after | allocations | | --- | ---: | ---: | ---: | | Explore.tsx (35 KB) | 49.6 ms | 23.5 ms (**2.1×**) | 1.24M → 220K (**−82%**) | | MessageItem.tsx (30 KB) | 28.4 ms | 20.9 ms (**1.36×**) | 542K → 297K (**−45%**) | | Drawer.tsx (21 KB) | 9.7 ms | 8.7 ms (1.11×) | 183K → 155K (−15%) | \#2 is the larger lever — the reason-set clones dominated allocation in the pass. \#1 is a complementary ~6–10% CPU win from avoiding the redundant frontier recomputation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
b80d351d5c |
refactor(react_compiler): drop lint allows and fix clippy warnings (#24449)
Follow-up to #24442 / #24448 (now merged). Removes clippy `"allow"`s from `crates/oxc_react_compiler` and fixes the warnings they were hiding. ## Crate-wide allows removed (`[lints.clippy]`) Only `result_large_err` (the whole-crate `Result<T, OxcDiagnostic>` trade-off) remains. | lint | warnings | fix | | --- | --- | --- | | `collapsible_if` | 197 | `cargo clippy --fix` (nested `if` → `&&` / `if let` chains) | | `unnecessary_unwrap` | 4 | rewritten as `if let Some(..)` | | `disallowed_types` | 0 | allow was dead — no `std::HashMap`/`HashSet` in the crate (the `ScopeInfo`/`ScopeData` comment was stale) | | `needless_return` | 0 | allow was dead — no trailing `return`s | ## Inline allows removed | lint | fix | | --- | --- | | `only_used_in_recursion` (3) | drop the recursion-only params: `func` (`apply_effect` → `apply_signature`), `types` (`get_context_reassignment`), `is_first_pass` (`record_instruction_derivations`) | | `large_enum_variant` (3) | box `ReactiveStatement::Terminal` and `CompileResult`'s `output` (unboxed at the `lib.rs` boundary, so the public `compile` API is unchanged); `AliasingEffect`'s allow was already dead | | `enum_variant_names` (1) | rename `Type::TypeVar` → `Type::Var` | ## Notes - Behavior-preserving: the insta snapshot corpus and all 15 transform tests are byte-identical; `clippy` is clean. - Deliberately left in place (would need bigger refactors, out of scope): `result_large_err` (whole-crate), `too_many_arguments` (×15 — arg-bundling structs), and `HIR`'s `upper_case_acronyms`. - This diverges the vendored `src/` modules a bit further from upstream `react_compiler_oxc` (the `collapsible_if` collapses especially) — worth a note for whoever re-syncs. - One thing the lint surfaced: `is_first_pass` in `record_instruction_derivations` was passed a real value by its fixpoint-loop caller but never read, so both passes were already identical — removing it is behavior-preserving but flags a latent gap if the passes were meant to differ. |
||
|
|
53342c91e9 |
refactor(react_compiler): define IDs with oxc_index nonmax index types (#24442)
## What Migrate the React Compiler's HIR ID newtypes from hand-rolled `pub struct X(pub u32)` / `type X = u32` to oxc's `oxc_index::define_nonmax_u32_index_type!` — the same index-type idiom used by `SymbolId`, `ScopeId`, `NodeId`, `ReferenceId`, `BasicBlockId`, etc. Migrated: `BlockId`, `IdentifierId`, `InstructionId`, `EvaluationOrder`, `DeclarationId`, `ScopeId`, `TypeId`, `FunctionId`, `MutableRangeId`, and the validation-pass `RefId`. ## Why `NonMaxU32` backing adds a niche, so `Option<Id>` is **4 bytes instead of 8**. The crate has 48 `Option<Id>` fields — many on hot HIR structs (`Identifier`, `Place`, `MutableRange`, `ReactiveScope`, `Instruction`) — which shrink for free, plus `RefId`'s `Option<RefId>` fields. It also aligns the crate with the rest of oxc, and the macro's `Add`/`PartialOrd<usize>` impls let the pervasive `id.0 + 1` / `a.0 > b.0 + 1` arithmetic collapse to `id + 1` / `a > b + 1`. ## Notes - `ValueId` is intentionally **not** migrated. It overlays two id-spaces by OR-ing bit 31 (`| 0x80000000`), whose value space includes `u32::MAX` and would panic under `NonMaxU32`; it is also only ever a hashmap/set key (never a `Vec` index or inside `Option<ValueId>`), so a nonmax index buys nothing. It stays a plain `u32` newtype, with the bit-tag now behind a named `ValueId::from_identifier` constructor. - Named sentinels replace repeated magic zeros: `EvaluationOrder::UNSET` (the "not-yet-numbered" order, ~106 sites) and `BlockId::PLACEHOLDER` (the never-read block installed by the final `terminate()`; uses `MAX_INDEX` so it can't alias the real entry block, which is `0`). - The old `u32::MAX` sentinels: the two never-read placeholders now use the named consts above; the `infer_types` one is a plain `u32` function-key and is unchanged. - Behavior-preserving: the insta snapshot corpus and all 15 transform tests are byte-identical. - These `src/` modules track upstream closely; this deliberately diverges, consistent with the recent oxc-integration work on this crate. |
||
|
|
cc820cb2c7 |
refactor(react_compiler): use oxc utilities instead of reimplementations (#24430)
Replaces hand-rolled JavaScript utilities in `oxc_react_compiler` with oxc's canonical implementations, each of which is also strictly more spec-correct than the local version.
## Replaced
- **`is_valid_identifier`** (two copies) → `oxc_syntax::identifier::is_identifier_name` + `oxc_syntax::keyword::is_reserved_keyword`. Removes duplicated 46-word reserved-word lists and approximate `is_alphabetic`/`is_alphanumeric` char checks (oxc uses exact ECMAScript `ID_Start`/`ID_Continue`). Also fixes one copy that silently allowed `await` as an identifier.
- **`js_to_number`** → `oxc_ecmascript::StringToNumber`. The local version accepted `"inf"`/`"nan"` and used Rust's Unicode `.trim()` instead of JS whitespace.
- **`js_to_int32` / `js_to_uint32`** → `oxc_ecmascript::{ToInt32, ToUint32}`. The local `(n.trunc() as i64) & 0xFFFFFFFF` saturated for large magnitudes (e.g. `1e300` produced `-1` instead of `0`).
- **`format_js_number`** → `oxc_syntax::number::ToJsString`. Replaces a documented `Number.prototype.toString()` approximation (which fell back to Rust's `Display`) with the dragonbox-based, spec-correct formatter.
- **`ox_parse_regexp_flags`** → `oxc::RegExpFlags::try_from(char)`. Removes a duplicated 8-arm flag `match`.
Adds the `oxc_ecmascript` dependency and enables the `to_js_string` feature on `oxc_syntax`. The single-call numeric conversions are inlined at their call sites; `is_valid_identifier` (composes two calls, used as a fn-pointer), `format_js_number` (pub, cross-file `Display` helper), and `ox_parse_regexp_flags` (a per-char loop) remain thin helpers.
Snapshot conformance (over the upstream fixture corpus) and the transform integration tests pass unchanged.
|
||
|
|
cadbfee9a5 |
refactor(react_compiler): remove dead code (#24426)
Removes all compiler-flagged dead code from `oxc_react_compiler`.
## Removed
- **Superseded functions** (`propagate_scope_dependencies_hir`): `collect_hoistable_property_loads`, `collect_hoistable_property_loads_impl`, `key_by_scope_id` — the live pipeline uses the restructured `collect_hoistable_and_propagate` instead.
- **Unused methods/wrappers**: `kind_opt`, `mutate`, `define_context`.
- **Unused fields** (removed with their construction sites): `PropertyPathNode::{parent, root}`, `DependencyCollectionContext::temporaries_used_outside_scope` (cascaded cleanly through `collect_dependencies`), `JsxInstrInfo::instr_id`, `ControlFlowTarget::Loop::owns_block`, `OxcContext::fn_name`, `StartMemoInfo::span`, `Callbacks::memo_locals`.
- **Unused enum variant**: `MutationKind::None` (the `Ord` ordering of the remaining variants is preserved).
- **Dormant scaffolding**: `TransformedValue::Replace` — collapsed the base traversal's replace path down to direct `visit_value` calls (the 11 transform passes are unaffected) — and `LvalueRef::Spread` plus its codegen match arm.
- **`hmac-sha256` dependency** — orphaned once `source_file_hash` was removed; dropped from the crate and workspace manifests.
Pre-existing `#[allow(dead_code)]` markers on live-but-unread code were left intact, so the diff is purely dead-code removal. Snapshot conformance (over the upstream fixture corpus) and the transform integration tests pass unchanged.
|
||
|
|
7ae9257187 |
refactor(react_compiler): replace String with arena Ident/Str in HIR (#24393)
Converts `oxc_react_compiler` HIR strings from owned `String` to arena types from `oxc_str`, mirroring the `oxc_ast` conventions. Output is byte-identical over the 1806-fixture snapshot corpus, and the public `transform`/`lint` API is unchanged.
## Type mapping
- Identifier-ish names → `Ident<'a>` (Copy, precomputed hash): `IdentifierName`, `PropertyLiteral`, `ObjectPropertyKey`, `NonLocalBinding`/`VariableBinding` names, JSX attribute/tag names, `StoreGlobal`, `MetaProperty`, function ids/name-hints, `Type::shape_id`/`object_name`
- Text values → `Str<'a>`: directives, `JSXText`, template quasis, regex pattern/flags, import module specifiers
- `JsString` is now Copy with `Utf8(Str<'a>) | Wtf16(&'a [u16])` — string literals borrow AST arena text directly; constant-folding results allocate once into the arena
- Name-keyed maps → `IdentHashMap`/`IdentHashSet`/`IdentIndexMap` (str lookups keep working via `Equivalent` with the precomputed hash)
- `type_annotation_kind` → `Option<&'static str>` (`"as"`/`"satisfies"`)
## Where names come from
- AST names are copied out of node fields as `Ident<'a>` values (free); binding names resolved through `Scoping` are arena-copied once by `ScopeResolver::symbol_ident()` (the `Scoping` name storage lives in the `Semantic` borrow, not the arena)
- `Environment<'a>` now carries `allocator: &'a Allocator`; synthesized names (`#t{n}` temporaries, `name_{i}` collision suffixes, `_temp{i}` uids, `$` cache vars, outlined-component names) build with `format_ident!`
- `BUILT_IN_*` shape ids are `Ident<'static>` consts (`static_ident!`), so shape-id comparisons take the len+hash fast path; the static globals/shapes base tables are `IdentHashMap<'static, _>` built with zero startup `String` allocations (the handful of `<generated_N>` anon ids minted during the once-per-process static build are leaked as static data; per-compilation ids go in the arena)
## Structural payoff
Codegen previously kept the HIR at a separate lifetime `'h` and re-allocated every identifier into the output arena via `ox_str`. Input AST, HIR, and output AST share one allocator, so the lifetimes are unified: a name flows from source text through lowering, SSA versioning, and renaming into the output AST without a single copy. Per-operand `Constant` clones in constant propagation and per-version name clones in `enter_ssa` are now 16-byte copies.
To keep the public API borrow-free (`&Program<'a>`, `&Semantic<'_>`, unchanged from before), the HIR holds no references into the input `Program`: the two AST nodes it used to keep verbatim — `TypeCastExpression` type annotations and `UnsupportedNode` statements (inline TS `enum`) — are cloned into the arena at lowering with `clone_in_with_semantic_ids` (preserving the semantic id cells codegen's rename-by-reference-identity relies on). `FunctionNode` and the discovery/lowering paths carry the node borrow and the arena lifetime separately.
## Deliberately still `String`
- Config API (`options.rs`, `environment_config.rs`, `type_config.rs`) — created before the arena exists; converted at the `with_config` boundary
- `Cow<'static, str>` where values are static-or-config-owned: `FunctionSignature::canonical_name`/`known_incompatible`, `get_react_compiler_runtime_module`
- Suppression comment values are now `&'a str` source subslices; `decode_jsx_entities` returns `Cow` (borrows when no entity)
- Diagnostics/debug text (`format_place`, dependency printers, sort keys, `format_js_number`) and aliasing-config placeholder names (`"@rest"`, …)
## Verification
- `cargo test -p oxc_react_compiler`: 1806-fixture snapshot suite unchanged, 15 integration tests pass (tests/example untouched from main)
- `oxc_linter` / `oxc_transformer` (+tests) / benchmark build clean; transformer integration tests pass
- clippy (CI profile), typos, shear, fmt clean
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||
|
|
0e8ecbe16d |
refactor(react_compiler): remove for_kv_map, question_mark, unneeded_wildcard_pattern clippy allows (#24342)
Remove three clippy lint allows from `oxc_react_compiler` and fix the six spots that triggered them: - `unneeded_wildcard_pattern` (3): drop redundant `children: _` / `span: _` fields next to `..` in match patterns - `for_kv_map` (1): iterate `temporaries.values()` instead of discarding the key from `iter()` - `question_mark` (2): replace `match`-with-`return None` arms with `?` in `constant_propagation.rs` (same early-return semantics) 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
0e00b91b5a |
chore(deps): update dependency rust to v1.97.0 (#24328)
This PR contains the following updates: | Package | Update | Change | |---|---|---| | [rust](https://redirect.github.com/rust-lang/rust) | minor | `1.96.1` → `1.97.0` | --- ### Release Notes <details> <summary>rust-lang/rust (rust)</summary> ### [`v1.97.0`](https://redirect.github.com/rust-lang/rust/blob/HEAD/RELEASES.md#Version-1970-2026-07-09) [Compare Source](https://redirect.github.com/rust-lang/rust/compare/1.96.1...1.97.0) \========================== <a id="1.97.0-Language"></a> ## Language - [Consider `Result<T, Uninhabited>` and `ControlFlow<Uninhabited, T>` to be equivalent to `T` for must use lint](https://redirect.github.com/rust-lang/rust/pull/148214) - [Add allow-by-default `dead_code_pub_in_binary` lint for unused pub items in binary crates](https://redirect.github.com/rust-lang/rust/pull/149509) - [Stabilize the `div32`, `lam-bh`, `lamcas`, `ld-seq-sa` and `scq` target features](https://redirect.github.com/rust-lang/rust/pull/154510) - [Stabilize `cfg(target_has_atomic_primitive_alignment)`](https://redirect.github.com/rust-lang/rust/pull/155006) - [Allow trailing `self` in imports in more cases](https://redirect.github.com/rust-lang/rust/pull/155137) <a id="1.97.0-Platform-Support"></a> ## Platform Support - [nvptx64-nvidia-cuda: drop support for old architectures and old ISAs](https://redirect.github.com/rust-lang/rust/pull/152443) Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. [platform-support-doc]: https://doc.rust-lang.org/rustc/platform-support.html <a id="1.97.0-Stabilized-APIs"></a> ## Stabilized APIs - [`Default for RepeatN`](https://doc.rust-lang.org/stable/std/iter/struct.RepeatN.html#impl-Default-for-RepeatN%3CA%3E) - [`Copy for ffi::FromBytesUntilNulError`](https://doc.rust-lang.org/stable/std/ffi/struct.FromBytesUntilNulError.html#impl-Copy-for-FromBytesUntilNulError) - [`Send for std::fs::File` on UEFI](https://redirect.github.com/rust-lang/rust/pull/154003) - [`<{integer}>::isolate_highest_one`](https://doc.rust-lang.org/stable/std/primitive.u32.html#method.isolate_highest_one) - [`<{integer}>::isolate_lowest_one`](https://doc.rust-lang.org/stable/std/primitive.u32.html#method.isolate_lowest_one) - [`<{integer}>::highest_one`](https://doc.rust-lang.org/stable/std/primitive.u32.html#method.highest_one) - [`<{integer}>::lowest_one`](https://doc.rust-lang.org/stable/std/primitive.u32.html#method.lowest_one) - [`<{integer}>::bit_width`](https://doc.rust-lang.org/stable/std/primitive.u32.html#method.bit_width) - [`NonZero<{integer}>::isolate_highest_one`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html#method.isolate_highest_one) - [`NonZero<{integer}>::isolate_lowest_one`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html#method.isolate_lowest_one) - [`NonZero<{integer}>::highest_one`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html#method.highest_one) - [`NonZero<{integer}>::lowest_one`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html#method.lowest_one) - [`NonZero<{integer}>::bit_width`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html#method.bit_width) These previously stable APIs are now stable in const contexts: - [`char::is_control`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_control) <a id="1.97.0-Cargo"></a> ## Cargo - [Stabilize `build.warnings` config.](https://redirect.github.com/rust-lang/cargo/pull/16796) This controls how lint warnings from local packages are treated. Useful for enforcing a warning-free build in CI, replacing `-Dwarnings`. [docs](https://doc.rust-lang.org/nightly/cargo/reference/config.html#buildwarnings) - [Stabilize `resolver.lockfile-path` config.](https://redirect.github.com/rust-lang/cargo/pull/16694) This allows specifying the path to the lockfile to use when resolving dependencies. Useful when working with read-only source directories. [docs](https://doc.rust-lang.org/nightly/cargo/reference/config.html#resolverlockfile-path) - [cargo-clean: Error when `--target-dir` doesn't look like a Cargo target directory.](https://redirect.github.com/rust-lang/cargo/pull/16712) This prevents accidental deletion of non-target directories. - [Add `-m` shorthand for `--manifest-path`](https://redirect.github.com/rust-lang/cargo/pull/16858) - [Remove `curl` dependency from `crates-io` crate](https://redirect.github.com/rust-lang/cargo/pull/16936) <a id="1.97.0-Rustdoc"></a> ## Rustdoc - [Stabilize `--emit` flag](https://redirect.github.com/rust-lang/rust/pull/146220) - [Stabilize `--remap-path-prefix`](https://redirect.github.com/rust-lang/rust/pull/155307) <a id="1.97.0-Compatibility-Notes"></a> ## Compatibility Notes - [Emit a future-compatibility warning when relying on `f32: From<{float}>` to constrain `{float}`](https://redirect.github.com/rust-lang/rust/pull/139087) - [Rust will use the v0 symbol mangling scheme by default.](https://redirect.github.com/rust-lang/rust/pull/151994) This may cause some tools (such as debuggers or profilers, especially with old versions) to fail to demangle symbols emitted by Rust. It may also cause the formatting of text in backtraces to change. - [Prevent deref coercions in `pin!`, in order to prevent unsoundness.](https://redirect.github.com/rust-lang/rust/pull/153457) The most likely case where this might impact users is: writing `pin!(x)` where `x` has type `&mut T` will now always correctly produce a value of type `Pin<&mut &mut T>`, instead of sometimes allowing a coercion that produces a value of type `Pin<&mut T>`. This coercion was previously incorrectly allowed since Rust 1.88.0. - [Deprecate `std::char` constants and functions](https://redirect.github.com/rust-lang/rust/pull/153873) - [Warn on linker output by default](https://redirect.github.com/rust-lang/rust/pull/153968) - [Remove hidden `f64` methods which have been deprecated since 1.0](https://redirect.github.com/rust-lang/rust/pull/153975) - [report the `varargs_without_pattern` lint in deps](https://redirect.github.com/rust-lang/rust/pull/154599) - [Forbid passing generic arguments to module path segments even if the module reexports a generic enum variant](https://redirect.github.com/rust-lang/rust/pull/154971) - [Error on invalid macho `link_section` specifier](https://redirect.github.com/rust-lang/rust/pull/155065) - The encoding of certain `enum`s [have changed](https://redirect.github.com/rust-lang/rust/pull/155473). This is not a breaking change, as it only applies to `enum`s without layout guarantees, but is noted here as we've seen people impacted from having made assumptions about the layout algorithm. - [Error on `#[export_name = "..."]` where the name is empty](https://redirect.github.com/rust-lang/rust/pull/155515) - [Syntactically reject tuple index shorthands in struct patterns](https://redirect.github.com/rust-lang/rust/pull/155698) - [validate `#[link_name = "..."]` & `#[link(name = "...")]` parameters](https://redirect.github.com/rust-lang/rust/pull/155817) - On Windows, after calling `shutdown` on a socket to shut down the write side, attempting to write to the socket will now produce a `BrokenPipe` error rather than `Other`. [Map `WSAESHUTDOWN` to `io::ErrorKind::BrokenPipe`](https://redirect.github.com/rust-lang/rust/pull/156063) </details> --- ### Configuration 📅 **Schedule**: (in timezone Asia/Shanghai) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNDIuMiIsInVwZGF0ZWRJblZlciI6IjQzLjI0Mi4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Cameron <cameron.clark@hey.com> |
||
|
|
5a9721aa8f |
refactor(react_compiler): use oxc_diagnostics directly, delete react_compiler_diagnostics (#24322)
The crate-private diagnostics data model (`react_compiler_diagnostics`: `CompilerDiagnostic`, `CompilerDiagnosticDetail`, `CompilerErrorDetail`, `CompilerErrorOrDiagnostic`, `ErrorSeverity`) duplicated what `OxcDiagnostic` already models and was converted to it at the program boundary anyway. This deletes the module and has passes construct `OxcDiagnostic` eagerly. ### What survives, and where the category went - `ErrorCategory` stays (it drives TS-parity semantics). The aggregate `CompilerError` recovers it from the deterministic `[ReactCompiler] <Category>: ` message prefix that `ErrorCategory::diagnostic` writes — no field on the diagnostic changes, so consumers see exactly the same `OxcDiagnostic`s as before. Category-driven control flow is preserved: `Invariant` throws from `record_error`, `Config` always trips the panic threshold, and `PreserveManualMemo` displays as an error while staying internally a warning for `panicThreshold: critical_errors`. - `CompilerError` slims to `Vec<OxcDiagnostic>` plus the two control-flow flags (`is_thrown`, `unimplemented`); pass signatures use `Result<T, OxcDiagnostic>` with `From` conversions keeping `?` working. - `js_string.rs` was never diagnostics code (WTF-16 string values) — moved to `react_compiler_utils`. `GENERATED_SOURCE`/`Span` moved to `react_compiler_hir`. ### Output parity Zero output change. The two legacy carrier types rendered labels differently (plain underline vs `span.label(text)`), and thrown Todo/`enter_ssa` errors were flattened to span-only form; each converted site preserves its path's rendering. The 1736-fixture snapshot corpus and the oxlint `react/react-compiler` rule snapshot pass **unchanged** — no snapshot files are touched in this PR. Net −784 lines. `cargo lint` needed a crate-local `result_large_err = "allow"` (the crate defines its own `[lints.clippy]` and doesn't inherit the workspace allow; same rationale — `OxcDiagnostic` is deliberately inlined). 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
06db0c21ef |
refactor(react_compiler): remove no-op debug logging and HIR printers (#24252)
## What
`ProgramContext::log_debug` had an **empty body** — so every
`DebugLogEntry` built behind the ~57 `if context.debug_enabled { … }`
gates in the pipeline (and the 16 `log_reactive_debug!` calls) was
computed and immediately discarded. The `debug` cargo feature gated
~2500 lines of HIR/reactive printers (`print.rs`, `debug_print.rs`,
`print_reactive_function.rs`) that fed only those discarded entries.
`PluginOptions::debug` (public, default `false`) had no consumer other
than toggling that no-op.
## Changes
- Remove the no-op sink: `DebugLogEntry`, `log_debug`,
`ProgramContext::debug_enabled`, `PluginOptions::debug`, the ~57 gated
blocks, and the `log_reactive_debug!` macro.
- Delete the three printers and the `debug` cargo feature.
- Prune the HIR / reactive-IR metadata fields that only the printers
read — reactive terminal/value `span`s (keeping the ones codegen
actually reads, e.g. `ForOf`/`ForIn`), type-annotation metadata — plus
the helpers that became unreachable.
## Notes
- Behavior-preserving: the 1806-fixture snapshot corpus and integration
tests are **byte-identical**, and `oxc_transformer`/`oxc_linter` compile
unchanged.
- Net ~−3000 lines.
Follow-up to #24248.
|
||
|
|
69b2dfc181 |
release(crates): oxc v0.139.0 (#24218)
### 🚀 Features - |
||
|
|
d966d0bfd3 |
fix(react_compiler): remove clippy allows (#24168)
Removes the blanket `clippy::all` module allowances from `oxc_react_compiler` and fixes the resulting diagnostics with mechanical cleanups, targeted item-level allowances, and normal dependency access to `cow-utils`. Validated with `just fmt`, `cargo clippy -p oxc_react_compiler --lib --all-targets -- -D warnings`, and `cargo test -p oxc_react_compiler`. AI-assisted. |
||
|
|
09c8f59654 |
fix(react_compiler): normalize snapshot fixture paths (#24142)
## Summary - Normalize React compiler snapshot names using path components instead of splitting on `/fixtures/`. - Normalize fixture source newlines before parsing so diagnostic byte offsets are stable across Windows and Unix checkouts. - Allow manually dispatched CI runs to execute the Windows cargo test job, without enabling it for normal pull requests. ## Root Cause Windows `insta::glob!` passes fixture paths like `\?\E:\oxc\crates\oxc_react_compiler\fixtures\...`. The old string split only handled Unix `/fixtures/`, so Windows generated absolute-path snapshot names and treated every fixture as a new snapshot. After fixing that, Windows still differed because CRLF fixture checkout shifted diagnostic source offsets relative to LF snapshots. |
||
|
|
6efce65746 |
test(react_compiler): snapshot the upstream fixture corpus (#24101)
## Summary `oxc_react_compiler` had no committed test over the upstream React Compiler fixture corpus — the fixtures lived only in the `oxc-project/forked-react-compiler` checkout, exercised out-of-tree. That gap let real regressions slip past the 15 in-crate integration tests. This PR closes it. - **`crates/oxc_react_compiler/fixtures/`** — 1734 fixture *input* files (`.js`/`.ts`/`.tsx`/`.jsx`/`.mjs`), copied from the fork's `babel-plugin-react-compiler/src/__tests__/fixtures/compiler` tree with subdirectories preserved. Flow fixtures (the `@flow`-pragma ones) are excluded — oxc has no Flow parser. The upstream `.expect.md` goldens are also not copied; insta is the golden here. - **`crates/oxc_react_compiler/tests/snapshot.rs`** — an `insta::glob!` test that, per fixture, derives `PluginOptions`/`EnvironmentConfig` from the first-line `// @directive` pragmas (base `compilationMode=all` / `panicThreshold=all_errors`, matching the upstream `snap` runner), parses → builds semantic → runs `transform`, and snapshots the compiled output plus diagnostics. Unrecognised directives are ignored, as upstream does; camelCase flag directives map to `EnvironmentConfig` fields via `convert_case`. - **`crates/oxc_react_compiler/tests/snapshots/`** — 1734 committed `.snap` goldens (oxc's own output). - **`.typos.toml`** — excludes the fixtures dir (the upstream fixtures contain intentional typos; `**/*.snap` was already excluded). These snapshots are oxc's own golden output, so `cargo test` (and CI) now catches any change in compiler behaviour across the corpus. Regenerate after an intended change with `cargo insta accept`. ## Verification - `cargo test -p oxc_react_compiler` passes — the 1734-fixture snapshot test plus the existing 15 integration tests; also green under `--all-features` (matches the cross-target CI job). - clippy `-D warnings`, `cargo fmt`, and `typos` clean. - No fixture panics; 1336 compiled / 398 unchanged / 335 with diagnostics. - The `error.*` fixtures capture the exact diagnostics — including the "Cannot reassign variable after render" error that a recent scoping change had silently suppressed, confirming the suite catches real regressions. --- AI usage disclosure: authored with Claude Code and reviewed before submission. 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
3cad48d67b |
refactor(react_compiler): gate HIR debug printing behind a debug feature (#24048)
Puts the HIR debug printer (`react_compiler::debug_print`, ~600 lines)
behind a new off-by-default `debug` cargo feature, so it isn't compiled
into normal builds.
### How
- `Cargo.toml`: add `[features]` with `debug = []`.
- `react_compiler/mod.rs`: `#[cfg(feature = "debug")]` on `pub mod
debug_print;`, plus a `#[cfg(not(feature = "debug"))]` no-op stub module
exposing the two entry points the pipeline calls (`debug_hir`,
`format_hir_function_into`).
The printer is threaded through the vendored `pipeline.rs` at ~70 `if
context.debug_enabled { … }` sites (plus a closure capture and a local
formatter fn that are required pass arguments). Gating each site would
scatter ~75 `#[cfg]` attributes through vendored code and fight
re-syncability, so gating the module with a stub keeps
`pipeline.rs`/`imports.rs` untouched while still compiling the printer
out by default.
### Behavior
No change to default builds: nothing in the workspace sets
`PluginOptions::debug`, so the printer was never triggered. To get HIR
dumps, build with `--features oxc_react_compiler/debug` and set
`PluginOptions::debug = true`.
### Verified
- Default build (stub) and `--features debug` (real printer) both
compile clean.
- `oxc_react_compiler` tests pass in both modes (15/15); clippy clean in
both.
- `oxc`, `oxc_linter`, `oxc_transformer` build with default features.
|
||
|
|
64683a7784 |
refactor(react_compiler): drop the oxc_parser dependency (#24038)
Removes `oxc_parser` from `oxc_react_compiler`'s library dependencies. The compiler is handed an already-parsed `Program` (via `transform`/`lint`), so the library itself no longer needs to parse anything. The only remaining `src/` use was in `codegen_reactive_function.rs`, when re-emitting a stored TS type annotation (on an `as`/`satisfies` cast) whose inner identifiers had binding renames applied. The old code sliced the original source, applied the renames as text edits, wrapped the result in `let __oxc_t = null as …;`, and **re-parsed** it. That path is replaced with a `clone_in` of the stored `TSType` followed by an in-place identifier rename via `VisitMut`. `clone_in` preserves spans, so the renames stay keyed by source offset — the exact same reference set that drove the text edits before. Both approaches rename the same identifiers (both are driven by the `visit_ts_type` walk plus the `reference_node_ids`/`renames` filter) and yield structurally identical ASTs, so codegen output is unchanged. It's also cheaper (no source slicing, no re-parse) and can no longer fail, so the helper's return type drops from `Option<TSType>` to `TSType` and the dead `None` fallback at the two call sites is removed. `oxc_parser` moves to `[dev-dependencies]` (the example and integration tests still parse source). Depends on the API in #24028 (already merged). |
||
|
|
3c2a0f0e39 |
refactor(react_compiler): drop the old AstBuilder compat shim (#24027)
## Summary Follow-up cleanup after the de-Babel (#24009). The ported codegen called deprecated inherent `AstBuilder` methods (`vec` / `alloc` / `expression_*` / `statement_*` / …), which the crate's `disable_old_builder` dev-dep flags for migration; a compat trait `OldBuilderExt` (`old_builder_ext.rs`) mirrored them on the new API to ease the port. This removes that shim: all ~300 call sites (`codegen_reactive_function.rs` + `program.rs`) now use the new `AstBuilder` API directly (`ArenaVec::*_in` / `ArenaBox::new_in` / `Type::new_*`), and `old_builder_ext.rs` (~1.7k lines) is deleted. The now-unused `oxc_str` dependency is dropped. ## Verification - No deprecated builder methods remain (`cargo check` reports 0 `use of deprecated`). - clippy `--all-features --all-targets -D warnings`: clean. - Differential over the 1,805 upstream React Compiler fixtures: byte-identical (`same=1805 diff=0`). - 15 integration tests pass; `cargo shear` / `cargo fmt --check` / `typos` clean. --- Produced with AI assistance (Claude Code); verified byte-identical against the 1,805-fixture differential and the crate's tests. |
||
|
|
269ce46cdb |
test(react_compiler): move end-to-end tests to tests/, drop internal unit tests (#24022)
## Summary Follow-up to #24009 (de-Babel). Now that `oxc_react_compiler` speaks the oxc AST natively, this tidies its test + dependency layout: - **Move the 15 end-to-end tests to `tests/transform.rs` as integration tests** — they exercise the crate through its public `transform_source` API instead of `#[cfg(test)]` modules inside `lib.rs`. - **Remove the internal unit tests** (function discovery, `JsString`, HIR `Environment`, codegen hashing, prefilter) — the crate is covered through its public API. - **Move `oxc_codegen` to `[dev-dependencies]`** — the library builds the oxc AST but never codegens it; only the example and integration tests print the program. Net −397 lines. ## Verification - `cargo test -p oxc_react_compiler`: 15 integration tests pass, 0 unit. - Differential over the 1,805 upstream React Compiler fixtures: byte-identical (`same=1805 diff=0`). - clippy `-D warnings`, `cargo fmt --check`, `typos`, `cargo shear`: clean. Example builds. --- Produced with AI assistance (Claude Code); verified byte-identical against the 1,805-fixture differential and the crate's tests. --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> |
||
|
|
36088087f8 |
refactor(react_compiler): replace the vendored Babel AST with the oxc AST (#24009)
## Summary
`oxc_react_compiler` (the Rust port of the React Compiler) worked internally on a **vendored Babel-shaped AST**: the pipeline converted the oxc `Program` into that AST, compiled against it, then converted back to oxc for codegen. That cost ~6k lines of conversion glue plus a whole Babel-AST module, and it couldn't carry TypeScript type nodes through the IR (type annotations were serialized to JSON and re-parsed from source).
This PR removes the Babel AST entirely. The compiler now consumes the **oxc AST natively**: it lowers the oxc AST directly to the HIR, and codegen builds oxc via `AstBuilder` and splices the compiled functions into the `&mut Program` in place. Since oxc already models every TS type-annotation node, the HIR carries borrowed `&'a TSType<'a>` nodes directly instead of re-parsing.
```
oxc Program → convert_scope → discovery (oxc_ast_visit::Visit)
→ build_hir (oxc AST → HIR) → passes
→ codegen (oxc AstBuilder) → splice into &mut Program
```
## Commits
1. `RawNode` JSON blob → structured metadata; drop serde / serde_json
2. Front-end: lower the oxc AST → HIR directly (transitional span-bridge)
3. Back-end: codegen emits oxc via `AstBuilder` + splices in place; delete `convert_ast_reverse`
4. Delete the vendored `react_compiler_ast` + `convert_ast`; discovery walks the oxc `Program`
5. Thread `'a` through the HIR to carry `&'a TSType` / `&'a Statement` (no source-reparse)
Net **−13k lines** (71 files).
## Verification
Every commit is **byte-identical** to the pre-change compiler over the 1,805 upstream React Compiler fixtures (`same=1805 diff=0`), and `cargo test -p oxc_react_compiler` (38 tests) passes throughout. The public API (`transform(&mut Program)` / `lint` / `TransformResult`) is unchanged.
## Follow-ups (not in this PR)
- The codegen still calls deprecated `AstBuilder` methods (surfaced by `disable_old_builder`); they need migrating to the new builder interface (#23043) and the transitional `old_builder_ext.rs` shim removed. **CI `-D warnings` will flag these until then.**
- Optional ecosystem-fidelity fixes not covered by the fixture suite.
---
Produced with AI assistance (Claude Code); all output verified byte-identical against the 1,805-fixture differential and the crate's tests.
|
||
|
|
74fb16871f |
refactor(react_compiler): vendor forked-react-compiler crates as in-crate modules (#23993)
## Summary Vendors the React Compiler *core* — the 12 `react_compiler*` crates from the MIT fork [oxc-project/forked-react-compiler](https://github.com/oxc-project/forked-react-compiler) @ `58d13c6` — directly into `crates/oxc_react_compiler`, one module per upstream crate, **replacing the three crates.io `forked_react_compiler*` dependencies**. This lets us edit and re-sync the compiler core in-tree instead of consuming it as published crates. The oxc↔Babel conversion boundary (`convert_ast`, `convert_ast_reverse`, `convert_scope`, `prefilter`, …) is unchanged. ## How Two commits, kept separate for reviewability: 1. **Verbatim copy** — the 12 crates' `src/` trees copied unmodified (114 files, `lib.rs` → `mod.rs`). Diff this commit against upstream to confirm fidelity. 2. **Wire-up** — a scripted, compiler-verified path rewrite: - each module's own `crate::` → `crate::<module>::`; sibling refs `react_compiler_x::` → `crate::react_compiler_x::` - `lib.rs` declares the 12 modules — `pub` (so the public API can name types that originate in them) and `#[allow(clippy::all, dead_code, unused)]` (kept near byte-for-byte with upstream) - `Cargo.toml`: drop the 3 fork deps; add the externals they need (`serde`, `serde-transcode`, `hmac-sha256`) and extend `serde_json` features - add `hmac-sha256` + `serde-transcode` to the workspace dependencies; allowlist 4 vendored local-variable abbreviations in `.typos.toml` ## Verification - `cargo test -p oxc_react_compiler`: **38 pass** (boundary smoke tests + vendored inline tests); codegen output byte-identical - `cargo ck` (workspace, all-features/targets, `--locked`), clippy (default + `dev-no-debug-assertions`), `cargo doc -D warnings`, `fmt`, `typos`, `cargo shear`, `cargo deny` — all clean - dependents build: `oxc_transformer --features react_compiler`, `oxc_linter` Behavior is unchanged — same compiler code, only module paths differ. --- 🤖 Generated with [Claude Code](https://claude.com/claude-code) — AI-assisted, reviewed before submission (per the repo AI usage policy). |
||
|
|
8bf69a3076 |
release(crates): oxc v0.138.0 (#23934)
### 💥 BREAKING CHANGES - |
||
|
|
3d61dea7e2 |
docs(all): correct capitalization in comments (#23887)
Just fix capitalization in comments. |
||
|
|
f2091b3846 |
feat(ast): unify old and new AstBuilders (#23875)
Part of #23043. Recent PRs have introduced a new `AstBuilder` type, and migrated all Oxc's crates over to it. To allow downstream consumers to incrementally migrate from old `AstBuilder` to new one, unify the two implementations into a single `AstBuilder` type. Remove the `builder_new` Cargo feature and instead add a new feature `disable_old_builder`. When enabled, this feature removes all the methods from `AstBuilder`, and makes `AstBuilder` non-`Copy`. Consumers should migrate, and then enable this feature to ensure later changes don't use the methods which are slated for removal. Enable the `disable_old_builder` feature in all Oxc crates which use `AstBuilder` _in tests_. This ensures we don't go back to using the deprecated methods, while not forcing the feature on consumers (e.g. Rolldown) who use e.g. `oxc_transformer` but also use `AstBuilder` directly. |
||
|
|
3ea9304bd4 |
perf(react_compiler): use faster API to arena allocate strings (#23849)
Small perf optimization to React Compiler. Replace `ArenaStringBuilder::from_str_in(s, self.allocator).into_str()` with `Str::from_str_in(s, self)`. The latter is faster - `ArenaStringBuilder` is designed for building up a string from multiple parts. Here we just want to allocate a single string, so `Str::from_str_in` is faster, and simpler. Using `ArenaStringBuilder` was a weird choice. 🚨 Slop alert! 🚨 Also, return a `Str<'a>`. There's no advantage to coverting to a `&str`, and this removes having to convert _back_ to a `Str` elsewhere. |
||
|
|
8e31977907 |
refactor(react_compiler): switch to new AstBuilder (#23838)
Part of #23043. Migrate `oxc_react_compiler` over to new `AstBuilder`. |
||
|
|
6d56d57535 |
release(crates): oxc v0.137.0 (#23591)
### 💥 BREAKING CHANGES - |
||
|
|
2bac45ecc7 |
chore(react_compiler): bump forked_react_compiler to 0.2.0 (#23581)
Bumps `forked_react_compiler`, `forked_react_compiler_ast`, and `forked_react_compiler_hir` from `0.1.4` to the published `0.2.0` and adapts the OXC ↔ React Compiler AST bridge to the new API. ## API changes adapted - **`RawNode`** — type-annotation and TS passthrough fields moved from `Box<serde_json::Value>` to the lazily-parsed `RawNode`. Construct via `RawNode::from_value` / `RawNode::null`; read back via `parse_value()`. - **`StringLiteral.value`** is now a JS string type — write with `.into()`, read with `.to_string_lossy()`. - **`ScopeInfo`** maps now use the deterministic Fx hasher (`FxHashMap` / `FxIndexMap`) to match the upstream field types. - **`PluginOptions`** no longer derives `Deserialize`; the test constructs it typed via `default_plugin_options()`. ## Binary size (`napi/transform`) Net **−533 KiB (−7.2%)** on the shipped binary, despite 0.2.0 pulling in new transitive deps. Measured as the release cdylib (fat-LTO, `--features allocator`, `aarch64-apple-darwin`, stripped); only the bump differs between the two builds. | Segment | Before (`main`) | After (this PR) | Δ | |---|--:|--:|--:| | **Total file** | 7,554,352 B | 7,008,592 B | **−545,760 B (−7.2%)** | | `__TEXT` (code) | 7,274,496 B | 6,750,208 B | −524,288 B | | `__DATA_CONST` | 163,840 B | 147,456 B | −16,384 B | | `__LINKEDIT` | 98,304 B | 81,920 B | −16,384 B | Almost all of it is `__TEXT` — likely the eager `serde_json::Value` machinery dropped in favor of `RawNode`'s lazily-parsed raw JSON. ## Verification - `cargo test -p oxc_react_compiler` — 17 passed - `cargo check -p oxc_linter` and `cargo check -p oxc_transformer --features react_compiler` — both clean --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> |
||
|
|
827248a7fb |
release(crates): oxc v0.136.0 (#23443)
### 💥 BREAKING CHANGES - |
||
|
|
ec266bb733 |
feat(transformer): run React Compiler as a feature-gated transform pass (#23201)
## Summary Exposes the React Compiler from `oxc_transformer` behind a Cargo feature so callers no longer need a separate `oxc_react_compiler::transform` + scoping-rebuild step before transforming. - **`oxc_transformer`**: new `react_compiler` Cargo feature (off by default) + `TransformOptions::react_compiler` field. When set, `Transformer::build_with_scoping` runs the React Compiler first (via a private `run_react_compiler` method), replacing the program and rebuilding scoping for the downstream transforms. - **Opt-in**: the feature is **not** enabled by `oxc_transformer`'s defaults, nor by `oxc`'s `transformer`/`full` features — enabling the transformer does not pull the heavy `oxc_react_compiler` dependency. It is a separate `react_compiler` feature on `oxc` (which implies `transformer`); the napi transform binding opts in explicitly. - **Dedupe**: removes the inline React-Compiler orchestration (and the `react_compiler_options()` hook) from `oxc`'s `CompilerInterface` and the napi transform binding; both now drive it through `TransformOptions::react_compiler`. - **Diagnostics**: the compiler's errors and warnings are merged into `TransformerReturn::errors` (each keeps its severity; downstream filters). `compile()` reports them but no longer aborts codegen — the transformer always leaves a valid program, matching the documented "code may still be available even if there are errors" behaviour. - **Links**: updates the React Compiler references to the merged upstream location (`react/react/tree/main/compiler`). ## Notes Transform/codegen output is unchanged when the feature is off (the field defaults to `None` everywhere). The diagnostics behaviour change (no codegen abort) is conformance-safe — the transform-conformance harness keys off reported diagnostics, not printed output. 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
48c6f28c4a |
refactor(react_compiler): split diagnostics into errors/warnings and simplify transform API (#23168)
## What Reworks the `oxc_react_compiler` public API: - Renames the standalone `run` entrypoint to `transform`. It now returns a `TransformResult` instead of taking a `&mut errors` vec and rebuilding `Scoping` internally. Callers use `result.program` (`Some`/`None`) to decide whether to rebuild scoping — the `oxc::Compiler` callsite does exactly this. - Splits `TransformResult`/`LintResult` diagnostics into separate `errors` and `warnings` (partitioned by `Severity`), and documents `errors` / `warnings` / `events`. - Adds `#[derive(Default)]` to `TransformResult` for the bail-out paths. - Inlines the former `transform_impl`; semantic is now built internally, after the cheap prefilter bail-outs (so non-React files skip semantic construction). - Bumps the `forked_react_compiler` family `0.1.3` → `0.1.4`. Example and benchmark updated to the new `transform(&program, &allocator, options)` signature. 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
e9b8fd595c |
release(crates): oxc v0.135.0 (#23117)
### 💥 BREAKING CHANGES - |
||
|
|
b846ab2d9a |
feat(react_compiler): integrate the Rust port of the React Compiler (#22942)
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×)** | |