Commit Graph

863 Commits

Author SHA1 Message Date
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
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
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
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
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
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
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 3ab9bd122c fix(parser): do not re-lex template substitution tail after fatal error (#26230)
When the parser records a fatal error it fast-forwards the lexer to end of file. `re_lex_template_substitution_tail` did not check for that, so an incomplete template substitution would still re-lex the `}` and derive the token's start from a cursor which had already jumped to the end.

With tokens enabled, that fails the debug assertion in `finish_next_inner`, because the token being replaced is no longer the one on top of the collected token stream. Release builds silently overwrite an unrelated token instead. Tokens are only collected for Oxlint's JS plugins, which bail out if any parsing error, which is why this hadn't been noticed before.

Fix by adding the same `fatal_error` guard, added to other re-lex methods in #11023.

This does make a difference to diagnostics output for invalid code matching this pattern. TypeScript snapshot loses an "Unterminated string" diagnostic on 2 fixtures. Those errors came from the bogus re-lex reading past end of file. Both these fixtures already have an "Unexpected token" error. The additional "Unterminated string" errors were incorrect, and this fix has the side effect of removing them.
2026-09-02 21:41:11 +00:00
camc314 4adfb4c949 fix(semantic): validate chained continue labels (#26157)
## Summary

- follow chained labels to their terminal statement when validating labeled `continue`
- reject label chains that terminate in a non-iteration statement
- add a focused negative coverage fixture and update the parser coverage snapshot
2026-08-28 18:45:13 +00:00
camc314 dc09a3aa9d fix(parser): avoid panic on escaped string export names (#26146)
## Summary

Fix a parser panic when a string-named export decodes to a literal `\u` sequence.

Lone-surrogate validation now uses the metadata captured by the lexer instead of rescanning decoded string contents. This also prevents false diagnostics for names such as `"\\uD800"`.

## Before:

```

thread 'main' (10990283) panicked at crates/oxc_ast/src/ast_impl/literal.rs:89:42:
end byte index 4 is out of bounds for string of length 0
stack backtrace:
   0: __rustc::rust_begin_unwind
   1: core::panicking::panic_fmt
   2: core::str::slice_error_fail_rt
   3: core::str::slice_error_fail
   4: <core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<str>>::index
   5: <str as core::ops::index::Index<core::ops::range::RangeTo<usize>>>::index
   6: <oxc_ast::ast::literal::StringLiteral>::is_string_well_formed_unicode
   7: <oxc_parser::ParserImpl<oxc_parser::config::NoTokensParserConfig>>::parse_module_export_name
```
2026-08-28 13:37:48 +00:00
Dunqing c3dedc9b0c fix(semantic): skip function body bindings in parameters (#26099)
Function parameters, TypeScript signatures, and function bodies currently share one Oxc semantic scope. A reference in a parameter can therefore bind to a declaration inside the body, even though JavaScript does not make body declarations visible there. Rolldown may then treat a global as local, skip a configured define, or remove live code.

## Example

```js
export function load(value = typeof window !== "undefined") {
  var window;
  return value;
}
```

The body `var window` is not visible to the default value. Before this change, Oxc resolved `window` in the default value to that body declaration. It should remain a global reference.

The workaround resolves parameter and signature references before visiting the body, while only parameter bindings are present. If a reference is still unresolved, its `lookup_scope_id` advances to the function's parent. Final resolution resumes there, so declarations added while visiting the body are skipped. References created in the body still begin at the function scope and resolve normally.

```text
Before: parameter reference -> completed function scope -> body binding (wrong)

After:  parameter reference -> parameter bindings -> parent scopes
        body reference      -> completed function scope -> parent scopes
```

Parameter decorators already begin in the enclosing class scope, so they are left for normal final resolution. This emulates separate parameter and body scopes until https://github.com/oxc-project/backlog/issues/176 is implemented.

The corrected semantic data also exposes the transformer case covered by #26105.

Verified with semantic and transformer-plugin tests, Clippy, coverage, allocation snapshots, and diff checks. `just ready` completed workspace checks but stopped at a codegen snapshot recorded with Node.js v26.5.0; the local version is v25.8.1.

Closes #20427
Closes #22783

Downstream reports:

- https://github.com/rolldown/rolldown/issues/10722
- https://github.com/rolldown/rolldown/issues/10779

AI assistance: OpenAI Codex was used to investigate, implement, and test this change. The contributor is responsible for the submitted change.
2026-08-27 17:23:18 +00:00
camc314 8a9bdbd6d8 fix(estree): include decorators in FormalParameterRest spans (#26021)
Serialize `FormalParameterRest` with its outer span so its range includes parameter decorators. Regenerate the raw-transfer deserializers and remove `sourceMapValidationDecorators.ts` from the ESTree mismatch baseline.

Fixes #26011.
2026-08-23 18:32:30 +00:00
Boshen fca2e0cfed fix(parser): reject initialized lexical declarations in for-in (#25700)
Rejects initialized `let` and `const` declarations in `for...in` during parsing while preserving Annex B's non-strict `var` form.

Adds misc coverage for valid and invalid initializer forms.

Verified with `just ready` and parser conformance.

Closes #25149.

AI-assisted.
2026-08-15 06:58:08 +00:00
Boshen ae9be8f8bd fix(parser): forbid type parameters on quoted constructors (#25696)
Quoted constructor methods bypassed the AST-based constructor validation. Validate type parameters after resolving the method key, preserving the AST shape.

Validation: `just ready`, parser conformance, and allocation checks.

Closes #25692.

AI-assisted with Codex.
2026-08-15 05:02:23 +00:00
camc314 6e040e494e fix(coverage): ignore unable to resolve parameter decorator TS1239 (#25583) 2026-08-13 10:30:36 +00:00
Boshen cdf1846af2 fix(semantic): allow legacy escapes in JSX attributes (#25576)
Quoted JSX attribute values do not use ECMAScript escape sequences. Skip strict-mode legacy escape validation for JSX attributes and cover the behavior in misc conformance.

AI-assisted by Codex.
2026-08-13 07:06:42 +00:00
Boshen 23a7ad096a fix(parser): stop delimited lists at end of file (#25542)
Stop parsing delimited-list elements after a separator when EOF or an undetermined token follows, preventing malformed tuple syntax from creating reversed spans during error recovery.

Validated with `cargo coverage -- parser --filter oxc-23670 --detail`.

AI assistance was used to prepare this change.

Closes #23670.
2026-08-12 13:58:51 +00:00
Boshen 73acba93fb fix(parser): preserve fatal errors during await reparse (#25541)
Fixes #23681.

Preserve initial fatal parser errors during top-level `await` reparsing, preventing malformed recovery AST nodes from reaching Oxlint.

Validated with parser unit/conformance suites and allocation snapshots. `just ready` only fails three unrelated ANSI snapshot checks in the current environment.

AI-assisted.
2026-08-12 11:25:27 +00:00
oxc-guard 7ebbdddce7 chore(submodules): update submodule SHAs to latest commits (#25505)
Updates submodule dependencies to their latest commits.

## Changes

- test262: `b363f29` → `be13516`
- babel: `06b6eae` → `1eac448`
- estree-conformance: `f7a4e0c` → `8d4e1fa`

This PR is automatically generated by the [update_submodules workflow](https://github.com/oxc-project/oxc/blob/main/.github/workflows/update_submodules.yml).
2026-08-11 16:17:31 +00:00
Dunqing 66cfe0a49a chore(coverage): update stale test262 runtime snapshot (#25471)
The automated submodule bump #25261 regenerated `runtime.snap` on a loaded CI runner where two tests hit the global timeout, recording transient `timeout: global` failures (`expressions/arrow-function/name.js`, `function-code/10.4.3-1-13-s.js`) and dropping the pass count from 17306 to 17304. Both tests pass on a normal run, so monitor-oxc's Test262 drift check has failed on every run since ([example](https://github.com/oxc-project/monitor-oxc/actions/runs/31359248351/job/93364683855)).

This restores the snapshot to what `cargo coverage runtime` actually produces. Rather than regenerating locally (which could bake in this machine's own timeouts), the CI-reported diff was applied directly and verified byte-identical to CI's output (`git hash-object` matches the diff's `65e3fa9` blob).

Timeouts can get baked in again whenever an automated regen lands on a slow runner; retrying timed-out tests before recording them would close that hole and is left for a follow-up.

This PR was assisted by Claude.
2026-08-10 10:16:19 +00:00
Cameron 12937b3201 fix(parser): reject comma expressions in class fields (#25385)
## Summary

- parse ordinary class field initializers as `AssignmentExpression`
- reject unparenthesized comma expressions while preserving
parenthesized sequence expressions
- add paired misc conformance fixtures and update the generated
snapshots

## Root cause

Ordinary class field initializers used `parse_expr`, which accepts a
top-level comma and constructs a sequence expression. The ECMAScript
`Initializer` grammar requires an `AssignmentExpression`, so the
unparenthesized comma must remain for the class-element terminator check
to reject.
2026-08-08 10:59:23 +00:00
camc314 9e93ba6908 fix(parser): reset auto-accessor initializer context (#25384)
## Summary

- Align auto-accessor initializer parsing with class-field initializer grammar.
- Add regressions for `in` in a `for` initializer and disallowed inherited `await`/`yield` contexts.

## Root cause

The auto-accessor path only enabled `new.target`. It therefore inherited outer `~In`, `Await`, and `Yield` grammar contexts: `a in b` could not parse in a `for` initializer, while `await` and `yield` could incorrectly parse from enclosing async/generator functions. The fix applies the same `In | NewTarget` addition and `Yield | Await` removal already used for class fields, while retaining AssignmentExpression parsing.

## References

- [ECMAScript `FieldDefinition` grammar](https://tc39.es/ecma262/#prod-FieldDefinition)
- [ECMAScript `Initializer` grammar](https://tc39.es/ecma262/#prod-Initializer)
- [TC39 decorators proposal: class auto-accessors](https://github.com/tc39/proposal-decorators#introduction)
2026-08-07 23:03:24 +00:00
camc314 5c5cdcd522 feat(ast)!: narrow TSInterfaceHeritage::expression to TSTypeName (#24360)
## Summary

Narrow `TSInterfaceHeritage` from a general JavaScript `Expression` to `TSTypeName`.

```rust
pub struct TSInterfaceHeritage<'a> {
    pub type_name: TSTypeName<'a>,
    pub type_arguments: Option<Box<'a, TSTypeParameterInstantiation<'a>>>,
}
```

## Breaking Change

The Rust AST field changes from:

```rust
expression: Expression<'a>
```

to:

```rust
type_name: TSTypeName<'a>
```

## Why?

The current AST can represent shapes such as:

```ts
interface A extends foo() {}
interface A extends A + B {}
interface A extends new Foo() {}
interface A extends true {}
```

Which is an overly wide type since all of the above variants are invalid.

This PR tightens up the AST, making these invalid variants irrepresentable.

## How to migrate?

This should be a trivial migration:
1. instead of accessing `expression` on `TSInterfaceHeritage`, now access `type_name`
2. change any pattern matching on the `type_name` field to use `TypeName` (this is a smaller subset so should allow deleting code!)

closes https://github.com/oxc-project/backlog/issues/215
2026-08-07 06:00:42 +00:00
camc314 4d723caaff fix(parser): report TS1035 for quoted module names (#25305)
Quoted module names are only valid in ambient contexts in TypeScript, but we were accepting them in regular TypeScript files.

This reports TS1035 when a quoted module name appears outside a declaration file or ambient declaration. The conformance snapshots now cover both TypeScript cases, and the old invalid codegen fixture has been replaced with a valid internal module declaration.
2026-08-05 10:21:52 +00:00
camc314 0c9b980cb1 fix(semantic): report module declaration diagnostics (#25285)
## Summary

- report TS1234 for function-local ambient module declarations
- preserve TS1235 for function-local namespace and internal module declarations
- report TS2435 for ambient modules nested in namespaces while allowing module augmentation inside ambient external modules

## Babel Conformance Snapshot Parse Failure

This intentionally introduces one known Babel conformance false positive: `typescript/scope/redeclaration-in-nested-module/input.ts`. The Babel harness supplies `sourceType: "module"`, so Oxc reports TS2435 for its nested ambient module. This affects one unique fixture in both the parser and semantic Babel summaries. This change aligns with TS, and TS expects this error.
2026-08-04 15:06:10 +00:00
oxc-guard[bot] 4e7007118d chore(submodules): update submodule SHAs to latest commits (#25261)
Updates submodule dependencies to their latest commits.

## Changes

- test262: `d1d583d` → `b363f29`
- babel: `c86e9e4` → `06b6eae`
- TypeScript: `637d574` → `b465fdb`
- estree-conformance: `e8fd120` → `f7a4e0c`


This PR is automatically generated by the [update_submodules
workflow](https://github.com/oxc-project/oxc/blob/main/.github/workflows/update_submodules.yml).

Co-authored-by: oxc-guard[bot] <276638029+oxc-guard[bot]@users.noreply.github.com>
2026-08-03 22:09:18 +01:00
camc314 a70035d743 fix(parser): report export imports in namespaces (#25086)
## Summary

- report TS(1147) for exported TypeScript import-equals declarations that reference external modules inside namespaces
- inspect the wrapped `TSImportEqualsDeclaration` within `ExportNamedDeclaration`
- update TypeScript parser coverage snapshots for all affected conformance cases
2026-07-29 15:44:48 +00:00
Boshen e935064d33 refactor(ast_visit): migrate JS-only mutable visitors (#24849)
## Summary

Migrate seven runtime-only `VisitMut` implementations to `VisitJsMut`.

This avoids monomorphizing pure TypeScript type-space traversal for
these consumers.

## Binary size

On arm64 macOS, `cargo build --release -p oxc_transform_napi` produces a
stripped dylib that changes from 3,365,584 to 3,332,480 bytes: **-33,104
bytes (-0.98%)**. Its Mach-O `__text` section changes from 2,909,108 to
2,876,892 bytes: **-32,216 bytes (-1.11%)**.

AI assistance was used to implement this change. I reviewed and take
responsibility for the result.

<sub>Stack created with <a
href="https://github.com/github/gh-stack">GitHub Stacks CLI</a></sub>
2026-07-27 16:20:25 +08:00
camc314 9fbbaf8607 fix(parser): clarify return in class static blocks (#24899)
## Summary

- report TypeScript diagnostic TS18041 for `return` statements in class static initialization blocks
- reuse the existing `NewTarget`/`Return` parser-context invariant without adding a new context flag
- update the TypeScript, Babel, and Test262 parser snapshots

## Root cause

Class static blocks disable the parser's `Return` context, so their `return` statements previously fell through to the generic top-level TS1108 diagnostic. Static blocks already enable `NewTarget`, which distinguishes this case when `Return` is absent.
2026-07-24 14:26:41 +00:00
camc314 4d6f623cda feat(parser): emit error for type args in JS files (#24896)
## Summary

- Emit TS8011 when a JavaScript class heritage clause uses TypeScript type arguments.
- Cover the diagnostic with a misc parser failure fixture and snapshot.
2026-07-24 09:46:34 +00:00
camc314 5b4ae548e6 fix(parser): use specific for-await diagnostic (#24856)
## Summary

- add a dedicated diagnostic for invalid `for await` loops
- report “`for await` loops are only allowed…” instead of the generic `await` expression message
- update Babel and TypeScript parser conformance snapshots

## Impact

Users now receive an error that identifies the invalid loop construct directly while retaining the existing guidance to remove `await` or mark the enclosing function `async`.
2026-07-23 18:09:23 +00:00
camc314 ffcc33a676 fix(parser): report for-await in non-async functions (#24855)
## Summary

- report invalid `for await` loops inside non-async functions immediately, including when an unambiguous source later resolves to a module
- update the TypeScript parser conformance snapshot with the newly reported diagnostics

## Root cause

The parser deferred every `for await` context error in unambiguous sources as a script-only error. When later `export` syntax resolved the source as a module, it discarded that deferred error even when the loop was nested inside a non-async function, where `await` is never permitted.
2026-07-23 17:58:55 +00:00
Boshen 582805df03 fix(parser): parse unary conditional after satisfies (#24807)
Fixes #24804.

Recognize `!` as a type-start token so `?` after `satisfies` remains the conditional-expression operator instead of being consumed as a JSDoc nullable type.

Validated with `just ready`.

AI-assisted.
2026-07-22 13:22:14 +00:00
camc314 3048594401 fix(parser): use correct diagnostic for await using in bare switch case (#24798)
This improve the error diagnostic for await using in bar switch case clauses, as well as aligning more closely with  the behaviour for using/await using in ambient contexts:

https://github.com/oxc-project/oxc/blob/981a9522f5fb658943e89501b35543ff3283eea5/crates/oxc_parser/src/js/declaration.rs#L197-L204
2026-07-22 09:04:49 +00:00
camc314 47ddedf011 fix(semantic): allow arguments in ambient declarations (#24758)
## Summary

- allow `eval` and `arguments` as direct bindings in ambient declarations
- continue reporting strict-mode errors for destructured ambient bindings
- add focused coverage for declared functions, classes, object patterns, and array patterns

## Why

The semantic checker previously identified allowed bindings by walking to a `TSDeclareFunction`. That missed other ambient declarations, including declared class constructors and methods, and produced diagnostics for TypeScript cases that require no runtime code generation.

The check now uses the existing ambient-context state and rejects only destructuring binding shapes.
2026-07-21 12:43:21 +00:00
camc314 ddacf617f1 feat(semantic): add context notes for strict assignments (#24728)
## Summary

Adds context notes to `Cannot assign to '{x0}' in strict mode` diagnostics, explaining whether strict mode comes from an explicit directive, class body, or module.
2026-07-20 17:17:30 +00:00
camc314 76ec104498 fix(semantic): resolve import-equals namespaces (#22696)
Fixes `import =` semantic reference resolution so internal module references are resolved as namespace lookups instead of ordinary value reads.

TypeScript treats the RHS of an internal `import =` specially. In the checker, `getTargetOfImportEqualsDeclaration` delegates internal module references to `getSymbolOfPartOfRightHandSideOfImportEquals`, which resolves bare RHS names and intermediate qualified names with `SymbolFlags.Namespace` rather than value meaning:

- `getTargetOfImportEqualsDeclaration`: https://github.com/microsoft/TypeScript/blob/f350b52331494b68c90ab02e2b6d0828d2a22a74/src/compiler/checker.ts#L3708-L3733
- `getSymbolOfPartOfRightHandSideOfImportEquals`: https://github.com/microsoft/TypeScript/blob/f350b52331494b68c90ab02e2b6d0828d2a22a74/src/compiler/checker.ts#L4480-L4499
- `getSymbolOfNameOrPropertyAccessExpression` also routes names on the RHS of import/export assignments through that same helper: https://github.com/microsoft/TypeScript/blob/f350b52331494b68c90ab02e2b6d0828d2a22a74/src/compiler/checker.ts#L50014-L50019

Before this change, Oxc could count plain values as references from `import =`:

```ts
const x = 1;
import foo = x;
```

Before:

```text
x references: 1
```

After:

```text
x references: 0
```

That matches TypeScript’s behavior because `x` is only a value symbol, not a namespace-capable symbol.

The same applies to qualified names:

```ts
const x = { y: 1 };
import foo = x.y;
```

Before:

```text
x references: 1
```

After:

```text
x references: 0
```

But namespace-capable declarations still resolve:

```ts
namespace x {}
import foo = x;
```

After:

```text
x references: 1
```

and:

```ts
namespace x {
  export namespace y {}
}

import foo = x.y;
```

After:

```text
x references: 1
```

This updates the semantic snapshots to reflect the corrected reference/declaration matching.
2026-07-20 13:10:54 +00:00
camc314 cc3d17f063 feat(semantic): add context notes for reserved keyword diagnostic (#24715)
## Summary

Reserved-keyword diagnostics now explain the language context that makes an identifier invalid, rather than only reporting that the keyword is reserved.

## Details

- Add context-aware notes for strict mode, classes, and modules.
- Add a dedicated note for `await` in module code.
- Update parser-conformance snapshots for the expanded diagnostics.

Before:

```text
× The keyword 'package' is reserved
```

After, for strict-mode code:

```text
× The keyword 'package' is reserved
note: This identifier is reserved in strict mode code
```

After, for class code:

```js
class Example {
  method() {
    const static = 1;
  }
}
```

```text
× The keyword 'static' is reserved
note: Classes are always strict mode code
```

After, for module code:

```js
export const await = 1;
```

```text
× The keyword 'await' is reserved
note: The identifier `await` is reserved in module code
2026-07-20 10:59:00 +00:00
camc314 48b59f450d fix(parser): span ambient generator diagnostics (#24711)
## Summary

Make TS1221 underline the generator declaration consistently from the `*` token.

## Why

The previous diagnostic used the generic function span, but that span has different start points depending on how the function is parsed:

- A class method enters function parsing after its name, so `declare class C { *generator(): any; }` highlighted only `(): any;` (starting at column 15), omitting both the generator marker and its name.
- A function declaration starts its span at the `function` keyword, so `declare namespace M { function *generator(): any; }` highlighted the whole declaration (starting at column 5), including text that is not the invalid generator construct.

For example, the prior output treated these equivalent generator markers differently:

```ts
declare class C {
    *generator(): any;
//            ^^^^^^^^
}

declare namespace M {
    function *generator(): any;
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
```

The parser now carries the `*` token location as `Option<u32>` while parsing a function. TS1221 uses that location through the declaration end, so both cases consistently highlight the relevant generator declaration:

```ts
*generator(): any;
^^^^^^^^^^^^^^^^^^
```

The AST continues to store `generator` as a boolean; the location exists only while parsing diagnostics.
2026-07-20 09:44:55 +00:00
sapphi-red 4c71560a72 feat(parser): more friendly error for spread element in dynamic imports (#24705)
This PR makes parse error message for spread element in dynamic imports more friendly.

**Before**
```
  × Unexpected token
   ╭─[babel/packages/babel-parser/test/fixtures/es2020/dynamic-import/invalid-arguments-spread/input.js:1:8]
 1 │ import(...[1])
   ·        ───
   ╰────
```
**After**
```
  × TS(1325): Argument of dynamic import cannot be a spread element.
   ╭─[babel/packages/babel-parser/test/fixtures/es2020/dynamic-import/invalid-arguments-spread/input.js:1:8]
 1 │ import(...[1])
   ·        ───
   ╰────
```
2026-07-20 08:23:46 +00:00
camc314 b14d52e647 refactor(parser): move require after optional param check to parser (#24600)
## Summary
- report TS1016 while parsing formal parameter lists
- preserve initialized-parameter and rest-parameter behavior
- remove the equivalent semantic check and diagnostic
- update parser and semantic coverage snapshots

Follows #24596, which has now merged.
2026-07-16 15:50:50 +00:00
camc314 7cd106daab refactor(parser): move abstract constructor check to the parser (#24595)
## Summary
- report TS1242 for abstract constructors in the parser
- remove the equivalent semantic diagnostic
- update TypeScript parser coverage snapshots

## Why?

This check needs to be moved to the parser, as the data is not retained after we change the Constructor ast type.
2026-07-16 14:35:42 +00:00
camc314 129b759131 feat(parser): improve diagnostics for unparenthesized LHS on exponential expr (#24569)
## Summary

- Report operator-specific diagnostics when unary and `await` expressions are used as exponentiation left operands.
- Reject unparenthesized TypeScript type assertions in the same position while preserving explicitly parenthesized forms.
- Add regression fixtures and update the affected conformance snapshots.
2026-07-15 18:38:30 +00:00
camc314 7b4baff16c fix(parser): reject new import member access (#23459)
Reject `new import(...).prop`, `new import.source(...).prop`, and `new import.defer(...).prop` by treating member access on an unparenthesized import expression as invalid after `new`.

Fixes #23458
2026-07-15 10:38:34 +00:00