Commit Graph

101 Commits

Author SHA1 Message Date
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
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
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
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 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 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 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
camc314 c517aa08a8 fix(parser): reject invalid accessor assertions (#24504)
## Summary

- Align auto-accessor definite assignment assertions with TypeScript.
- Report TS1263 when an accessor has both `!` and an initializer.
- Report TS1264 when an accessor has `!` but no type annotation.
- Report TS1255 for typed definite assertions in static, abstract, and ambient contexts.
- Highlight only the `!` token, matching TypeScript.

fixes #24503.

## TypeScript behavior

Given:

```ts
class A {
    accessor missingType!;
    // ^: TS1264: Declarations with definite assignment assertions must also have type annotations.
    accessor initialized! = 1;
    // ^: TS1263: Declarations with initializers cannot also have definite assignment assertions.
    accessor typed!: number;
    // ^: valid
    static accessor staticTyped!: number;
    // ^: TS1255: A definite assignment assertion '!' is not permitted in this context.
}
```

TypeScript treats auto-accessors as property declarations and applies the following grammar check:

https://github.com/microsoft/TypeScript/blob/637d5746b70257028fb95aad32ddec6b26ab0a14/src/compiler/checker.ts#L53443-L53452

This establishes the diagnostic precedence:

1. An initializer produces TS1263.
2. Otherwise, a missing type annotation produces TS1264.
3. Otherwise, an invalid context produces TS1255.
2026-07-14 10:16:51 +00:00
sapphi-red 38c4b0628b feat(parser): add friendly error for adjacent JSX elements (#23378)
Add a friendly error for adjancent JSX element case:

```
  × Adjacent JSX elements must be wrapped in an enclosing tag.
   ╭─[misc/fail/jsx-adjacent-elements.jsx:3:3]
 2 │   <div />
 3 │   <span />
   ·   ─
 4 │ );
   ╰────
  help: Did you want a JSX fragment `<>...</>`?
```

This error message exists in babel.
2026-06-16 14:50:53 +00:00
camc314 1d3af58c4a feat(parser): add TS2398 parameter property diagnostic (#23216)
## Summary

- Report TS2398 when a TypeScript constructor parameter property is named `constructor`.
- Add coverage for the upstream TypeScript fixture plus dedicated misc pass/fail cases for ordinary `constructor` parameters versus invalid parameter properties.

```
  × TS(2398): 'constructor' cannot be used as a parameter property name.
   ╭─[misc/fail/oxc-ts-2398.ts:2:31]
 1 │ class A {constructor(public constructor){}}
 2 │ class B {constructor(readonly constructor){}}
   ·                               ───────────
   ╰────
```
2026-06-11 08:39:25 +00:00
camc314 8edd23459d fix(parser): report accessor definite assertion on token (#23203)
## Summary
- Pass the definite-assignment assertion token offset through the class accessor-property parser path.
- Report invalid ambient and abstract `accessor prop!` diagnostics on the `!` token, matching the span behavior used by variable declarators and normal class properties.
- Add focused misc parser coverage for the accessor-specific invalid cases.

## Rationale
This follows up #23170. That parser change already narrowed definite-assignment diagnostics for variables and normal class properties, but accessor properties still kept only a boolean. That meant `accessor prop!` could only report TS1255 using the full class element span. Carrying the offset into `parse_class_accessor_property` aligns accessor diagnostics with the other definite-assignment diagnostics and keeps the AST shape unchanged by storing only `definite.is_some()`.

The misc fixture is needed because upstream TypeScript coverage exercises invalid definite assertions on normal fields, but not invalid accessor properties. Existing misc coverage only had a valid `accessor y!` pass case, so `just coverage` did not specifically protect the accessor diagnostic span this fixes.
2026-06-10 07:46:45 +00:00
Boshen cf53285466 fix(parser): report reserved type-declaration names in the parser (#23035)
## What

Moves the reserved built-in type name check (a type's name may not be `any`, `string`, `number`, …) out of the semantic checker into the parser, via a reusable `check_reserved_type_name` helper. Covers **all** declaration forms:

- class → TS2414
- interface → TS2427
- type alias → TS2457
- enum → TS2431
- type parameter → TS2368

The semantic `check_type_name_is_reserved` helper and its diagnostic are removed.

## Why it moves cleanly

- **Zero state:** each is a name-vs-reserved-list match at the parse site where the identifier is parsed.
- **Node-final:** these declarations are never reinterpreted by cover grammar.
- **Negative-only:** confirmed by `cargo coverage` — no positive/negative count changes; only the errors relocating in `parser_typescript.snap`.

## Class needs an `is_ts` guard + a fixture fix

`class string {}` is valid JavaScript (these names are reserved only as *type* names), so the class check is guarded by `is_ts`. The interface/type-alias/enum/type-parameter forms are TypeScript-only parser paths, so they need no guard.

The `no-shadow-restricted-names` rule had `class undefined {}` / `(class undefined {})` fixtures. Since the lint test harness parses fixtures as TSX, those are now parse errors (TS2414). They're dropped — class-name shadowing is still covered by `class globalThis {}` (globalThis isn't a reserved type name), and `undefined` shadowing by the `var`/`import` fixtures.

## Verification

- `class number {}`, `interface any {}`, `type any = number`, `enum string {}`, `function f<any>() {}` → error; `class string {}` in `.js` → clean; valid names → clean.
- Parser/semantic/linter (1155) tests pass; clippy clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-06-07 02:05:14 +00:00
Boshen 17e7cf3ce4 fix(parser): disallow unerasable as/satisfies assertions (#22986)
Port of [microsoft/typescript-go#4192](https://github.com/microsoft/typescript-go/pull/4192), which fixes [microsoft/TypeScript#63527](https://github.com/microsoft/TypeScript/issues/63527).

## Problem

`as`/`satisfies` are supposed to be erasable without changing runtime semantics. But for an expression of the form `a ## b as T $$ c`, where `##` has *lower* precedence than `$$`, erasing the assertion silently changes the parse:

```ts
const x = 1 + 1 as number * 2;
```

This parses as `((1 + 1) as number) * 2` (= `4`), but textually erasing `as number` yields `1 + 1 * 2` (= `3`). TypeScript now rejects such constructs as a syntax error, forcing explicit parentheses.

## Change

In `parse_binary_expression_rest`, after parsing an `as`/`satisfies` type, stop parsing if the following operator binds tighter than the operator that produced the running left-hand operand. This leaves the higher-precedence operator dangling and surfaces as a parse error.

A chained `a as T as U` keeps referring back to the original operator's precedence (the tracked precedence is intentionally not updated while consuming `as`/`satisfies`), so `1 + 1 as any as number * 2` is rejected too.

## Behavior

| Expression | Result |
| --- | --- |
| `1 as number * 2` | ok |
| `1 * 1 as number + 2` | ok (`+` does not bind tighter than `*`) |
| `1 + 1 as number * 2` | **error** |
| `1 + 1 as any as number * 2` | **error** |
| `1 >> 1 as number + 2` | **error** |
| `(1 + 1 as number) * 2` | ok |

`satisfies` behaves identically to `as`.

## Tests

Added `misc` coverage fixtures mirroring the upstream test matrix: `pass/ts-erasable-as-satisfies.ts` for the erasable cases and `fail/ts-unerasable-{as,as-chained,satisfies}.ts` for the rejected ones. Full conformance (test262 / babel / typescript) shows zero regressions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-06-05 13:10:42 +00:00
Boshen beb46d31fa fix(parser): commit to module goal on decorated exports (#22941)
## Summary

In unambiguous (`.js`) sources, `@foo export default class C { x = await + 1 }` reported a spurious `A module cannot have multiple default exports`.

A leading decorator makes the statement start with `@`, not `export`, so the eager Module-goal switch from #22684 didn't fire. The `await` identifier in the field initializer then triggered the unambiguous-mode top-level-await reparse, which re-ran `parse_statement_list_item` and recorded the `export default` a second time.

## Fix

- Commit to the Module goal in `parse_export_declaration` — the single place both leading and decorated exports flow through — so the export body parses under `Await` on the first pass, matching a non-decorated leading `export` (`ExportDeclaration` is unambiguously a `ModuleItem`, ECMA-262 §16.2.3).
- Skip the reparse for module declarations (`!stmt.is_module_declaration()`): an `export` / `import` is recorded on the first pass and is goal-independent, so reparsing only double-records it.

This also simplifies `parse_directives_and_statements`: the mutable `track_await_reparse` flag and the inline eager-commit block are removed; committing is now driven by `!ctx.has_await()`.

`await` stays correctly reserved in the module, so the input is still a syntax error (`The keyword 'await' is reserved`) — just no longer a *spurious* duplicate-export one. `tasks/coverage/misc/fail/oxc-22684.js` covers this.

Conformance: zero snapshot drift outside the new `misc` fixture.

Follow-up to #22684.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-06-04 04:05:46 +00:00
sapphi-red 661132d5ac feat(parser): more friendly error messages for rest assignment target and rest binding element (#22719)
Made the errors for `({...[]} = {});` and `const {...[]} = obj;` a bit more easier to understand:

```
  × Invalid rest element target in destructuring assignment
   ╭─[misc/fail/rest-assignment-target.js:1:6]
 1 │ ({...[]} = {});
   ·      ──
   ╰────
  help: Expected an identifier or member expression, like `...rest` or `...obj.prop`.
```

```
  × Invalid rest element target in destructuring pattern
   ╭─[misc/fail/rest-binding-element.js:1:11]
 1 │ const {...[]} = obj;
   ·           ──
   ╰────
  help: Expected an identifier, like `...rest`.
```
2026-05-25 12:47:34 +00:00
camc314 e184f74d11 fix(parser): improve invalid import property access diagnostic (#22693)
This improves the parser diagnostic for invalid `import.<property>` access.

Previously, invalid properties like `import.sync("baz")` were reported as if only `import.meta` were valid, which is misleading now that `import.source()` and `import.defer()` are also supported.

Before:

```text
  × The only valid meta property for import is import.meta
    ╭─[index.ts]
 37 │
 38 │ import.foo();
      ──────────
 39 │
    ╰────
```

After:

```text
  × The only valid property accesses on import are `import.meta`, `import.source()`, and `import.defer()`
    ╭─[index.ts]
 37 │
 38 │ import.foo();
      ──────────
 39 │
    ╰────
```

Also adds a coverage fixture for the `import.sync("baz")` case and updates the parser coverage snapshots.
2026-05-25 09:58:50 +00:00
Boshen e431a0eb52 fix(parser): break extends clause loop on fatal error (#22517)
## Summary

`parse_extends_clause` kept iterating after `parse_lhs_expression_or_higher` set a fatal error, producing a `TSInterfaceHeritage` with an inverted span (`start > end`). `parse_class` then passed that span to `classes_can_only_extend_single_class`, which panicked in `miette` when converting the span to a label (`debug_assert!(self.start <= self.end)` in `Span::size`). Release builds silently produced garbage diagnostics.

Repro from the issue:

```js
class extends,{
```

Closes #22515

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-05-18 05:50:19 +00:00
camc314 ffacf99cc1 fix(semantic): report error on await inside block inside static block (#20750) 2026-03-26 14:17:31 +00:00
camc314 ccf9301b93 fix(semantic): report error on for-await inside block inside static block (#20749) 2026-03-26 14:00:25 +00:00
Boshen c205b0df51 fix(ast): remove ThisExpression from TSModuleReference (#18489)
## Summary

- Removes `ThisExpression` variant from `TSModuleReference` since `import x = this` is invalid TypeScript (error TS1359)
- Adds parser error when `this` is used in import equals declaration
- Updates codegen, transformer, and linter rules to handle the new enum structure

Closes #16841

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-01-24 15:25:10 +00:00
Boshen aed3669a02 fix(parser): parse HTML-like comments in unambiguous mode (#18442)
## Summary

Closes #18392

Support HTML-like comments (`<!--` and `-->`) per ECMAScript Annex B.1.1:

- **Script/CommonJS mode**: HTML comments recognized as single-line comments
- **Unambiguous mode (.js)**: HTML comments recognized; error deferred until ESM syntax detected
- **Module mode (.mjs)**: HTML comments at start of line emit "HTML comments are not allowed in modules" error; `<!--` in middle of expression (e.g. `foo <!--bar`) parses as operators

This enables proper detection of HTML comment injection vectors in security tools like [AikidoSec/zen-internals](https://github.com/AikidoSec/zen-internals/pull/125).

🤖 Generated with [Claude Code](https://claude.ai/code)
2026-01-23 11:35:33 +00:00
overlookmotel 22b4d39bd5 test(semantic): add test cases for function redeclaration check (#18288)
Follow-on after #18231. Add test cases to make sure function redeclaration check works correctly in script, module, and CommonJS files.
2026-01-20 14:09:09 +00:00
Boshen 92e27b4e01 feat(parser): reparse await expressions in unambiguous mode when ESM detected (#18139)
## Summary

- Implements TypeScript-compatible await expression reparsing for unambiguous mode
- When `sourceType` is `unambiguous`, `await / 0 /u; export {}` now correctly parses as `await /0/u` (await expression with regex)
- Follows TypeScript's two-pass approach: initially parse `await` as identifier, then reparse with await context if ESM is detected

## Test plan

- Added `tasks/coverage/misc/pass/unambiguous-await-regex.js` test case
- Moved `tasks/coverage/misc/fail/babel-16776-s.js` to pass (now parses as division in script mode)
- All parser tests pass
- Conformance tests show improvements in parser_babel and semantic_babel

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-01-17 15:27:42 +00:00
Boshen 66b8c022ab feat(parser): implement unambiguous module parsing for JS/TS files (#18124)
## Summary

- Implements speculative/unambiguous parsing for `.js`, `.jsx`, `.ts`, and `.tsx` files
- Instead of assuming module or script upfront, parses with `ModuleKind::Unambiguous` and upgrades to module mode when ESM syntax is detected
- ESM indicators: `import`, `export`, `import.meta` (NOT top-level await alone)
- Defers top-level await errors until module type is resolved
- Vue loader upgrades unambiguous scripts to module mode
- Updates linter tests to use explicit ESM extensions (`.mjs`/`.mts`) where needed

## Test plan

- [x] All parser tests pass
- [x] All linter tests pass
- [x] All semantic tests pass
- [x] Coverage conformance tests updated

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-01-17 13:40:28 +00:00
Boshen fb181ccdff fix(semantic): error on using at top level in scripts (#18090)
## Summary

- Add check to error on `using` declarations at the top level of scripts
- `using` declarations require block scope semantics and are not allowed
at the top level of scripts

`using` declarations are allowed:
- At the top level of ES modules
- At the top level of CommonJS modules (files are wrapped in a function)
- Inside any block scope in scripts

But NOT at the top level of scripts.

Closes #11862

## Test plan

- [x] Added test case
`tasks/coverage/misc/fail/script-top-level-using.js` for invalid usage
- [x] Added test case
`tasks/coverage/misc/pass/script-using-in-block.js` for valid usage in
block
- [x] All existing tests pass

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

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 12:18:26 +08:00
Boshen 08dad63678 feat(span): add sourceType: 'commonjs' support (#18089)
## Summary

- Add `ModuleKind::CommonJS` variant to support CommonJS module type in the parser
- Enable top-level `return` statements (CommonJS files are wrapped in a function)
- Enable top-level `new.target` (allowed in CommonJS function wrapper)
- Add proper errors for `import`/`export` statements in CommonJS
- Add proper errors for `import.meta` in CommonJS

The CommonJS source type can be set via:
- `SourceType::with_commonjs(true)` method
- Babel's `sourceType: "commonjs"` option

Closes #16200

## Test plan

- [x] Added test cases in `tasks/coverage/misc/pass/` for valid CommonJS features
- [x] Added test cases in `tasks/coverage/misc/fail/` for invalid CommonJS usage
- [x] Enabled Babel conformance tests for `sourceType: "commonjs"`
- [x] All existing tests pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-01-16 16:08:27 +00:00
Copilot 59a6228ef9 fix(parser): detect TS1363 error for type-only imports with mixed default and named/namespace bindings (#17712)
The parser was not detecting `import type foo, {} from 'bar';` and `import type A, * as NS from 'mod';` as errors. TypeScript's TS1363 requires that type-only imports specify either a default import or named/namespace bindings, but not both—even when the named bindings list is empty.

## Changes

- **Parser**: Added TS1363 check in `parse_import_declaration_specifiers` when encountering `LCurly` or
`Star` token after a type-only default import
- **Module record**: Removed redundant TS1363 validation that couldn't detect empty `{}` cases
- **Error span**: Now points at the default specifier instead of the entire import statement

## Examples

The following patterns now correctly error with TS1363:

```typescript
// Empty named bindings
import type foo, {} from 'bar';

// Named bindings with specifiers
import type foo, { bar } from 'baz';

// Namespace import
import type A, * as NS from 'mod';
```

The parser-level check is comprehensive and catches all cases including
empty braces and namespace imports, which weren't being detected
previously.


- Fixes oxc-project/oxc#17684

---------

Signed-off-by: Cameron <cameron.clark@hey.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: camc314 <18101008+camc314@users.noreply.github.com>
Co-authored-by: Cameron <cameron.clark@hey.com>
2026-01-06 14:45:14 +00:00
camc314 d99134d70c feat(parser): improve diagnostic message for phase imports (#17092)
We now produce the same error codes as typescript
2025-12-21 08:14:16 +00:00
sapphi-red cb515fac28 feat(parser): improve error message for yield as identifier usage (#16950)
Improved error message for `yield` as identifier usage.

**Before**
```
  × Cannot use `yield` as an identifier in a generator context
    ╭─[test262/test/language/expressions/generators/yield-weak-binding.js:17:33]
 16 │
 17 │ var g = function*() { yield 3 + yield 4; };
    ·                                 ─────
    ╰────
```
**After**
```
  × Cannot use `yield` as an identifier in a generator context
    ╭─[test262/test/language/expressions/generators/yield-weak-binding.js:17:33]
 16 │
 17 │ var g = function*() { yield 3 + yield 4; };
    ·                                 ─────
    ╰────
  help: Wrap this in parentheses if you want to use a `yield` expression here
```
2025-12-16 11:30:44 +00:00
overlookmotel 75f9800166 test(parser): combine test cases for let as identifier (#16861)
Follow-on after #16840 and #16857. We had a few test cases relating to the same thing, and one of them called the undescriptive `oxc.js`. Combine them, and rename the test case files with a more accurate name.
2025-12-14 21:30:55 +00:00
Copilot d3208dc969 fix(parser): parse let?.x (#16840)
Fixes #16839.

Make parser parse `let?.x` successfully.

There's a failure in codegen idempotency tests, but that's an unrelated
and pre-existing bug, so am leaving that to another PR.

Co-authored-by: overlookmotel <theoverlookmotel@gmail.com>
2025-12-14 19:26:57 +00:00
sapphi-red da87812ac7 feat(semantic): add TS2309 error for export assignment with other exports (#15992)
Added TS2309 error check.
2025-12-06 08:30:06 +00:00
copilot-swe-agent 74cf5720bc feat(ast)!: Make source field of TSImportType a StringLiteral (#16114)
- [x] Change `source` field type in `TSImportType` from `TSType<'a>` to `StringLiteral<'a>` in `crates/oxc_ast/src/ast/ts.rs`
- [x] Remove `#[estree(via = TSImportTypeSource)]` attribute from the field
- [x] Run `just ast` to regenerate all derived code
- [x] Update the parser in `crates/oxc_parser/src/ts/types.rs` to parse a `StringLiteral` directly and emit errors for non-string literals
- [x] Delete the dead code `TSImportTypeSource` serializer from `crates/oxc_ast/src/serialize/ts.rs`
- [x] Add `ts_string_literal_expected` diagnostic (TS1141)
- [x] Update semantic snapshot for `import-type-with-type-params.snap`
- [x] Add test case for invalid import type source
- [x] Verify all tests pass
- [x] Simplify error recovery - just report error and create dummy string literal (per review feedback)
- [x] Fix spurious "Expected ')'" error by skipping invalid tokens in error recovery

<!-- START COPILOT CODING AGENT SUFFIX -->

<details>

<summary>Original prompt</summary>

>
> ----
>
> *This section details on the original issue you should resolve*
>
> <issue_title>AST: Make `source` field of `TSImportType` a `StringLiteral`</issue_title>
> <issue_description>Continuation of oxc-project/oxc#16074.
>
> The expression inside `import(...)` in TS context (`TSImportType`) cannot legally be anything other than a string literal.
>
> Our parser is too liberal. We currently accept all kind of crazy stuff like:
>
> ```ts
> type A = typeof import(`react`);
> type B = typeof import(A);
> type C = typeof import(`${A} ${B}`);
> type D = typeof import(typeof import('react'));
> ```
>
> [Playground](https://playground.oxc.rs/#eNptU9tOGzEQ/ZXIQqJIqUSRKqFUfQjQSJVooaUqL31g1jsbDF7bHc/molX+nfEmdkDhyfaZ+5njXmk1UbwOOJqOvo7SxTcj0wZP/OGBEDQ/nHz55waPiwOPabFdHkYf9dPN6Ki/2OwzXB14vX0dDxWPT1KAGiuvJr2izqXDGsdq0oCNOFaNpxaYkQrCBC4muCAmeguM9RVqCwRsvIvFuHw0jDGAxgK14OZ2/9S+DYRxHxK1D2Jm6tJj3Vbe5pdu5ju3zVgFoJga6xWuGF2UuoniKPOAtX75G7kjd9NxNDXOOqdTZzlTKom0wFsgCc3oEPf3/LtjMpJQF0NE6ZqN/kbkaYdKC4mroQW5v6KqV13EP1DtZ2Ko7k3Nj2pyNlbo6pvm2jgZUtlG2g1SjXf281OpZhJDvzrPe5qe4uruHfh/et2SD1JLQfzoEGusJafsyUh780vftpBs1goqc5gyrMyyzPOLfQnrxF1FoJ+R72RnEp6dMwotbjvf1ffVE2q+JwiSI5OaCg29TlmIrDrpEOlNGK4CkmnRMdgbuQJ7uvXRbFeUGFJCadHallQGmqNoU2E8O/30WaoIzVfYSOKZp0sLMc4M2rps7XUVUacfyuytreGC/kCGGliY2q32fVX3KspEQQSC5EB0mcWofY1zHD6QS0Iokn2KtZevv6PcOc9DroxYnGffIUv+C0lR+aPI5D5c4wJL0mfE8FNWkQU2hIpovZ2JgFPEAqnyMROe5nFpUclUbhuB64G+BJfbJuGJZoisNi/WFa5W)
>
> TypeScript says these are all errors: [TS Playground](https://www.typescriptlang.org/play/?#code/C4TwDgpgBAglC8VSQPYDMoEsC2YUCdgAKAA3wgEMBjYEgSgG4AoZaAIQSXAnS1wOIxGLblADCnVrxx5CpACQBvGAF8oStivrNWUACKTu0-nKkYZAogHJy1YFbrCgA)
>
> ### AST change
>
> We should alter the type of the `source` field from `TSType<'a>` to `StringLiteral<'a>`:
>
> https://github.com/oxc-project/oxc/blob/35d0ee491cbcd271ebceaac7e25cff0490ded5c4/crates/oxc_ast/src/ast/ts.rs#L1382-L1389
>
> ```diff
> pub struct TSImportType<'a> {
>     pub span: Span,
> -   #[estree(via = TSImportTypeSource)]
> -   pub source: TSType<'a>,
> +   pub source: StringLiteral<'a>,
>     pub options: Option<Box<'a, ObjectExpression<'a>>>,
>     pub qualifier: Option<TSImportTypeQualifier<'a>>,
>     pub type_arguments: Option<Box<'a, TSTypeParameterInstantiation<'a>>>,
> }
> ```
>
> ### Parser changes
>
> If we change the AST first and run `just ast` to regenerate traits code, then all the places which rely on the type of `source` field will become apparent. We'll then need to alter the parser to throw an error if it encounters something that isn't a string literal.
>
> ### `ESTree` serialization
>
> Currently there's a custom deserializer to alter the AST on JS side from `TSType` to `StringLiteral`:
>
> https://github.com/oxc-project/oxc/blob/91eb3f2be509cef11cffeff51fac61a3a4fbd12c/crates/oxc_ast/src/serialize/ts.rs#L506-L538
>
> Once we've changed the field type in AST, this code can be deleted - it's dead code once `#[estree(via = TSImportTypeSource)]` attribute is removed from the `source` field in AST struct.</issue_description>
>
> ## Comments on the Issue (you are @copilot in this section)
>
> <comments>
> </comments>
>

</details>

- Fixes oxc-project/oxc#16111

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey).
2025-11-25 18:51:16 +00:00
camc314 1199cee3ae fix(parser): reject invalid modifiers on parameter properties with binding patterns (#16083)
Fixes #16077
2025-11-25 09:43:09 +00:00
sapphi-red d60ca818e7 fix(parser): reject import something 'source' (#15746)
```js
import something 'source'
```
was not rejected but this should be rejected.
https://tc39.es/ecma262/2025/multipage/ecmascript-language-scripts-and-modules.html#prod-ImportDeclaration
2025-11-17 02:58:51 +00:00
sapphi-red 9f54a36de3 fix(semantic): error on \00 in strict mode (#15743)
`\00` matches LegacyOctalEscapeSequence and should be an error in strict mode.
https://tc39.es/ecma262/2025/multipage/ecmascript-language-lexical-grammar.html#sec-string-literals-early-errors
2025-11-16 09:25:13 +00:00
sapphi-red 77efb7698d feat(parser): improve error message for invalid switch clauses (#15728)
Improved error message for invalid switch clauses.

**Before**
```
  x Unexpected token
   ,-[:2:3]
 1 | switch (foo) {
 2 |   caze 1:
   :   ^^^^
 3 | }
   `----
```

**After**
```
  × Expected switch clause
   ╭─[misc/fail/switch-invalid-clause.js:2:3]
 1 │ switch (foo) {
 2 │   caze 1:
   ·   ──┬─
   ·     ╰── `case` or `default` clause expected here
 3 │ }
   ╰────
  help: If this is intended to be the condition for the switch statement, add `case` before it.
```
2025-11-16 02:57:35 +00:00
sapphi-red 56917278ca feat(parser): improve import source from error message (#15727)
Improved error message for `import source` + something + `from`.

**Before**
```
  x Unexpected token
   ,-[:1:19]
 1 | import source foo bar from 'module';
   :                   ^^^
   `----
```

**After**
```
  × Expected `from` but found `Identifier`
   ╭─[misc/fail/import-source-non-from.js:1:19]
 1 │ import source foo bar from 'module';
   ·                   ─┬─
   ·                    ╰── `from` expected
   ╰────
```
2025-11-16 02:57:35 +00:00
sapphi-red 71c2fb05bc feat(parser): improve error message when JSX is found while not enabled (#15725)
Improved the error message when JSX syntax is found while not enabled.

The idea came from esbuild's error message ([esbuild try](https://esbuild.github.io/try/#dAAwLjI3LjAAAGV4cG9ydCBjb25zdCBmb28gPSA8Rm9vIC8+Ow)).

**Before**
```
  x Unexpected token
   ,-[:1:20]
 1 | export const foo = <Foo />;
   :                    ^
   `----
```

**After**
```
  × Unexpected JSX expression
   ╭─[misc/fail/jsx-in-js.js:1:20]
 1 │ export const foo = <Foo />;
   ·                    ───────
   ╰────
  help: JSX syntax is disabled and should be enabled via the parser options
```
2025-11-16 02:57:34 +00:00
camc314 8951953008 feat(parser): improve diagnostic messages for merge conflicts (#15443)
Adds detection and improved error messages for version control merge conflicts encountered in the parser.

This is based upon rustc's implementation.
2025-11-08 06:53:50 +00:00
sapphi-red d4f6545078 feat(parser): improve error message for missing closing tokens (#15269)
Improves error message for imbalanced tokens.
```
 × Expected `,` or `]` but found `const`
   ╭─[misc/fail/imbalanced-array-expr.js:2:1]
 1 │ const foo = [0, 1
   ·             ┬
   ·             ╰── Opened here
 2 │ const bar = 2
   · ──┬──
   ·   ╰── `,` or `]` expected
   ╰────
```

The error message for this case was:
```
  x Expected `,` but found `const`
   ,-[:2:1]
 1 | const foo = [0,1
 2 | const bar = 2
   : ^^|^^
   :   `-- `,` expected
   `----
```

This change makes it clear why the parser is expecting `,` and also tell that it can be fixed by adding the closing token somewhere.
2025-11-04 13:13:00 +00:00
sapphi-red 2ef8f01624 feat(parser): improve error message for missing conditional alternative (#15268)
Improve error message for missing alternative for conditional expressions.
```
 × Expected `:` but found `EOF`
   ╭─[misc/fail/missing-conditional-alternative-type.ts:2:1]
 1 │ type A = 1 extends 2 ? 3
   ·                      ┬
   ·                      ╰── Conditional starts here
   ╰────

  × Expected `:` but found `EOF`
   ╭─[misc/fail/missing-conditional-alternative.js:2:1]
 1 │ const foo = 1 ? 2
   ·               ┬
   ·               ╰── Conditional starts here
   ╰────
```
Without this PR, the error mesage is a simple ``Expected `:` but found `EOF` `` only.
2025-11-04 13:12:59 +00:00
sapphi-red c28807b32c fix(parser): reject async await => {} in scripts (#15222)
`async await => {}` was rejected in modules but should be rejected in scripts as well.
2025-11-02 12:08:56 +00:00
camc314 384ea3c7be fix(parser): report err on missing function body in expression (#14946)
partially addresses #14944
2025-10-27 11:04:22 +00:00
Ulrich Stark 81a28d4bff fix(parser): forbid abstract class members with implementation in parser instead of semantic (#14325)
The following four cases are now errors in parser instead of semantic
errors.
[TS
Playground](https://www.typescriptlang.org/play/?#code/IYIwzgLgTsDGEAJYBthjAgYge2wg3gFAIKiQzwIAOU2VCAvAgMwDchxp40ciAtgFMIAC2wATABQBKAggC+HEmR6UA5kITqIEAVGkFOJKEICuUAHYIAjOxILOyiojAaX23RIBuwZCYEAuBHMTPhBdGSISEk4FOSA)
for reference.
Closes #14013 

```typescript
abstract class Foo {
  abstract prop = 3;

  abstract method() { }

  abstract get getter() {
    return 1;
  }

  abstract set setter(value: number) {
    
  }
}
```
2025-10-05 09:11:58 +08:00