Commit Graph
21410 Commits
Author SHA1 Message Date
leaysgur 3e7f0f5b73 chore(oxfmt): bump prettier-plugin-astro to 1.1.2 (#28162)
Also updated peerDeps range `^0.5.0` only.
2026-10-26 03:52:43 +00:00
leaysgur 2b5a3fd678 chore(formatter_css): bump oxc-css-parser to 0.0.18 (#28161)
Fixes #28102
2026-10-26 03:52:43 +00:00
leaysgur 2604b5482b chore(oxfmt): remove stale DIVERGENCES comment from fixtures (#28160)
Prettier fixed this in the last release.
2026-10-26 03:52:42 +00:00
leaysgur f525b34636 refactor(formatter_core): make embedded dispatch parent-to-child only (#28159)
Remove `child_context`, every usecases are handled only parent -> child direction.
2026-10-26 03:52:42 +00:00
Yuji Sugiura 014e3d2676 chore(deps): bump tokio to 1.54.1 (#28163)
This fixes RUSTSEC-2026-0386 which makes `cargo deny` fail.

[v1.53.3](https://github.com/tokio-rs/tokio/releases/tag/tokio-1.53.3)
seems enough to fix, but for sure.
2026-10-26 02:26:28 +00:00
Armano 3fbef5bac0 refactor(minifier): use ast helpers for enum tests (#28148) 2026-10-25 16:37:31 -07:00
renovate[bot] 1a37731685 chore(deps): update dependency serialize-javascript to v7.1.3 (#28156)
This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Adoption](https://docs.renovatebot.com/merge-confidence/) |
[Passing](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|---|---|
|
[serialize-javascript](https://redirect.github.com/yahoo/serialize-javascript)
| [`7.1.2` →
`7.1.3`](https://renovatebot.com/diffs/npm/serialize-javascript/7.1.2/7.1.3)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/serialize-javascript/7.1.3?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/serialize-javascript/7.1.3?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/serialize-javascript/7.1.2/7.1.3?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/serialize-javascript/7.1.2/7.1.3?slim=true)
|

---

### Release Notes

<details>
<summary>yahoo/serialize-javascript (serialize-javascript)</summary>

###
[`v7.1.3`](https://redirect.github.com/yahoo/serialize-javascript/releases/tag/v7.1.3)

[Compare
Source](https://redirect.github.com/yahoo/serialize-javascript/compare/v7.1.2...v7.1.3)

See:
<https://github.com/yahoo/serialize-javascript/security/advisories/GHSA-m5mm-p8h7-m29v>

#### What's Changed

- fix: escape `</script` at the end of a serialized function body by
[@&#8203;redonkulus](https://redirect.github.com/redonkulus) in
[#&#8203;235](https://redirect.github.com/yahoo/serialize-javascript/pull/235)
- Fix serialization of Dates with expanded ISO years by
[@&#8203;Shubham-Padkonde](https://redirect.github.com/Shubham-Padkonde)
in
[#&#8203;232](https://redirect.github.com/yahoo/serialize-javascript/pull/232)
- fix: ignore functions without mutating input objects by
[@&#8203;Shubham-Padkonde](https://redirect.github.com/Shubham-Padkonde)
in
[#&#8203;233](https://redirect.github.com/yahoo/serialize-javascript/pull/233)
- release: v7.1.3 by
[@&#8203;redonkulus](https://redirect.github.com/redonkulus) in
[#&#8203;236](https://redirect.github.com/yahoo/serialize-javascript/pull/236)

##### Note on `ignoreFunction`

With `ignoreFunction: true`, function values are now omitted the same
way `JSON.stringify` omits them, without deleting them from the input
object. Functions inside arrays are emitted as `null` (previously this
produced `Array.prototype.slice.call(...)` output).

#### New Contributors

-
[@&#8203;Shubham-Padkonde](https://redirect.github.com/Shubham-Padkonde)
made their first contribution in
[#&#8203;232](https://redirect.github.com/yahoo/serialize-javascript/pull/232)

**Full Changelog**:
<https://github.com/yahoo/serialize-javascript/compare/v7.1.2...v7.1.3>

</details>

---

### Configuration

📅 **Schedule**: (in timezone Asia/Shanghai)

- Branch creation
  - "before 10am on monday"
- 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:eyJjcmVhdGVkSW5WZXIiOiI0NC4xODAuMCIsInVwZGF0ZWRJblZlciI6IjQ0LjE4MC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-25 22:36:05 +00:00
renovate[bot] fef11e819a chore(deps): update npm packages (#28152)
This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Adoption](https://docs.renovatebot.com/merge-confidence/) |
[Passing](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|---|---|
|
[@typescript-eslint/parser](https://typescript-eslint.io/packages/parser)
([source](https://redirect.github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser))
| [`8.71.2` →
`8.72.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fparser/8.71.2/8.72.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2fparser/8.72.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@typescript-eslint%2fparser/8.72.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@typescript-eslint%2fparser/8.71.2/8.72.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2fparser/8.71.2/8.72.0?slim=true)
|
|
[@typescript-eslint/scope-manager](https://typescript-eslint.io/packages/scope-manager)
([source](https://redirect.github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/scope-manager))
| [`8.71.2` →
`8.72.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fscope-manager/8.71.2/8.72.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2fscope-manager/8.72.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@typescript-eslint%2fscope-manager/8.72.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@typescript-eslint%2fscope-manager/8.71.2/8.72.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2fscope-manager/8.71.2/8.72.0?slim=true)
|
| [@typescript-eslint/visitor-keys](https://typescript-eslint.io)
([source](https://redirect.github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/visitor-keys))
| [`8.71.2` →
`8.72.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fvisitor-keys/8.71.2/8.72.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2fvisitor-keys/8.72.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@typescript-eslint%2fvisitor-keys/8.72.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@typescript-eslint%2fvisitor-keys/8.71.2/8.72.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2fvisitor-keys/8.71.2/8.72.0?slim=true)
|
| [execa](https://redirect.github.com/sindresorhus/execa) | [`10.1.1` →
`10.2.0`](https://renovatebot.com/diffs/npm/execa/10.1.1/10.2.0) |
![age](https://developer.mend.io/api/mc/badges/age/npm/execa/10.2.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/execa/10.2.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/execa/10.1.1/10.2.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/execa/10.1.1/10.2.0?slim=true)
|
|
[vscode-languageserver-protocol](https://redirect.github.com/microsoft/vscode-languageserver-node/tree/main/protocol)
([source](https://redirect.github.com/Microsoft/vscode-languageserver-node/tree/HEAD/protocol))
| [`3.18.4` →
`3.18.5`](https://renovatebot.com/diffs/npm/vscode-languageserver-protocol/3.18.4/3.18.5)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/vscode-languageserver-protocol/3.18.5?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vscode-languageserver-protocol/3.18.5?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vscode-languageserver-protocol/3.18.4/3.18.5?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vscode-languageserver-protocol/3.18.4/3.18.5?slim=true)
|
|
[vscode-languageserver-textdocument](https://redirect.github.com/microsoft/vscode-languageserver-node/tree/main/textDocument)
([source](https://redirect.github.com/Microsoft/vscode-languageserver-node/tree/HEAD/textDocument))
| [`1.0.15` →
`1.0.16`](https://renovatebot.com/diffs/npm/vscode-languageserver-textdocument/1.0.15/1.0.16)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/vscode-languageserver-textdocument/1.0.16?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vscode-languageserver-textdocument/1.0.16?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vscode-languageserver-textdocument/1.0.15/1.0.16?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vscode-languageserver-textdocument/1.0.15/1.0.16?slim=true)
|

---

### Release Notes

<details>
<summary>typescript-eslint/typescript-eslint
(@&#8203;typescript-eslint/parser)</summary>

###
[`v8.72.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#8720-2026-10-19)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v8.71.2...v8.72.0)

This was a version bump only for parser to align it with other projects,
there were no code changes.

See [GitHub
Releases](https://redirect.github.com/typescript-eslint/typescript-eslint/releases/tag/v8.72.0)
for more information.

You can read about our [versioning
strategy](https://typescript-eslint.io/users/versioning) and
[releases](https://typescript-eslint.io/users/releases) on our website.

</details>

<details>
<summary>typescript-eslint/typescript-eslint
(@&#8203;typescript-eslint/scope-manager)</summary>

###
[`v8.72.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/scope-manager/CHANGELOG.md#8720-2026-10-19)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v8.71.2...v8.72.0)

##### 🩹 Fixes

- **eslint-plugin:** \[no-deprecated] report deprecated properties in
object literals
([#&#8203;12704](https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12704))

##### ❤️ Thank You

- Junichiro Kasuya [@&#8203;jksy](https://redirect.github.com/jksy)

See [GitHub
Releases](https://redirect.github.com/typescript-eslint/typescript-eslint/releases/tag/v8.72.0)
for more information.

You can read about our [versioning
strategy](https://typescript-eslint.io/users/versioning) and
[releases](https://typescript-eslint.io/users/releases) on our website.

</details>

<details>
<summary>typescript-eslint/typescript-eslint
(@&#8203;typescript-eslint/visitor-keys)</summary>

###
[`v8.72.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/visitor-keys/CHANGELOG.md#8720-2026-10-19)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v8.71.2...v8.72.0)

This was a version bump only for visitor-keys to align it with other
projects, there were no code changes.

See [GitHub
Releases](https://redirect.github.com/typescript-eslint/typescript-eslint/releases/tag/v8.72.0)
for more information.

You can read about our [versioning
strategy](https://typescript-eslint.io/users/versioning) and
[releases](https://typescript-eslint.io/users/releases) on our website.

</details>

<details>
<summary>sindresorhus/execa (execa)</summary>

###
[`v10.2.0`](https://redirect.github.com/sindresorhus/execa/releases/tag/v10.2.0)

[Compare
Source](https://redirect.github.com/sindresorhus/execa/compare/v10.1.1...v10.2.0)

##### Behavior changes

These are bug fixes, but they might affect code that relied on the
previous incorrect behavior.

- Exceeding [`maxBuffer`](docs/api.md#optionsmaxbuffer) now terminates
the subprocess with [`killSignal`](docs/api.md#optionskillsignal),
instead of leaving it running and the promise pending
[`f6de9be`](https://redirect.github.com/sindresorhus/execa/commit/f6de9be)
- `maxBuffer: 0` now limits the output of synchronous methods, like
asynchronous methods
[`224dd20`](https://redirect.github.com/sindresorhus/execa/commit/224dd20)
- Options of `$` set to `undefined` now use `$`'s defaults, such as
inheriting `stdin`
[`f61a6e9`](https://redirect.github.com/sindresorhus/execa/commit/f61a6e9)

##### Fixes

- Fix invalid file descriptor objects, such as closed file handles,
crashing the current process instead of throwing
[`d0a5968`](https://redirect.github.com/sindresorhus/execa/commit/d0a5968)
- Fix synchronous transforms: errors being hidden, filtered output being
returned on failure, mixed text and byte chunks being reordered, and
`final()` being skipped without input
[`0ba2b6e`](https://redirect.github.com/sindresorhus/execa/commit/0ba2b6e)
[`ed80079`](https://redirect.github.com/sindresorhus/execa/commit/ed80079)
[`9c54833`](https://redirect.github.com/sindresorhus/execa/commit/9c54833)
- Fix `result.all` changing objects when only `stdout` or `stderr` is
buffered
[`8629132`](https://redirect.github.com/sindresorhus/execa/commit/8629132)
- Fix writing objects to a web `WritableStream`
[`5ea2900`](https://redirect.github.com/sindresorhus/execa/commit/5ea2900)
- Fix an invalid `subprocess.duplex()` option making later stream
conversions hang
[`5e4345b`](https://redirect.github.com/sindresorhus/execa/commit/5e4345b)
- Fix `execaNode()` not running its file when the current process uses
`--print`
[`e747872`](https://redirect.github.com/sindresorhus/execa/commit/e747872)

##### Types

- Fix result and subprocess types when the options are a union,
including IPC
[`f5772f3`](https://redirect.github.com/sindresorhus/execa/commit/f5772f3)
[`355d917`](https://redirect.github.com/sindresorhus/execa/commit/355d917)
[`cb8aaf6`](https://redirect.github.com/sindresorhus/execa/commit/cb8aaf6)
- Fix result types when options bound with `execa(options)` are
overridden or reset with `undefined`
[`708fed7`](https://redirect.github.com/sindresorhus/execa/commit/708fed7)
- Fix `subprocess.stdin` types with the `input` and `inputFile` options
[`236c831`](https://redirect.github.com/sindresorhus/execa/commit/236c831)
- Fix chunk types of `subprocess.iterable()` with object-mode transforms
[`a2912e5`](https://redirect.github.com/sindresorhus/execa/commit/a2912e5)
- Fix fd-specific option types, and `execaNode()` types with `node:
undefined`
[`80b01e9`](https://redirect.github.com/sindresorhus/execa/commit/80b01e9)
[`523cf9b`](https://redirect.github.com/sindresorhus/execa/commit/523cf9b)

***

</details>

---

### Configuration

📅 **Schedule**: (in timezone Asia/Shanghai)

- Branch creation
  - "before 10am on monday"
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- 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:eyJjcmVhdGVkSW5WZXIiOiI0NC4xODAuMCIsInVwZGF0ZWRJblZlciI6IjQ0LjE4MC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-25 18:39:52 +00:00
Armano 3493ce30c4 perf(minifier): reuse is_error_constructor and simplify substitute_global_new_expression (#28149) 2026-10-24 18:13:04 -07:00
camc314 a22c9f2abc perf(parser): move annotation comment handling out of hot paths (#28139)
Applying `@__PURE__` and `@__NO_SIDE_EFFECTS__` comments is rare, so move it into `#[cold]` helpers to keep `with_pure_comments`, `parse_assignment_expression` and `parse_statement_list_item` small.
2026-10-23 22:58:23 +00:00
sarankumarandCameron 7f3c908642 fix(linter/eslint/array-callback-return): check callbacks passed with extra arguments (#28133)
Fixes #28128

`array-callback-return` only checked array method calls with exactly one
argument, so a callback followed by anything else was skipped. That's
why `reduce`/`reduceRight` with an initial value were never reported.
The same thing happened to `foo.map(cb, thisArg)` and `Array.from(x, cb,
thisArg)`.

ESLint's rule checks the first argument (the second for
`Array.from`/`Array.fromAsync`) no matter how many arguments follow it.
This PR does the same.

```js
[1, 2].reduce((total, x) => {
  if (x > 1) {
    return total + x;
  }
}, 0); // now reported, same as ESLint
```

Tests: new pass/fail cases for `reduce`/`reduceRight` with an initial
value, `map` with `thisArg`, `Array.from` with `thisArg`, and a callback
that isn't the first argument (`foo.reduce(bar, function() {})` stays
unreported). Snapshot updated. `cargo test -p oxc_linter`, `cargo clippy
-p oxc_linter --all-targets -- -D warnings` and `cargo fmt --check`
pass.

AI disclosure: I used an AI assistant while writing this change. I
reviewed the code and tests myself.

---------

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-10-23 15:00:29 -07:00
NavpreetSSidhuandCameron 53be530876 fix(linter): filter by type aware rules when looking up tsgolint rule severity (#28138)
Closes #28136

Severity for tsgolint diagnostics was looked up in the file's resolved
rules by name only. `unicorn/prefer-string-starts-ends-with` has the
same name as `typescript/prefer-string-starts-ends-with`, so whichever
came first in the list won, and the order differs for files that match
an `overrides` entry. Both lookups (CLI and `lint_source`) now only
match type-aware rules.

Added a CLI fixture with the config from the issue; the snapshot shows a
warning for both files, and it fails on main with an error for `b.tsx`.
`cargo test -p oxlint --lib tsgolint`, `cargo test -p oxc_linter --lib`,
clippy and fmt pass.

AI disclosure: I used Claude Code to help trace the cause and write the
patch, and I reviewed and tested it myself.

---------

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-10-23 21:22:35 +00:00
Sysix cf34678cd6 feat(oxlint): export Oxlintrc type (#28132)
Exporting the `Oxlintrc` type with all expected values (including `$schema` and the json form of `extends`).
The background is that the `eslint-plugin-oxlint` package currently needs to rebuild this type manually.

https://github.com/oxc-project/eslint-plugin-oxlint/blob/b41a301a79d4684effb3297e5b0e196c2bb48f06/src/build-from-oxlint-config/types.ts#L26-L35

Instead of rebuilding  `Oxlintrc` by hand, I would prefer to import the original JSON-Struct from `oxlint` itself.
2026-10-23 18:20:00 +00:00
Sysix f61ae9ab42 fix(lsp): return default diagnostic report when server is not in pull mode (#27745)
Addresses one problem in #27736.
Clients should respect the the `ServerCapabilities` from the `intialize` response.
When no `diagnosticProvider` is provided, the server says to the client that `textDocument/diagnostic` is not supported.

```
        /**
	 * The server has support for pull model diagnostics.
	 *
	 * @since 3.17.0
	 */
	diagnosticProvider?: DiagnosticOptions | DiagnosticRegistrationOptions;
```
_https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#pull-diagnostics_

Sadly the client does not need to respect them and can requzest `textDocument/diagnostic` even if we told him not to do.
To avoid duplicate linting processes on push mode (server is sending diagnostics to the client on `didOpen/didChange`, we check if we are in the right mode, or else bail out earlier.
2026-10-23 15:16:02 +00:00
Dunqing 0e6498f7e2 perf(tasks): build the coverage profile without cross-crate LTO (#28007)
> AI disclosure: this PR, the measurements behind it, and this description were produced with Claude Code at a maintainer's request. It should get human review before it leaves draft.

## Summary

This PR does three things:
- **`Cargo.toml`:** `[profile.coverage]` changes from `lto = "thin"` to `lto = false`.
- **`AGENTS.md`:** adds an opt-in note on incremental compilation for this profile, with its measured cost.
- **`AGENTS.md`:** the `cargo coverage -- <tool>` examples become `cargo coverage <tool>`; the old form runs every suite.

## Why

With `lto = "thin"`, the library crates are compiled to bitcode only (`-C linker-plugin-lto`). The final binary (`-C lto=thin`) then re-optimizes and re-codegens the whole program on every rebuild. After a one-line `oxc_minifier` edit, `cargo build --timings` showed where the time went:

| | `oxc_minifier` lib | `oxc_minsize` lib | `oxc_minsize` bin |
|---|---|---|---|
| `lto = "thin"` | 5.2s | 1.9s | **19.4s** (whole-program ThinLTO) |
| `lto = false` | 7.2s | 2.3s | **0.7s** (plain link) |

Every binary built with this profile pays that step separately. That covers the harnesses (`oxc_minsize`, `oxc_track_memory_allocations`, `oxc_coverage`) and the NAPI test builds (`pnpm build-test`). The profile's own comment says `lto = "thin"` was chosen for "faster compile time", and turning LTO off is faster still. The profile exists to run the harnesses with debug assertions, which doesn't need cross-crate LTO.

## Evidence: replaying 11 real `main` commits

Setup:
- **Commits:** the 11 picked from the rust 1.99.1 window. They cover minifier, ecmascript, codegen, parser, transformer and formatter, plus two `oxc_ast`/`oxc_str` refactors that rebuild 66 crates. Four of them change `allocs_*.yaml`, and one also changes `minsize.snap`.
- **Per commit and config:**
  1. Build at the commit's parent (untimed).
  2. Check out the commit.
  3. Time `cargo minsize`, `cargo allocs` and `cargo coverage`, with build and run timed separately.
- **Machine:** 4-core Linux VM; each config used its own target dir.

| config | total edit→result | per commit | harness run (median) | target dir after 11 commits |
|---|---|---|---|---|
| `lto = "thin"` (before) | 1580s | 110–174s | 16.0s | 2.1 GB |
| **`lto = false` (this PR)** | **923s (1.7×)** | 36–140s (1.2× deep → 3.8× leaf) | **16.0s** | **1.8 GB** |
| `lto = false` + `CARGO_PROFILE_COVERAGE_INCREMENTAL=true` | 463s (3.4×) | 23–83s | 16.9s (+6%) | 12 GB (9.9 GB of it the incremental cache) |

**Correctness:** all 33 runs (3 configs × 11 commits) produced outputs byte-identical to the snapshots committed at each commit. That includes the commits whose snapshots changed.

## CI

PR CI on `c6014a89` passed. Several jobs that build with this profile are path-filtered or Windows-only on PRs. So I also triggered `ci.yml` manually on this branch ([run 39706156660](https://github.com/oxc-project/oxc/actions/runs/39706156660)), which runs them regardless of what changed. All 21 jobs that ran passed. The coverage-profile ones:

| job | how it uses the profile | result |
|---|---|---|
| Conformance, Minification Size, Allocations, Linter changes | `cargo coverage` / `minsize` / `allocs` / `lint-timings` | ✅ snapshots unchanged |
| Lexer (generic, AVX2, Neon) | lexer conformance via `oxc_coverage` | ✅ snapshots unchanged |
| Test NAPI Compiler, Test NAPI Oxlint, Test NAPI Oxfmt, Test Codegen | `pnpm build-test` | ✅ |
| Test NAPI Compiler (windows) | `cargo build --profile coverage` of the NAPI crates | ✅ |

**Not run before merge:** Test NAPI Oxlint (windows) and Test NAPI Oxfmt (windows). Their condition is `github.ref_name == 'main'`, with no manual trigger. The risk is low:
- Their Linux versions, which run the same `build-test` scripts, passed.
- Building NAPI libraries with this profile on Windows passed in Test NAPI Compiler (windows).

**Not affected:** the lexer benchmark uses the `bench` profile.

## Incremental: documented as opt-in only

Incremental roughly halves edit→result again, but its cache grew to ~10 GB over 11 commits and harness runs got ~6% slower. So `AGENTS.md` documents it as an opt-in env var with those costs, and it stays out of the profile.

## `cargo coverage -- <tool>` examples

The `coverage` alias already ends in `--`, so `cargo coverage -- parser` passes `-- parser` to the binary. `pico_args::subcommand()` then returns `None`, and the binary runs `run_all()`:

| command | suites run | time |
|---|---|---|
| `cargo coverage parser` | 4 | 5.0s |
| `cargo coverage -- parser` | 28 | 15.3s |

**Not included (possible follow-ups):**
- `just conformance <tool>` has the same problem.
- `oxc_coverage` could skip a leading `--`, so both forms work.

## Verification
- `typos` and the repo's pinned `oxfmt@0.74.0 --check` pass on `AGENTS.md` and `Cargo.toml`.
- `pnpm install` failed in the sandbox with a proxy 403 on a GitHub tarball, so I ran oxfmt directly.
- Before pushing, I also ran the harnesses, lexer conformance (generic and AVX2) and the NAPI crate build locally with LTO off. All matched HEAD.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01GZu5GvJLQYkfYHTAoH2yac
2026-10-23 03:06:26 +00:00
leaysgur 1ed93afeda perf(data_structures): copy short strings without a memcpy call (#27953)
Fast path for short strings.

---

According to local benchmark, it seemed to be effective for the formatter as well, but on CodSpeed, it appears to be effective only for codegen... 🤔
2026-10-23 02:52:52 +00:00
camc314 831cdf19d4 feat(oxlint): require mininum oxlint-tsgolint version v7.0.2005 (#28118)
Raise Oxlint's optional `oxlint-tsgolint` peer dependency from `>=7.0.2003` to `>=7.0.2005` and update the lockfile specifier. Version 7.0.2005 is the latest published release and is already pinned by the workspace.
2026-10-23 01:39:17 +00:00
camc314 d1b00f45ec feat(linter/typescript): implement no-unsafe-enum-assignment rule (#28117)
Register `typescript/no-unsafe-enum-assignment` as a type-aware rule backed by oxlint-tsgolint 7.0.2005, following https://github.com/oxc-project/tsgolint/pull/1316. Add rule documentation and regenerate the rule registry, JSON schema, and TypeScript config types.

Extend the existing type-aware CLI fixture with unsafe assignments, arguments, returns, assertions, mutations, and enum-key access, plus valid enum-member and bitwise-combination cases. Reuse the existing tests and update their diagnostic and count snapshots.
2026-10-23 01:29:21 +00:00
camc314 165c91f9c1 feat(linter/typescript/await-thenable): support allowMixedPromiseArrays option (#28116)
Add `allowMixedPromiseArrays` to `typescript/await-thenable`, following https://github.com/oxc-project/tsgolint/pull/1307. Oxlint now validates and forwards the option, and exposes it in the JSON schema and TypeScript config types. It defaults to `false`; when enabled, Promise aggregators accept mixed synchronous and Promise-like inputs while synchronous-only inputs still report errors.
2026-10-23 01:17:54 +00:00
camc314 7d2e9ebb8a chore(deps): update oxlint-tsgolint to 7.0.2005 (#28115)
Update the pinned `oxlint-tsgolint` dependency from 7.0.2004 to [7.0.2005](https://github.com/oxc-project/tsgolint/releases/tag/v7.0.2005).
2026-10-23 01:02:43 +00:00
renovate[bot] 8d6923b921 chore(deps): update napi to v3.15.0 (#28092)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [napi](https://redirect.github.com/napi-rs/napi-rs) |
workspace.dependencies | minor | `3.14.2` → `3.15.0` |
| [napi-derive](https://redirect.github.com/napi-rs/napi-rs) |
workspace.dependencies | patch | `3.6.12` → `3.6.13` |

---

### Release Notes

<details>
<summary>napi-rs/napi-rs (napi)</summary>

###
[`v3.15.0`](https://redirect.github.com/napi-rs/napi-rs/releases/tag/napi-v3.15.0)

[Compare
Source](https://redirect.github.com/napi-rs/napi-rs/compare/napi-v3.14.2...napi-v3.15.0)

##### Added

- *(napi)* cancel a ReadableStream through its Reader, and fix
ReadableStream::cancel
([#&#8203;3623](https://redirect.github.com/napi-rs/napi-rs/pull/3623))

##### Fixed

- *(napi)* set the custom GC aborted flag before Node closes its tsfn
([#&#8203;3626](https://redirect.github.com/napi-rs/napi-rs/pull/3626))
- *(napi)* TypedArray input leaks and compat buffer copies on wasm
([#&#8203;3612](https://redirect.github.com/napi-rs/napi-rs/pull/3612))
- *(napi)* copy managed array inputs
([#&#8203;3607](https://redirect.github.com/napi-rs/napi-rs/pull/3607))
- *(napi)* reject a value of another class on builds without type tags
([#&#8203;3610](https://redirect.github.com/napi-rs/napi-rs/pull/3610))
- *(napi)* drop unadopted class value and reset factory flag on failed
conversion
([#&#8203;3603](https://redirect.github.com/napi-rs/napi-rs/pull/3603))
- *(napi)* join the Tokio runtime threads at env teardown
([#&#8203;3592](https://redirect.github.com/napi-rs/napi-rs/pull/3592))
- *(napi)* keep borrowed class args alive across AsyncTask/AsyncBlock
([#&#8203;3584](https://redirect.github.com/napi-rs/napi-rs/pull/3584))

##### Other

- *(cli)* cover FreeBSD arm64
([#&#8203;3620](https://redirect.github.com/napi-rs/napi-rs/pull/3620))
- *(cli)* record the design behind the threaded WASI heap sync
([#&#8203;3581](https://redirect.github.com/napi-rs/napi-rs/pull/3581))

</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 these
updates 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:eyJjcmVhdGVkSW5WZXIiOiI0NC4xNzEuMiIsInVwZGF0ZWRJblZlciI6IjQ0LjE3MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-22 23:28:55 +00:00
camc314 9ce5ee4556 chore(deps): update rustls webpki crates for security advisories (#28112)
Updates `webpki-roots` 1.0.8 -> 1.0.10, `webpki-root-certs` 1.0.8 -> 1.0.10, and `rustls-webpki` 0.103.15 -> 0.103.16 to resolve RUSTSEC-2026-0381, RUSTSEC-2026-0382, and RUSTSEC-2026-0383.
2026-10-22 22:57:36 +00:00
ArmanoandCameron 6d7b372be7 fix(minifier): handle sequence exprs when folding if to expr statement (#27939)
Handle sequence expressions when converting if statements to logical
expression statements:

`if (a(), !b); else c();` -> `a(), b && c();`
`if (a(), !b) c();` -> `a(), b || c();`

this change has been extracted from #27664

---------

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-10-22 22:28:14 +00:00
camc314 e3eca411d5 fix(runtime): align async iterator throw with Babel (#28059)
Async-from-sync `.throw(error)` currently looks up the sync iterator's `return` method. Change that lookup to `throw` in both CommonJS and ESM helpers, matching [Babel's implementation](https://github.com/babel/babel/blob/main/packages/babel-helpers/src/helpers/asyncIterator.ts).

The upstream `yield-star/throw-method-sync-iterator` regression added in #28057 now passes; update its execution snapshot. `just test-transform` reproduces the expected results: 320/418 Babel execution tests and 40/42 local execution tests, with no new failures. Direct delegation checks also pass for both helper formats.
2026-10-22 19:27:40 +00:00
camc314 af0258d583 fix(parser): parse source imports named type (#28062)
Source imports such as `import source type from "./f.wasm"` were rejected because a shortcut for value imports named `type` skipped the required `from` token.

Remove that shortcut. The ambiguous `import type from "module"` form is already handled before specifier parsing, so source imports now consume their `from` clause normally. The TypeScript `importSource3.ts` fixture added in #28057 covers the regression; the snapshots also record the more precise recovery diagnostic for an invalid deferred import.
2026-10-22 18:08:55 +00:00
camc314 83633a7a64 fix(parser): parse escaped class field names after initializers (#28061)
The Babel class-field fixtures added in #28057 use escaped `in` and `instanceof` names after an initializer. Oxc consumes these names as binary operators and rejects valid class members.

Stop binary-expression parsing at these escaped names after a newline so ASI can end the initializer and class-member parsing can consume the name. Preserve escaped-keyword diagnostics for same-line operator expressions and after ASI, with diagnostic fixtures for both newline cases.
2026-10-22 18:02:31 +00:00
camc314 90c58ac971 fix(parser): parse postfix updates of sloppy let identifiers (#28060)
The Annex B fixtures added in #28057 expose that `let-- > 0` and `let /* comment */ --> 0` are incorrectly parsed as lexical declarations. In sloppy scripts, `let` can be an identifier followed by a postfix update.

Include `++` and `--` in the expression lookahead, preserving normal postfix and line-terminator handling. Regression coverage comes from the upstream fixtures now merged into `main`.

Rebased onto the merged submodule update. `just submodules` and `just coverage` completed on the rebased branch; Babel parser positives improve from 2257/2280 to 2259/2280, and the corresponding semantic failures disappear. The existing HTML-comment formatter failures now report an AST mismatch instead of a parse error; their separate fix is being prepared. Parser lint, formatting, and allocation tracking also completed.
2026-10-22 17:41:22 +00:00
leaysgur f1d90329e2 refactor(formatter_core): remove JS-only method (#28099)
Just inlined in `oxc_formatter`.
2026-10-22 07:45:34 +00:00
leaysgur 5f1fd3dcb9 fix(formatter): measure width heuristics by display width (#28098)
Standardizing the inconsistent ways of measuring width used across various places.

NOTE: JSDoc is left as-is for now, there are many exceptions...
2026-10-22 07:45:33 +00:00
leaysgur 4829118e52 refactor(formatter): add AstNodes::is_binary_like for parent paren checks (#28097) 2026-10-22 07:36:10 +00:00
leaysgur a5a52cf5f7 fix(formatter): keep parens around private in expressions (#28096)
Should keep:

```ts
class C {
  #x;
  m(a, b, c) {
    x = (#x in b).c; // THIS parens with `PrivateInExpression`
```
2026-10-22 07:36:09 +00:00
leaysgur db55461552 docs(formatter_core): document text width divergence (#28095) 2026-10-22 06:50:42 +00:00
Dunqing e0f8937ae4 fix(react-compiler): compile a try whose catch is unreachable instead of panicking (#28066)
Fixes #27404

```jsx
export function Component() {
  let x = 0;
  try {
    const unused = 1;
  } catch {
    x = 2;
  }
  return <div>{x}</div>;
}
```

Before: `assertion failed: Found a block with a single predecessor but where a phi has multiple (2) operands`, which aborts the process in release builds (Vite with `oxc-transform-react`, oxlint `react/*` rules).
After: compiles, with `x` folded to the constant `0`.

## Cause

Once dead-code elimination empties the `try` body, `prune_maybe_throws` removes the edge to the `catch`, and the catch blocks become unreachable. Two references to them were left behind:

- The phi at the join after the `try` kept an operand for the catch path, so `merge_consecutive_blocks` hit its `assert_eq!`.
- The join's `preds` still counted the removed blocks, so it was not merged into its real predecessor. When the `catch` had more than one block, the code after the `try` was silently dropped: `try { const u = 1 } catch { if (c) a(); else b(); } return <div />` compiled to `function Component(props) {}`.

Babel's React Compiler (1.0.0 and upstream main at `ab0d927f`) reports the first case as an invariant error and skips the function, and compiles the second to the same empty function, which renders `null`.

## Fix

- `prune_maybe_throws` recomputes predecessors, drops phi operands from removed blocks, and eliminates phis this makes redundant, as constant propagation already does.
- The `merge_consecutive_blocks` assertion is now an Invariant diagnostic, so any remaining case skips the function instead of crashing.

## Tests

Five new fixtures: the issue repro, an `if` inside the `catch`, a dead `try` in a loop, nested `try`, and a `catch` with no reassignment. On `main`, three panic, one bails with a different invariant and one compiles to an empty function. With this PR, all five compile, and their output renders the same as the original source in React 19 across the fixtures' `sequentialRenders`. No existing snapshot changes. The issue repro is also a `pass` case for `react/invariant`.

AI disclosure: written with Claude Code.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01Bvq2daQaudW29wmuShT7jq
2026-10-22 06:43:33 +00:00
999496e4ed fix(formatter): measure a short key by its display width (#28026)
`js/object-prop-break-in/short-keys.js` is in the "Not idempotent" list
of the Prettier conformance report. The cause is how a property key's
width is measured for the short-key check (`width < indent_width +
MIN_OVERLAP_FOR_BREAK`):

- a quoted key goes through `FormatLiteralStringToken::width()`, its
display width (`'古体诗'` -> 6)
- an unquoted key goes through `SourceText::span_width()`, its `char`
count (`古体诗` -> 3)

So the first pass breaks after `'古体诗':` like Prettier, unquotes the key,
and the second pass sees a 3-wide key and joins the line again:

```js
// pass 1 (same as Prettier)
  古体诗:
    "https://prettier.io/docs/en/rationale.html#what-prettier-is-concerned-about",
// pass 2
  古体诗: "https://prettier.io/docs/en/rationale.html#what-prettier-is-concerned-about",
```

An unquoted wide key (`古体诗: ...` in the input) never breaks at all,
unlike Prettier, whose `isObjectPropertyWithShortKey` uses
`getStringWidth`.

This makes `span_width` return the display width
(`UnicodeWidthStr::width`). Its only callers are these key-width checks
(object/binding/assignment-target properties, plain and computed), so
nothing else changes.

Tests:
- New fixture `js/unicode/wide-char-short-key.js` (unquoted, quoted and
computed wide keys, destructuring); it fails on `main`, and its output
is identical to Prettier 3.9.10 (the pinned version) at both option sets
and stable on a second pass.
- `short-keys.js` drops out of the "Not idempotent" list in
`conformance__prettier-js.snap`; no other conformance change.
- `cargo test -p oxc_formatter -p oxc_formatter_core --all-features`,
`cargo fmt --check` and `cargo clippy --all-targets --all-features` on
both crates pass.

AI disclosure: this PR (code, tests and description) was written with
Claude Code (Claude Opus 5.5); the verification above is what was run.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Yuji Sugiura <6259812+leaysgur@users.noreply.github.com>
2026-10-22 06:42:39 +00:00
7e9aa449c5 fix(formatter): keep parens around a looser operand of an instantiation expression (#28025)
When the operand of an instantiation expression binds looser than the
type arguments, the formatter drops its parentheses:

```ts
// input
x = (c ? a : b)<T>;
x = (y++)<T>;
x = (a as B)<T>;

// before
x = c ? a : b<T>;   // instantiates only `b`
x = y++<T>;         // does not parse
x = a as B<T>;      // `B<T>` is now the type

// after: unchanged from the input
```

The same happens for binary/logical operands, `++y`, unary operators
(`!`, `typeof`, `void`, `delete`, `-`), `satisfies` and `<B>x`. Found by
formatting Biome's `ts/expression/instantiation_expression.ts` fixture
twice: the second pass failed to parse.

`<T>` binds like a non-null `!`, so this adds
`TSInstantiationExpression` next to `TSNonNullExpression` in the three
helpers that decide those parens (`type_cast_like_needs_parens`,
`binary_like_needs_parens`, `update_or_lower_expression_needs_parens`).
Operands that don't need them (`(a.b)<T>`, `(a())<T>`, `` (a`x`)<T> ``)
still lose them.

Prettier (pinned version and 3.9.10) prints the broken form too, so I
extended `DIVERGENCES.md#instantiation-expression-parens` and its pin
fixture instead of adding a new entry.

Verification:
- Parsed each of 33 operand shapes before and after formatting with
TypeScript 5.9.3 and compared the ASTs (parens stripped): on `main` 17
change shape or fail to parse, with this change all 33 match.
- The extended fixture fails on `main` and passes with this change.
`cargo test -p oxc_formatter --all-features` (fixtures + Prettier
conformance, no snapshot changes besides the fixture), `cargo fmt
--check` and `cargo clippy -p oxc_formatter --all-targets
--all-features` pass.

AI disclosure: this PR (code, tests and description) was written with
Claude Code (Claude Opus 5.5); the verification above is what was run.

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: leaysgur <6259812+leaysgur@users.noreply.github.com>
2026-10-22 06:42:00 +00:00
leaysgur f7eb849e25 test(oxfmt): skip entries under symlinked dirs in snapshot (#28093)
This change is introduced by Node.js v26.9.0.
2026-10-22 06:28:46 +00:00
leaysgur b93e169ab5 chore(deps): bump .node-version to 26.12.1 (#28090)
Bump `.node-version` to 26.12.1.

- Node 24 moved to Maintenance LTS on 2026-10-20.
- Node 26 enters Active LTS on 2026-10-28.
- Includes the fixes from the [October 2026 security releases](https://nodejs.org/en/blog/vulnerability/october-2026-security-releases).
- Update the Node.js version in snapshots.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-10-22 05:12:51 +00:00
Cam McHenryandCopilot 85561cc49f refactor(linter): reuse object property lookup in Vitest rule (#28088)
Using the new `find_property` helper (added in #28076) in more places.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-22 00:44:18 -04:00
Cam McHenryandCopilot 79be134021 refactor(linter): reuse object property lookup in Vue rules (#28087)
Using the new `find_property` helper (added in #28076) in more places.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-22 00:44:18 -04:00
Cam McHenryandCopilot a057c427e3 refactor(linter): reuse object property lookup in React rules (#28086)
Using the new `find_property` helper (added in #28076) in more places.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-22 00:44:17 -04:00
Cam McHenryandCopilot 48c7ca77ce refactor(linter): share IIFE recognition (#28084)
Extracting shared `is_iife` code.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-22 00:44:16 -04:00
Cam McHenryandCopilot 807893e1ea refactor(linter): share test callback discovery (#28083)
Extracting shared jest code.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-22 00:33:02 -04:00
Cam McHenryandCopilot 588f34aee3 refactor(linter): share nullish JSX attribute predicate (#28082)
Extracting shared code.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-22 00:33:01 -04:00
Cam McHenryandCopilot c3b4e6bd24 refactor(linter): share React class component recognition (#28081)
Extracting shared code.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-22 00:33:01 -04:00
Cam McHenryandCopilot d04695bd06 refactor(linter): share JSX multiline whitespace predicate (#28080)
Adds an extracted `is_jsx_multiline_whitespace` helper

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-22 00:33:00 -04:00
Cam McHenryandCopilot 91e971dbc8 refactor(linter): inline regular line break check (#28079)
Use builtin contains instead of a custom function.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-22 00:33:00 -04:00
Cam McHenryandCopilot e68f0be856 refactor(linter): reuse inclusive span checks (#28078)
Using the built-in span range check

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-22 00:32:59 -04:00
Cam McHenryandCopilot e96eeb8e82 refactor(linter): share configured global reference check (#28077)
Extracting shared code.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-22 00:32:59 -04:00
Cam McHenryandCopilot 4a823f57f3 refactor(ast): move property lookup onto ObjectExpression (#28076)
Adds `ObjectExpression::find_property` for more idiomatic checking of
props.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-22 00:32:59 -04:00
Cam McHenryandCopilot 0a9b8bcbfa refactor(linter): reuse default property lookup (#28075)
Use existing find property helper

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-22 00:32:58 -04:00