Commit Graph

2615 Commits

Author SHA1 Message Date
camc314 c917f204a7 feat(ast)!: introduce ArrowFunctionBody enum (#24987)
## Summary

- Introduces `ArrowFunctionBody` to represent concise expression and block bodies explicitly.
- Removes the `ArrowFunctionExpression::expression` boolean.
- Makes invalid arrow body combinations unrepresentable.

## Breaking Change

The Rust AST changes from:

```rust
pub struct ArrowFunctionExpression<'a> {
    pub expression: bool,
    pub body: Box<'a, FunctionBody<'a>>,
}
```

to:

```rust
pub enum ArrowFunctionBody<'a> {
    FunctionBody(Box<'a, FunctionBody<'a>>) = 64,
    INHERIT(Expression<'a>),
}

pub struct ArrowFunctionExpression<'a> {
    pub body: ArrowFunctionBody<'a>,
}
```

Concise arrow bodies are now stored directly as expressions instead of synthetic `FunctionBody` and `ExpressionStatement` nodes. Block bodies continue to use `FunctionBody`.

## Why?

The previous representation required consumers to maintain this implicit invariant:

```text
expression == true
→ no directives
→ exactly one statement
→ that statement is an ExpressionStatement
```

Invalid combinations could cause panics, skipped work, or fallback behavior. The enum encodes the grammar directly and makes those invalid states unrepresentable.

Concise expressions also now have `ArrowFunctionExpression` as their direct traversal ancestor, without synthetic `FunctionBody` or `ExpressionStatement` nodes.

## How to migrate

Use the arrow body accessors or match on `ArrowFunctionBody` rather than inspecting `expression` and synthetic statements.

Common field migrations:

| Previous representation | New representation |
| --- | --- |
| `arrow.expression` | `arrow.is_expression()` |
| `arrow.get_expression()` | `arrow.get_expression()` |
| `&arrow.body.statements` | `arrow.get_function_body().map(\|body\| &body.statements)` |
| `&mut arrow.body.statements` | `arrow.get_function_body_mut().map(\|body\| &mut body.statements)` |
| Synthetic expression statement in `arrow.body` | Direct `ArrowFunctionBody` expression variant |
| `arrow.body = function_body` | `arrow.body = ArrowFunctionBody::FunctionBody(function_body)` |
| Expression-to-block conversion | Create a `FunctionBody` containing a return statement |
| Block-to-expression conversion | Assign the expression directly to `arrow.body` |
| Builder `(expression, body)` arguments | Pass a single `ArrowFunctionBody` |

closes https://github.com/oxc-project/backlog/issues/211
2026-07-29 13:32:32 +00:00
Faris Tristan Fabian 1fb3d7073c feat(oxlint): show file:line:col in github format annotation messages (#25020)
In GitHub Actions the annotation parameters (`file=`, `line=`, `col=`)
only feed the annotations panel, so the log line itself has no location:

```
Error: Function 'foo' is declared but never used.
```

A teammate hit this in my repo's CI and could not tell which file broke
the lint job. My workaround was re-running oxlint with
`--format=default` on failure, same as csvn in #21574.

This prefixes the message with the location, same layout as [Ruff's
GitHub
renderer](https://github.com/astral-sh/ruff/blob/main/crates/ruff_db/src/diagnostic/render/github.rs):

```
::error file=test.js,line=5,endLine=5,col=1,endColumn=10,title=eslint(no-debugger)::test.js:5:1: `debugger` statement is not allowed
```

The location does get duplicated in the annotation bubble, which is
already anchored to the line. Ruff accepted that trade for a readable
log. The filename is escaped twice on purpose, property rules for
`file=` and data rules for the message text, with a unit test covering
the difference.

Related to #21574 but this does not implement multi-format output.

Updated the unit tests, the CLI snapshots, and the github e2e fixture.
`cargo test -p oxlint` passes (396) and so does the apps/oxlint vitest
suite.

I used Claude Code to help investigate and draft this. I reviewed the
change and ran the tests myself.
2026-07-29 11:56:05 +01:00
Sysix 2ff0ccc594 refactor(oxlint/linter/lsp): extend "ignore fixes" on diagnostic creation (#24958)
This PR refactors the "ignore fixes" code, to be created on diagnostic creation.
With an extra flag in `LintOptions` and `LintRunner`, the caller can include automatically the fix for ignoring the diagnostic.
This flag is only enabled on `oxlint --lsp` side and is not effected by normal CLI usage.

Important changes:
- The "fixes" are working now with `Spans` instead of `Position`
- The calculation of the right span is not depending on the partial source text, instead of the full source text
- new `FixKind` for the `ignore` fixes.

Generated by GPT-5.3-Codex 🤖 Reviewed by myself
2026-07-29 10:17:49 +00:00
Faris Tristan Fabian 2b027111db fix(oxlint): correct --warn flag help text (#25059)
The `-W, --warn` help text says "Deny the rule or category (emit a
warning)", copied from the `-D, --deny` entry.

With that wording, `--warn` and `--deny` look like they do the same
thing in `--help`, but `-W` reports a warning and `-D` reports an error.

Evidence why I think this is not intentional, and instead a typo:

- The other two entries start with their own flag's verb ("Allow the
rule...", "Deny the rule..."). Only the `-W` entry starts with its
sibling's verb, in a sentence identical to the `-D` one except the
parenthetical.
- These flags mirror rustc and clippy's `-A`/`-W`/`-D`, where warn and
deny are two different levels and deny specifically means "make it an
error".
- In this same file, `-W` maps to `AllowWarnDeny::Warn` and `-D` maps to
`AllowWarnDeny::Deny` (`into_tuple`). The internal name for what `-W`
does is warn, not deny.

What changed:

- The `-W` help text is now "Warn on the rule or category (emit a
warning)"
- Updated the two website_linter snapshots, so the generated CLI docs
page picks up the fix

I used Claude Code to help find and fix this.

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-07-29 11:05:18 +01:00
Sysix 7807304a70 refactor(oxlint/linter/lsp): move ignore logic to oxc_linter (#24951)
The start for fixing https://github.com/oxc-project/oxc/issues/24570

At the moment the "ignore this line" / "ignore this section" logic is living inside `oxlint/lsp` directory.
Because we now need to know the AST parents, the code should live inside `oxc_linter`.

This PR refactors the 2 methods into a new `oxc_linter` file.
2026-07-29 09:40:58 +00:00
leaysgur 87e0970e7a test(oxfmt): fix windows ci (#25069)
It seems that picocolors, which Vite uses, always outputs color.
2026-07-29 09:13:56 +00:00
leaysgur 1b57f783fb feat(oxfmt): support tsx-in-vue (#25063)
Part of #16608, closes #25046.

---

Even with a simple regexp, I don't want to impact the performance of the vast majority of ts-in-vue paths.

With this approach, only tsx-in-vue use cases will be affected, and even that will be kept to a minimum since it can be handled entirely on the Rust side. (JS <-> Rust roundtrip is also slow)
2026-07-29 07:27:43 +00:00
leaysgur be7f6da49a feat(oxfmt): colorize diff file list in check mode (#25061)
Fixes #25018
2026-07-29 06:00:25 +00:00
leaysgur f56009a676 fix(oxfmt): correct prose about comment width in fits measurement (#25054)
Audited every formatter crate against the trailing-comment width discipline.

- same-line trailing line comments ride `line_suffix` and are excluded from the fits measurement
- while trailing block comments print inline and count

Corrected the prose that misstated it.
2026-07-29 02:57:17 +00:00
leaysgur 22fdda4634 fix(oxfmt/conformance): fix typo (#25053)
Typo...
2026-07-29 02:57:17 +00:00
leaysgur 62a5ceaa4e test(oxfmt): add yaml conformance fixtures (#24892) 2026-07-28 07:43:14 +00:00
leaysgur 34c944f32f test(oxfmt/conformance): serialize fixture download of the same repo (#25015)
Fixes degit race issue: https://github.com/oxc-project/oxc/actions/runs/30334528300/job/90203690852?pr=24892
2026-07-28 07:31:08 +00:00
leaysgur 0c16cb5aba feat(oxfmt)!: Format parser:yaml files by oxc_formatter_yaml (#24890)
Format `.yaml`, `.yml` and others by `oxc_formatter_yaml`.

Also handle maybe-json-or-yaml files like `.prettierrc`.
2026-07-28 06:16:26 +00:00
leaysgur e6e584b9be fix(oxfmt): type jsdoc. enum options (#25008)
Fixes #24999
2026-07-28 01:22:23 +00:00
renovate[bot] c8c26a8ec3 chore(deps): update oxc to ^0.142.0 (#24992)
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/) |
|---|---|---|---|---|---|
| [@oxc-project/types](https://oxc.rs)
([source](https://redirect.github.com/oxc-project/oxc/tree/HEAD/npm/oxc-types))
| [`^0.141.0` →
`^0.142.0`](https://renovatebot.com/diffs/npm/@oxc-project%2ftypes/0.141.0/0.142.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@oxc-project%2ftypes/0.142.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@oxc-project%2ftypes/0.142.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@oxc-project%2ftypes/0.141.0/0.142.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@oxc-project%2ftypes/0.141.0/0.142.0?slim=true)
|
| [oxc-parser](https://oxc.rs/docs/guide/usage/parser)
([source](https://redirect.github.com/oxc-project/oxc/tree/HEAD/napi/parser))
| [`^0.141.0` →
`^0.142.0`](https://renovatebot.com/diffs/npm/oxc-parser/0.141.0/0.142.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/oxc-parser/0.142.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/oxc-parser/0.142.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/oxc-parser/0.141.0/0.142.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/oxc-parser/0.141.0/0.142.0?slim=true)
|

---

### Release Notes

<details>
<summary>oxc-project/oxc (oxc-parser)</summary>

###
[`v0.142.0`](https://redirect.github.com/oxc-project/oxc/blob/HEAD/napi/parser/CHANGELOG.md#01420---2026-07-27)

##### 🚀 Features

-
[`11f5d1f`](https://redirect.github.com/oxc-project/oxc/commit/11f5d1f)
ast\_visit: Add `Utf8ToUtf16::convert_program_and_comments`
([#&#8203;24859](https://redirect.github.com/oxc-project/oxc/issues/24859))
(overlookmotel)

##### 🐛 Bug Fixes

-
[`e80574f`](https://redirect.github.com/oxc-project/oxc/commit/e80574f)
estree: Handle empty spans serializing `ImportMeta` and `NewTarget`
([#&#8203;24775](https://redirect.github.com/oxc-project/oxc/issues/24775))
(overlookmotel)

</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:eyJjcmVhdGVkSW5WZXIiOiI0My4yODAuMCIsInVwZGF0ZWRJblZlciI6IjQzLjI4MC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-27 17:56:45 +01:00
oxc-guard 65fe65d842 release(apps): oxlint v1.76.0 && oxfmt v0.61.0 (#24976)
# Oxlint
### 🚀 Features

- 8d31dfa linter: Verify eslint/no-restricted-globals config schema (#24598) (vigneshwar)
- 7069621 linter: Verify jest/vitest prefer-lowercase-title config schema (#24724) (Bartok)
- 016cf2a linter/oxc: Add bad-match-all-arg rule (#24900) (camc314)
- cdc941e linter/n: Implement `exports-style` rule (#24087) (Mikhail Baev)
- 1ad6f6c linter/eslint: Implement `id-denylist` rule (#24632) (Mikhail Baev)
- 678bbb5 linter/typescript-eslint: Implement suggestion for `class-literal-property-style` rule (#24766) (Mikhail Baev)

### 🐛 Bug Fixes

- a5f3a0e linter: Mark missing suggestions as pending (#24956) (Mikhail Baev)
- a065946 oxlint: Absolutize explicit CLI paths even with --no-ignore (#24646) (Bez Sahara)
- 17688bb linter/jsx-a11y/interactive-supports-focus: Match eslint behavior for custom components (#24780) (Cole Ellison)
- 0aef19e linter/typescript/no-confusing-non-null-assertion: Report `in` and `instanceof` (#24825) (Mikhail Baev)
- 361dce9 linter: Unicorn/no-array-reverse and no-array-sort replacements should be suggestions (#24848) (klem)
- 9213560 config: Preserve defineConfig field JSDoc (#24326) (周星星同学)
- 334d884 linter/node/no-top-level-await: Clarify diagnostic (#24803) (camc314)
- b9fc6af linter/eslint/func-names: Ignore overloads (#24801) (camc314)
- e80574f estree: Handle empty spans serializing `ImportMeta` and `NewTarget` (#24775) (overlookmotel)

### ⚡ Performance

- c75dc60 linter: Avoid `Vec` allocations via `bound_names` (#24959) (connorshea)
- 9f9f39d linter/eslint/no-const-assign: Avoid `Vec` allocation per `const` declarator (#24953) (connorshea)
- 10a621e linter/typescript/adjacent-overload-signatures: Avoid collecting vec in some cases (#24874) (connorshea)
- ed167e1 linter/node/exports-style: Iterate once over global references (#24877) (connorshea)
- 69908fe linter: Avoid allocations in jest/no-deprecated-functions (#24866) (Connor Shea)
- a3585d7 linter: Speed up jest/vitest prefer-each (#24872) (Connor Shea)
- 62fe640 linter/eslint/prefer-rest-params: Run once per file (#24873) (Connor Shea)
- 7a7aa54 linter/eslint/no-this-before-super: Skip files without classes (#24869) (Connor Shea)
- 4ad0c94 linter/plugins: Faster copying comments to JS allocator (#24858) (overlookmotel)
- 4c25b91 linter/plugins: Test booleans with explicit `=== false` (#24830) (overlookmotel)
- b7add00 linter/plugins: Remove check in loop in `getDisableDirectives` (#24833) (overlookmotel)

### 📚 Documentation

- 3ff2e0e linter: Clarify config extends types (#24936) (Boshen)
# Oxfmt
### 🚀 Features

- eabfe01 oxfmt/lsp: Support `oxc.fmt.disableNestedConfig` (#24965) (leaysgur)
- 2357a10 formatter_yaml: Implement YAML formatter (#24534) (leaysgur)

### 🐛 Bug Fixes

- 761a882 formatter_css: Keep leading `+` in An+B to enable idempotency check (#24973) (leaysgur)
- e037709 formatter: Stop preserving indent for embedded template exprs (#24972) (leaysgur)
- ae1a39b formatter_css: Align wrapped selector-arg indent (#24971) (leaysgur)
- 143fd1f formatter: Align quoted `new` signature (#24883) (leaysgur)
- 07ff12f formatter_yaml: Fix indent, blank, and spacing issues (#24837) (leaysgur)
- d076b40 formatter: Check calee chain is_simple (#24871) (leaysgur)
- fb34196 formatter_css: Keep non-ASCII strings with quotes (#24870) (leaysgur)
- 9213560 config: Preserve defineConfig field JSDoc (#24326) (周星星同学)
- 31783e9 formatter_css: Print nested SCSS map with consistent indent (#24789) (leaysgur)
- 8eb9eca formatter/jsdoc: Respect `singleQuote` option in `@import` (#24787) (leaysgur)
- 6f05ac4 formatter: Fix template literal formatting (#24786) (leaysgur)

### ⚡ Performance

- bb73b23 formatter_core: Bound the thread-local scratch cache (#24793) (leaysgur)
- a5f7b15 formatter: Stage assignment-like left hand side on the heap (#24613) (leaysgur)
- 94de05f formatter: Accumulate JSX child-list builders on the heap (#24585) (leaysgur)
- 7810e8a formatter_core: Share one thread-cached scratch vector across staging buffers (#24583) (leaysgur)
- c191f51 formatter_core: Stage IR buffers on the heap to reduce arena memory (#24582) (leaysgur)

### 📚 Documentation

- 69126a0 formatter_css,fomatter_graphql,formatter_yaml: Update AGENTS.md (#24821) (leaysgur)
2026-07-27 15:17:12 +00:00
leaysgur e037709234 fix(formatter): stop preserving indent for embedded template exprs (#24972)
Fixes idempotency issue in html|css-in-js. (= align gql-in-js behavior)
2026-07-27 08:04:57 +00:00
leaysgur ae1a39b71c fix(formatter_css): align wrapped selector-arg indent (#24971)
Fixes #24843

---

Tracing back to the root cause, this is also related to what had diverged because of Prettier's inconsistent behavior.
Since I cannot determine for sure how it should be output in more complex cases (like that issue) at this point, decided to revert to being Prettier-compatible.
2026-07-27 06:47:19 +00:00
leaysgur dbf85def42 refactor(formatter_graphql): rework comment printing (#24970)
Also fixes #24927

- rework comment printing to follow the rules and align with other formatters
- bump `oxc-graphql-parser`
  - to track comments inside a node's span more accurately
2026-07-27 05:31:01 +00:00
Boshen 3ff2e0e6fa docs(linter): clarify config extends types (#24936)
The generated config reference only described the JSON schema's `string[]` form. Clarify that `oxlint.config.ts` accepts imported `OxlintConfig[]`, add an example and public JSDoc, and regenerate the derived artifacts.

Closes #20238.

Validated with the website generator suite, targeted TypeScript checks, and the relevant Oxlint tests. The full `just ready` run reached an unrelated parallel suppression-fixture cleanup race; the failing test passes in isolation.

AI-assisted.
2026-07-27 01:51:16 +00:00
leaysgur eabfe016cf feat(oxfmt/lsp): support oxc.fmt.disableNestedConfig (#24965)
Refs: voidzero-dev/vite-plus#2245

(I had assumed Oxlint didn't have an option for LSP either, but that wasn't the case.)
2026-07-27 01:32:09 +00:00
vigneshwar 8d31dfa393 feat(linter): verify eslint/no-restricted-globals config schema (#24598)
Part of #22955. Follow-up to the resolved #23617.

## What

`eslint/no-restricted-globals` stayed in `NO_VERIFIED_VALID_SCHEMA`
after #23617 was resolved, because the derived schema described the
internal `NoRestrictedGlobalsConfig` struct (a `globals` hash map)
rather than the user-facing positional-array format the rule actually
parses.

This PR adds a hand-written `JsonSchema` following the existing
`no-restricted-imports` pattern, describing the three accepted
positional item forms:

1. `"event"` — a global name string
2. `{ "name": "event", "message": "…" }` — a name/message object
3. `{ "globals": [ … ], "checkGlobalObject": true, "globalObjects": [ …
] }` — the object form added in #23617

Generated TS declaration:

```ts
"no-restricted-globals"?:
  RuleNoConfig | [AllowWarnDeny, NoRestrictedGlobalsConfigEnum, ...NoRestrictedGlobalsConfigEnum[]];
export type NoRestrictedGlobalsConfigEnum = string | RestrictedGlobal | NoRestrictedGlobalsObjectConfig;
```

Verified against the #22955 checklist: reflects all accepted user
configuration forms, denies unknown fields on object forms, and produces
no `[k: string]: unknown` in the TS declaration. `from_configuration`
and rule behavior are unchanged; rule tests pass.

Note: this branch removes only the `no-restricted-globals` entry from
`NO_VERIFIED_VALID_SCHEMA`; #24586 (separate PR) removes the
`filename-case` entry, so whichever merges second will have a trivial
conflict in that array.

## Disclosure

This contribution was developed with assistance from Claude Code
(Anthropic); I have reviewed and tested all changes.

---------

Signed-off-by: Alexander S. <sysix@sysix-coding.de>
Co-authored-by: Alexander S. <sysix@sysix-coding.de>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-26 16:55:55 +02:00
Bartok 7069621199 feat(linter): verify jest/vitest prefer-lowercase-title config schema (#24724)
## Summary

- Unskip `jest/prefer-lowercase-title` and
`vitest/prefer-lowercase-title` from `NO_VERIFIED_VALID_SCHEMA`.
- PreferLowercaseTitleConfig already derives `Deserialize` +
`JsonSchema` with `deny_unknown_fields` and docs for all public options,
so the generated schema/types can describe the real config.
- Regenerates `npm/oxlint/configuration_schema.json` and
`apps/oxlint/src-js/package/config.generated.ts`.

## Motivation

Part of #22955. These two plugin names shared a clean config struct
already used at runtime; they were still emit-as-`DummyRule` only
because of the broader #23186 split note (mainly about `valid-title`
option divergence). Leaving `valid-title` skipped.

Generated config now exposes:

- `allowedPrefixes: string[]` (default `[]`)
- `ignore: string[]` (default `[]`)
- `ignoreTopLevelDescribe: boolean` (default `false`)
- `lowercaseFirstCharacterOnly: boolean` (default `true`)
- `additionalProperties: false` / no `[k: string]: unknown`

## Verification

- `cargo test -p website_linter` — 8 passed
- `cargo test -p oxc_linter --features ruledocs
test_rules_with_custom_configuration_have_schema` — passed
- `cargo test -p oxc_linter prefer_lowercase_title --lib` — 2 passed
(jest + vitest)
- Inspected generated schema/TS: not DummyRule; no index signature

## AI disclosure

Assisted by AI (Hermes/Sera). I reviewed the existing
PreferLowercaseTitleConfig against the GFI checklist, regenerated
schema/types locally, and ran the tests above.

---
**Agent-Owner:** `sera` · **Platform:** hermes · **Claim:** `sera`

---
<!-- fleet-pr-claim: agent_id=sera platform=hermes -->
**Agent-Owner:** `sera` · **Platform:** hermes · **Claim-TTL:** 24h

---------

Co-authored-by: Bartok9 <259807879+Bartok9@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-26 10:30:37 +08:00
Bez Sahara a065946a8c fix(oxlint): absolutize explicit CLI paths even with --no-ignore (#24646)
## Summary

Explicit CLI paths (e.g. `oxlint some/relative/dir`) were only
absolutized as a side effect of the ignore-file pre-filtering step,
which `--no-ignore` skips entirely. That let relative paths flow through
to `Walk`, and from there to every downstream consumer - including the
type-aware tsgolint integration, which invokes typescript-go's
`ComputeConfigFileName` expecting absolute paths and panics ("vfs: path
... is not absolute") on a relative one.

This is the companion fix requested in
[oxc-project/tsgolint#1088](https://github.com/oxc-project/tsgolint/pull/1088),
where a maintainer asked for the absolute-path invariant to be enforced
on the oxc side rather than defensively inside tsgolint itself.

## Repro

`oxlint --no-ignore -c <config with options.typeAware=true>
node_modules/some-pkg` (a relative path) panicked with the vfs error
above. The same command with an absolute path worked fine, confirming
the gap was specific to `--no-ignore` skipping absolutization.

## Fix

Absolutizes CLI paths unconditionally in a new branch that mirrors the
existing ignore-block's absolutization logic, but only runs for
`--no-ignore` (the existing branch already absolutizes as part of its
own filtering - left untouched here to avoid changing its
ignore-matching behavior). Both paths share a small `absolutize`
closure, which also skips the redundant extra allocation
`std::path::absolute` would otherwise do on top of `cwd.join()` when the
path is already absolute (a common case for CI/automation scripts that
already pass absolute paths).

## Testing

- Repro'd against a real `node_modules` package (`lucide-react`) with
`--no-ignore` + type-aware enabled + a relative path: panicked before
this fix, 0 panics after (including a genuine type-aware finding,
confirming tsconfig resolution now succeeds end-to-end).
- Confirmed the standard case (absolute path, no `--no-ignore`) is
unaffected.
- `cargo test -p oxlint --lib`: one pre-existing failure,
`lint::suppression::test_only_non_fixed_diagnostics_are_reported`
(`STATUS_STACK_BUFFER_OVERRUN`) - confirmed via revert-and-rebuild that
it crashes identically without this change, so it's unrelated (appears
specific to this GNU-toolchain-on-Windows build environment, not
something CI building the MSVC target would hit).

## Disclosure

Found and fixed with Claude's (Anthropic) assistance, following up on
[oxc-project/tsgolint#1088](https://github.com/oxc-project/tsgolint/pull/1088)
- reviewed and verified locally (repro before/after, test suite) before
submitting.

---------

Signed-off-by: Cameron <cameron.clark@hey.com>
Co-authored-by: Cameron <cameron.clark@hey.com>
2026-07-24 18:29:17 +01:00
camc314 016cf2acd6 feat(linter/oxc): add bad-match-all-arg rule (#24900)
## Summary

- add oxc/bad-match-all-arg for non-global regular expressions passed to matchAll
- share cycle-safe RegExp flag resolution with bad-replace-all-arg
- support callable and global-qualified RegExp constructors
- update generated metadata, diagnostics, timings, and CLI rule-count snapshots

Closes #24823.
2026-07-24 14:48:45 +00:00
leaysgur d7c222dc54 test(oxfmt): remove unicode-ascii replaces (#24895)
Now it is forced by env var.
2026-07-24 09:27:12 +00:00
leaysgur f5bfec5014 chore(oxfmt): update prettier to 3.9.6 (#24880)
https://github.com/prettier/prettier/blob/3.9.6/CHANGELOG.md#396
2026-07-24 05:39:15 +00:00
leaysgur 9bf5c71ac7 refactor(formatter_core): introduce exact_line_breaks builder (#24865)
Introduce `exact_line_breaks(count)` IR builder.

This produces a line element that prints exactly `count` line breaks, exempt from the printer's hardline collapsing / empty-line capping.

Blank runs inside verbatim values (YAML block/flow scalars, GraphQL block strings) are the value itself and must not be normalized.
Previously this was emulated by emitting raw `\n` text followed by a re-arming `hard_line_break()`..., hack.

Also removed the printer behavior that trims end of line whitespaces.
2026-07-24 04:05:12 +00:00
overlookmotel 99d263b123 refactor(linter/plugins): simplify getDisableDirectives (#24852)
Pure refactor, except for fixing a TS type, and correcting some comments. Runtime behavior is unaltered.

- `LABEL_PATTERN` captures the directive type as well as the label, so the multi-line check is a
single comparison, and `type` no longer comes from `label.slice(7)`.
- Numbered capture groups instead of named ones, so the match check is just `match === null`.
- `match` is no longer reused for a second, unrelated regex.
- `justification` is always set, so it's not optional - correct the type def accordingly.
- Simplify splitting off `justification`.
- Doc comment referenced `match_disable_directive` / `match_enable_directive`. The Rust function is
`match_directive` - correct the comment.
2026-07-23 16:59:45 +00:00
overlookmotel c126eebef6 refactor(linter/plugins): remove dead code in getDisableDirectives (#24851)
`LINE_DIRECTIVE_PATTERN` had a stray hyphen (`disable-(?:-next)?-line`), so it only matched
`disable--line` / `disable--next-line` - strings `LABEL_PATTERN` can never produce. Therefore it was dead code - remove it.

If the regex _was_ correctly written, the behavior would be wrong. Looks like this is a hangover from the code being taken from ESLint.
2026-07-23 16:59:44 +00:00
overlookmotel 3446ee7ebc test(linter/plugins): check comments and tokens within bounds of source text (#24832)
Add more debug assertions to debug build-only code which checks the validity of comments and tokens.

Make sure all comments and tokens have spans which are wihin bounds of source text. In particular, this will surface any problems where the source text contains a BOM, which causes us to adjust spans on Rust side when trimming off the BOM.
2026-07-23 09:29:53 +00:00
overlookmotel f5b9e01cf6 refactor(linter/plugins): remove unnecessary type asserts (#24831)
Pure refactor. Remove some type assertions which were unnecessary - TS already knows these vars can't be `null`.
2026-07-23 09:29:53 +00:00
overlookmotel 4c25b91c64 perf(linter/plugins): test booleans with explicit === false (#24830)
Tiny perf optimization to linter plugins.

`if (x === false)` is longer than `if (!x)`, but is more performant. The 1st compiles down to a simple equality check between `<value x>` and `kFalse` constant, whereas the 2nd is more like `coerceToBoolean(<value x>) === kFalse` - a more expensive operation.

This follows our convention in all JS plugins code of always using explicit `=== false` / `=== true` comparisons.
2026-07-23 09:29:53 +00:00
overlookmotel f85e47d7e6 refactor(linter/plugins): add debug asserts (#24829)
Pure refactor. Use debug asserts instead of type assertions in code for deserializing comments and tokns. This gives better error messages if we break the invariants in tests. Makes no difference in release build.
2026-07-23 09:29:52 +00:00
overlookmotel b7add00c28 perf(linter/plugins): remove check in loop in getDisableDirectives (#24833)
Small optimization to `context.sourceCode.getDisableDirectives`.

`Shebang` comment can only be the first comment in a file, so there's no need to check "is it a `Shebang`?" for every comment in a loop. Instead, just check the first comment before the loop.

Also add type annotation for the function's return type.
2026-07-23 09:10:58 +00:00
Mikhail Baev cdc941e5f8 feat(linter/n): implement exports-style rule (#24087)
this PR implements `n/exports-style` rule. Issue #493

---------

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-07-22 16:50:23 +01:00
周星星同学 9213560fe7 fix(config): preserve defineConfig field JSDoc (#24326)
## Summary

- contextually type oxlint and oxfmt `defineConfig` object arguments as
their config interfaces
- keep the identity-helper return type so literal inference is preserved
- restore field-level JSDoc hover for config object properties in
editors

## Validation

Manual expansion of `just ready` because `just` is not installed in my
local shell:

- `pnpm install`
- `typos`
- `cargo lintgen`
- `cargo shear --fix --check-test-targets` (returned 0; emitted an
unrelated existing redundant-ignore warning for `oxc_lexer` in workspace
metadata)
- `cargo fmt`
- `node --run fmt`
- `cargo ck`
- `env -u NO_COLOR cargo test --all-features`
- `cargo lint -- --deny warnings`
- `RUSTDOCFLAGS='-D warnings' cargo doc --no-deps
--document-private-items --all-features`
- `cargo run -p oxc_ast_tools`

TypeScript language-service probe using VS Code's bundled TypeScript
SDK:

- old `defineConfig<T extends Config>(config: T): T` returned no docs
for object fields
- new `defineConfig<T extends Config>(config: T & Config): T` returned
JSDoc for `oxlint.ignorePatterns` and `oxfmt.semi`
- invalid property/type probes still reported TS2561 and TS2322
- return literal inference stayed unchanged for representative
oxlint/oxfmt config objects

## AI Assistance

This PR was prepared with AI assistance. I reviewed the change,
validation approach, and PR contents before submission.

Co-authored-by: cixiangtao <cixiangtao@kanyun.com>
Co-authored-by: Cameron <cameron.clark@hey.com>
2026-07-22 16:41:41 +01:00
Mikhail Baev 1ad6f6c823 feat(linter/eslint): implement id-denylist rule (#24632)
this PR implements `eslint/id-denylist`, issue #479
2026-07-22 16:30:20 +01:00
overlookmotel e80574fdf0 fix(estree): handle empty spans serializing ImportMeta and NewTarget (#24775)
Follow-on after #24557. Handle when `ImportMeta` / `NewTarget` has an empty span (`SPAN`). This code path is not exercised at present, but it seems a good idea to be prepared for when we may serialize AST after transformation.
2026-07-22 08:05:57 +00:00
renovate[bot] 935e9c8b26 chore(deps): update oxc to ^0.141.0 (#24771) 2026-07-21 17:33:16 +01:00
Boshen 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.
2026-07-21 15:22:46 +00:00
oxc-guard[bot] 83abe3b49c release(apps): oxlint v1.75.0 && oxfmt v0.60.0 (#24713)
# Oxlint
### 💥 BREAKING CHANGES

- 54cc121 ast: [**BREAKING**] Split `MetaProperty` into `ImportMeta` and
`NewTarget` (#24557) (camc314)

### 🚀 Features

- 7b045cd minfier: Drop last break from last switch case (#24673)
(Armano)
- dd18383 linter/node: Implement no-top-level-await rule (#24634)
(Connor Shea)
- 16a65f2 linter/react: Implement function-component-definition rule
(#24471) (Cole Ellison)
- 7f1f585 linter: Reuse `jest/padding-around-test-blocks` for
`vitest/padding-around-test-blocks` (#24519) (Mikhail Baev)
- 99978a8 linter/import/consistent-type-specifier-style: Support
`prefer-top-level-if-only-type-imports` option (#24502) (camc314)

### 🐛 Bug Fixes

- 0184ad6 linter/unicorn/no-useless-undefined: Preserve valid parameter
defaults (#24686) (camc314)
- 8694167 linter/eslint/prefer-destructuring: Handle typed declarations
(#24616) (camc314)
- 477cf0f linter/eslint/no-throw-literal: Handle assigned errors
(#24561) (Cole Ellison)
- ac9200a linter: Detect React components from returned JSX (#24521)
(camc314)
- c0a6522 linter/eslint/no-useless-computed-key: Allow TS syntax in
computed keys (#24524) (Cole Ellison)

### ⚡ Performance

- 346eed1 linter/unicorn/prefer-event-target: Only run on `Class` and
`NewExpression` nodes (#24685) (Mikhail Baev)
- 7be5cf0 oxlint/lsp: Only invoke lint on code actions when document is
not opened (#24676) (Sysix)
- d3f07a0 diagnostics: Box OxcDiagnosticInner to reduce binary size
(#24665) (Boshen)
- 90ae040 linter/reporter/stylish: Compute diagnostic Info once per
diagnostic (#24525) (connorshea)

### 📚 Documentation

- e6f7174 linter/valid-expect: Fix correct example being identical to
incorrect one (#24468) (mkan0141)
# Oxfmt
### 💥 BREAKING CHANGES

- 54cc121 ast: [**BREAKING**] Split `MetaProperty` into `ImportMeta` and
`NewTarget` (#24557) (camc314)

### 🚀 Features

- 3d22307 parser: Add `ParseOptions::enable_ident_hashes` (#24491)
(Boshen)

### 🐛 Bug Fixes

- 6fe866a oxfmt: Keep tailwind classes glued to template expr with
`preserveWhitespace` (#24609) (leaysgur)
- 33e32d8 formatter_css: Use `line_suffix` for EOL line comment (#24580)
(leaysgur)
- 5f76998 formatter_graphql: Keep same line comments pending across
intervening tokens (#24579) (leaysgur)

Co-authored-by: Boshen <1430279+Boshen@users.noreply.github.com>
Co-authored-by: Cameron <cameron.clark@hey.com>
2026-07-21 16:10:25 +01:00
camc314 6ce51d3ff3 chore(deps): update dependency oxlint-tsgolint to v7.0.2000 (#24763) 2026-07-21 14:55:25 +00:00
leaysgur e81b2ff6c5 fix(oxlint,oxfmt): report error for invalid glob patterns (#24744)
Fixes #24612

- Update `fast-glob` to `1.1.0` which exposes `validate()` api
- Use it in `oxc_config`, apps will be validated through `deserialize`
- Oxfmt supports globs for CLI paths, also validated
2026-07-21 04:43:49 +00:00
renovate 577cbbe3ed chore(deps): update dependency execa to v10 (#24695)
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/) |
|---|---|---|---|---|---|
| [execa](https://redirect.github.com/sindresorhus/execa) | [`^9.6.0` → `^10.0.0`](https://renovatebot.com/diffs/npm/execa/9.6.1/10.0.0) | ![age](https://developer.mend.io/api/mc/badges/age/npm/execa/10.0.0?slim=true) | ![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/execa/10.0.0?slim=true) | ![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/execa/9.6.1/10.0.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/execa/9.6.1/10.0.0?slim=true) |

---

### Release Notes

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

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

[Compare Source](https://redirect.github.com/sindresorhus/execa/compare/v9.6.1...v10.0.0)

##### Breaking

- Require Node.js 22. ([#&#8203;1243](https://redirect.github.com/sindresorhus/execa/issues/1243))  [`04b4454`](https://redirect.github.com/sindresorhus/execa/commit/04b4454)

- The subprocess is now a normal promise, instead of a [`ChildProcess`](https://nodejs.org/api/child_process.html#class-childprocess) instance augmented with promise methods. All the methods and properties [documented by Execa](docs/api.md#subprocess) are unchanged. Node.js-specific `ChildProcess` APIs (such as `.on()`, `.send()`, `.ref()` and `.unref()`) must now be accessed through the new [`subprocess.nodeChildProcess`](docs/api.md#subprocessnodechildprocess) property. ([#&#8203;1255](https://redirect.github.com/sindresorhus/execa/issues/1255))  [`ade74bf`](https://redirect.github.com/sindresorhus/execa/commit/ade74bf)

```diff
const subprocess = execa('node', ['file.js']);
- subprocess.on('spawn', onSpawn);
+ subprocess.nodeChildProcess.on('spawn', onSpawn);
```

- Removed `execaCommand()` and `execaCommandSync()`. Use the [template string syntax](docs/execution.md#template-string-syntax) instead, which splits on spaces. If the command is a dynamic string, split it with [`parseCommandString()`](docs/api.md#parsecommandstringcommand). ([#&#8203;1244](https://redirect.github.com/sindresorhus/execa/issues/1244))  [`3ced394`](https://redirect.github.com/sindresorhus/execa/commit/3ced394)

```diff
- await execaCommand('npm run build');
+ await execa`npm run build`;

- await execaCommand(commandString);
+ await execa`${parseCommandString(commandString)}`;
```

- Removed the old undocumented `stdio: [..., 'ipc']` syntax. Use the [`ipc: true`](docs/api.md#optionsipc) option instead. ([#&#8203;1245](https://redirect.github.com/sindresorhus/execa/issues/1245))  [`dcf611c`](https://redirect.github.com/sindresorhus/execa/commit/dcf611c)

```diff
- await execa('node', ['file.js'], {stdio: ['pipe', 'pipe', 'pipe', 'ipc']});
+ await execa('node', ['file.js'], {ipc: true});
```

- When the [`input`](docs/api.md#optionsinput) or [`inputFile`](docs/api.md#optionsinputfile) option is combined with an inherited [`stdin`](docs/api.md#optionsstdin) (for example `stdio: 'inherit'`), the explicit input is now used, instead of being ignored. To combine [multiple inputs](docs/input.md#multiple-inputs), pass an array like `stdin: ['inherit', {string: 'input'}]`. ([#&#8203;1232](https://redirect.github.com/sindresorhus/execa/issues/1232))  [`3ed0544`](https://redirect.github.com/sindresorhus/execa/commit/3ed0544)

##### Improvements

- Terminate the subprocess' [descendant processes](docs/termination.md#killing-descendant-processes) by using the [`killDescendants`](docs/api.md#optionskilldescendants) option. This is useful when the subprocess spawns its own processes, such as when using the [`shell`](docs/api.md#optionsshell) option. ([#&#8203;1256](https://redirect.github.com/sindresorhus/execa/issues/1256))  [`84fa0ec`](https://redirect.github.com/sindresorhus/execa/commit/84fa0ec)

```js
await execa('npm', ['run', 'build'], {killDescendants: true, timeout: 5000});
```

- [Convert the subprocess](docs/streams.md#converting-a-subprocess-to-a-web-stream) to a web stream by using [`subprocess.readableStream()`](docs/api.md#subprocessreadablestreamreadableoptions), [`subprocess.writableStream()`](docs/api.md#subprocesswritablestreamwritableoptions) or [`subprocess.transformStream()`](docs/api.md#subprocesstransformstreamduplexoptions). ([#&#8203;1254](https://redirect.github.com/sindresorhus/execa/issues/1254))  [`29d9cfc`](https://redirect.github.com/sindresorhus/execa/commit/29d9cfc)

```js
await execa`npm run build`
	.readableStream()
	.pipeTo(writableWebStream);
```

- The value returned by [`subprocess.pipe()`](docs/api.md#subprocesspipefile-arguments-options) now exposes the destination subprocess' methods, so the piped output can be consumed directly: [iterate](docs/pipe.md#iterate-stream-and-ipc) over its output lines, [convert it to a stream](docs/streams.md#converting-a-subprocess-to-a-stream), or [exchange IPC messages](docs/ipc.md#exchanging-messages). ([#&#8203;1252](https://redirect.github.com/sindresorhus/execa/issues/1252))  [`c31c94c`](https://redirect.github.com/sindresorhus/execa/commit/c31c94c)

```js
for await (const line of execa`npm run build`.pipe`sort`) {
	console.log(line);
}
```

- Use an [additional file descriptor as input](docs/input.md#additional-file-descriptors) by wrapping its [`stdio`](docs/api.md#optionsstdio) value as a `{value, input: true}` object. Direction-ambiguous values (`'pipe'`, `'inherit'`, [files](docs/input.md#file-input) and [transforms](docs/transform.md)) default to output on additional file descriptors. ([#&#8203;1246](https://redirect.github.com/sindresorhus/execa/issues/1246), [#&#8203;1249](https://redirect.github.com/sindresorhus/execa/issues/1249))  [`487a3a4`](https://redirect.github.com/sindresorhus/execa/commit/487a3a4) [`9fbf5ba`](https://redirect.github.com/sindresorhus/execa/commit/9fbf5ba)

```js
const subprocess = execa({stdio: ['pipe', 'pipe', 'pipe', {value: 'pipe', input: true}]})`npm run scaffold`;

const writable = subprocess.writable({to: 'fd3'});
```

- The [transform](docs/transform.md) generator function's `chunk` argument is now typed based on the transform's mode, instead of always being `unknown`: `string` for line transforms, `Uint8Array` for [binary transforms](docs/binary.md#transforms), and `unknown` in [object mode](docs/transform.md#object-mode). ([#&#8203;1247](https://redirect.github.com/sindresorhus/execa/issues/1247))  [`0a7b4f8`](https://redirect.github.com/sindresorhus/execa/commit/0a7b4f8)

##### Fixes

- Fixed [fd-specific options](docs/output.md#stdoutstderr-specific-options) ([`verbose`](docs/api.md#optionsverbose), [`maxBuffer`](docs/api.md#optionsmaxbuffer), etc.) when the [`ipc`](docs/api.md#optionsipc) option is `true`: `fd3` and `ipc` no longer target the same file descriptor. ([#&#8203;1241](https://redirect.github.com/sindresorhus/execa/issues/1241))  [`b886883`](https://redirect.github.com/sindresorhus/execa/commit/b886883)

***

</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:eyJjcmVhdGVkSW5WZXIiOiI0My4yNjUuMSIsInVwZGF0ZWRJblZlciI6IjQzLjI2NS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
2026-07-20 07:17:09 +00:00
Armano 7b045cd417 feat(minfier): drop last break from last switch case (#24673)
After many trial and errors, this seem to be the best way to remove
break stmts in switch cases,

This change targets only last break in last case of switch smts if its
unlabelled

this change differs from #23914 as its no longer targets all branches as
that should not be no longer necessary if all cases are correctly
rewritten

https://github.com/oxc-project/oxc/issues/24672

-----

cases like `switch (a) { case 3: if (b) break; }` are not changed

-----

ref: #17544
2026-07-20 13:21:03 +08:00
renovate[bot] 68142924f7 chore(deps): update npm packages (#24682)
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.63.0` →
`8.64.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fparser/8.63.0/8.64.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2fparser/8.64.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@typescript-eslint%2fparser/8.64.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@typescript-eslint%2fparser/8.63.0/8.64.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2fparser/8.63.0/8.64.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.63.0` →
`8.64.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fscope-manager/8.63.0/8.64.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2fscope-manager/8.64.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@typescript-eslint%2fscope-manager/8.64.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@typescript-eslint%2fscope-manager/8.63.0/8.64.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2fscope-manager/8.63.0/8.64.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.63.0` →
`8.64.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fvisitor-keys/8.63.0/8.64.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2fvisitor-keys/8.64.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@typescript-eslint%2fvisitor-keys/8.64.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@typescript-eslint%2fvisitor-keys/8.63.0/8.64.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2fvisitor-keys/8.63.0/8.64.0?slim=true)
|
| [degit](https://redirect.github.com/Rich-Harris/degit) | [`3.4.7` →
`3.6.1`](https://renovatebot.com/diffs/npm/degit/3.4.7/3.6.1) |
![age](https://developer.mend.io/api/mc/badges/age/npm/degit/3.6.1?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/degit/3.6.1?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/degit/3.4.7/3.6.1?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/degit/3.4.7/3.6.1?slim=true)
|
| [eslint](https://eslint.org)
([source](https://redirect.github.com/eslint/eslint)) | [`10.6.0` →
`10.7.0`](https://renovatebot.com/diffs/npm/eslint/10.6.0/10.7.0) |
![age](https://developer.mend.io/api/mc/badges/age/npm/eslint/10.7.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/eslint/10.7.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/eslint/10.6.0/10.7.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/eslint/10.6.0/10.7.0?slim=true)
|
| [svelte](https://svelte.dev)
([source](https://redirect.github.com/sveltejs/svelte/tree/HEAD/packages/svelte))
| [`5.56.4` →
`5.56.5`](https://renovatebot.com/diffs/npm/svelte/5.56.4/5.56.5) |
![age](https://developer.mend.io/api/mc/badges/age/npm/svelte/5.56.5?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/svelte/5.56.5?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/svelte/5.56.4/5.56.5?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/svelte/5.56.4/5.56.5?slim=true)
|
| [tsx](https://tsx.hirok.io)
([source](https://redirect.github.com/privatenumber/tsx)) | [`4.23.0` →
`4.23.1`](https://renovatebot.com/diffs/npm/tsx/4.23.0/4.23.1) |
![age](https://developer.mend.io/api/mc/badges/age/npm/tsx/4.23.1?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/tsx/4.23.1?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/tsx/4.23.0/4.23.1?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/tsx/4.23.0/4.23.1?slim=true)
|

---

### Release Notes

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

###
[`v8.64.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#8640-2026-07-13)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v8.63.0...v8.64.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.64.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.64.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/scope-manager/CHANGELOG.md#8640-2026-07-13)

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

##### 🚀 Features

- support parsing `import defer`
([#&#8203;12513](https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12513))

##### ❤️ Thank You

- Evyatar Daud
[@&#8203;StyleShit](https://redirect.github.com/StyleShit)

See [GitHub
Releases](https://redirect.github.com/typescript-eslint/typescript-eslint/releases/tag/v8.64.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.64.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/visitor-keys/CHANGELOG.md#8640-2026-07-13)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v8.63.0...v8.64.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.64.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>Rich-Harris/degit (degit)</summary>

###
[`v3.6.1`](https://redirect.github.com/Rich-Harris/degit/compare/v3.6.0...v3.6.1)

[Compare
Source](https://redirect.github.com/Rich-Harris/degit/compare/v3.6.0...v3.6.1)

###
[`v3.6.0`](https://redirect.github.com/Rich-Harris/degit/compare/v3.5.1...v3.6.0)

[Compare
Source](https://redirect.github.com/Rich-Harris/degit/compare/v3.5.1...v3.6.0)

###
[`v3.5.1`](https://redirect.github.com/Rich-Harris/degit/compare/v3.5.0...v3.5.1)

[Compare
Source](https://redirect.github.com/Rich-Harris/degit/compare/v3.5.0...v3.5.1)

###
[`v3.5.0`](https://redirect.github.com/Rich-Harris/degit/compare/v3.4.7...v3.5.0)

[Compare
Source](https://redirect.github.com/Rich-Harris/degit/compare/v3.4.7...v3.5.0)

</details>

<details>
<summary>eslint/eslint (eslint)</summary>

###
[`v10.7.0`](https://redirect.github.com/eslint/eslint/releases/tag/v10.7.0)

[Compare
Source](https://redirect.github.com/eslint/eslint/compare/v10.6.0...v10.7.0)

#### Features

-
[`cf2a9bf`](https://redirect.github.com/eslint/eslint/commit/cf2a9bf2d982642f760370c15f1196f4658f4e27)
feat: add errorClassNames option to preserve-caught-error rule
([#&#8203;21032](https://redirect.github.com/eslint/eslint/issues/21032))
(sethamus)
-
[`f8b873a`](https://redirect.github.com/eslint/eslint/commit/f8b873aae53610b80b5c1005606716e05ed3b91f)
feat: max-nested-callbacks option for constructor callbacks
([#&#8203;21063](https://redirect.github.com/eslint/eslint/issues/21063))
(fnx)
-
[`557fde8`](https://redirect.github.com/eslint/eslint/commit/557fde8bc633d26ea4fe287d4483f287e8e6080f)
feat: support computed `Number.parseInt` member access in `radix` rule
([#&#8203;21041](https://redirect.github.com/eslint/eslint/issues/21041))
(Pixel)
-
[`0b4a73b`](https://redirect.github.com/eslint/eslint/commit/0b4a73b65808f5a8fd192f15db2bf5e47002b9f7)
feat: add suggestions to no-compare-neg-zero
([#&#8203;21034](https://redirect.github.com/eslint/eslint/issues/21034))
(den$)
-
[`96cdd42`](https://redirect.github.com/eslint/eslint/commit/96cdd427db5f26c6403fba92b0f7ae4556c595ec)
feat: report invalid signed numeric radix values in `radix` rule
([#&#8203;21030](https://redirect.github.com/eslint/eslint/issues/21030))
(Pixel)

#### Bug Fixes

-
[`3e7bf15`](https://redirect.github.com/eslint/eslint/commit/3e7bf15e69e6d3a2c8832356bcc2e9903cc4eede)
fix: apply `ignoreClassesWithImplements` to class expressions
([#&#8203;21069](https://redirect.github.com/eslint/eslint/issues/21069))
(Pixel)
-
[`0d7d70c`](https://redirect.github.com/eslint/eslint/commit/0d7d70cf013ec5bf1e4f5a0fcf7128bdf059b2d4)
fix: insert cause outside wrapping parens in preserve-caught-error
([#&#8203;21062](https://redirect.github.com/eslint/eslint/issues/21062))
(Mahin Anowar)
-
[`75ec753`](https://redirect.github.com/eslint/eslint/commit/75ec753226010867270787b412f3dae412e421e6)
fix: handle static template literals in `eqeqeq` rule
([#&#8203;21058](https://redirect.github.com/eslint/eslint/issues/21058))
(Pixel)
-
[`b717a22`](https://redirect.github.com/eslint/eslint/commit/b717a22e2408389a2ad40af66543e46390669eb6)
fix: prevent `eqeqeq` null option from reporting non-equality operators
([#&#8203;21057](https://redirect.github.com/eslint/eslint/issues/21057))
(Pixel)
-
[`e35b05f`](https://redirect.github.com/eslint/eslint/commit/e35b05f1961dcd691611bd68b6ff8a87072d6f76)
fix: avoid `no-invalid-regexp` false positive for shadowed RegExp
([#&#8203;21051](https://redirect.github.com/eslint/eslint/issues/21051))
(Pixel)
-
[`a3172b6`](https://redirect.github.com/eslint/eslint/commit/a3172b69c7db63ea0321355543e3f527c7d8b76a)
fix: avoid `no-control-regex` false positive for shadowed RegExp
([#&#8203;21050](https://redirect.github.com/eslint/eslint/issues/21050))
(Pixel)
-
[`d1f637e`](https://redirect.github.com/eslint/eslint/commit/d1f637eca27e523d613991c6bea5b8726b810e4c)
fix: parenthesize sequence expression operands in no-implicit-coercion
([#&#8203;21045](https://redirect.github.com/eslint/eslint/issues/21045))
(spokodev)
-
[`8859baf`](https://redirect.github.com/eslint/eslint/commit/8859bafb018e2b23b5110d52e491b69b94ad890a)
fix: avoid prefer-numeric-literals false positive for shadowed globals
([#&#8203;21047](https://redirect.github.com/eslint/eslint/issues/21047))
(한국)
-
[`a9e5961`](https://redirect.github.com/eslint/eslint/commit/a9e5961050676ef29dba9649dfcd7233d21760c7)
fix: use-isnan false positive on shadowed NaN/Number
([#&#8203;20958](https://redirect.github.com/eslint/eslint/issues/20958))
(sethamus)
-
[`8a240a7`](https://redirect.github.com/eslint/eslint/commit/8a240a76108f30f2476e61a925e4d32d378cce5e)
fix: avoid false positives in `radix` rule for spread arguments
([#&#8203;21044](https://redirect.github.com/eslint/eslint/issues/21044))
(Pixel)

#### Documentation

-
[`c30d808`](https://redirect.github.com/eslint/eslint/commit/c30d80801ca561bdf65c6c3eba4ee57dced278cf)
docs: Update README (GitHub Actions Bot)
-
[`5139800`](https://redirect.github.com/eslint/eslint/commit/5139800b23e77fdd1a76664e1b36f478942eae55)
docs: document ESLint migration codemods in v9 and v10 guides
([#&#8203;20980](https://redirect.github.com/eslint/eslint/issues/20980))
(Alex Bit)
-
[`04174cb`](https://redirect.github.com/eslint/eslint/commit/04174cbfaac1f9555400b5332d69056e6aab9cc6)
docs: Update README (GitHub Actions Bot)
-
[`026e130`](https://redirect.github.com/eslint/eslint/commit/026e1304080512bcddfd2af3557fff86474ff949)
docs: update semver policy for bug fixes
([#&#8203;21048](https://redirect.github.com/eslint/eslint/issues/21048))
(Milos Djermanovic)
-
[`9d42fef`](https://redirect.github.com/eslint/eslint/commit/9d42fefb0e05ecd0b256c2ebed479fc868862f0c)
docs: Update README (GitHub Actions Bot)
-
[`b230159`](https://redirect.github.com/eslint/eslint/commit/b23015955c8d6e6516076190730f538c86927f26)
docs: Update README (GitHub Actions Bot)
-
[`0129972`](https://redirect.github.com/eslint/eslint/commit/0129972ba122e95bece6040fda44d20f6799246a)
docs: correct `**/.js` glob to `**/*.js` in config files guide
([#&#8203;21036](https://redirect.github.com/eslint/eslint/issues/21036))
(EduardF1)

#### Chores

-
[`9489379`](https://redirect.github.com/eslint/eslint/commit/948937986f2aa3cccb27a4c80694a85e5b0a5f64)
chore: update dependency
[@&#8203;eslint/eslintrc](https://redirect.github.com/eslint/eslintrc)
to ^3.3.6
([#&#8203;21076](https://redirect.github.com/eslint/eslint/issues/21076))
(renovate\[bot])
-
[`81a4774`](https://redirect.github.com/eslint/eslint/commit/81a4774a928211bd0c01a06a1517736ece594522)
chore: updates for v9.39.5 release (Jenkins)
-
[`9835414`](https://redirect.github.com/eslint/eslint/commit/983541491393323d17717683f6a2e6dbef4bc3f4)
chore: enable `$ExpectType` annotations in all TypeScript files
([#&#8203;21071](https://redirect.github.com/eslint/eslint/issues/21071))
(Francesco Trotta)
-
[`72adf6b`](https://redirect.github.com/eslint/eslint/commit/72adf6bd214c142b38aabb4b8f6f908079c5301a)
chore: restrict `markdownlint-cli2` updates in renovate
([#&#8203;21067](https://redirect.github.com/eslint/eslint/issues/21067))
(lumir)
-
[`833ec10`](https://redirect.github.com/eslint/eslint/commit/833ec10fd702644e94334edd3cd2aa313174a958)
chore: update dependency prettier to v3.9.4
([#&#8203;21061](https://redirect.github.com/eslint/eslint/issues/21061))
(renovate\[bot])
-
[`7ea106d`](https://redirect.github.com/eslint/eslint/commit/7ea106ddcb6af7db8f36d62a28dbaba94d33598e)
chore: update ecosystem plugins
([#&#8203;21059](https://redirect.github.com/eslint/eslint/issues/21059))
(ESLint Bot)
-
[`8fb550e`](https://redirect.github.com/eslint/eslint/commit/8fb550e7c257fbdc4108fc8e63db43c1d914d472)
chore: add prettier update commit to `.git-blame-ignore-revs`
([#&#8203;21056](https://redirect.github.com/eslint/eslint/issues/21056))
(lumir)
-
[`e4e1166`](https://redirect.github.com/eslint/eslint/commit/e4e11668ead6b950328c71e894563a13ef72bf84)
chore: update dependency prettier to v3.9.1
([#&#8203;21055](https://redirect.github.com/eslint/eslint/issues/21055))
(renovate\[bot])
-
[`0493f53`](https://redirect.github.com/eslint/eslint/commit/0493f53f3fcec4ed69a1808dffa153dcff1380d3)
chore: update prettier to v3.9.0
([#&#8203;21054](https://redirect.github.com/eslint/eslint/issues/21054))
(Pixel)
-
[`1056a99`](https://redirect.github.com/eslint/eslint/commit/1056a996c657b377dc16a58c28890d2940394408)
chore: update dependency prettier to v3.8.5
([#&#8203;21049](https://redirect.github.com/eslint/eslint/issues/21049))
(renovate\[bot])
-
[`4d4155d`](https://redirect.github.com/eslint/eslint/commit/4d4155df4a21d711e8dd21a467de085e770bad35)
ci: run ecosystem tests on pull requests
([#&#8203;21027](https://redirect.github.com/eslint/eslint/issues/21027))
(sethamus)
-
[`993539f`](https://redirect.github.com/eslint/eslint/commit/993539fd45d3d01aad3fbc13963e2245fdf7ee0d)
chore: update dependency
[@&#8203;eslint/json](https://redirect.github.com/eslint/json) to ^2.0.1
([#&#8203;21042](https://redirect.github.com/eslint/eslint/issues/21042))
(renovate\[bot])
-
[`53f8b69`](https://redirect.github.com/eslint/eslint/commit/53f8b69c15af7398c989071ee4788b88edd48bdd)
test: add error locations to `no-constant-binary-expression`
([#&#8203;21039](https://redirect.github.com/eslint/eslint/issues/21039))
(lumir)
-
[`5ab71d5`](https://redirect.github.com/eslint/eslint/commit/5ab71d52f9d860df04e626fcd819a36257f21f9e)
refactor: clean up radix rule internals
([#&#8203;21015](https://redirect.github.com/eslint/eslint/issues/21015))
(Pixel)
-
[`a80a9a4`](https://redirect.github.com/eslint/eslint/commit/a80a9a461478838930c5545f840473840b26b0e6)
chore: update ecosystem plugins
([#&#8203;21035](https://redirect.github.com/eslint/eslint/issues/21035))
(ESLint Bot)
-
[`7c9a029`](https://redirect.github.com/eslint/eslint/commit/7c9a02933cf1c231237babb8a7a32150ab72e263)
ci: add Node.js 26 to CI
([#&#8203;20847](https://redirect.github.com/eslint/eslint/issues/20847))
(lumir)

</details>

<details>
<summary>sveltejs/svelte (svelte)</summary>

###
[`v5.56.5`](https://redirect.github.com/sveltejs/svelte/blob/HEAD/packages/svelte/CHANGELOG.md#5565)

[Compare
Source](https://redirect.github.com/sveltejs/svelte/compare/svelte@5.56.4...svelte@5.56.5)

##### Patch Changes

- chore: drop dead code that make TSGO fail
([#&#8203;18496](https://redirect.github.com/sveltejs/svelte/pull/18496))

- fix: don't (re)connect deriveds when read inside branch/root effects
([#&#8203;18527](https://redirect.github.com/sveltejs/svelte/pull/18527))

- fix: skip unnecessary derived effect in earlier batch
([#&#8203;18525](https://redirect.github.com/sveltejs/svelte/pull/18525))

- fix: avoid declaration tag warning in event handlers
([#&#8203;18500](https://redirect.github.com/sveltejs/svelte/pull/18500))

- fix: abort deriveds own AbortSignal when it disconnects
([#&#8203;18400](https://redirect.github.com/sveltejs/svelte/pull/18400))

- fix: ensure `$state.eager()` is correctly transormed for SSR output
([#&#8203;18530](https://redirect.github.com/sveltejs/svelte/pull/18530))

- fix: correctly transform declaration tags during SSR
([#&#8203;18492](https://redirect.github.com/sveltejs/svelte/pull/18492))

- fix: transform computed keys in keyed `{#each}` destructuring patterns
([#&#8203;18521](https://redirect.github.com/sveltejs/svelte/pull/18521))

- fix: chain preprocessor sourcemaps with an empty `sources[0]` instead
of dropping them
([#&#8203;18518](https://redirect.github.com/sveltejs/svelte/pull/18518))

- fix: clear previous\_task reference after abort in Tween to prevent
memory leak on interrupted tweens
([#&#8203;18541](https://redirect.github.com/sveltejs/svelte/pull/18541))

- fix: don't treat declaration tags as parts inside each blocks
([#&#8203;18507](https://redirect.github.com/sveltejs/svelte/pull/18507))

</details>

<details>
<summary>privatenumber/tsx (tsx)</summary>

###
[`v4.23.1`](https://redirect.github.com/privatenumber/tsx/releases/tag/v4.23.1)

[Compare
Source](https://redirect.github.com/privatenumber/tsx/compare/v4.23.0...v4.23.1)

##### Bug Fixes

- support tsImport after global preload
([8d4ffc2](https://redirect.github.com/privatenumber/tsx/commit/8d4ffc24f37b396ca2fe3f251aa92c4919f2c1a4))
- **watch:** avoid clearing piped output
([95d0672](https://redirect.github.com/privatenumber/tsx/commit/95d0672e0247a829ae4469daa493212967ea768e))
- **watch:** treat script and dependency paths literally
([79fddde](https://redirect.github.com/privatenumber/tsx/commit/79fddde523d3bb7d0af66682ce1265f95113a073))

##### Performance Improvements

- index transform cache lazily
([e818ad6](https://redirect.github.com/privatenumber/tsx/commit/e818ad608159a6fb36fb8a0bd59327fec313323d))
- load esbuild lazily in CLI
([d067938](https://redirect.github.com/privatenumber/tsx/commit/d0679381b60a55a9b5863603a4022a81db5d13c8))
- map Node TypeScript formats directly
([cdcc623](https://redirect.github.com/privatenumber/tsx/commit/cdcc6232a3277fb3028b226958b66c49a6d86c17))
- use sync module hooks on Node v22.22.3+
([f8992f1](https://redirect.github.com/privatenumber/tsx/commit/f8992f1a50213e11b7ef8ab5121c78e0d2f29384))

***

This release is also available on:

- [npm package (@&#8203;latest
dist-tag)](https://www.npmjs.com/package/tsx/v/4.23.1)

</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:eyJjcmVhdGVkSW5WZXIiOiI0My4yNjUuMSIsInVwZGF0ZWRJblZlciI6IjQzLjI2NS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Cameron Clark <cameron.clark@hey.com>
2026-07-19 18:22:13 +01:00
Sysix 7be5cf08f3 perf(oxlint/lsp): only invoke lint on code actions when document is not opened (#24676)
Some clients can send code actions for documents, which are not opened and already analyzed with a lint process.
A good example is the IntelliJ plugin, which allows the "fix all" code action from the file explorer.

> This PR refactors the language-server → tool code-action API to pass a single request struct (including an “is document open” flag), enabling the oxlint LSP linter to avoid re-running lint for code-action requests when the document is already open (and presumably already linted/cached).

This is mostly needed for https://github.com/oxc-project/oxc/pull/23768
2026-07-19 17:16:22 +00:00
Connor Shea dd18383ee1 feat(linter/node): implement no-top-level-await rule (#24634)
This implements
[`no-top-level-await`](https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/no-top-level-await.md)
from the Node ESLint plugin (#493).

AI Disclosure: Generated with Claude Code. Reviewed and tested by me.

I have an alternative implementation using a Program visitor but it made
no difference performance-wise on vscode or in benchmarking outside
extreme cases, so I don't think it's really worth the trouble vs the
simpler implementation here. It's still in the commit history if that
implementation is preferred.

There is one notable difference between this and the original
implementation, which is that the `convertPath` option is not
implemented, and the checking of `package.json`/`.npmignore` is not
implemented (it was used for checking if the given module was actually
exposed in the library) as there's no way to check against those in
oxlint. There's an argument to be made that this makes the rule not
worth implementing, and I'm open to that argument if we'd prefer to mark
this rule as unsupported instead.

All tests were ported from the original rule (excluding those reliant on
the mentioned config options/checks that were skipped). I've also had
Claude add a few additional test cases (see commit
40418f7e63) on top to cover behavior that
wasn't tested previously. I have confirmed that all of these tests are
identical to the behavior of the upstream rule, but I can remove them if
we don't want to have any divergence from the upstream test suite.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 14:10:52 +01:00
Boshen d3f07a0b9c perf(diagnostics): box OxcDiagnosticInner to reduce binary size (#24665)
`OxcDiagnostic` is an unboxed ~300-byte struct constructed at thousands of callsites. Boxing its inner data behind an 8-byte handle means every callsite, every `Result<T, OxcDiagnostic>`, and every move copies 8 bytes instead of ~300, so the compiler emits far less inlined construction/copy code.

## Binary size (stripped, real release builds, aarch64-apple-darwin)

| Binary | Before | After | Delta |
|---|---:|---:|---:|
| `oxlint` | 14,177,616 B | 13,665,680 B | **−499.9 KiB (−3.61%)** |
| napi transform (`.node`) | 3,482,624 B | 3,433,040 B | **−48.4 KiB (−1.42%)** |

Most of the win lands in `oxc_linter`, whose ~1,500 diagnostic-construction sites inline into rule bodies; `oxc_react_compiler` also contributes.

The `error`/`warn` constructors delegate to an outlined `#[inline(never)] fn new`, so the `Box` allocation + field initialization exist once in the binary rather than inlined at every construction site.

This reverses #22406, which unboxed the inner to save a heap allocation. That is now safe: the parser no longer constructs diagnostics on its hot path (#24663).

Supersedes the draft #24656, which additionally carried a now-redundant copy of the parser deferral that has since landed via #24663.
2026-07-19 11:54:30 +00:00