Commit Graph

19944 Commits

Author SHA1 Message Date
oxc-guard[bot] 0db127cc16 release(apps): oxlint v1.79.0 && oxfmt v0.64.0 (#25866)
# Oxlint
### 💥 BREAKING CHANGES

- 8c4552d linter: [**BREAKING**] Split react/react-compiler into
per-category rules (#25500) (Boshen)

### 🚀 Features

- 9b7394e linter/typescript/no-empty-object-type: Implement suggestion
(#25833) (Mikhail Baev)

### 🐛 Bug Fixes

- 345f981 react_compiler: Skip node_modules by default (#25859) (Boshen)
- 2f40afa linter/unicorn/no-array-callback-reference: Ignore effect
library imports (#25857) (Michaël Bitard)
- 7b565a0 linter: Align React Compiler rule categories (#25840) (Boshen)
- 228e8e0 linter: Resolve inactive React compiler rules (#25830)
(Boshen)
- f8e4884 linter/eslint/no-useless-constructor: Allow parameter
properties (#25811) (camc314)
- e4b6993 linter: Report exhaustive effect dependencies (#25829)
(Boshen)
- 742e25f linter/eslint/no-return-assign: Anchor diagnostic on return
stmt (#25803) (camc314)
- b831ca8 react-compiler: Improve derived state diagnostic (#25804)
(Boshen)
- 5908c87 linter/jest/prefer-mock-return-shorthand: Preserve
implementations using this (#25802) (camc314)
- f6b2265 linter/eslint/no-redeclare: Run in ES modules, skipping only
the globals check (#25691) (Hamody We)
- ca9f553 linter/unicorn/prefer-default-parameters: Mark fixer as a
suggestion (#25801) (camc314)
- aa49d86 linter: Allow spread rule options in config types (#25675)
(ch3rry)
- d5483f8 linter/typescript/no-useless-empty-export: Skip TS declaration
files (#25789) (Evyatar Daud)
- 57f2199 linter/typescript/no-useless-empty-export: Report after
imports (#25786) (camc314)
- 633bc19 linter/typescript/no-unnecessary-type-conversion: Mark fixer
as `suggestion` (#25787) (camc314)
- dea3339 linter/typescript/explicit-module-boundary-types: Anchor
diagnostics on arrows (#25779) (camc314)
- 5cd6f02 linter/eslint/array-callback-return: Anchor diagnostic on
callback (#25780) (camc314)
- ef8cebf linter/eslint/preserve-caught-error: Handle AggregateError
options (#25775) (camc314)
- c108d5c linter: Improve React Compiler diagnostics (#25742) (Boshen)
- c9ec55e react-compiler: Improve diagnostic spans (#25731) (Boshen)
- 1cbbcb7 linter/unicorn/prefer-string-replace-all: Apply fixes in one
pass (#25709) (Mikhail Baev)
- dec0a86 react-compiler: Standardize diagnostics (#25702) (Boshen)
- 5fd77f7 linter/react/display-name: Report curried HOC inner component
(#25662) (camc314)
- 4dbb80e linter/import/no-named-as-default: Report local export
conflicts (#25658) (camc314)
- e8a7214 linter/react/rules-of-hooks: Report hooks inside try blocks
(#25670) (camc314)
- 36f8451 linter/eslint/no-eval: Align indirect default with ESLint
(#25656) (camc314)
- d901d24 linter/react/exhaustive-deps: Handle destructured object
dependencies (#25669) (camc314)
- beb724d linter/eslint/no-unused-vars: Report bare underscore
parameters (#25663) (camc314)
- fa36f26 linter/react/no-this-in-sfc: Detect this in nested arrow
callbacks (#25653) (camc314)
- 44d1be3 linter/typescript/no-var-requires: Run rule on JavaScript
(#25664) (camc314)
- 4004c10 linter/eslint/no-irregular-whitespace: Check comments by
default (#25660) (camc314)
- 625401d linter/import/no-named-default: Flag type-only named defaults
(#25661) (camc314)
- 8eacb2d linter/typescript/no-non-null-asserted-optional-chain: Detect
assertions after continued optional chains (#25659) (camc314)
- d55b76c linter/react/no-direct-mutation-state: Detect computed state
mutations (#25654) (camc314)
- f92c651 linter/unicorn/no-abusive-eslint-disable: Use directive prefix
in diagnostic (#25657) (camc314)
- ee44996 linter/eslint/max-classes-per-file: Anchor diagnostic at
program start (#25652) (camc314)
- 403ec40 linter/eslint/no-multi-assign: Handle parenthesized declarator
initializers (#25651) (camc314)
- 6c9ba37 linter/jest/expect-expect: Detect assertions in nested
function declarations (#25650) (camc314)
- 285820e linter/no-large-snapshots: Precompile and document allowed
snapshot matchers (#25611) (Mikhail Baev)
- 1be1e20 linter/eslint/prefer-promise-reject-errors: Report on spread
arguments (#25648) (Mikhail Baev)
- a38f7b3 oxlint,oxfmt: Apply .gitignore only to walk targets, not
explicitly named files (#25531) (leaysgur)
- 509931b semantic: Classify global references per identifier (#25608)
(camc314)
- 0c68b7f estree: Emit `decorators` on `FormalParameterRest` (#25582)
(camc314)
- 1d22912 linter/plugins: Parse rule-less directive justifications
(#25559) (camc314)
- eaf80d8 linter/unicorn/prefer-node-protocol: Validate exact Node.js
built-in specifiers (#25558) (camc314)
- 57b94af linter/promise/no-multiple-resolved: Ignore unresolved globals
(#25530) (Tushar Singh)
- 80e64c2 linter/expect-expect: Validate assertion regex (#25504)
(Mikhail Baev)
- 7830604 linter/react/exhaustive-deps: Treat binary expressions as a
stable dependency (#25508) (Hamody We)
- 4df5835 linter: Allow capitalized built-in calls (#25516) (Boshen)
- 9d49d27 react_compiler: Bail out instead of panicking on "Expected a
node for all scopes" (#25506) (Boshen)
- d43b562 linter/vitest/prefer-expect-assertions: Handle parameterized
Vitest assertion suggestions (#25476) (camc314)

### ⚡ Performance

- e8303d6 linter: Shrink rule serialization dispatch (#25818) (Boshen)
- c84ede3 estree_tokens: Share JS token update entry point (#25826)
(Boshen)
- 35c8eb2 linter: Compute sort keys once with sort_by_cached_key
(#25821) (Boshen)
- f0121ed linter: Share config deserialization entry point (#25820)
(Boshen)
- 2dacf7a oxlint: Reduce debug formatting code size (#25797) (Boshen)
- 9ed10b7 linter: Use unstable sorts for unique keys (#25778) (Boshen)
- 63ff8ef linter: Outline diagnostic construction (#25762) (Boshen)
- 2dd7446 diagnostics: Preallocate graphical output (#25721) (Boshen)
- 9c8abab diagnostics: Batch graphical reports (#25710) (Boshen)
- 8e9b95f linter: Use table for rule names (#25458) (Boshen)
# Oxfmt
### 🚀 Features

- c07fe7c oxfmt: Support `experimentalOperatorPosition` (#25643)
(leaysgur)
- 2adb8fb formatter: Implement `operatorPosition` option (#25581)
(leaysgur)

### 🐛 Bug Fixes

- 44231fb formatter: Fix comment and indent issues around unions
(#25665) (leaysgur)
- 2465e87 formatter: Keep comments in place when dropping
`EmptyStatement` (#25730) (leaysgur)
- 7e4f3b7 formatter: Print `JSDocUnknownType` (#25729) (leaysgur)
- 5238d9e formatter: Keep nested awaited-paren member chain grouped in
call arguments (#25646) (leaysgur)
- a38f7b3 oxlint,oxfmt: Apply .gitignore only to walk targets, not
explicitly named files (#25531) (leaysgur)
- 5c0a5ff formatter_css: Fill own-line block comments inside
space-separated values (#25578) (leaysgur)
- 53debfa formatter_css: Keep trailing comma and indent after
comment-preceded last map value (#25577) (leaysgur)
- 1a83a8d oxfmt: Mirror printer line suppression and restore
dedent-to-root (#25573) (leaysgur)
- 7f350d1 formatter: Keep unary comment and print only needed parens
(#25526) (leaysgur)
- f405789 formatter_yaml: Consistent chomped eos behavior (#25523)
(leaysgur)
- a243311 formatter_yaml: Bump oxc-yaml-parser for contentless block
scalar (#25519) (leaysgur)
- 40d38a0 formatter_css: Keep multi value function args intact after
leading comment (#25518) (leaysgur)

### 📚 Documentation

- 223e785 oxfmt/conformance: Update notes on conformance (#25757) (Yuji
Sugiura)
- 673dc6d oxfmt: Move some docs from AGENTS.md to code comment (#25649)
(leaysgur)
- fed6681 oxfmt: Skip expanding overrides options (#25572) (leaysgur)

Co-authored-by: Boshen <1430279+Boshen@users.noreply.github.com>
oxfmt_v0.64.0 apps_v1.79.0 oxlint_v1.79.0
2026-08-18 22:27:08 +08:00
oxc-guard[bot] 4a4a1fb2e7 release(crates): oxc v0.145.0 (#25865)
### 💥 BREAKING CHANGES

- 365274e packages/codegen: [**BREAKING**] `printSync` return an object
(#25720) (overlookmotel)

### 🚀 Features

- 6a7eb60 packages/codegen: Alter capitalization of `sourceFilename`
option (#25854) (overlookmotel)
- 300763f packages/codegen: Add full source map support (#25585)
(camc314)
- a169e4a napi/minify: Expose property name mangling options (#24741)
(Dunqing)
- 2f5cdb1 minifier: Add property name mangling (#24740) (Dunqing)
- 4922141 mangler: Deduplicate private accessor names (#25601) (camc314)
- 1c4f519 napi: Add Relay transform plugin (#25503) (Boshen)
- a4478e9 codegen: Add `oxc-codegen` package (#25488) (overlookmotel)

### 🐛 Bug Fixes

- 0fbcf64 codegen: Validate sourcemap options (#25860) (camc314)
- 345f981 react_compiler: Skip node_modules by default (#25859) (Boshen)
- ab81f3f minifier: Drop side-effect-free additions (#25639) (Dunqing)
- 241c559 napi/minify: Accept RegExp for property filters (#25827)
(Dunqing)
- 4cc7ea4 codegen: Reject invalid indent options (#25807) (camc314)
- 53f9295 isolated-declarations: Preserve undefined for defaulted any
(#25292) (camc314)
- 8ab883a codegen: Preserve property key annotations (#25766) (Dunqing)
- b13fd48 minifier: Model uninitialized module vars as undefined
(#25497) (Dunqing)
- f6000ac ecmascript: Fold `**` with `Number::exponentiate`, not IEEE
`pow` (#25644) (Kotaro Chikuba)
- b846abc isolated-declarations: Handle ambient expando properties
(#25655) (camc314)
- dec0a86 react-compiler: Standardize diagnostics (#25702) (Boshen)
- fca2e0c parser: Reject initialized lexical declarations in for-in
(#25700) (Boshen)
- ae9be8f parser: Forbid type parameters on quoted constructors (#25696)
(Boshen)
- c5f188a react-compiler: Use Babel v1 validation defaults (#25676)
(Boshen)
- db44651 napi: Disable reuseWorker in browser bindings (#25640)
(leaysgur)
- ce35d47 react_compiler: Preserve JSX import source pragmas (#25592)
(Boshen)
- 059784d semantic: Respect shadowed `Infinity` and `NaN` in enum
evaluation (#25604) (camc314)
- bb5a232 minifier: Keep variable declaration initilized with class when
keepNames is enabled (#25584) (sapphi-red)
- f49229d minifier: Keep side effects when rotating bitwise operands
(#25596) (Kotaro Chikuba)
- e82495b ecmascript: Derive `ToNumber` of `!x` from `ToBoolean`
(#25595) (Kotaro Chikuba)
- 509931b semantic: Classify global references per identifier (#25608)
(camc314)
- 80484ce mangler: Correct base54 safety comment (#25606) (camc314)
- c1369a7 codegen: Resolve private names in class heritage (#25588)
(camc314)
- c002f29 codegen: Escape sources for empty import specifiers (#25586)
(camc314)
- 0c68b7f estree: Emit `decorators` on `FormalParameterRest` (#25582)
(camc314)
- cdf1846 semantic: Allow legacy escapes in JSX attributes (#25576)
(Boshen)
- e75e102 minifier: Preserve block statement in labeled iteration
statements (#25162) (Armano)
- 771d79a mangler: Exclude non-manglable symbols from slot assignment
(#25539) (sapphi-red)
- 76b19f5 minifier: Avoid duplicating large folded strings (#25532)
(Dunqing)
- 59e8895 codegen: Validate starting indent level (#25550) (camc314)
- 88b34f2 clippy: Remove unneeded `unsafe` (#25551) (camc314)
- 23a7ad0 parser: Stop delimited lists at end of file (#25542) (Boshen)
- 73acba9 parser: Preserve fatal errors during await reparse (#25541)
(Boshen)
- c3e99d1 minifier: Avoid invalid octal escapes in template folds
(#25495) (Dunqing)
- b4e6a9e codegen: Output newline after `export default interface`
(#25487) (overlookmotel)
- 5fcf683 minifier: Correct issue with try finally termination (#25185)
(Armano)
- 1645d93 react_compiler: Preserve source spans (#25462) (Boshen)
- 8d7f9cf react_compiler: Honor eslint suppressions (#25394) (Boshen)

### ⚡ Performance

- 568203e ecmascript: Use binary search for known globals (#25817)
(Boshen)
- c84ede3 estree_tokens: Share JS token update entry point (#25826)
(Boshen)
- 9a6e862 minifier: Move owned statements directly (#25835) (Dunqing)
- 61b2aef minifier: Move owned AST nodes directly (#25837) (Dunqing)
- 673b04b minifier: Replace expressions without take_in dummies (#25836)
(Dunqing)
- 63ff8ef linter: Outline diagnostic construction (#25762) (Boshen)
- 621808e diagnostics: Measure graphemes lazily (#25723) (Boshen)
- f62ed0e diagnostics: Optimize graphical number rendering (#25715)
(Boshen)
- 7152834 diagnostics: Reduce graphical formatting overhead (#25714)
(Boshen)
- 10fc4b7 diagnostics: Reduce graphical rendering allocations (#25711)
(Boshen)
- 9c8abab diagnostics: Batch graphical reports (#25710) (Boshen)
- 757f3d4 mangler: Share allocated names across reused slots (#25605)
(camc314)
- 5444cbf codegen: Skip escaping harmless `<` tokens (#25564) (camc314)

### 📚 Documentation

- 58f7ab9 packages/codegen: Reformat docs and comments (#25848)
(overlookmotel)
- 627466e transform-react: Document all options (#25800) (Boshen)
- ce03ac1 packages/codegen: Fix JSDoc comments for `printSync` (#25722)
(overlookmotel)
- 386a699 packages/codegen: Correct JSDoc comment (#25716)
(overlookmotel)
- 31e571d mangler: Update code example (#25599) (camc314)
- fd62354 codegen: Revamp package readme (#25560) (camc314)
- ffa3153 codegen: Clarify raw transfer Node requirement (#25565)
(camc314)
- c5d4063 codegen: Clarify binary walk allocations (#25562) (camc314)
- 5703d7a codegen: Correct stale printer comments (#25561) (camc314)

Co-authored-by: Boshen <1430279+Boshen@users.noreply.github.com>
crates_v0.145.0
2026-08-18 22:26:40 +08:00
camc314 90098e65b3 refactor(codegen): remove legacy import type support (#25862)
## Summary
- remove the legacy TSImportType argument fallback
- require Oxc's source AST shape
- update compatibility documentation
2026-08-18 14:18:15 +00:00
camc314 b564ec82f4 refactor(codegen): remove legacy mapped type support (#25861)
## Summary
- remove the pre-v6 TS-ESLint TSMappedType.typeParameter fallback
- require Oxc's key / constraint mapped-type AST shape
- update compatibility documentation
2026-08-18 14:07:15 +00:00
camc314 0fbcf6420b fix(codegen): validate sourcemap options (#25860)
## Summary
- require a string sourceText when sourcemaps are enabled
- reject non-string supplied sourceFilename values before map generation
- cover invalid and valid source-map option combinations
2026-08-18 13:57:46 +00:00
Boshen 345f9818c5 fix(react_compiler): skip node_modules by default (#25859)
## Summary
- skip React Compiler transform and lint analysis for `node_modules` by default
- let explicit transform `sources` allowlists opt dependencies back in
- document the behavior and add regression coverage

## Validation
- focused Oxlint and transform-react checks
- Clippy with warnings denied
- `just ready` reached the all-features suite; three Oxlint ANSI-color snapshots differed in this environment

AI assistance: Codex was used to implement and verify this change.
2026-08-18 13:50:31 +00:00
Michaël Bitard 2f40afa45b fix(linter/unicorn/no-array-callback-reference): ignore effect library imports (#25857)
Fix #25856

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-18 14:49:54 +01:00
camc314 3bf05309dd ci(labeler): label codegen package PRs (#25784)
## Summary

- automatically apply A-codegen to changes under packages/codegen
- keep the Rust and TypeScript code generators in the same functional area

## Naming

Reuse A-codegen because recent packages/codegen PRs already receive it manually. A-printer is stale, while names such as A-codegen-js or P-codegen would introduce a distinction or label prefix the repository does not currently use.
2026-08-18 13:25:19 +00:00
overlookmotel 6a7eb602ed feat(packages/codegen): alter capitalization of sourceFilename option (#25854)
Follow-on after [#25585](/github/pr-or-issue/oxc-project/oxc/25585).

Rename `options.sourceFileName` to `sourceFilename`. We use both capitalizations internal Rust code, but always `filename` in external JS APIs (Oxlint plugins etc).

NOTE: this is not marked as a breaking change as it was merged before the feature was released.
2026-08-18 13:16:15 +00:00
overlookmotel 578a81105d refactor(packages/codegen): printSync return consistent object shape (#25853)
Follow-on after #25585.

Nit. Make `printSync` return an object with consistent shape. With `sourcemap: false` it now returns `{ code: string, map: null }` instead of just `{ code: string }`.

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-08-18 13:04:06 +00:00
Boshen 7b565a0344 fix(linter): align React Compiler rule categories (#25840)
Align React Compiler rule categories with the ESLint presets in `babel-plugin-react-compiler@0.0.0-experimental-a1856f3-20260507`. Rules that are off upstream no longer use Oxlint's default correctness category, while `incompatible-library` uses correctness because it is recommended upstream.

| Rule name | ESLint preset | Oxlint category | Note |
| --- | --- | --- | --- |
| `error-boundaries` | `recommended` | `correctness` |  |
| `globals` | `recommended` | `correctness` |  |
| `immutability` | `recommended` | `correctness` |  |
| `incompatible-library` | `recommended` | `correctness` |  |
| `preserve-manual-memoization` | `recommended` | `correctness` |  |
| `purity` | `recommended` | `correctness` |  |
| `refs` | `recommended` | `correctness` |  |
| `set-state-in-effect` | `recommended` | `correctness` |  |
| `set-state-in-render` | `recommended` | `correctness` |  |
| `static-components` | `recommended` | `correctness` |  |
| `use-memo` | `recommended` | `correctness` |  |
| `unsupported-syntax` | `recommended` | `restriction` | Compiler support boundary. |
| `config` | `recommended` | Not implemented | Oxlint uses fixed, valid compiler options. |
| `gating` | `recommended` | Not implemented | Oxlint does not expose compiler gating options. |
| `void-use-memo` | `recommended-latest` | `correctness` | Enabled by the newer upstream preset. |
| `no-deriving-state-in-effects` | `off` | `perf` | Performance and derived-state guidance. |
| `invariant` | `off` | `restriction` | Internal compiler invariant. |
| `rule-suppression` | `off` | `restriction` | Compiler policy restriction. |
| `syntax` | `off` | `restriction` | Compiler syntax restriction. |
| `todo` | `off` | `restriction` | Unimplemented-feature diagnostic; a hint upstream. |
| `capitalized-calls` | `off` | `suspicious` | Kept out of default correctness. |
| `exhaustive-effect-dependencies` | `off` | `suspicious` | Dependency diagnostic, not default correctness. |
| `hooks` | `off` | `suspicious` | Overlaps the non-compiler `rules-of-hooks` rule. |
| `memo-dependencies` | `off` | `suspicious` | Overlaps the non-compiler `exhaustive-deps` rule. |
| `fbt` | `off` | Not implemented | This is a Meta-internal FBT category. |
| `memoized-effect-dependencies` | `off` | Not implemented | Upstream's `EffectDependencies` category is absent from the Rust compiler port. |

Validated with `just ready` and the category integration test after rebasing onto main.

AI-assisted: Codex was used to implement and validate this change.
2026-08-18 12:57:01 +00:00
overlookmotel 43c65f0255 refactor(packages/codegen): re-order options (#25852)
Follow-on after #25585.

Pure refactor. Re-order options so `sourcemap` is first. The other 2 are sourcemap-related, so it makes sense to have them after.
2026-08-18 12:45:35 +00:00
overlookmotel 0638010f2c refactor(packages/codegen): remove redundant types export (#25851)
Remove a redundant type export. Nothing reads it.
2026-08-18 12:45:35 +00:00
overlookmotel e1085e5185 refactor(packages/codegen): move consts to top of file (#25850)
Follow-on after #25585.

Pure style change. Move consts up to top of file.
2026-08-18 12:45:34 +00:00
overlookmotel 6803a46b5e refactor(packages/codegen): add line breaks (#25849)
Follow-on after #25585.

Pure style change. Similar to #25848 - just remove the worst excesses of LLM coding style where it produces dense blocks of code with no line breaks, which makes code hard to read.

No substantive changes, just adds line breaks.
2026-08-18 12:45:34 +00:00
overlookmotel 58f7ab9c1d docs(packages/codegen): reformat docs and comments (#25848)
Follow-on after #25585.

Pure style change. I hate the way LLMs put line breaks in weird places like after "the" - it makes comments hard to read. And what's with all the colons and semicolons?

No substantive changes, just reformatting comments and docs to avoid this unreadable formatting.
2026-08-18 12:24:56 +00:00
camc314 300763f328 feat(packages/codegen): add full source map support (#25585)
## Summary

Align `oxc-codegen` source maps with Rust `oxc_codegen`, using the Rust implementation as the conformance oracle.

This PR:

- changes `printSync` to return `{ code, map? }`;
- returns a standard Source Map v3 object;
- exposes Rust’s generated source map through `codegen_conformance`;
- compares the complete JS and Rust source maps;
- supports Oxc `start`/`end` offsets and TS-ESTree `range` offsets;
- uses `sourceText` to convert UTF-16 offsets and recover original identifier spellings;
- validates both maps and no-maps builds in both `preserveParens` modes;
- aligns mapping placement across JavaScript, TypeScript, JSX, templates, imports, destructuring, delimiters, and postfix chains;
- handles astral characters and all ECMAScript line terminators.
`loc`-only ASTs are not supported for source maps.

## API change

```ts
const { code, map } = printSync(program, {
  sourcemap: true,
  sourceFileName: "input.js",
  sourceText,
});
```

`map` is a Source Map v3 object:

```ts
interface SourceMap {
  version: 3;
  mappings: string;
  names: string[];
  sources: string[];
  sourcesContent?: string[];
}
```

## Implementation

Mapped writes collect only:

- the generated UTF-16 offset;
- the original source offset;
- the optional original identifier name.

After printing, the generator builds line tables for the generated output and `sourceText`, converts the offsets to line/column positions, suppresses duplicate source positions, and encodes the result as base64 VLQ.

The no-maps builds continue to remove mapping-specific writes at build time.

## Validation flow

```mermaid
flowchart TB
    fixture["Fixture<br/>filename + sourceText + parse options"]

    fixture --> rustParse
    fixture --> jsParse

    subgraph rust["Rust oracle"]
        direction TB
        rustParse["Parse with oxc_parser"]
        normalize["Normalize Rust-only AST information"]
        rustPrint["Print with oxc_codegen<br/>source maps enabled"]
        rustResult["Expected result<br/>{ code, map }"]

        rustParse --> normalize
        normalize --> rustPrint
        rustPrint --> rustResult
    end

    subgraph js["JavaScript candidate"]
        direction TB
        jsParse["Parse ESTree with oxc-parser<br/>start/end or range offsets"]

        plainPrint["Print with no-maps build"]
        plainResult["Actual code"]

        mappedPrint["Print with maps-enabled build"]
        deferred["Record generated offsets,<br/>source offsets, and names"]
        encode["Convert UTF-16 offsets to positions<br/>deduplicate and encode VLQ"]
        mappedResult["Actual result<br/>{ code, map }"]

        jsParse --> plainPrint
        plainPrint --> plainResult

        jsParse --> mappedPrint
        mappedPrint --> deferred
        deferred --> encode
        encode --> mappedResult
    end

    rustParse --> parseGate
    jsParse --> parseGate

    rustResult --> codeGate
    plainResult --> codeGate
    mappedResult --> codeGate

    rustResult --> mapGate
    mappedResult --> mapGate

    parseGate["Parse agreement<br/>Rust success requires no JS errors"]
    codeGate["Code equality<br/>both JS builds equal Rust"]
    mapGate["Source Map v3 equality<br/>mappings + names + sources + content"]

    parseGate --> pass["Fixture passes"]
    codeGate --> pass
    mapGate --> pass
```

Each fixture runs with both `preserveParens: false` and `preserveParens: true`.

## AST normalization

Rust’s AST contains information that ESTree cannot represent. The Rust AST is normalized before printing so the comparison measures code generation rather than representation differences.

This includes:

- parenthesized function and arrow-expression flags;
- `import "m"` versus `import {} from "m"`;
- absent versus empty import-attribute clauses;
- `assert` versus `with` attribute keywords;
- the unavailable ESTree span for a complete `with` clause.
2026-08-18 11:41:34 +00:00
Boshen 228e8e0f85 fix(linter): resolve inactive React compiler rules (#25830)
Enable React Compiler memo dependency validation so `react/memo-dependencies` reports missing and extra values. Remove `react/gating` until Oxlint exposes compiler gating options.

Validated with `just ready`.

AI-assisted.
2026-08-18 16:16:24 +08:00
Boshen 568203e24f perf(ecmascript): use binary search for known globals (#25817)
Replaces the 639-arm known-global string match with a sorted static table and binary search. The table is guarded for sortedness, uniqueness, and representative lookups.

Release `oxlint`: 12,491,264 → 12,474,736 bytes (−16,528 bytes, −0.13%); `__text` is reduced by 29,252 bytes.

Prepared with AI assistance.
2026-08-18 08:04:34 +00:00
Dunqing ab81f3f7f8 fix(minifier): drop side-effect-free additions (#25639)
An unused addition can be side-effect-free even when constant folding keeps it. This happens when replacing the expression with its exact constant value would make the output longer.

For example, constant folding correctly keeps `0.1 + 0.2` instead of expanding it to `0.30000000000000004`. But when the result is unused, the whole expression can be removed.

This PR checks the existing side-effect analysis before running the string-addition cleanup. It removes the whole addition when it is safe. Additions that can run code or throw still use the existing cleanup and are preserved when needed.

Tests cover both the removable numeric addition and an addition containing `foo()` that must stay.

Verified with the full `oxc_minifier` test suite (652 passed, 34 ignored), Clippy, formatting, minsize, and allocation checks. Minsize and allocation snapshots are unchanged.

AI-assisted by OpenAI Codex.
2026-08-18 07:59:10 +00:00
Boshen 691a1f0135 refactor(react_compiler): remove unreachable JSX colon check (#25810)
Remove an unreachable React Compiler diagnostic for colons in JSX attribute identifiers. Oxc's parser represents namespaced attributes with `JSXNamespacedName`, so parser-produced identifiers cannot contain colons.

Validated with `cargo test -p oxc_react_compiler`. `just ready` passed formatting and workspace checks, but its full suite hit environment-sensitive ANSI snapshot mismatches in unrelated Oxlint CLI tests.

AI-assisted; reviewed and validated by the contributor.
2026-08-18 07:48:12 +00:00
camc314 f8e488496f fix(linter/eslint/no-useless-constructor): allow parameter properties (#25811)
## Summary
 - avoid reporting forwarding constructors that declare TypeScript parameter properties
 - share the modifier and decorator check across base and derived constructors
 - cover private, public, protected, readonly, and combined parameter-property variants

Closes #25806
2026-08-18 07:44:01 +00:00
Boshen e8303d6fc8 perf(linter): shrink rule serialization dispatch (#25818)
Generate `RuleEnum::to_configuration` arms only for the 33 rules that override the trait default, returning `None` for all other rules.

Release `oxlint`: 12,491,264 → 12,491,200 bytes (-64 bytes). `__text`: 10,589,512 → 10,585,376 bytes (-4,136 bytes).

AI-assisted; reviewed and validated by the contributor.
2026-08-18 07:38:14 +00:00
Dunqing 65da89795a refactor(napi): share JavaScript RegExp conversion (#25834)
Oxc and Rolldown currently duplicate the N-API conversion between a JavaScript `RegExp` and owned Rust data.

This moves that conversion to `oxc_napi::JsRegExp`. It copies `source`, `flags`, and `lastIndex`, supports converting back to a JavaScript `RegExp`, and keeps regex compilation in each consumer. `oxc_minify_napi::JsRegExp` remains available as a re-export.

This is a good place to put since Rolldown already used `oxc_napi` and crate is exactly for napi related struct
2026-08-18 07:25:04 +00:00
Boshen c84ede371b perf(estree_tokens): share JS token update entry point (#25826)
Add a shared non-generic JS-style token update entry point so `oxc_linter` and `oxlint` do not each instantiate the ESTree token visitor.

On `aarch64-apple-darwin`, `cargo build -p oxlint --release --features allocator` reduces the `oxlint` binary by 49,616 bytes (48.5 KiB, 0.39%), from 12,756,960 to 12,707,344 bytes.

Validated with `just ready`.

AI assistance was used for implementation and measurement.
2026-08-18 07:19:31 +00:00
Mikhail Baev 9b7394ed8b feat(linter/typescript/no-empty-object-type): implement suggestion (#25833)
Implement suggestion for `typescript/no-empty-object-type` rule, issue
#2180. Tests ported from
[upstream](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/tests/rules/no-empty-object-type.test.ts)
2026-08-18 08:18:48 +01:00
Dunqing 9a6e86226e perf(minifier): move owned statements directly (#25835)
Statement transforms still use `take_in` after popping or consuming their parent nodes. Removing those dummies is less mechanical because references from discarded branches and pass mutations must remain accounted for.

Move the owned statement fields directly, centralize the shared return/throw conditional rewrite, and use explicit dropped-subtree or mutation reporting at each ownership boundary. The adjacent-`if` rewrite also uses the closure-based replacement API introduced at the bottom of this stack.

Relative to its parent, the tracked allocation fixtures record 2,039 fewer arena allocations and 31,552 fewer arena bytes. Across the complete stack, the improvement is 25,252 arena allocations and 404,352 arena bytes. Minsize output is unchanged.

Validated with `cargo test -p oxc_minifier`, `just minsize`, `cargo clippy -p oxc_minifier -- -D warnings`, `just fmt`, and `git diff --check`.

AI assistance was used for research, implementation, review, and testing. I reviewed and take responsibility for the changes.
2026-08-18 06:57:09 +00:00
Dunqing 61b2aefa94 perf(minifier): move owned AST nodes directly (#25837)
Several peephole transforms call `take_in` after removing or consuming the parent AST node. At that point there is no borrowed slot to preserve, so allocating a dummy replacement is unnecessary.

Move those already-owned child nodes directly in the straightforward expression and declaration cases. This second branch stays intentionally mechanical and leaves the statement/reference-bookkeeping cases to the final PR in the stack.

Relative to its parent, the tracked allocation fixtures record 22,957 fewer arena allocations and 370,544 fewer arena bytes. Minsize output is unchanged.

Validated with `cargo test -p oxc_minifier`, `just minsize`, `cargo clippy -p oxc_minifier -- -D warnings`, `just fmt`, and `git diff --check`.

AI assistance was used for research, implementation, review, and testing. I reviewed and take responsibility for the changes.
2026-08-18 06:57:08 +00:00
Dunqing 673b04bc46 perf(minifier): replace expressions without take_in dummies (#25836)
`replace_expression` currently makes callers extract the old value before constructing its replacement, leaving an arena-backed dummy node behind.

Add a closure-based replacement path that owns the old expression and records the AST mutation. Its dropped-subtree contract remains explicit: callers report discarded subtrees, while values moved into the replacement stay live. Convert the logical-not unwrapping sites whose discarded wrappers contain no references.

This is the foundation of a three-PR Graphite stack. The tracked allocation fixtures record 256 fewer arena allocations and 2,256 fewer arena bytes. Minsize output is unchanged.

Validated with `cargo test -p oxc_minifier`, `just minsize`, `cargo clippy -p oxc_minifier -- -D warnings`, `just fmt`, and `git diff --check`.

AI assistance was used for research, implementation, review, and testing. I reviewed and take responsibility for the changes.
2026-08-18 06:57:08 +00:00
Dunqing 241c559b83 fix(napi/minify): accept RegExp for property filters (#25827)
This follows up on #24741 and addresses API feedback received after it was merged.

### Feature

`mangleProps.include` and `mangleProps.exclude` now accept JavaScript `RegExp` values instead of strings.

The binding copies the regular expression source and flags before async minification starts, then compiles the pattern once with Rust's regex engine. Native and WASI bindings expose the same API. The core Rust minifier API is unchanged.

### Example

```js
mangleProps: {
  include: /^_/,
  exclude: /^__public/,
}
```

### Limitation

Matching uses Rust regex syntax. The `i`, `m`, `s`, and `u` flags are supported. Unsupported JavaScript syntax or flags are returned as option errors.

### AI assistance

OpenAI Codex was used for research, implementation, review, and testing. I reviewed and take responsibility for the changes.
2026-08-18 05:37:31 +00:00
Armano bfb0832d24 refactor(minifier): simplify if-statement minimization (#25178)
Refactors `try_minimize_if` to improve clarity:

- restructures the function around `alternate` presence rather than
`consequent` type
- removes a recursive `Self::try_minimize_if` call — the fallthrough
after branch-flip achieves the same result
- this also removes need for code duplication for inlining expressions
to `||` or `&&`
  - `if (!a) {} else b();` → `a && b();`
  - `if (!a) b();` → `a || b();`
  - `if (a) {} else b();` → `a || b();`
  - `if (a) b();` → `a && b();`
- we also do not have to always call for `wrap_to_avoid_ambiguous_else`
and we can do that after we update code (eg, after rotation, and never
when we convert it to expression)

----------------------

#### changes in stack:
- https://github.com/oxc-project/oxc/pull/25267 
- https://github.com/oxc-project/oxc/pull/25178 👈
- `main`
2026-08-18 13:37:07 +08:00
Boshen 35c8eb2b0f perf(linter): compute sort keys once with sort_by_cached_key (#25821)
Three sorts pass a comparator that recomputes a derived key on every comparison. A sort instantiation expands to about eight functions — `quicksort`, `heapsort`, `small_sort_general`, `median3_rec`, `bidirectional_merge`, … — and the comparator is inlined into each of them, so an expensive key is duplicated eight times over and costs several KiB per call site:

- `OxlintRules::override_rules` sorted errors by `ToString::to_string`, which allocates a `String` and pulls the whole `Display` impl into the sort.
- `LintIgnoreMatcher::new` sorted nested configs by `Path::components().count()`.
- The `sort_imports` member fixer sorted specifiers by `cow_to_ascii_lowercase()`.

`sort_by_cached_key` computes each key once, up front, and sorts those.

For `sort_imports` the resulting order is identical: itertools' `sorted_by` and `sorted_by_cached_key` are both stable sorts (`Vec::sort_by` / `Vec::sort_by_cached_key`). The other two go from an unstable sort to a stable one, so entries with an equal key keep their input order instead of an arbitrary one. Both of those sort for deterministic output in the first place, so that is a small improvement rather than a change in behavior.

### Size

Release `oxlint`, `__text`: 10,582,632 → 10,553,076 bytes — **-29,556 bytes (-0.28%)**; stripped binary -33,024 bytes.

Where it comes from:

| call site | before | after | delta |
| --- | ---: | ---: | ---: |
| `override_rules` (`OverrideRulesError`) | 14,656 B / 11 symbols | 656 B / 4 symbols | -14,000 |
| `sort_imports` member fixer | 28,896 B / 18 symbols | 9,108 B / 11 symbols | -19,788 |
| `LintIgnoreMatcher::new` | 11,648 B / 10 symbols | 2,700 B / 3 symbols | -8,948 |

(The per-call-site figures cover each site's whole symbol group, so they overlap where a sort shares a monomorphization; `core::slice::sort::*` overall goes from 379,100 to 348,136 bytes.)

Validated with `cargo test -p oxc_linter -p oxlint` and `cargo clippy` with warnings denied.

AI assistance was used for implementation and measurement.
2026-08-18 04:53:31 +00:00
Boshen 627466ee8c docs(transform-react): document all options (#25800)
Documents the combined React transform pipeline and every supported transform, JSX, Fast Refresh, React Compiler, and environment option, including ESLint and Oxlint suppression comments.

Validation: Oxfmt, typos, and `git diff --check`.

AI-assisted.
2026-08-18 04:45:32 +00:00
Boshen f0121edb71 perf(linter): share config deserialization entry point (#25820)
Share a non-generic JSON deserialization entry point across `oxc_linter` and `oxlint`, avoiding duplicate monomorphizations. Also deserialize well-known settings without deep-cloning the raw JSON value.

Validated with `just ready`.

AI assistance was used for implementation and measurement.
2026-08-18 04:40:16 +00:00
Boshen e4b69935fe fix(linter): report exhaustive effect dependencies (#25829)
Enable React Compiler exhaustive effect dependency validation in Oxlint so the rule reports missing and extra dependencies instead of remaining inert.

Validated with `just ready`.

AI-assisted.
2026-08-18 04:35:11 +00:00
Dunqing a169e4adf8 feat(napi/minify): expose property name mangling options (#24741)
The property mangler added in #24740 is not available through `oxc-minify`. This adds `mangleProps` for configuring it and `mangleCache` for reusing chosen property names.

### Feature

- `include` selects property names to mangle. `exclude` and `reserved` keep names unchanged.
- `quoted` also mangles quoted property names. `debug` produces readable output names.
- `cache` fixes a property to a chosen name. A `false` value keeps the original name.
- Property mangling works in both sync and async APIs. It is separate from identifier mangling.
- When property mangling is enabled and the call succeeds, the result includes the updated `mangleCache`.
- Invalid `mangleProps` regexes and cache entries are returned in `result.errors`.

### Design

The binding converts JavaScript values into core minifier options and results. The core minifier still chooses names and rewrites properties, so both APIs follow the same rules.

A parser error may leave an incomplete AST. In that case, property mangling is skipped and no partial cache is returned.

### Example

```js
const result = minifySync(
  "test.js",
  "let local; obj._often; obj._rare; obj._often;",
  {
    compress: false,
    mangle: false,
    mangleProps: { include: "^_" },
  },
);

result.code; // "let local;obj.e;obj.t;obj.e;"
result.mangleCache; // { _often: "e", _rare: "t" }
```

### Limitation

- `include` and `exclude` use Rust regex syntax. They match anywhere unless the pattern includes anchors.
- Do not reuse the cache on already-mangled output. A mapping is not always safe to apply twice.
- The cache only remembers recorded mappings. It cannot find unchanged names in another input or in external code. Reserve, exclude, or pin those names before the first call.
- String cache targets must be valid JavaScript `IdentifierName` values and cannot be `__proto__`, `constructor`, or `prototype`. The original name `__proto__` cannot be a cache key.

AI assistance: OpenAI Codex and Claude were used for research, implementation, adversarial review, and verification. The contributor remains responsible for reviewing, understanding, and submitting the changes under the repository AI usage policy.
2026-08-18 02:40:36 +00:00
Boshen d0d41099be refactor(linter): route two config parses through the shared path (#25823)
#25765 routed rule configuration parsing through `DefaultRuleConfig::from_value`, which deserializes from `&serde_json::Value`. Two call sites were missed and still went through `serde_json::from_value`, which instantiates the owned-`Value` deserializer for those configuration types on top of the borrowed-`Value` one every other rule uses:

- `react_perf_from_configuration`, shared by the `react_perf` rules.
- `ConsistentTestItConfig::from_configuration`, shared by the jest and vitest `consistent-test-it` rules. This one also cloned the configuration value before parsing it; deserializing by reference drops the clone.

### Size

Release `oxlint`, `__text`: **-2,072 bytes** — `consistent_test_it` 5,784 → 3,760 bytes (its `TestCaseName` owned-`Value` deserializer goes away entirely) and `react_perf` 10,004 → 9,956 bytes. The stripped binary comes out the same size, as a saving this small falls inside existing padding.

Mostly a consistency fix, then, rather than a size win on its own.

Validated with `cargo test -p oxc_linter` and `cargo clippy` with warnings denied.

AI assistance was used for implementation and measurement.
2026-08-18 01:51:24 +00:00
camc314 742e25f42b fix(linter/eslint/no-return-assign): anchor diagnostic on return stmt (#25803)
## Summary

 - align with ESLint and anchor the diagnostic on the full return stmt

closes #25628
2026-08-17 16:00:27 +00:00
Boshen b831ca8af9 fix(react-compiler): improve derived state diagnostic (#25804)
Improve `react/no-deriving-state-in-effects` diagnostics with labeled state updates, named reactive dependencies, and actionable render guidance. Adds fixture coverage for single and multiple dependencies.

AI assistance was used for this change.
2026-08-17 14:33:28 +00:00
camc314 5908c87e0b fix(linter/jest/prefer-mock-return-shorthand): preserve implementations using this (#25802)
## Summary

- skip prefer-mock-return-shorthand when the returned expression references this
- reuse the existing return-expression traversal without adding another AST pass
- cover the reported typed this parameter and mockImplementationOnce arrow callback cases

Closes #25796
2026-08-17 14:28:35 +00:00
camc314 4cc7ea4595 fix(codegen): reject invalid indent options (#25807)
## Summary

 - throw a TypeError when indent is empty, contains characters other than spaces or tabs, or is not a string
 - preserve the existing default tab indentation and unchanged printIndent hot path
 - update API documentation and validation coverage
2026-08-17 14:22:56 +00:00
Hamody We f6b22654d2 fix(linter/eslint/no-redeclare): run in ES modules, skipping only the globals check (#25691)
Closes #25339.

## The problem

`no-redeclare` gated the entire rule on the file not being an ES module:

```rust
fn should_run(&self, ctx: &ContextHost) -> bool {
    // ES modules run in their own scope, and don't conflict with existing globals
    !ctx.source_type().is_module()
}
```

The comment justifies the globals half of the rule, and it is right
about that: an ES module has its own top-level scope, so declaring
`Object` or `self` there shadows nothing, which is why ESLint reports
`builtinGlobals` redeclarations against the global scope rather than
inside a module. But the gate took the rest with it — plain `var a = 3;
var a = 10;`, redeclarations in nested scopes, and the TS type/value
collision check added for #10396 all stopped running too.

**One correction to the issue's framing, from testing it rather than
reading it.** `.ts` is parsed as `ModuleKind::Unambiguous`, which
resolves to `Module` only when ESM syntax is actually present. So a
`.ts` file with no `import`/`export` is a script, and the rule *did* run
there — `var a = 3; var a = 10;` on its own is reported today. What was
dead is every `.ts` file that contains an import or an export, which in
practice is nearly all of them. The effect the issue describes is real;
the boundary is ESM syntax, not the extension.

The rule's own tests hid this either way. Every failing case runs under
`.change_rule_path_extension(".cts")` — CommonJS, never a module — and
the single `.ts` block asserts a *pass*, which it would do whether or
not the rule executed.

## The change

Drop `should_run`, and narrow the exemption to the thing the comment
actually describes:

```rust
// ES modules run in their own scope, so a top-level `Object` or `self` shadows nothing.
// Only the globals half of the rule is skipped for them -- redeclaring a local binding is
// still a redeclaration.
let builtin_globals = if self.builtin_globals && !ctx.source_type().is_module() {
    Some(&GLOBALS_BUILTIN)
} else {
    None
};
```

`builtin_globals` is already the single switch for that half — it drives
`is_builtin`, which chooses between
`no_redeclare_as_builtin_in_diagnostic` and the plain redeclaration
diagnostic — so `None` in modules disables exactly the globals
reporting, for the builtin table and user-configured `globals` alike,
and leaves both redeclaration loops running.

## Tests

A new `.ts` block under the `es-modules` snapshot suffix. Every case
carries ESM syntax so it resolves as a module — otherwise it would test
the script path by accident, which is the trap above:

- **pass** — `export {}; var Object = 0;` and `export {}; var globalThis
= 0;` (a module shadows nothing, so these must stay quiet), plus a
redeclaration-free case and a TS overload pair.
- **fail** — `export {}; var a = 3; var a = 10;`; `export {}; function
f() { var a; var a; }` (nested scope — nothing to do with global scope
at all, and previously silent); the #10396 `type foo = 1; export
function foo(): void; …` case; and `export {}; var Object = 0; var
Object = 0;`.

That last one is the seam this change creates, so it is worth pinning:
inside a module the first `var Object` is no longer reported as
shadowing a builtin, but the second is still reported as a redeclaration
of the first. Without it, narrowing the gate could quietly have turned
builtin-named symbols into a blind spot.

The existing `.cts` blocks and their snapshot are untouched — `.cts` is
CommonJS, so `is_module()` was already false there.

## Verification

Ran locally with `cargo test -p oxc_linter --lib no_redeclare`: passes,
the existing `eslint_no_redeclare.snap` is unchanged, and the new
`eslint_no_redeclare@es-modules.snap` is included. `cargo clippy -p
oxc_linter --lib` is clean.

> AI disclosure, per the contributing policy: I used an AI assistant
while investigating and writing this. I have read and understand the
change, ran the tests myself, and stand behind it.

---------

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-08-17 13:20:33 +00:00
camc314 ca9f5534a5 fix(linter/unicorn/prefer-default-parameters): mark fixer as a suggestion (#25801)
## Summary

- mark `unicorn/prefer-default-parameters` as suggestion-only
- prevent `--fix` from changing behavior for `null` and other falsy values

Closes #25799
2026-08-17 13:13:58 +00:00
ch3rry aa49d86046 fix(linter): allow spread rule options in config types (#25675)
## Summary

- represent variadic rule options as a severity followed by zero or more
option values
- regenerate the Oxlint configuration schema and TypeScript declarations
- add a type-level regression for mapped options spread into
`no-restricted-globals`

## Root cause

The schema wrapper materialized the first `additionalItems` entry as a
required tuple element and set `minItems` to 2. A dynamic TypeScript
spread has type `T[]` and may be empty, so it cannot satisfy that
required position even though the severity-only form is already valid
through `RuleNoConfig`.

Keeping severity as the only fixed tuple item and leaving the rule
options in `additionalItems` generates `[severity, ...options]`, which
accepts both an empty spread and populated spreads without changing
runtime rule behavior.

Closes #25666


## AI assistance

Implemented with assistance from OpenAI Codex. The contributor remains
responsible for reviewing, understanding, and submitting the change
under the repository AI usage policy.

---------

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-08-17 14:11:07 +01:00
Boshen 2dacf7a9b6 perf(oxlint): reduce debug formatting code size (#25797)
Use compact `Display` formatting for React Compiler terminals and reuse `ConfigBuilderError`'s existing `Display` implementation for `Debug`.

This reduces the release `oxlint` binary from 12,773,552 to 12,740,432 bytes: **-33,120 bytes (-0.26%)**, with `__text` reduced by 24,452 bytes.

Validated with the affected crate tests, workspace checks, and oxlint snapshot tests.

AI assistance was used for implementation and measurement.
2026-08-17 13:04:51 +00:00
camc314 e60f50b7c8 ci(labeler): label React Compiler PRs (#25782)
## Summary

- automatically apply the A-react-compiler label to React Compiler changes
- cover the compiler crate, linter bridge, N-API binding, benchmark, and release workflow
2026-08-17 11:29:31 +00:00
Evyatar Daud d5483f829b fix(linter/typescript/no-useless-empty-export): skip TS declaration files (#25789)
Closes #25788 

Ports https://github.com/typescript-eslint/typescript-eslint/pull/7718

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-08-17 11:28:36 +00:00
camc314 57f2199017 fix(linter/typescript/no-useless-empty-export): report after imports (#25786)
## Summary:
- consider static requested modules when deciding whether an empty export is redundant
- add regression coverage for default, side-effect, and namespace imports
- verify autofixes remove the empty export

Closes #25785.
2026-08-17 11:16:43 +00:00
camc314 633bc19c0f fix(linter/typescript/no-unnecessary-type-conversion): mark fixer as suggestion (#25787)
## Summary

- classify typescript/no-unnecessary-type-conversion as suggestion-only
- prevent its runtime-changing removal from being advertised as a normal autofix
- keep TSGolint RuleSuggestion edits available through suggestion handling

Related to #25549.
2026-08-17 11:04:32 +00:00
camc314 6d8b3e2b62 ci(labeler): label ECMAScript PRs (#25783)
## Summary

- automatically apply the A-ecmascript label to changes in crates/oxc_ecmascript
- add the corresponding repository area label
2026-08-17 10:36:09 +00:00