Commit Graph

21 Commits

Author SHA1 Message Date
Boshen e74de61886 fix(transform-react): match Babel diagnostic reporting (#26128)
Match Babel’s default React Compiler diagnostic reporting and severity.

AI-assisted.
2026-08-27 05:27:21 +00:00
Boshen 28c0493682 fix(react-compiler): support typed assignment targets (#25758)
Support TypeScript-wrapped assignment targets in context analysis and
HIR lowering.

AI-assisted; reviewed and validated by the contributor.
2026-08-17 17:22:29 +08:00
Boshen dec0a86412 fix(react-compiler): standardize diagnostics (#25702)
Standardize React Compiler diagnostics with concise titles, primary labels, actionable help, notes, structured categories, and official guidance links.

Preserve React guidance when diagnostics are surfaced through Oxlint, and refresh affected snapshots.

AI-assisted; reviewed and validated by the contributor.
2026-08-15 13:31:34 +00:00
Boshen ad963b689d refactor(react_compiler): centralize diagnostics (#25699)
Centralizes React compiler diagnostics in explicit `#[cold]` functions and removes the `[ReactCompiler]` prefix, keeping diagnostic formatting off hot paths. Updates related NAPI expectations.

AI assistance was used.
2026-08-15 05:57:29 +00:00
Boshen 8d7f9cff3f fix(react_compiler): honor eslint suppressions (#25394)
Honor React ESLint suppressions independently of internal compiler validation settings, matching `babel-plugin-react-compiler@1.0.0`.

Closes #25392.

AI-assisted.
2026-08-10 10:42:23 +00:00
Boshen 28c2e09838 feat(react_compiler): recognize oxlint suppressions (#25456)
Recognize `oxlint-disable*` and `oxlint-enable` comments wherever React Compiler accepts their ESLint-prefixed equivalents.

AI-assisted.
2026-08-10 05:19:14 +00:00
Boshen 92426aefeb fix(react_compiler): align nested ref validation (#25427)
Align ref validation with Babel React Compiler 1.0 by limiting call-site alias-effect checks to values actually passed to the call. This keeps refs captured by returned event handlers valid while preserving diagnostics for refs passed to invoked functions.

Validated with `cargo test -p oxc_react_compiler`, the rebuilt `oxc-transform-react` binding against Outline’s `ContentEditable.tsx`, and `just ready`.

AI-assisted; the contributor remains responsible for review and submission.
2026-08-09 13:15:18 +00:00
Boshen 937825c6a6 fix(react_compiler): disable exhaustive memo validation by default (#25417)
Disable exhaustive memo dependency validation by default and align
suppression handling.

AI-assisted.

<sub>Stack created with <a
href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a
href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>
2026-08-09 11:18:12 +08:00
Boshen ad4479ea28 test(react_compiler): cover manual memo semantics (#25415)
Cover manual memoization semantics.

AI-assisted.

<sub>Stack created with <a
href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a
href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>
2026-08-09 11:18:12 +08:00
camc314 1bdedd11ca feat(ast)!: introduce ExportDeclaration, ExportFromDeclaration (#25095)
## Summary

Split the overloaded Rust `ExportNamedDeclaration` into syntax-specific AST nodes:

- `ExportDeclaration` for exported declarations
- `ExportNamedDeclaration` for local exports
- `ExportFromDeclaration` for re-exports

## Breaking Change

The Rust AST changes from:

```rust
pub struct ExportNamedDeclaration<'a> {
    pub node_id: Cell<NodeId>,
    pub span: Span,
    pub declaration: Option<Declaration<'a>>,
    pub specifiers: Vec<'a, ExportSpecifier<'a>>,
    pub source: Option<StringLiteral<'a>>,
    pub export_kind: ImportOrExportKind,
    pub with_clause: Option<Box<'a, WithClause<'a>>>,
}

pub enum ModuleDeclaration<'a> {
    // ...
    ExportNamedDeclaration(Box<'a, ExportNamedDeclaration<'a>>),
    // ...
}
```

to:

```rust
pub struct ExportDeclaration<'a> {
    pub node_id: Cell<NodeId>,
    pub span: Span,
    pub declaration: Declaration<'a>,
}

pub struct ExportNamedDeclaration<'a> {
    pub node_id: Cell<NodeId>,
    pub span: Span,
    pub specifiers: Vec<'a, ExportSpecifier<'a>>,
    pub export_kind: ImportOrExportKind,
}

pub struct ExportFromDeclaration<'a> {
    pub node_id: Cell<NodeId>,
    pub span: Span,
    pub specifiers: Vec<'a, ExportSpecifier<'a>>,
    pub source: StringLiteral<'a>,
    pub export_kind: ImportOrExportKind,
    pub with_clause: Option<Box<'a, WithClause<'a>>>,
}

pub enum ModuleDeclaration<'a> {
    // ...
    ExportDeclaration(Box<'a, ExportDeclaration<'a>>),
    ExportNamedDeclaration(Box<'a, ExportNamedDeclaration<'a>>),
    ExportFromDeclaration(Box<'a, ExportFromDeclaration<'a>>),
    // ...
}
```

## Why?

The previous node represented three distinct syntax forms through optional and mutually exclusive fields:

```text
export const value = 1;       -> ExportDeclaration
export { value };             -> ExportNamedDeclaration
export { value } from "mod";  -> ExportFromDeclaration
```

This allowed invalid combinations such as declarations with specifiers or sources, and import attributes without a source. The new nodes make these states unrepresentable and remove repeated `declaration`/`source` branching from consumers.

## How to migrate

Match the syntax-specific `ModuleDeclaration`, `Statement`, or `AstKind` variant instead of inspecting optional fields. Generated builders, visitors, traversal ancestors, and formatter wrappers now expose corresponding APIs for all three nodes.

Common field migrations:

| Previous representation | New representation |
| --- | --- |
| `declaration: Some(declaration)` | `ExportDeclaration { declaration }` |
| `declaration.as_ref()` | `&export.declaration` |
| `source.is_none()` for local exports | Match `ExportNamedDeclaration` |
| `source: Some(source)` | `ExportFromDeclaration { source }` |
| `source.as_ref().unwrap()` | `&export.source` |
| `with_clause` | Only available on `ExportFromDeclaration` |
| Stored `export_kind` on exported declarations | `ExportDeclaration::export_kind()` |
| `ExportNamedDeclaration::boxed_plain_declaration(...)` | `ExportDeclaration::boxed(...)` |
| `ExportNamedDeclaration::boxed(..., None, specifiers, None, ...)` | `ExportNamedDeclaration::boxed(..., specifiers, ...)` |
| `ExportNamedDeclaration::boxed(..., None, specifiers, Some(source), ...)` | `ExportFromDeclaration::boxed(..., specifiers, source, ...)` |

closes https://github.com/oxc-project/backlog/issues/219
2026-07-31 10:25:47 +00:00
Boshen 5d8ccf510b fix(react_compiler): preserve nonfatal diagnostics (#25066)
Preserves nonfatal React Compiler diagnostics and covers warning bailouts through the N-API binding.

AI-assisted.
2026-07-29 13:09:20 +00:00
Boshen d349e4a449 fix(react_compiler): match eslint suppression gating (#25068)
Matches React Compiler ESLint suppression gating for internal validation options.

AI-assisted.
2026-07-29 12:41:00 +00:00
Boshen 9d7745af95 fix(react-compiler): preserve warning bailouts (#24935)
Preserve warning-level React Compiler diagnostics instead of wrapping pipeline bailouts in a synthetic fatal error. This keeps expected incompatible-library and Todo bailouts non-fatal so sibling functions can still compile.

Adds regression coverage and refreshes the affected snapshots. Validated with `just ready`.

AI-assisted: Codex was used to investigate, implement, and validate this change.
2026-07-26 06:26:02 +00:00
Boshen 4b81f4d963 fix(react_compiler): honor default suppressions (#24747)
Honor Babel React Compiler 1.0.0's default ESLint and Flow suppression bailouts even when validation flags are enabled.

Validation:
- `cargo test -p oxc_react_compiler`
- `cargo clippy -p oxc_react_compiler --all-targets -- -D warnings`
- Direct fixture comparison with `babel-plugin-react-compiler@1.0.0`

Caveat: Babel 1.0.0 treats block disables as open-ended; this change preserves that behavior.

AI-assisted.
2026-07-21 07:02:25 +00:00
Boshen 6427542c8d refactor(react_compiler): split public API into compile + in-place CompileOutput::transform (#24401)
Splits `oxc_react_compiler`'s public API into two phases so the transform rewrites the caller's program in place instead of returning a whole-program clone:

- `compile(&Program, &Semantic, &Allocator, PluginOptions) -> (Option<CompileOutput>, Diagnostics)` — read-only; `None` means no changes (or error / lint output mode).
- `CompileOutput::transform(self, &mut Program, &Allocator)` — substitutes the compiled functions into the program in place. `CompileOutput` owns only arena data (replacements + `ProgramContext`), so the caller drops its `Semantic` between the two calls, releasing the shared borrow that previously forced `ox_splice_program` to `clone_in_with_semantic_ids` the entire program.
- `lint` is unchanged and structurally never runs the transform phase; the oxlint rule needed no changes.

The old `transform` free function and `TransformResult` are removed; `oxc_transformer` no longer does the `*program = result.program.take()` swap and just applies the output to its `&mut Program`.

The 1806-fixture snapshot corpus is byte-identical, and the transform path drops one whole-program clone per compiled file.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-07-12 14:35:19 +00:00
Boshen 26db2f152b refactor(react_compiler): prune dangling comments in place after compile (#24258)
## What

Simplify the post-compile comment cleanup in `oxc_react_compiler`.

The output program is built by cloning the source (`ox_splice_program` → `program.clone_in()`), and `CloneIn` for `Program` copies both `comments` and `source_text`. So the compiled program already carries every original comment and the correct `source_text` before the cleanup step runs.

The old `preserve_comments` re-derived that from scratch:

- allocated a second `ArenaVec` and re-filtered `source.comments` into it, then
- re-assigned an already-correct `source_text`,

which forced it to take `source: &Program` and `allocator` params it didn't need.

## Change

Filter the already-cloned `compiled.comments` in place with `retain`, dropping the extra allocation, the redundant `source_text` write, and both params. Renamed to `prune_inner_comments`, and corrected the doc comments — the old ones claimed the roundtrip *drops* comments, when it actually clones them and this step prunes only the ones anchored inside rewritten functions (whose spans no longer resolve).

## Verification

Output is unchanged: the fixture snapshot suite passes byte-identical (no `.snap` updates) and all 15 unit tests pass. `cargo clippy -p oxc_react_compiler --all-targets` is clean.
2026-07-07 09:15:35 +00:00
Boshen 8dd81f2e65 refactor(react_compiler): remove unused js options (#24065)
Removes unused upstream JS option fields from Oxc's React Compiler options and deletes the dead filename plumbing they carried through the compile environment.

Stacked on #24063.

AI-assisted.
2026-07-02 11:54:58 +00:00
Boshen 1fff15c499 refactor(react_compiler): borrow semantic in compile pipeline (#24063)
Borrow existing semantic data and caller allocator in React Compiler transform/lint paths to avoid hidden rebuild/allocation work.

Transform now returns the compiled program so callers can install it after the semantic borrow ends.

AI-assisted.
2026-07-02 10:17:42 +00:00
Boshen 579f025c7c refactor(react_compiler): trim PluginOptions and remove timing instrumentation (#24042)
Slims down `oxc_react_compiler`'s `PluginOptions` and removes the now-dead timing infrastructure. Four related cleanups:

### Remove `source_code` from `PluginOptions`
It was redundant — `compile` in `lib.rs` always overwrote it with `program.source_text`, and no caller set it. The one consumer (`ProgramContext::new` in `program.rs`) now reads `program.source_text` directly (the oxc `Program` is already in scope there), and the threading block in `lib.rs` is gone.

### `default_plugin_options()` → `impl Default for PluginOptions`
Converted the free function into a manual `Default` impl (the defaults are non-trivial: `should_compile: true`, `target: "19"`, `flow_suppressions: true`, …). All callers now use `PluginOptions::default()`.

### Remove `profiling`
The field was always `false` in practice (no caller set it). Its sole consumer now passes `TimingData::new(false)` — which leads into…

### Remove the timing instrumentation entirely
With `profiling` gone, timing was pure, always-disabled instrumentation: every `context.timing.start/stop` was a no-op and the collected `Vec<TimingEntry>` was always empty and never read (`lib.rs` destructures `CompileResult` with `..`). Removed:
- `timing.rs` (the `TimingData`/`TimingEntry` module) and its `mod` declaration
- ~218 `context.timing.start/stop(...)` calls across `pipeline.rs`
- the `timing` field on `ProgramContext` and on both `CompileResult` variants, plus all initializers

### Verification
- `oxc_react_compiler`: builds, 15/15 tests pass.
- `oxc_linter`: `react_compiler` rule snapshot test passes — **snapshot unchanged** (diagnostics identical).
- `oxc_transformer` react_compiler integration: 2/2 pass; `oxc_benchmark` bench compiles.
- rustc warnings, clippy (`dev-no-debug-assertions`), and `cargo shear` all clean.
2026-07-02 06:21:54 +00:00
Boshen f27bbc7760 refactor(react_compiler): remove transform_source and lint_source (#24028)
Remove the `transform_source` and `lint_source` convenience wrappers from `oxc_react_compiler`'s public API.

- `lint_source` had no callers anywhere in the workspace.
- `transform_source` (parse-then-`transform`) was only used by the crate's own integration tests, so it moves into `tests/transform.rs` as a private helper — the 17 call sites are unchanged.
- Dropped the now-unused `oxc_parser::Parser` import in `lib.rs` and narrowed `oxc_span::{GetSpan, SourceType}` to `GetSpan`.

`transform`, `lint`, and `LintResult` are kept — they remain in use by the benchmark/example (`transform`) and the `react/react_compiler` linter rule (`lint`).
2026-07-02 02:07:47 +00:00
Boshen 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>
2026-07-02 08:12:43 +08:00