mirror of
https://github.com/oxc-project/oxc.git
synced 2026-09-14 19:36:11 +08:00
agent/benchmark-upstream-react-compiler
8 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
00e1b762e0 |
refactor(diagnostics): vendor oxc-miette (#25499)
We no longer need to maintain the `oxc-miette` repo as most of the code is now removed, the remaining code is minimal and can be vendored. |
||
|
|
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
|
||
|
|
66e1a25c0e |
chore(all): fix clippy::manual_assert_eq (#24351)
|
||
|
|
dbbc059eff |
perf(jsdoc): skip should_attach_jsdoc when no remaining comments (#22409)
## Summary `JSDocBuilder::retrieve_attached_jsdoc` is called for every AST node during the semantic build. Even when the source contains no JSDoc comments, the per-node `should_attach_jsdoc(kind)` `matches!` over 33 variants still runs. This adds a fast-path early return when `not_attached_docs` is empty — true for files with no JSDoc, and for the tail of every walk once all comments have been attached — and marks `retrieve_attached_jsdoc` `#[inline]` so the guard fuses into `SemanticBuilder::create_ast_node`. ## Measurements `xcrun xctrace record --template 'Time Profiler'`, semantic stage on the standard benchmark inputs. Profile binary built with `--profile release-with-debug`. `retrieve_attached_jsdoc` self-time: | file | before | after | |---|---|---| | antd.js (6.7M, sparse JSDoc) | 2.59% | **0.04%** | | checker.ts (2.8M, JSDoc throughout) | 3.23% | **0.17%** | Hot-path bundle (retrieve + should_attach + create_ast_node) drops ~2pp on both files. Wall-time on 50 iters of parse+semantic: antd −9%, checker −8%, cal.com.tsx −5%. ## Notes - `should_attach_jsdoc` still runs when there are comments left to attach, so behavior is unchanged. - The `#[inline]` lets LLVM fuse the empty-map check into the visitor body, which is what amplifies the win on JSDoc-heavy inputs (the guard fires once all comments are placed). 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
611b3b69ef |
chore(deps): update dependency rust to v1.95.0 (#21509)
This PR contains the following updates: | Package | Update | Change | |---|---|---| | [rust](https://redirect.github.com/rust-lang/rust) | minor | `1.94.1` → `1.95.0` | --- ### Release Notes <details> <summary>rust-lang/rust (rust)</summary> ### [`v1.95.0`](https://redirect.github.com/rust-lang/rust/compare/1.94.1...1.95.0) [Compare Source](https://redirect.github.com/rust-lang/rust/compare/1.94.1...1.95.0) </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:eyJjcmVhdGVkSW5WZXIiOiI0My4xMjMuOCIsInVwZGF0ZWRJblZlciI6IjQzLjEyMy44IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> |
||
|
|
4fec907ad5 |
feat(formatter): add JSDoc comment formatting support (#19828)
## Summary Implements native JSDoc comment formatting in oxfmt, porting behavior from [prettier-plugin-jsdoc](https://github.com/hosseinmd/prettier-plugin-jsdoc) (v1.8.0). Tracked in #19702. ### Conformance **145/145 (100%)** compatibility with prettier-plugin-jsdoc test suite. - 1 fixture intentionally skipped (`descriptions/032-jsx-tsx-css`) — requires embedded CSS/HTML formatter callbacks not available in the standalone conformance runner - Run with: `cargo run -p oxc_prettier_conformance -- --jsdoc` Prettier conformance (non-JSDoc): - **JS**: 746/753 (99.07%) - **TS**: 591/601 (98.34%) ### Real-World Repository Testing Validated against 5 real-world repositories (7,542 JSDoc tags total) using Prettier 3.8.1 + prettier-plugin-jsdoc 1.8.0 as baseline: | Repository | JSDoc Tags | Files with Diffs | |------------|-----------|-----------------| | evolu | 134 | 13 | | wxt | 1,183 | 1 | | typedoc | 792 | 11 | | Chart.js | 1,276 | 4 | | svelte | 4,157 | 5 | | **Total** | **7,542** | **34** | All 34 remaining diffs are **intentional design differences**, not bugs: - `{@link}` kept atomic (upstream breaks across lines) — ~11 files - `{@includeCode}` placed on own line (upstream splits tag syntax) — 3 files - Sub-list continuation indent normalized to 4-space — 5 files - `?Type` expanded to `Type | null` — 1 file - Minor line-break position differences — 5 files - Double-space normalized to single space — 1 file 10 upstream bugs documented in `tasks/prettier_conformance/jsdoc/upstream-jsdoc-bugs.md` — oxfmt intentionally produces correct output where the upstream plugin has known issues. ### Performance Measured with `hyperfine` using `oxfmt --check` on real-world repos (16 threads): | Repository | Without JSDoc | With JSDoc | Overhead | |------------|--------------|------------|-------------| | evolu | 434ms | 427ms | ~0% (noise) | | wxt | 410ms | 410ms | ~0% (noise) | | typedoc | 532ms | 567ms | ~7% | | Chart.js | 497ms | 479ms | ~0% (noise) | | svelte | 510ms | 549ms | ~8% | typedoc and svelte (highest JSDoc density) show measurable ~7-8% wall-clock overhead. The rest are within noise. CPU time overhead is ~1-2% as JSDoc work parallelizes across threads. ### Architecture The formatting pipeline processes each JSDoc comment through these stages: 1. **Parse** — Extract JSDoc structure via `oxc_jsdoc` (description, tags with type/name/comment) 2. **Normalize** — Canonicalize tag aliases (`@return` → `@returns`), normalize types (`Array.<T>` → `T[]`, `?Type` → `Type | null`), normalize markdown emphasis (`__bold__` → `**bold**`, `*italic*` → `_italic_`) 3. **Sort & Group** — Sort tags by upstream priority weights within `@typedef`/`@callback` groups; reorder `@param` tags to match function signature 4. **Format** — Route each tag to its specific formatter (type+name+comment, type+comment, generic, example); format descriptions via markdown AST with word wrapping; format embedded code blocks 5. **Serialize** — Assemble final comment with `/** ... */` wrapper, `* ` prefixes, and single-line optimization **Key modules:** - `serialize.rs` — Main pipeline orchestrator (`JsdocFormatter` struct) - `tag_formatters.rs` — Tag-specific formatters (type+name+comment, type+comment, generic, example) - `normalize.rs` — Type/emphasis/capitalization normalization - `mdast_serialize.rs` — Markdown AST → formatted text serialization with `tag_string_length` offset - `wrap.rs` — Word wrapping with `first_line_offset`, atomic JSDoc link tokens, table formatting - `embedded.rs` — Embedded JS/TS/JSX/TSX code formatting in @example blocks - `imports.rs` — `@import` tag parsing, merging, and sorting - `param_order.rs` — `@param` tag reordering to match function signature - `line_buffer.rs` — Single-allocation line accumulator ### Options Support All 11 options from prettier-plugin-jsdoc are implemented: | Option | Default | Status | |--------|---------|--------| | `capitalizeDescriptions` | `true` | ✅ | | `commentLineStrategy` | `"singleLine"` | ✅ | | `separateTagGroups` | `false` | ✅ | | `separateReturnsFromParam` | `false` | ✅ | | `bracketSpacing` | `false` | ✅ | | `descriptionWithDot` | `false` | ✅ | | `addDefaultToDescription` | `true` | ✅ | | `preferCodeFences` | `false` | ✅ | | `lineWrappingStyle` | `"greedy"` | ✅ (greedy + balance) | | `descriptionTag` | `false` | ✅ | | `keepUnparsableExampleIndent` | `false` | ✅ | **Not yet ported** (no conformance fixtures): `jsdocVerticalAlignment`, `tsdoc` mode — can be added when needed. ### Features - **Description formatting**: Capitalize first letter, normalize markdown emphasis, wrap text to print width - **Markdown AST processing**: Parse descriptions via mdast for heading normalization, list formatting, reference links, code blocks, blockquotes, tables - **Tag description wrapping**: Matches upstream's `tagStringLength` architecture — full description passes through markdown AST with first-line offset - **Tag normalization**: 17 tag synonyms, sort by upstream priority weights within groups - **Type formatting**: Normalize JSDoc types, format via the formatter's TS parser (simulating upstream's `formatType()`), handle rest params, bracket spacing - **@example formatting**: Format embedded JS/TS/JSX/TSX code; fenced code blocks with language detection - **@import handling**: Parse, merge by module path, sort (third-party before relative), format consolidated imports - **@param reordering**: Reorder tags to match function signature parameter order - **Default value handling**: Extract `[name=value]` defaults with "Default is \`value\`" suffix ### Upstream Fidelity Verified against [prettier-plugin-jsdoc](https://github.com/hosseinmd/prettier-plugin-jsdoc) v1.8.0 source: - **Identical**: Tag synonyms (17), sort priorities (46 tags), grouping logic (`TAGS_GROUP_HEAD`, `TAGS_GROUP_CONDITION`), type normalization pipeline, rest param handling, JSDoc link protection, emphasis normalization, capitalization rules - **Architecture aligned**: Tag description wrapping uses `tag_string_length` / `first_line_offset` (equivalent to upstream's `!...?` prefix trick), balance mode effective width calculation, greedy fallback - **10 upstream bugs documented** — oxfmt intentionally produces correct output where the plugin has known issues (HTML comment wrapping, `{@link}` off-by-one, `{@includeCode}` splitting, `@type` capitalization inconsistency, etc.) ### Optimization Techniques - Single `LineBuffer` allocation per comment (one contiguous `String`, not `Vec<String>`) - `Cow<'_, str>` throughout normalization — borrows when unchanged, allocates only when modified - Fast-path skip of mdast parsing for plain-text descriptions (`needs_mdast_parsing()` heuristic) - Fast-path skip of TS formatter for simple types (`needs_formatter_pass()` check) - `SmallVec<[usize; 4]>` for import tag indices (stack allocation for common case) ## Test plan - [x] `cargo test -p oxc_formatter` — 335 tests pass (76 unit + 259 fixture) - [x] `cargo run -p oxc_prettier_conformance -- --jsdoc` — 145/145 (100%) - [x] Prettier conformance: JS 746/753 (99.07%), TS 591/601 (98.34%) - [x] Real-world repos: 34 diffs across 5 repos (7,542 JSDoc tags) — all design differences - [x] Performance: 0-8% overhead across 5 real-world repos (typedoc ~7%, svelte ~8%, rest within noise) - [x] `cargo clippy -p oxc_formatter --all-targets` — clean - [x] `cargo fmt -- --check` — clean 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
5e893d7efe | fix(jsdoc): parse tags after interval notation in descriptions (#20046) | ||
|
|
14b0fb7031 |
refactor(semantic): extract oxc_jsdoc crate from oxc_semantic (#19706)
## Summary - Extract JSDoc parsing code from `oxc_semantic` into a new `oxc_jsdoc` crate - Move parser (`JSDoc`, `JSDocTag`), builder (`JSDocBuilder`), and all supporting types to the new crate - Keep `JSDocFinder` in `oxc_semantic` since it depends on semantic types (`AstNode`, `AstNodes`) - All existing imports via `oxc_semantic` continue to work through re-exports — no changes needed in `oxc_linter` 🤖 Generated with [Claude Code](https://claude.com/claude-code) |