Commit Graph

4836 Commits

Author SHA1 Message Date
Cameron Clark c77cd1e005 test(codegen): benchmark without sourcemap 2026-09-10 17:34:51 +01:00
Cameron Clark 572cea4548 perf(codegen): benchmark ASCII-only output 2026-09-10 17:34:31 +01:00
camc314 75cd919ffb fix(transformer): preserve receivers in private optional chains (#26535)
Only bind a private field when it is the result of an optional chain being called. In `(this.#items.get(key)?.find(fn))?.()`, the intermediate `#items` field must not receive `.bind(this)`.

Normalize non-null assertions in the TypeScript transform before other transforms inspect the chain. This preserves the receiver for `(this?.#fn!)()` and `(this?.#fn!!)()` without mixing TypeScript assertion removal into the class transform.

Fixes #26528
2026-09-10 15:09:24 +00:00
camc314 b32d25d418 fix(parser): reject escaped import-phase keywords (#26534)
The parser consumes `source`, `defer`, and sometimes `from` as binding identifiers before resolving their role in an import declaration. Validate escapes once they are known to be keywords, so declarations such as `import s\u006furce wasm from "m"` and `import source fr\u006fm "m"` report an error.

Escaped binding names remain valid, including `import s\u006furce from "m"` and `import source fr\u006fm from "m"`.
2026-09-10 14:55:08 +00:00
renovate[bot] 59e8d5fb91 chore(deps): update napi (#26533)
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/) | Type |
Update |
|---|---|---|---|---|---|---|---|
| [@napi-rs/cli](https://napi.rs/)
([source](https://redirect.github.com/napi-rs/napi-rs)) | [`3.9.0` →
`3.9.1`](https://renovatebot.com/diffs/npm/@napi-rs%2fcli/3.9.0/3.9.1) |
![age](https://developer.mend.io/api/mc/badges/age/npm/@napi-rs%2fcli/3.9.1?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@napi-rs%2fcli/3.9.1?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@napi-rs%2fcli/3.9.0/3.9.1?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@napi-rs%2fcli/3.9.0/3.9.1?slim=true)
| pnpm.catalog.default | patch |
| [napi](https://redirect.github.com/napi-rs/napi-rs) | `3.12.2` →
`3.12.3` |
![age](https://developer.mend.io/api/mc/badges/age/crate/napi/3.12.3?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/napi/3.12.3?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/napi/3.12.2/3.12.3?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/napi/3.12.2/3.12.3?slim=true)
| workspace.dependencies | patch |
| [napi-derive](https://redirect.github.com/napi-rs/napi-rs) | `3.6.3` →
`3.6.4` |
![age](https://developer.mend.io/api/mc/badges/age/crate/napi-derive/3.6.4?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/napi-derive/3.6.4?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/napi-derive/3.6.3/3.6.4?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/napi-derive/3.6.3/3.6.4?slim=true)
| workspace.dependencies | patch |

---

### Release Notes

<details>
<summary>napi-rs/napi-rs (@&#8203;napi-rs/cli)</summary>

###
[`v3.9.1`](https://redirect.github.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.9.0...@napi-rs/cli@3.9.1)

[Compare
Source](https://redirect.github.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.9.0...@napi-rs/cli@3.9.1)

</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.

👻 **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:eyJjcmVhdGVkSW5WZXIiOiI0NC43MS4wIiwidXBkYXRlZEluVmVyIjoiNDQuNzEuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Cameron Clark <cameron.clark@hey.com>
2026-09-10 14:26:42 +00:00
camc314 47b83115f0 fix(parser): recognize contextual binding names in type lookaheads (#26532)
Recognize `await` and `yield` as binding names when looking ahead for TypeScript function types and index signatures. This allows valid syntax such as `(await: number) => void` and `interface I { [await: string]: unknown }`, while leaving contextual legality to actual parsing.
2026-09-10 14:05:25 +00:00
camc314 d6b6705f8f fix(parser): require arrow separator in TypeScript function types (#26529)
Require `=>` when parsing TypeScript function and constructor types, while retaining `:` for function, method, and arrow return annotations. Previously, any token could be consumed as the separator, accepting invalid types such as `type F = (): number` and `type F = new () + number`.

This also prevents a valid conditional expression from being silently grouped into the wrong arrows:

```ts
const a = true, b = 1, c = 2;
const f = a ? (b) : (): any => b ? c : (x = 1): any => x;
console.log(typeof f);
```

The transformed program now prints `number`; previously it printed `function`.
2026-09-10 13:05:18 +00:00
camc314 e98beef227 fix(parser): disambiguate await using in for initializers (#26527)
Allow classic `for` initializers such as `for (await using;;)` when `using` is an ordinary identifier. Reuse the statement parser’s `await using` lookahead so resource declarations require a following binding identifier, preserving the existing line-break restrictions.
2026-09-10 10:59:58 +00:00
camc314 92afee6734 fix(parser): allow parenthesized JSX comma expressions with preserve_parens=false (#26524)
Allow parenthesized comma expressions such as `<A>{(a, b)}</A>` and `<A x={(a, b)} />` when `preserve_parens` is false.

Compare the sequence expression's start with the first token's start to retain the grouping distinction after parentheses are omitted from the AST. Ungrouped comma expressions such as `{a, b}` and `{(a, b), c}` remain invalid.
2026-09-10 10:30:38 +00:00
camc314 31508b1be5 fix(parser): reject return types on constructor overloads (#26523)
Constructor overloads and ambient signatures previously bypassed the return type check because it required a body. Reject their return annotations with TS1093, matching constructor implementations.

Highlight only the return type itself, excluding the colon and preceding whitespace.
2026-09-10 10:10:39 +00:00
Armano 029c84bcda perf(minfier): update expressions in place when substituting alternate syntax (#26460)
- `substitute_typeof_undefined`: do not recreate binnary expression and
instead just update right/left argument and operator
- `substitute_rotate_binary_expression`: replace `take_in*2` and
reassign with `std::mem::swap`
- `substitute_object_or_array_constructor`,
`substitute_global_new_expression`: introduce new helper
`transform_new_expr_to_call_expr` to convert new to call expr
- `substitute_iife_call`: use array to alloc all items in sequence
without reallocs
2026-09-10 09:44:47 +08:00
camc314 a091fc4b42 fix(parser): validate await context for await using declarations (#26495)
Reject `await using` in non-async functions and ordinary generators, including `for` and `for...of` loop heads. Treat top-level `await using` as module syntax when the source type is unambiguous.
2026-09-09 15:21:18 +00:00
camc314 ed4357c620 perf(linter/eslint/no-restricted-properties): skip empty configurations (#26497)
Skip the rule when no property restrictions are configured, avoiding node callbacks and property-access analysis that cannot produce a diagnostic.
2026-09-09 15:02:44 +00:00
camc314 5501e86429 fix(parser): disallow in expressions in using for-loop initializers (#26490)
Reject invalid initializers such as `for (using x = a in b;;);` by parsing `using` and `await using` declarations with `Context::In` disabled, matching ordinary for-loop declarations. Restore the outer context afterward so parenthesized `in` expressions and the remaining loop expressions keep their existing behavior.
2026-09-09 14:03:17 +00:00
camc314 c8e5fa7656 fix(parser): allow escaped type names in import and export specifiers (#26487)
Allow escaped value names such as `import { t\u0079pe as x } from "m"` and the equivalent named exports. Reject escapes only after resolving `type` as a type-only modifier.

Preserve the decoded identifier name in the ambiguous `type as as` form so its AST name remains `type`.
2026-09-09 13:22:34 +00:00
camc314 2dcee2f216 fix(parser): reject async modifiers on class fields (#26486)
`class C { async x; }` was accepted in JavaScript and TypeScript, silently discarding `async` from the resulting field. Reject the modifier after parsing a class field, once fields have been distinguished from methods.

Async methods, fields named `async`, and newline-separated fields remain valid.
2026-09-09 13:04:01 +00:00
camc314 973d58e128 fix(parser): require comma after TypeScript this parameter (#26480)
Require a comma after a TypeScript `this` parameter when the parameter list continues. Previously, malformed syntax such as `function f(this: T x: T) {}` parsed without a diagnostic.
2026-09-09 12:26:51 +00:00
Armano 80a76a0a2b feat(minifier): negate binary comparison for typeof x < 'u' (#26367)
Allow inversion of binary operation when comparing `'u'` string with
`typeof

`!(typeof a < "u")` => `typeof a > "u"`
`!(typeof a > "u")` => `typeof a < "u"`

this is needed to support negation of short version of `typeof x ===
"undefined"` -> `typeof a > "u"` generated by
`substitute_typeof_undefined`

fixes #25294
related #26460
2026-09-09 09:19:02 +08:00
camc314 118adb0ea2 perf(linter/eslint/no-restricted-imports): avoid redundant import scans (#26455)
Skip the rule when neither paths nor patterns are configured. For side-effect import detection, build a set of import statement spans once instead of scanning every import entry for each request, and return early when the file has no requested modules.
2026-09-08 14:58:24 +00:00
leaysgur b26bf56cd5 refactor(formatter): route every assignment RHS shape rule through a cast-aware accessor (#26430)
Follow up on #26429, apply cast-aware behavior to assignment call sites.
2026-09-08 06:02:01 +00:00
camc314 cfa47ab396 fix(parser): allow in expressions in class static blocks (#26423)
Class static blocks inherit the disabled `in` context of a surrounding `for` initializer, causing valid code such as `for (class { static { a in b; } };;);` to report a missing semicolon at `in`. Enable `Context::In` while parsing the static block, with the existing context helper restoring the surrounding flags afterward.
2026-09-07 18:06:57 +00:00
camc314 d61e3bf887 fix(parser): validate TS named tuple rest elements (#26419)
## Problem

Named tuple rest elements bypass the parser's existing checks for optional elements after an array rest and for multiple array rests. For example, both of these declarations currently parse successfully even though TypeScript rejects them:

```ts
type OptionalAfterRest = [...a: string[], b?: number];
type RestAfterRest = [...a: string[], ...b: number[]];
```

The equivalent unnamed forms already produce TS1266 and TS1265, respectively. Mixed named and unnamed array rests have the same gap when either rest is named.

## Cause and change

`parse_tuple_type` inspects `TSRestType.type_annotation` to decide whether an element is an array rest. For a named element, that annotation is a `TSNamedTupleMember`, and the actual type is stored in its `element_type`. Matching directly on the outer annotation therefore skips the array check and fails to track the rest element.

Unwrap the named member with `as_ts_type()` before applying the existing classification. Named and unnamed elements then share the same validation and existing diagnostics:

- An optional element after an array rest reports TS1266.
- A second array rest reports TS1265, including mixed named and unnamed forms.

The diagnostic spans continue to use the complete tuple elements, including their labels. The change borrows the underlying type without changing the AST representation or introducing allocations.

## Preserved behavior

A rest marker alone does not make a spread an unbounded array. Fixed-tuple and generic variadic spreads continue to be accepted, including:

```ts
type FixedBeforeOptional = [...a: [string], b?: number];
type RestBeforeFixed = [...a: string[], ...b: [number]];
type VariadicBeforeOptional<T extends unknown[]> = [...a: T, b?: number];
type RestBeforeVariadic<T extends unknown[]> = [...a: string[], ...b: T];
type MultipleVariadic<T extends unknown[], U extends unknown[]> = [...a: T, ...b: U];
```

This change preserves the existing type-reference classification; it does not add type resolution or change how shadowed `Array` references are handled.
2026-09-07 17:43:20 +00:00
camc314 10521b288f fix(parser): allow escaped type default import bindings (#26409)
TypeScript allows a default import binding named `type` to contain Unicode escapes. Oxc currently reports `Keywords cannot contain escape characters` for these valid imports:

```ts
import t\u0079pe from "m";
import t\u0079pe, { x } from "m";
import t\u0079pe, * as ns from "m";
```

In each example, `t\u0079pe` is an identifier whose decoded name is `type`, and the declaration is a value import.

The parser initially recognizes the decoded `type` token before it has enough context to distinguish a default binding from a type-only import modifier. The escape check ran at that point, so it rejected the binding even when the following tokens established that this was a value import.

Move the escape check into the two branches that interpret `type` as a modifier: before a named or namespace import, and before another binding identifier after ruling out `import type from "m"`. The latter check also runs before the early return for a type-only import-equals declaration.

Escaped modifiers remain invalid, including these forms:

```ts
import t\u0079pe Foo = require("m");
import t\u0079pe { x } from "m";
import t\u0079pe * as ns from "m";
import { t\u0079pe Bar } from "m";
```

The change is limited to when the declaration-level escape diagnostic is emitted; import classification and specifier parsing retain their existing behavior.
2026-09-07 16:03:31 +00:00
camc314 72cb5e3539 fix(parser): reject rest parameters in getters (#26400)
## Summary

Getter accessors must have no formal parameters, but Oxc currently accepts a getter whose only parameter is a rest parameter. This affects class and object getters, as well as getter signatures in TypeScript interfaces and type literals.

```ts
class C { get x(...args) {} }
({ get x(...args) {} });
interface I { get x(...args: any[]): string }
type T = { get x(...args: any[]): string };
```

Each declaration above previously parsed without a diagnostic. It now reports the existing error: `A 'get' accessor must not have any formal parameters.`

## Cause and correction

`FormalParameters` stores ordinary parameters in `items` and the rest parameter separately in `rest`. Both getter checks inspected only whether `items` was empty, so a rest-only parameter list looked like a zero-parameter list.

Use `parameters_count() != 0` in both checks so the count includes the rest parameter. The shared `check_getter` path covers class and object getters; `parse_getter_setter_signature_member` covers interface and type-literal getter signatures.

The diagnostic still points at the full parameter list. Zero-parameter getters remain valid, ordinary getter parameters retain their existing diagnostic, and class/object accessors with type parameters retain the current type-parameter diagnostic precedence. Setter validation is unchanged.
2026-09-07 15:34:10 +00:00
camc314 4e76602fdd fix(parser): allow in in arrow block bodies within for initializers (#26395)
## Summary

Allow the `in` operator inside an arrow function’s block body when the arrow appears in a `for` initializer:

```js
for (() => { a in b; };;);
```

This is valid JavaScript, but the parser previously reported a missing semicolon at `in`. The block now parses successfully, including async arrows and arrows with a single unparenthesized parameter.

## Cause and fix

A `for` initializer disables `Context::In` so that an unparenthesized `in` can delimit a `for…in` statement. Arrow block bodies inherited that disabled context through `parse_arrow_function_expression_body`, which called `parse_function_body` directly.

The block-body branch now calls `parse_function_body` through `context_add(Context::In, ...)`. This enables `in` throughout the function body and restores the enclosing context afterward. It also permits nested concise arrows inside that block to use `in`.

The change is confined to block bodies because concise expression bodies inherit the surrounding grammar’s `In` parameter. For example, this remains invalid:

```js
for (var f = () => a in b;;);
```

Restoring the enclosing context also keeps this invalid, rather than accidentally treating `a in b` as a regular initializer expression after parsing the first arrow:

```js
for (var f = () => {}, value = a in b;;);
```
2026-09-07 15:07:31 +00:00
camc314 b20fc1950c fix(parser): reject partially parenthesized mixed coalesce expressions (#26394)
The parser currently accepts mixed nullish and logical expressions when parentheses cover only the first operand of the logical expression:

```js
(a) || b ?? c;
a ?? (b) || c;
(a) && b ?? c;
a ?? (b) && c;
```

These expressions require a syntax error because `??` cannot be mixed directly with `||` or `&&`. Parentheses around `a` or `b` do not group the complete logical expression. This change reports the existing mixed-coalesce diagnostic for all four forms.

Fully grouped operands remain valid:

```js
(a || b) ?? c;
a ?? (b || c);
(a && b) ?? c;
a ?? (b && c);
```

### Why the existing check misses these expressions

`parse_binary_expression_rest` used `lhs_parenthesized` and `rhs_parenthesized` flags captured before parsing an operand. Those flags describe whether the initial token is `(`, but the parser can subsequently accumulate a larger logical expression outside those parentheses. Applying the initial flag to that complete expression incorrectly suppresses the diagnostic.

### Complete-operand checks

Check both operands independently for an `And` or `Or` logical expression whose span starts at the operand's starting position. A logical expression accumulated outside initial parentheses starts at that position and must be rejected. Checking both operands also prevents a grouped right operand from hiding an invalid left operand.

This works with either `preserve_parens` setting. When parentheses are preserved, a fully grouped operand is a `ParenthesizedExpression`. When they are omitted, its inner logical expression retains a span beginning after the opening `(`, so its start differs from the operand start and it remains allowed. For `(a) || b`, the complete logical expression instead starts at the opening `(` and is correctly rejected.
2026-09-07 14:34:52 +00:00
sapphi-red 34a242e134 perf(minifier): use Ident for property mangler (#26334)
Use `Ident` in the property mangler. This reduces the `Set::contains` operation faster as the hashing doesn't happen.

The property names are not always an "ident" so it may not make sense to use the `Ident` type. But currently the `Ident` type allows characters that are not allowed in identifiers so the code works.

I used AI to generate the code and then reviewed the code and iterated a bit.
2026-09-07 12:58:02 +00:00
Changsu Seong 116c8b8303 fix(transformer/class-properties): keep private methods in class-expression scope (#26308)
Private methods lowered from a class expression inside a concise arrow
were inserted next to the arrow's outer statement, while private field
storage remained inside the arrow. Starting with Oxc 0.143, this could
leave the generated helper unable to resolve the private field and throw
a `ReferenceError` at runtime.

Concise arrow bodies have no statement list where the helper declaration
can be inserted. In that context, the helper is now emitted as an
assignment in the class-expression sequence, with its `var` binding
inside the expanded arrow body. Ordinary statement-backed class
expressions keep block-local function declarations so classes created by
repeated block evaluation retain their own captured values. The
generated symbol flags and scope parents match the emitted form in both
cases.

## Example

```js
const makeClass = () => class {
  #field = 41;
  #read() { return this.#field; }
  run() { return this.#read() + 1; }
};

new (makeClass())().run();
```

Before Oxc emitted a helper outside `makeClass`, and the call threw
`ReferenceError: _field is not defined`. After this change it returns
`42`.

Verified with the private-method transform conformance suite, runtime
regressions for concise arrows and repeated block evaluation, `cargo
test -p oxc_transformer`, and transformer clippy.

Fixes the upstream cause of
[rolldown/rolldown#10818](https://github.com/rolldown/rolldown/issues/10818).

AI assistance: Cursor was used for the original patch; OpenAI Codex was
used for follow-up review, fixes, and testing.

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Dunqing <dengqing0821@gmail.com>
2026-09-07 20:47:40 +08:00
camc314 1400a0f8be fix(parser): require a string source after export ... from (#26389)
Named exports must have a string literal module source once `from` is present. The parser previously combined consuming `from` with checking whether the next token was a literal:

```rust
if self.eat(Kind::From) && self.cur_kind().is_literal()
```

When the next token was not a literal, `from` had already been consumed, but parsing fell back to a local export. This incorrectly accepted `export {} from;`, `export {} from` at EOF, and this input:

```js
export {} from
foo();
```

In the last case, the newline allowed automatic semicolon insertion, so the parser accepted a local empty export followed by `foo()` despite the incomplete `from` clause.

Remove the literal-kind guard so consuming `from` always leads to `parse_literal_string()`. That helper already requires a string literal and handles malformed input through the existing parser diagnostics. A missing source now produces a syntax error instead of becoming a local export, while unterminated strings and comments retain the standard lexer diagnostics.

Valid local exports such as `export { foo };` and re-exports such as `export { foo } from "./module.js";` keep their existing behavior, including a module source placed on the next line.
2026-09-07 12:41:32 +00:00
Armano 5303f5c884 perf(minifier): unify merging of last expression into target sequence (#26264)
adds new helper `merge_last_expression_into_sequence` and uses it
everywhere when we want to merge last expression to target expression
`a; b;` -> `a, b;`

this change avoids creation of 2 dummy nodes and unnecessary
`drop_statement` on dummy stmt per merge
2026-09-07 20:40:49 +08:00
Shanon Jackson fed8ff8753 fix(lexer): close remaining grammar gaps in context-dependent tokenization (#26377)
Closes out remaining spec compliance gaps in the lexer, Regex vs
Division cases, `>>` cases, + many more.

Fully passes on Test262, All Typescript tests, Oxc tests, SWC tests,
VSCode (codebase), And 1_000 machine hours of differential fuzzing;
Confidence is high that it's either 'correct' or very close.

This PR specifically needs AI Disclosure in both finding and fixing the
cases now because the bitwise logic is complex; Something that I'll
start addressing once 'correctness' is locked in (and performance).

---------

Co-authored-by: overlookmotel <theoverlookmotel@gmail.com>
2026-09-07 11:12:57 +01:00
overlookmotel 66744f0eb9 feat(parser)!: rename panicked to fatal_error in ParserReturn (#26382)
`ParserReturn` contains a property `panicked`.

The name `panicked` is misleading. The parser did _not_ panic. When `true`, it means that the parser encountered a fatal error and is unable to parse the source, because it contains an unrecoverable syntax error.

Rename this property to `fatal_error`, to better describe what it means.

This is a breaking change, but one that's trivial to fix in downstream code - the property doesn't change its meaning or behavior, just its name.

All the changes in this PR in other crates are just reacting to this change and making everywhere use the term "fatal error" instead of "panicked", so the codebase is consistent.
2026-09-07 09:41:52 +00:00
Armano 2ca7d29b7a perf(minifier): consume nodes in minimize_statements in reverse order (#26258)
changes `minimize_statement`s to consume statement via a single
`reverse()` + `pop()` pass instead of repeatedly calling `take_in` on
each slot.

potential pitfall: result is in forward order, old stmts are in reverse,
thus we have to be careful in places where we want to take all of them

| File | Arena allocs | Delta | Arena size | Delta |
|---|---:|---:|---:|---:|
| `checker.ts` | `144024 -> 77557` | `-66467` | `19.13 MB -> 17.52 MB` |
`-1.61 MB` |
| `App.tsx` | `15675 -> 9622` | `-6053` | `2.88 MB -> 2.74 MB` | `-0.14
MB` |
| `RadixUIAdoptionSection.jsx` | `29 -> 16` | `-13` | `35.63 kB -> 35.63
kB` | `~0` |
| `pdf.mjs` | `44801 -> 26527` | `-18274` | `6.31 MB -> 5.89 MB` |
`-0.42 MB` |
| `antd.js` | `351645 -> 222308` | `-129337` | `48.77 MB -> 45.76 MB` |
`-3.01 MB` |
| `binder.ts` | `6809 -> 4124` | `-2685` | `1.16 MB -> 1.10 MB` | `-0.06
MB` |
| `kitchen-sink.tsx` | `64956 -> 34571` | `-30385` | `9.39 MB -> 8.74
MB` | `-0.65 MB` |

---------

Co-authored-by: Dunqing <dengqing0821@gmail.com>
2026-09-07 17:24:05 +08:00
Dunqing 3d95477214 fix(transformer): gate async-only rewrites by owning transform (#26326)
For targets that support async functions but not async generators, async-only converter mode still treated every async function as if the enabled transform would move its body. Plain async arrows and methods gained generated `this` and `super` bindings, and class-field arrows were wrapped unnecessarily.

Use the shared body-movement predicate for every async-only rewrite. Functions left native by the selected target now remain untouched, while async generator functions that are lowered keep their required lexical captures.

## Example

A plain async method using `super` previously gained a generated `_superprop_getValue` binding even though the method remained native. This made `eval("typeof _superprop_getValue")` return `"function"` instead of `"undefined"`. The method now remains unchanged.

Verified with focused output/runtime conformance, full transformer output conformance, and `cargo test -p oxc_transformer`.

Stacked on #26317.

AI assistance was used to diagnose the remaining transform boundaries, implement the predicate checks, and add tests. I remain responsible for reviewing and understanding the changes before merge.
2026-09-07 07:21:47 +00:00
Dunqing f45a9ee58b fix(transformer): limit arguments capture to lowered async functions (#26317)
For targets that support async functions but not async generators, plain async methods and arrows remain native. Async-only converter mode still captured `arguments` for all of them, exposing generated `_arguments` bindings even though their bodies never move.

Gate `arguments` capture on the transform that owns the function body. Native async functions now remain untouched, while lowered async generator methods still capture their original arguments.

## Example

This native async method previously changed from:

```js
async method() {
  void arguments;
  return eval("typeof _arguments");
}
```

to:

```js
async method() {
  var _arguments = arguments;
  void _arguments;
  return eval("typeof _arguments");
}
```

The generated binding changed the return value from `"undefined"` to `"object"`. The method now remains unchanged.

Verified with focused output/runtime conformance, full transformer output conformance, and `cargo test -p oxc_transformer`.

Stacked on #26227.

AI assistance was used to diagnose the transform boundary, implement the fix, and add tests. I remain responsible for reviewing and understanding the changes before merge.
2026-09-07 07:05:01 +00:00
Dunqing 789969f8a1 fix(transformer): gate this capture by owning async transform (#26227)
For targets that support async functions but not async generators, plain async methods remain native. The shared arrow converter still captured `this` whenever either async transform was active, injecting an observable `_this` binding into methods whose bodies never move.

Track async-to-generator and async-generator lowering separately. Plain async methods are now left untouched when only async generators require lowering, while transformed async generator methods still preserve their receiver.

## Example

With a Chrome 55 target, this method previously gained a generated binding:

```js
async method() {
  var _this = this;
  void _this;
  return eval("typeof _this");
}
```

It now remains unchanged, so the direct evaluation returns `"undefined"` as it does in the source program.

Verified with a Chrome 55 target output/runtime fixture, full transformer output conformance, and `cargo test -p oxc_transformer`.

AI assistance was used to diagnose the transform boundary, implement the fix, and add tests. I remain responsible for reviewing and understanding the changes before merge.
2026-09-07 07:05:01 +00:00
camc314 8b35abdfd9 fix(semantic): detect duplicate private class elements (#26361)
The duplicate class element check stored only the last element for each name. This allowed a public element to hide an earlier private declaration, and a setter to hide an earlier getter (or vice versa):

```js
class DuplicateField {
  #x;
  x;
  #x;
}

class DuplicateGetter {
  get #x() {}
  set #x(value) {}
  get #x() {}
}
```

Both classes were accepted despite declaring the same private field or getter twice. The same problem affected setter/getter/setter sequences.

Key a single map by both the element name and whether it is private, so public elements cannot replace private declarations. This keeps the namespaces separate while reserving map capacity only once. For each private name, retain separate slots for setters and other declarations. Look for a previous declaration in the matching slot first, then fall back to the other slot. This catches repeated getters and setters while still allowing one getter/setter pair when both have the same static status.

The existing diagnostic logic continues to reject private names shared by static and instance elements, including the TypeScript-specific diagnostic. Public elements continue through the existing public-element duplicate check.
2026-09-06 21:17:34 +00:00
renovate[bot] 2289d27099 chore(deps): update npm packages (#26366)
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.68.0` →
`8.69.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fparser/8.68.0/8.69.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2fparser/8.69.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@typescript-eslint%2fparser/8.69.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@typescript-eslint%2fparser/8.68.0/8.69.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2fparser/8.68.0/8.69.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.68.0` →
`8.69.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fscope-manager/8.68.0/8.69.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2fscope-manager/8.69.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@typescript-eslint%2fscope-manager/8.69.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@typescript-eslint%2fscope-manager/8.68.0/8.69.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2fscope-manager/8.68.0/8.69.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.68.0` →
`8.69.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fvisitor-keys/8.68.0/8.69.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2fvisitor-keys/8.69.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@typescript-eslint%2fvisitor-keys/8.69.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@typescript-eslint%2fvisitor-keys/8.68.0/8.69.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2fvisitor-keys/8.68.0/8.69.0?slim=true)
|
| [degit](https://redirect.github.com/Rich-Harris/degit) | [`3.8.0` →
`3.9.0`](https://renovatebot.com/diffs/npm/degit/3.8.0/3.9.0) |
![age](https://developer.mend.io/api/mc/badges/age/npm/degit/3.9.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/degit/3.9.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/degit/3.8.0/3.9.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/degit/3.8.0/3.9.0?slim=true)
|
|
[serialize-javascript](https://redirect.github.com/yahoo/serialize-javascript)
| [`7.1.0` →
`7.1.1`](https://renovatebot.com/diffs/npm/serialize-javascript/7.1.0/7.1.1)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/serialize-javascript/7.1.1?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/serialize-javascript/7.1.1?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/serialize-javascript/7.1.0/7.1.1?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/serialize-javascript/7.1.0/7.1.1?slim=true)
|
| [tsx](https://tsx.hirok.io)
([source](https://redirect.github.com/privatenumber/tsx)) | [`4.23.12` →
`4.23.13`](https://renovatebot.com/diffs/npm/tsx/4.23.12/4.23.13) |
![age](https://developer.mend.io/api/mc/badges/age/npm/tsx/4.23.13?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/tsx/4.23.13?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/tsx/4.23.12/4.23.13?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/tsx/4.23.12/4.23.13?slim=true)
|
| [type-fest](https://redirect.github.com/sindresorhus/type-fest) |
[`5.8.0` →
`5.9.0`](https://renovatebot.com/diffs/npm/type-fest/5.8.0/5.9.0) |
![age](https://developer.mend.io/api/mc/badges/age/npm/type-fest/5.9.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/type-fest/5.9.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/type-fest/5.8.0/5.9.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/type-fest/5.8.0/5.9.0?slim=true)
|

---

### Release Notes

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

###
[`v8.69.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#8690-2026-08-31)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v8.68.0...v8.69.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.69.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.69.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/scope-manager/CHANGELOG.md#8690-2026-08-31)

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

This was a version bump only for scope-manager 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.69.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.69.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/visitor-keys/CHANGELOG.md#8690-2026-08-31)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v8.68.0...v8.69.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.69.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.9.0`](https://redirect.github.com/Rich-Harris/degit/releases/tag/v3.9.0):
3.9.0

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

- Add `Degit#doActions()` for programmatic `degit.json` actions and make
the constructor source-optional
([#&#8203;33](https://redirect.github.com/Rich-Harris/degit/issues/33)).

</details>

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

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

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

#### What's Changed

- fix: fix XSS bypass via split `</script` payload across function
bodies by [@&#8203;okuryu](https://redirect.github.com/okuryu) in
[#&#8203;226](https://redirect.github.com/yahoo/serialize-javascript/pull/226)
- release: v7.1.1 by
[@&#8203;okuryu](https://redirect.github.com/okuryu) in
[#&#8203;227](https://redirect.github.com/yahoo/serialize-javascript/pull/227)

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

</details>

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

###
[`v4.23.13`](https://redirect.github.com/privatenumber/tsx/compare/v4.23.12...28e1f12d04cd2afe1db17f8555b14fe5fb567c6e)

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

</details>

<details>
<summary>sindresorhus/type-fest (type-fest)</summary>

###
[`v5.9.0`](https://redirect.github.com/sindresorhus/type-fest/releases/tag/v5.9.0)

[Compare
Source](https://redirect.github.com/sindresorhus/type-fest/compare/v5.8.0...v5.9.0)

##### New types

-
[`RenameKeys`](https://redirect.github.com/sindresorhus/type-fest/blob/main/source/rename-keys.d.ts)
([#&#8203;1435](https://redirect.github.com/sindresorhus/type-fest/issues/1435))
[`548e7df`](https://redirect.github.com/sindresorhus/type-fest/commit/548e7df)

##### Improvements

- `SharedUnionFieldsDeep`: Ensure it doesn't distribute processed union
over mapped type
([#&#8203;1509](https://redirect.github.com/sindresorhus/type-fest/issues/1509))
[`07a04de`](https://redirect.github.com/sindresorhus/type-fest/commit/07a04de)
- `TypedArray`: Add `Float16Array`
([#&#8203;1495](https://redirect.github.com/sindresorhus/type-fest/issues/1495))
[`ca27cce`](https://redirect.github.com/sindresorhus/type-fest/commit/ca27cce)

##### Fixes

- `Writable`: Fix behavior with index signatures
([#&#8203;1470](https://redirect.github.com/sindresorhus/type-fest/issues/1470))
[`48ddc4b`](https://redirect.github.com/sindresorhus/type-fest/commit/48ddc4b)
- `Jsonify`: Fix optional properties leaking `undefined` into the key
set
([#&#8203;1484](https://redirect.github.com/sindresorhus/type-fest/issues/1484))
[`5339fb3`](https://redirect.github.com/sindresorhus/type-fest/commit/5339fb3)
- `IsLiteral*`: Fix behavior with unions
([#&#8203;1482](https://redirect.github.com/sindresorhus/type-fest/issues/1482))
[`3425142`](https://redirect.github.com/sindresorhus/type-fest/commit/3425142)

***

</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:eyJjcmVhdGVkSW5WZXIiOiI0NC42MS4zIiwidXBkYXRlZEluVmVyIjoiNDQuNjEuMyIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Cameron Clark <cameron.clark@hey.com>
2026-09-06 21:05:25 +00:00
camc314 457ed57ff2 fix(semantic): reject await and yield in rest parameter defaults (#26359)
The parameter check only recognized `FormalParameter`, allowing `await` and `yield` in destructuring defaults inside rest parameters:

```js
async function f(...[x = await 0]) {}
function* g(...[x = yield 0]) {}
```

Include `FormalParameterRest` so both cases report the existing parameter diagnostic. The check still stops at nested functions, where `await` and `yield` can be valid.
2026-09-06 08:36:56 +00:00
camc314 4b89c7bd55 fix(semantic): reject jumps across arrow functions (#26357)
Reject labeled and unlabeled `break` and `continue` statements that cross an arrow-function boundary.

For example:
```ts
while (true) {
  (() => {
    break;
  });
}
```

now reports an illegal break, while jumps targeting loops inside the arrow remain valid.
2026-09-06 07:44:47 +00:00
Armano d19c42ac87 perf(minifier): merge nested if stmt in place instead of creating dummies (#26351)
reduce allocations when converting `if (a) if (b) x;` to `if (a && b)
x;`
2026-09-05 22:51:23 +01:00
renovate[bot] 8dd81f9bb8 chore(deps): update dependency @napi-rs/cli to v3.9.0 (#26256)
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/) |
|---|---|---|---|---|---|
| [@napi-rs/cli](https://napi.rs/)
([source](https://redirect.github.com/napi-rs/napi-rs)) | [`3.8.6` →
`3.9.0`](https://renovatebot.com/diffs/npm/@napi-rs%2fcli/3.8.6/3.9.0) |
![age](https://developer.mend.io/api/mc/badges/age/npm/@napi-rs%2fcli/3.9.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@napi-rs%2fcli/3.9.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@napi-rs%2fcli/3.8.6/3.9.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@napi-rs%2fcli/3.8.6/3.9.0?slim=true)
|

---

> [!WARNING]
> Some dependencies could not be looked up. Check the warning logs for
more information.

---

### Release Notes

<details>
<summary>napi-rs/napi-rs (@&#8203;napi-rs/cli)</summary>

###
[`v3.9.0`](https://redirect.github.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.8.6...@napi-rs/cli@3.9.0)

[Compare
Source](https://redirect.github.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.8.6...@napi-rs/cli@3.9.0)

</details>

---

### Configuration

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

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Enabled.

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

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/oxc-project/oxc).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC41Ny4zIiwidXBkYXRlZEluVmVyIjoiNDQuNjEuMyIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Cameron <cameron.clark@hey.com>
2026-09-04 14:22:16 +00:00
overlookmotel c966acaac5 fix(parser): do not omit < token opening type argument list (#26328)
Fix tokens produced when `<<` opens a type argument list. e.g.:

```typescript
type Bar = ReturnType<<T>(x: T) => number>;
```

Previously only 1 `<` token was produced between `ReturnType` and `T`. This PR corrects that so 2 `<` tokens are produced.

TS-ESLint get this wrong too - hence why this wasn't noticed before, as our conformance tests compare to TS-ESLint.

PR submitted to fix TS-ESLint: https://github.com/typescript-eslint/typescript-eslint/pull/12821

In meantime, this PR skips the erroneously failing ESTree tokens conformance tests. We can can re-enable those tests once the fix lands in TS-ESLint.
2026-09-04 12:08:49 +00:00
camc314 949d7a9302 chore(deps): update vitest to v5 (#26299)
## Summary

- update workspace test dependencies to Vitest 5.0.0
- pin Vitest and related tooling to Vite 8.2.2
- migrate removed sequential and benchmark APIs
- update the pnpm lockfile
2026-09-03 19:05:05 +00:00
overlookmotel b4f6593c4f ci(lexer): run lint, tests and conformance on both lexer implementations (#26298)
#26263 added the ability to run tests and conformance for both versions of `oxc_lexer` (SIMD and scalar fallback) on any platform.

Run tests and conformance on CI (both SIMD and scalar) on any PR which touches `oxc_lexer` crate or other files which affect conformance runner.

Additionally, run Clippy on the SIMD version (main Lint CI task doesn't lint it, due to the `target_feature = "avx2"` gate on the code).

All of this sets up `oxc_lexer` crate for further development, catching any regressions in CI.
2026-09-03 16:40:21 +00:00
Armano a17de58e30 feat(minifier): process of return/throw in non last position and fix async * inlining (#26214)
This Pr brings couple optimizations and refactor,

- Disable merging: `if (a) return x; return;` and `if (a) return; return
x;` when is descendant of `async* function`
- Handle empty chains: `if (a) return; return;` → `a; return;`
- Process returns/throw anywhere in block via handler merge `if (a)
return; return; var b` → `a; return; var b`

fixes #26255
ref #24331
2026-09-03 23:05:40 +08:00
overlookmotel 6365db964b test(lexer): enable oxc_lexer conformance tests on all platforms (#26263)
`oxc_lexer` has 2 implementations:

1\. SIMD-based on x86_64 with AVX2.
2\. Scalar/SWAR fallback which works on all platforms.

Both produce the same output.

This PR enables running the lexer conformance on either implementation. Which implementation is tested depends on what build flags are passed to `cargo coverage`.

It turns out that it's possible to test the SIMD implementation on Mac by compiling as x86_64, and running it under Rosetta 2.

This PR also adds `just` recipes to run tests and conformance on either implementation:

- `just test-lexer`
- `just test-lexer-simd`
- `just conformance-lexer`
- `just conformance-lexer-simd`

These commands should work correctly on any of Linux x86, Windows x86, Mac aarch64.
2026-09-03 10:59:05 +00:00
overlookmotel 651c54649a refactor(coverage/lexer): clarify code and fix clippy warnings (#26262)
Refactor the conformance tester for lexer.

The diff is large, as I've reordered the code so it now reads top-to-bottom, but it's pure refactor. The actual logic is exactly as it was before - just moved things around, renamed vars, shortened code etc.

This also fixes some Clippy warnings which were present before, but hidden because this code is gated behind `target_feature = "avx2"`. That changes in next PR #26263, at which point CI would have started failing if the warnings weren't fixed here first.
2026-09-03 10:59:05 +00:00
overlookmotel d752d501c6 ci(coverage): error if cargo coverage passed unknown argument (#26261)
Small fix to `cargo coverage`.

Previously a typo e.g. `cargo coverage prser` would fall through to the catch-all arm and would run all coverage tasks.

Instead, this PR makes it panic with an error `Unknown coverage task: "prser"`. This ensures you are running what you think you are.
2026-09-03 10:59:05 +00:00
overlookmotel ef0f33eb7d test(all): run conformance with panic = "unwind" (#26260)
Conformance tests for `oxc_lexer` crate rely on using `catch_unwind` to catch panics and report them, rather than crashing the whole process. Currently this doesn't work because conformance is compiled with `panic = "abort"` (inherited from `release` profile).

This PR fixes that by adding `panic = "unwind"` to `coverage` profile.

I've measured the time it takes to run conformance locally before/after this change, and the difference is within noise (+/- 2%), so this seems to have no adverse effects.

`codegen-conformance` profile only existed to add `panic = "unwind"` too, so after this change it becomes identical to `coverage` profile. That makes it redundant, so this PR removes it in favour of just using `coverage` everywhere.
2026-09-03 10:59:04 +00:00