Commit Graph

86 Commits

Author SHA1 Message Date
碳苯 Carbon bfb4c57a5d feat(parser): distinguish unapplied no-side-effects comments (#26120)
## Summary 

Fixes #26088

`NO_SIDE_EFFECTS` can either be applied to a function:

```rs
/* #__NO_SIDE_EFFECTS__ */ function foo() {}
```

Or be meaningless for its position, since it only works on function
declaration:
```rs
/* #__NO_SIDE_EFFECTS__ */ value;
```

But oxc could not distinguish these two cases. 

This PR adds `CommentContent::NoSideEffectsNotApplied`, mirroring the
existing `PureNotApplied`.

---------

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-09-03 11:14:24 +01:00
camc314 c002f29226 fix(codegen): escape sources for empty import specifiers (#25586)
## Summary
- Route empty named-import sources through the shared string-literal printer.
- Cover quote and newline escaping, including minified quote selection.

Given:
```ts
import {} from 'h"i'
```

Before it would be printed as:
```ts
import {} from "h"i" // missing escape of `"` or should be using `'` quotes
```

After:
```ts
import {} from 'h"i'
```
2026-08-13 11:26:56 +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 6ea3e0620c chore(deps): update Node.js to 26.5.0 (#24507)
## Summary

- update .node-version from 24.14.0 to 26.5.0
- verify v26.5.0 as the latest v26 release in the official Node.js distribution index (released 2026-07-08)
2026-07-14 14:05:31 +00:00
Boshen a4b1bf7337 fix(codegen): drop redundant whitespace in minified TypeScript output (#23038)
Removes redundant whitespace from minified output across many TypeScript constructs. Each change is minify-only: pretty-print output is byte-identical, all outputs round-trip, and a conservative `type_starts_with_non_identifier` helper only drops a space when the following token definitely begins with punctuation.

### Fixes

- **Decorators** — `@dec()class`, `export@dec class`, `accessor#x`
- **`as` / `satisfies`** — `foo()as X`, `` `s`as const ``, `as{a:1}`, `as(x)=>y`, `as[T]`
- **Non-null `!`** — `opts!.x`, `x!;`, `a!()`; the separator is kept only before `=`/`==`/`===` (which would retokenize as `!=`/`!==`), in both binary and assignment positions
- **`enum`** — `enum E{…}`
- **Conditional types** — `T extends[U]?X:Y`, `Foo<T>extends…`; the `? ?C` separator is preserved for a prefix JSDoc-nullable true branch
- **Heritage & constraints** — `class A<T>extends B<T>implements I`, `interface I<T=string>extends…`, `<T extends[a,b]>`
- **Type operators / constructors** — `readonly[…]`, `keyof[a,b]`, `readonly(keyof T)[]`, `new()=>T`, mapped-type `readonly[P in …]`, `export type*from`

### Verification

A whitespace analyzer over ~400 real-world `.ts` files went from **1410 → 4** removable spaces. The remaining 4 are a deliberate `i-->0` tie (handled elsewhere) and two higher-risk edge cases (`f<T>,` instantiation, mapped `in` before a template literal).

`oxc_codegen` and `oxc_minifier` suites pass, `just minsize` shows no drift, clippy is clean, and regression tests were added for each construct.
2026-06-07 02:42:28 +00:00
Boshen 325c94fefb fix(codegen): tighten conditional-type and constructor-type whitespace when minifying (#23033)
## What

Batches the remaining low-risk TS-minify whitespace patterns surfaced by the whitespace analyzer.

### Conditional types
`?`/`:` are now tight when minifying, like a JS conditional expression:

| Input | Before | After |
| --- | --- | --- |
| `A extends B ? C : D` | `A extends B ? C : D` | `A extends B?C:D` |

The leading `extends` space is emitted only when the check type ends in an identifier (so `T extends …` keeps it, `{} extends …` doesn't). The space *after* `extends` is kept to avoid merging a following type keyword (`keyof`, etc.).

### Constructor types
No space after `new` before `(`/`<`:

| Input | Before | After |
| --- | --- | --- |
| `new () => Foo` | `new () => Foo` | `new()=>Foo` |
| `abstract new (x: number) => Foo` | `abstract new (x: number) => Foo` | `abstract new(x:number)=>Foo` |

Pretty-print output is unchanged; `ts` minify snapshot updated. Verified round-trip.
2026-06-06 18:14:46 +00:00
Boshen 90180b8b37 fix(codegen): drop space after : in function return type when minifying (#23028)
## What

Found with the whitespace analyzer run over TypeScript sources. `Function` return-type annotations and `TSThisParameter` printed a hardcoded `": "`, so minified TS had a stray space — and inconsistent with methods/arrows which were already tight:

| Input | Before | After |
| --- | --- | --- |
| `function f(): Promise<void> {}` | `function f(): Promise<void>{}` | `function f():Promise<void>{}` |
| `function h(this: Foo): void {}` | `function h(this: Foo): void{}` | `function h(this:Foo):void{}` |
| `class C { m(): void {} }` | `m():void{}` (already tight) | `m():void{}` |

## Fix

Replace `print_str(": ")` with `print_colon()` + `print_soft_space()` (the soft space is dropped when minifying, kept when pretty-printing) — the same form methods, arrows, and parameter annotations already use. Pretty-print output is unchanged; the `ts` minify snapshot is updated.
2026-06-06 17:29:42 +00:00
Boshen 8b631bfeca fix(codegen): remove stray space before mapped type value colon (#23010)
## What

`TSMappedType` printed a `soft_space` immediately before the value colon, so the colon was spaced off from the key:

| Input | Before | After |
| --- | --- | --- |
| `{ [K in U]: V }` | `{ [K in U] : V }` | `{ [K in U]: V }` |
| `{ [K in U]?: V }` | `{ [K in U]? : V }` | `{ [K in U]?: V }` |
| `{ -readonly [K in U]-?: V }` | `{ -readonly [K in U]-? : V }` | `{ -readonly [K in U]-?: V }` |

Every other member colon (object types, interfaces) is printed as `key: value`; mapped types now match. Minified output was already correct (`[K in U]?:V`).

The stray `print_soft_space()` before `print_colon()` is removed.
2026-06-06 11:23:46 +00:00
Boshen 786d96f210 fix(codegen): give TSTypeAssertion unary precedence (#23002)
## What

A TS angle-bracket assertion `<T>x` is a unary expression (ECMA/TS grammar: `< Type > UnaryExpression`), but `TSTypeAssertion::precedence()` returned `Precedence::Lowest`. The wrap condition `precedence >= self.precedence()` is therefore always true, so the assertion was parenthesized in **every** position.

It now reports `Precedence::Prefix` like other unary expressions, and joins the `**`-base special case (a unary expression can't be a `**` base, so it must stay wrapped there).

## Examples

| Input | Before | After |
| --- | --- | --- |
| `y = <T>x` | `y = (<T>x)` | `y = <T>x` |
| `foo(<T>x)` | `foo((<T>x))` | `foo(<T>x)` |
| `z = <T>x + 1` | `z = (<T>x) + 1` | `z = <T>x + 1` |
| `c = -<T>x` | `c = -(<T>x)` | `c = -<T>x` |

Positions that genuinely require parentheses still keep them, because they print the assertion at a higher precedence than `Prefix`:

| Input | Output |
| --- | --- |
| `(<T>x).foo` | `(<T>x).foo` |
| `(<T>x)()` | `(<T>x)()` |
| `(<T>x) ** 2` | `(<T>x) ** 2` |
2026-06-06 07:44:12 +00:00
Dunqing 7914807b7b fix(codegen): map call-chain punctuation for correct V8 stack columns (#22789)
## Summary

- `oxc_codegen` produced off-by-one V8 stack-trace and coverage columns for call-chain shapes. When a `(`/`.`/`[` is chained directly onto a call — or any expression ending in `)`/`]` — that punctuation was left unmapped, so the lookup fell back to the closing delimiter one column to the left. Surfaced as vitest failures in vite-ecosystem-ci: `test.each([1, 2])(…)` reporting column 17 instead of 18, and `await expect(…).resolves.toBe(4)` reporting 40 instead of 41.
- Root cause: such operands end in `)` or `]`, so there is no trailing identifier token for a source-map consumer to anchor on. The fix maps that punctuation from `print_expr` — keyed on postfix precedence — back to the operand's exclusive end, exactly where V8 reports the frame. This is the trailing end-mapping that Babel and TSC apply to every node, scoped here to just the no-anchor sites. The closing `)`/`}`/`]` keep their existing at-delimiter mapping, which `v8-to-istanbul` relies on for coverage range boundaries (#22001).
- Only these no-anchor chain sites are mapped — not the byte past every delimiter — so the added source-map tokens stay at **+0.6%** over baseline. (A blanket variant that mapped every delimiter regressed codegen ~5% on CodSpeed.)
- Verified end-to-end through `node --enable-source-maps`: each chained frame resolves to the correct column (the outer `(` for curried calls, the `.` for a getter/member on a call result), and regresses by exactly one column when the mapping is disabled. Covered by the `stacktrace_is_correct` integration test and unit tests in `sourcemap.rs`.

## Example

`factory()()` — V8 reports the outer call at the `(` after the inner `)`:

```
without this fix:  at <anonymous> (input.js:7:9)    ← the inner `)`
with this fix:     at <anonymous> (input.js:7:10)   ← the outer `(`   ✓
```

The same one-column drift affected `expect(x).resolves` (the `.` getter access after the `)`).

## Compared with esbuild and tsc

Same input through each tool (identical generated code), visualized with [source-map-viewer](https://source-map-viewer.void.app):

```js
const outer = factory()();          // outer `(`  of factory()()
const member = expect(x).resolves;  // `.`        of expect(x).resolves
const indexed = arr[i]();           // `(`        of arr[i]()
```

| Source token | oxc (this PR) | tsc | esbuild |
| --- | :--: | :--: | :--: |
| outer `(` of `factory()()` | ✓ | ✓ | ✗ |
| `.` of `expect(x).resolves` | ✓ | ✓ | ✗ |
| `(` of `arr[i]()` | ✓ | ✓ | ✗ |

- **vs esbuild** ([compare](https://source-map-viewer.void.app/compare?a=QCnJWx7H&b=Y4FwbiMW)): oxc adds the three chain mappings esbuild lacks — esbuild maps the `]` one column left of the `(`, the exact off-by-one. This PR resolves what esbuild still gets wrong.
- **vs tsc** ([compare](https://source-map-viewer.void.app/compare?a=UjsQoNTX&b=Y4FwbiMW)): all three positions match tsc exactly. tsc maps ~10 more positions because it gives every node a trailing end-mapping; this PR maps only the no-anchor sites (+0.6% vs tsc's full density).

---

This PR was prepared with AI assistance; I reviewed, tested, and verified the changes.
2026-06-01 13:45:08 +00:00
Boshen c645615002 fix(parser): reject incompatible class member modifiers (#22843)
`static`/`abstract` and `declare`/`override` are mutually exclusive in either
order (TS1243):

- `static abstract m()` / `abstract static m()`
- `declare override x` / `override declare x`

oxc already validated modifier order (TS1029) and duplicates (TS1030). This extends
the existing `ILLEGAL_PRECEDING_MODIFIERS` table in both directions for these pairs
and reports them as "cannot be used with" (TS1243) rather than "must precede" — the
fast path is unchanged (still a table lookup + AND); only the cold error path picks
the message.

Matches babel and TypeScript: parser_babel +1 negative-pass
(`class/modifiers-incompatible`), positive/AST stay 100% across all suites, and the
correct TS1243 diagnostic is now emitted on existing TypeScript cases.
2026-05-30 02:23:40 +00:00
Dunqing d61e1d7caa fix(codegen): preserve verbatim text of pure/no-side-effects comments (#22525)
## Summary

- Stash `@__PURE__` / `@__NO_SIDE_EFFECTS__` (and `#`-prefixed) comments by `attached_to` during comment build, then emit the original source text at call / new / function-decl sites. Falls back to the canonical literal (`/* @__PURE__ */`, `/* @__NO_SIDE_EFFECTS__ */`) only when source text is unavailable or the stashed comment's kind doesn't match the emission site.
- Inputs like `/* #__PURE__ */`, `/*#__PURE__*/`, and `/* #__PURE__ -- @preserve */` round-trip verbatim instead of being normalized to `/* @__PURE__ */` ([rolldown#9408](https://github.com/rolldown/rolldown/issues/9408)).
- Verified by `cargo test -p oxc_codegen` (105 tests; includes new regression for mixed-kind `attached_to` collision in `pure_comment`).

## Problem

Codegen previously dropped pure / no-side-effects comments and emitted a canonical literal at every site marked with the AST `pure` flag. This lost the original text:

- `/* #__PURE__ */ foo()` → `/* @__PURE__ */ foo()` — bundlers / tools that prefer the `#` form lost it.
- `/*#__PURE__*/ foo()` (no spaces) was expanded to `/* @__PURE__ */ foo()`.
- `/* #__PURE__ -- @preserve */ foo()` lost the trailing `-- @preserve` marker that some tools key on (rolldown#9408).

## Fix

A new `annotation_comments: FxHashMap<u32, Comment>` stashes `is_pure()` / `is_no_side_effects()` comments keyed by `attached_to`. `Codegen::print_annotation_comment(start, kind, newline_after)` emits the verbatim source when available, otherwise prints the canonical literal owned by `AnnotationKind::canonical(newline_after)`.

Why a separate map from the existing `comments` (legal / JSDoc / not-applied / normal): applied pure annotations must be emitted **inline at the `pure` site** with a trailing space — not as a leading comment with a newline — and only when `node.pure == true`. Sharing storage would either double-print or conflate two formatting modes inside `print_comments`. Comments where the parser couldn't apply the annotation (e.g. `/* #__PURE__ */ function foo() {}` — wrong target; classified as `CommentContent::PureNotApplied`) still flow through `comments` and the existing leading-comment behavior is preserved.

### Mixed-kind collision

When multiple annotation comments share an `attached_to` (e.g. `/* @__PURE__ */ /* @__NO_SIDE_EFFECTS__ */ foo()`), the map is last-write-wins. The `AnnotationKind` filter on lookup ensures a `@__NO_SIDE_EFFECTS__` slot can't be emitted in place of `@__PURE__` (or vice versa); the dropped comment falls back to the canonical literal. Per the [compiler-notations-spec](https://github.com/javascript-compiler-hints/compiler-notations-spec), the two annotations only apply to their corresponding node kinds (call/new vs function declaration), so mixing them in front of a `CallExpression` would be a real semantic regression.

## Before / after

```js
// input
/* #__PURE__ -- @preserve */ pureOperation();
/*#__PURE__*/ foo(bar);
```

```js
// before
/* @__PURE__ */ pureOperation();
/* @__PURE__ */ foo(bar);

// after
/* #__PURE__ -- @preserve */ pureOperation();
/*#__PURE__*/ foo(bar);
```

AI assisted.
2026-05-19 10:13:25 +00:00
Mark Dalgleish 2493bdde8e fix(codegen): correct sourcemap end mappings for closing delimiters (#22001)
This fixes incorrect sourcemap end mappings for closing delimiters
emitted by `oxc_codegen`.

This came up while investigating [Remix 3](https://remix.run/) test
coverage reporting for code transformed with Oxc via the Remix `assets`
package, which we were using in our `test` package to run in-browser
tests. V8 reported uncovered functions and branches correctly, but
`v8-to-istanbul` could not always resolve the end of those covered
ranges back through Oxc's sourcemap, which caused coverage to be
over-reported. This meant that we saw cases of 100% coverage being
incorrectly reported because `v8-to-istanbul` dropped the whole function
block when it could not map the closing `}` line of an uncalled
function.

`add_source_mapping_end` used `Span::end` directly even though spans are
end-exclusive, so the generated token could land one character past the
real source span. Block printers also did not emit end mappings for
closing `}` consistently. Consumers that resolve V8 coverage range ends
through the sourcemap can then miss those block boundaries and
over-report coverage.

This PR maps end tokens to `span.end - 1` and emits them for block
closers, then extends the sourcemap tests with:

- a runtime stacktrace regression for normal function and arrow block
bodies
- a direct regression for the synthesized wrapper-block path used to
preserve `else` binding

The snapshot updates in `stacktrace_is_correct` are expected for the
same reason. Those column numbers come from Node consuming the generated
sourcemap at runtime. For example, one frame changes from
`/project/input.js:10:12` to `/project/input.js:10:11` for the source
line `obj.fn({a})()`. In 1-based columns, that line is `o1 b2 j3 .4 f5
n6 (7 {8 a9 }10 )11 (12 )13`. The error happens in the first call
expression, so the end position should resolve to column 11, the first
`)`, which is the closing character of `obj.fn({a})`. Before this change
it resolved to column 12, the next `(`, because the end mapping pointed
one character too far to the right. After switching end mappings to the
final real source character and adding the missing block-closer
mappings, that frame moves left by one column to the correct source
position.

Please note, I created this PR with AI assistance, but I worked closely
with the agent to design, review, and iterate on the changes until it
was at a level I was happy with.
2026-05-07 11:07:39 +08:00
bab 00fc13620d fix(codegen): preserve coverage comments before object properties (#21312)
Closes #21302

---------

Co-authored-by: Dunqing <dengqing0821@gmail.com>
2026-04-20 12:51:01 +08:00
Boshen 77abf546de fix(codegen): preserve coverage comments before ConditionalExpression alternate and between SwitchCases (#20718)
## Summary

- Print leading coverage ignore comments (e.g. `/* istanbul ignore next */`) before `ConditionalExpression`'s alternate expression
- Print leading coverage ignore comments before `case`/`default` keywords in `SwitchStatement`

Closes #20549

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-03-25 00:07:22 +00:00
Boshen abe21615db chore(node): bump .node-version to 24.14.0 (#20261)
Update the pinned Node.js version to 24.14.0 by changing only
.node-version.
2026-03-12 17:00:33 +08:00
connorshea 8126390ecb chore(test): Regenerate insta snapshots. (#18818)
Make insta stop logging massive diffs to the console for no reason. Regenerated with `cargo insta test --force-update-snapshots`

This was caused by the update to insta here: https://github.com/oxc-project/oxc/pull/18817
2026-02-02 00:06:52 +00:00
Boshen 4c16ae7d31 fix(codegen): remove spaces around = in minified type parameter defaults (#17989)
## Summary
- Remove unnecessary spaces around `=` in type parameter defaults
- Remove unnecessary spaces around `=` in import equals declarations

## Changes
- `<Props = any>` → `<Props=any>`
- `import a = require("a")` → `import a=require("a")`

Both syntaxes parse correctly without spaces (verified).

## Test plan
- [x] All codegen tests pass
- [x] All coverage tests pass (100%)

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-01-14 12:21:24 +00:00
Boshen 06bd17be03 fix(codegen): remove unnecessary double parentheses from satisfies expressions (#17986)
## Summary
- Fixed `TSSatisfiesExpression` to only add parentheses when precedence requires it
- Before: `((x) satisfies y)`, After: `x satisfies y`
- Aligned implementation with `TSAsExpression` pattern
- Added idempotency tests to ensure semantic correctness

## Test plan
- [x] Added `ts_satisfies_expression` test with 9 idempotency test cases
- [x] All codegen tests pass
- [x] Clippy passes

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-01-14 08:57:39 +00:00
Boshen 1874765a6c fix(codegen): fix inconsistent multiline EOF comment formatting (#17983)
## Summary

- Clear the `print_next_indent_as_space` flag before printing EOF legal comments to ensure consistent formatting

When inline comments set the `print_next_indent_as_space` flag, it was leaking to EOF comment printing, causing inconsistent formatting where some multiline block comments had a leading space before `*` and others didn't.

Before:
```js
/**
* @preserve
*/
/**
 * @preserve   <-- inconsistent leading space
*/
```

After:
```js
/**
* @preserve
*/
/**
* @preserve
*/
```

## Test plan

- Existing tests pass
- Snapshot updated to reflect the fix

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-01-14 08:15:52 +00:00
Boshen 2619c66f60 fix(codegen): remove leading whitespace from export statements after comments (#17982)
## Summary

- Clear the `print_next_indent_as_space` flag after printing comments in `ExportSpecifier` to prevent it from leaking to subsequent statements

When a block comment like `/* comment */` is printed inside an export specifier, the flag is set expecting `print_indent()` to consume it. However, `ExportSpecifier` calls `print_soft_space()` instead, leaving the flag set. This caused the next export statement to incorrectly print a leading space.

Before:
```js
export { name8, /* comment */ name81 };
 export { variable1 as name9 };  // <-- unwanted leading space
```

After:
```js
export { name8, /* comment */ name81 };
export { variable1 as name9 };
```

## Test plan

- Existing tests pass
- Snapshot updated to reflect the fix

Closes #17884

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-01-14 07:32:27 +00:00
camc314 10426af0be feat(codegen): print soft space between inline block comments on the same line (#17799) 2026-01-08 12:34:41 +00:00
camc314 7422b7ea25 fix(parser/trivia): correctly mark whether a block comment is on a newline (#17754)
CI is green(er) https://github.com/oxc-project/monitor-oxc/actions/runs/20788815777/job/59705840652
2026-01-08 12:34:40 +00:00
camc314 ef7e014c0b fix(parser): preserve @__NO_SIDE_EFFECTS__ annotation with parenthesized expressions (#17711)
Fixes #17670

Two issues caused the annotation to be lost:
1. LexerCheckpoint did not save/restore trivia flags, so lookahead operations would reset them
2. parse_parenthesized_expression did not capture the annotation before bumping `(`

monitor oxc https://github.com/oxc-project/monitor-oxc/actions/runs/20745400998/job/59561563786

CI is not yet green, but the codegen diff looks a lot better
2026-01-07 08:18:00 +00:00
Boshen b4f8b8a030 chore(js): node v24.12.0 (#17310) 2025-12-24 02:21:04 +00:00
夕舞八弦 67e9f9e671 feat(codegen): keep comments on the export specifiers (#16943)
resolve https://github.com/rolldown/rolldown/issues/6938

Co-authored-by: Boshen <boshenc@gmail.com>
2025-12-16 20:45:43 +08:00
copilot-swe-agent a607cc453e feat(codegen): preserve comments between CatchClause's param and body (#16167)
Fixes oxc-project/oxc#16076
2025-12-05 06:29:52 +00:00
Copilot 5233d737c4 test(codegen): Add regression tests for TSImportType string literal output (#16120)
PR #16114 fixed TSImportType codegen to prevent backticks in minified
output (which produces invalid TypeScript). This adds regression tests
to ensure the fix persists.

## Changes

- Added 4 test cases covering TSImportType variants:
  - Basic import types with single/double quotes
  - Import types with qualifiers (`.SomeType`)
  - Import types with type arguments (`<string>`)
- Tests verify both normal and minified output via snapshots

## Example

Input:
```typescript
type T = typeof import('react');
```

Minified output (now tested):
```typescript
type T=typeof import("react");  // ✓ double quotes, not backticks
```

The minify snapshot ensures backticks are never used, preventing invalid
TS like `import(\`react\`)`.

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



<details>

<summary>Original prompt</summary>

> 
> ----
> 
> *This section details on the original issue you should resolve*
> 
> <issue_title>Codegen: Do not use backticks when printing argument of
`TSImportType`</issue_title>
> <issue_description>Input:
> 
> ```ts
> type T = typeof import('react');
> ```
> 
> Codegen output (with `minify: true`):
> 
> ```ts
> type T=typeof import(`react`);
> ```
> 
>
[Playground](https://playground.oxc.rs/#eNptU01rGzEQ/StGl7TgQhooBJceSlJDIW3SJjSXXma1s44SrUYdzcY2xv+9o/VKTiCn1b7RfLw3TztjzcLINuLsbvZllg/UzVwfieXdCSNYOXn/+W8wc0NmsTM8hPzxLohZdOATzk1H3IMIckWEIaQMV8Ql8iDYXqL1wCCOQqrB9YMTTBEsmoXwoEgPYeX1b7pgqY+M6ZiRLMV6OW37hnz5s91qurafmwic8lw7gxvBkLRtppuUDnhP698oA4frQZJrcTkEmwcrlXJL5Ge8AdbUgo55f86/B2GnBW0NJNSpxdlvzMQTqiNkqcYR9PxCqZ0ZEt5Bc+Qk0Ny7Vh7M4mxuMLTX3ZULStL4TseN2k2m+PmpdnNZoV8DyVGmx7S5fQP+l/9umKL2MpA+BMQWW62pa3I63uqC+h5yzHtFlYerZJXLuvDX+Bq2WbuGwT6h3OrKNL1cLij0eJh86k/NI1q5Z4hao4iaG42zfhUVshl0QuRXabiJyK7HIOCv9QhCfEPJHVaUFTIqabXaQVQBXqFa02A6O/34SbuozJfYaeEl8YWHlJYOfVu39rKLmpPGNsdo76SiP1CgBVGlptW+beqdScooqkGQA6gvixkttbjC8f2EbIRq2cfUkj7DSfIQSMZaBfG4KnfHKuUtZEeVh6LMKV7hM9aiT4jxp66iGGxMVdOSX6qBc8YzckOpCJ75hLyoHKqnvcLtKF+G62mf8Sxz4bT/D3SBh38=)
> 
> This is invalid TypeScript. TS appears to require the argument to be a
string literal, and nothing else - template literal is not allowable
here.
> 
> [TS
Playground](https://www.typescriptlang.org/play/?#code/C4TwDgpgBAglC8VSQPYDMoEsC2YUCdgAKAA3wgEMBjYEgSgG4AoIA)
> 
> Related to oxc-project/oxc#16074.</issue_description>
> 
> <agent_instructions>The issue itself is solved. Add a test for
it.</agent_instructions>
> 
> ## Comments on the Issue (you are @copilot in this section)
> 
> <comments>
> <comment_new><author>@overlookmotel</author><body>
> We might want to do oxc-project/oxc#16111 first. That'll make this fix
easier to implement.</body></comment_new>
> <comment_new><author>@overlookmotel</author><body>
> oxc-project/oxc#16114 should have fixed this. We just need to add a
test to make sure.</body></comment_new>
> <comment_new><author>@camc314</author><body>
> There are tests for this, they regressed after just the AST change. I
fixed them back up in 16114 to avoid the regression</body></comment_new>
> </comments>
> 


</details>

- Fixes oxc-project/oxc#16078

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

✨ Let Copilot coding agent [set things up for
you](https://github.com/oxc-project/oxc/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: overlookmotel <557937+overlookmotel@users.noreply.github.com>
2025-11-25 22:44:17 +00:00
Ives van Hoorne e2ca770f64 fix(codegen): add support for printing type arguments in new expressions (#15963)
Code that's parsed as follows:

```
const a = new Map<string, number>();
```

Is printed by codegen as follows:

```
const a = new Map();
```

While for `CallExpression` we do render them:

```
const a = test<string, number>();
```

Is rendered the same. 

This PR adds support for rendering type parameters also for new
expressions.
2025-11-24 15:49:22 +08:00
sapphi-red b3d6f45d37 test(all): check parse errors existence (#15865)
Added `assert!(ret.errors.is_empty());` in many places so that invalid inputs are caught properly.
2025-11-19 13:56:55 +00:00
camc314 d27d0efc11 test(codegen): include Node.js version in stacktrace snapshot to clarify version-specific formatting differences (#15836) 2025-11-18 15:25:11 +00:00
Boshen 490471025e fix(codegen): print legal comments above directives (#14993)
## Summary

Fixes #14953

Legal comments (e.g., `/*! ... */`) that appear before directives like `"use strict"` are now properly preserved in the generated code.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2025-10-27 13:14:00 +00:00
leaysgur 75cbe11b23 chore(deps): Update Node.js version to 24.10.0 (#14982)
Node.js v22 active LTS has ended last week.

> https://nodejs.org/en/about/previous-releases
2025-10-27 08:46:15 +00:00
sapphi-red b53a2948cf fix(codegen): add end sourcemaps for arguments (#13355)
added end mappings for arguments to fix stack trace.
2025-08-29 02:38:29 +00:00
sapphi-red 10445662c6 fix(codegen): add end sourcemaps for array literals and object literals (#13354)
added end mappings for array literals and object literals to fix stack trace.

refs #13180
2025-08-29 02:38:29 +00:00
sapphi-red f547c94dff test(codegen): add test that verifies stack traces are correct (#13351)
Added tests that verifies the stack traces are correct.
2025-08-29 02:38:29 +00:00
Yuji Sugiura d565ed79b9 chore(codegen): Fix typo jsodc → jsdoc in codegen tests (#11451) 2025-06-03 13:13:32 +08:00
Boshen 25167f23ec perf(parser): parse ts type signature without rewind (#11443)
part of #11334
2025-06-02 14:49:00 +00:00
Boshen 1a4fec09dc fix(codegen)!: a legal comment can also be a jsdoc comment (#11158)
Breaking change: Changed the `CommentAnnotation` to `CommentContent` to
remove ambiguity on what an annotation is.

e.g. `/** @license */`

fixes #11093
2025-05-19 14:02:56 +00:00
Boshen c29b1b8e93 feat(codegen): deduplicate repeated legal comments (#11069)
related: https://github.com/evanw/esbuild/commit/a54916b92c128aa0596a65bcbafcde1074acf63d

closes #10688
2025-05-16 11:50:32 +00:00
Boshen 751876bf6a refactor(parser): rewrite parse class element (#11035)
closes #10942
closes #11010
2025-05-14 14:44:21 +00:00
Boshen 1673ffb05a feat(codegen): rework printing normal / legal / annotation comments (#10997)
fixes #10948

This PR changes how comment options are interpreted.

`CodegenOptions::comments`, `CodegenOptions::annotation_comments` and
`CodegenOptions::legal_comments` are now independent of each other.

### `CodegenOptions::comments`

Controls printing of normal comments. At present, only some leading
comments are preserved. It does not control legal and annotation
comments.


### `CodegenOptions::annotation_comments`

Controls printing of annotation comments

* jsdoc: `/** jsdoc */`                                                 
* pure: `/* #__PURE__ */` and `/* #__NO_SIDE_EFFECTS__ */`              
* webpack: `/* webpackChunkName */`                                     
* vite: `/* @vite-ignore */`                                            
* coverage: `v8 ignore`, `c8 ignore`, `node:coverage`, `istanbul ignore`

### `CodegenOptions::legal_comments`

Controls printing of legal comments

* starts with `//!` or `/*!`.                   
* contains `/* @license */` or `/* @preserve */`

---

Comment generation is also changed:

codegen first builds a comments map by keeping only the needed comments.
Printing functions will then print out comments in their respective
positions.

---

This PR reveals some incorrect comment interpretation:  

* https://github.com/oxc-project/oxc/issues/10998
2025-05-13 19:24:42 +08:00
Boshen b01cb45578 feat(codegen): a way to keep legal comments after minification (#10689)
fixes https://github.com/rolldown/rolldown/issues/4118
fixes #10626

At present, there is no option to keep legal comments when minification is turn on.

This PR allows Codegen to set legal comments with minfication turned on, with the following behavior:

* Inline: only if the attached code is not removed
* Eof: move all legal comments to the end of file, regardless of where they appear
* Linked and External: saved into `CodegenReturn::legal_comments` for the caller to use, regardless of where they appear

Code gets moved around or removed if minifier is turned on, so some legal comments may disappear from the final output.

The recommended legal comment option is Eof.

---

For Rolldown to keep legal comments, it should set `LegalComment::Inline` for chunk codegen and `LegalComment::Eof` for minification codegen.
2025-05-01 06:31:34 +00:00
Boshen 5ba02b0e49 feat(parser): set pure on typescript wrapped AST nodes (#10520)
Fixes https://github.com/rolldown/rolldown/issues/4166

Previously these inner call expressions were not annotated with `pure`.

```js
const Foo = /* @__PURE__ */ (((() => {})()))
const Foo = /* @__PURE__ */ (() => { })() as unknown as { new (): any };
const Foo = /* @__PURE__ */ (() => {})() satisfies X"
const Foo = /* @__PURE__ */ (() => {})()<X>"
const Foo = /* @__PURE__ */ <Foo>(() => {})()!
const Foo = /* @__PURE__ */ <Foo>(() => {})()! as X satisfies Y
```
2025-04-21 08:09:06 +00:00
Boshen 2c66ac2bcf feat(codegen): preserve code coverage ignore comments (e.g. v8 ignore) (#10338)
fixes #10091

This PR attempts to preserve any comments with a start match of

```
/* v8 ignore */
/* c8 ignore */
/* node:coverage */
/* istanbul ignore */
```

Added a special handle for coverage comment before `catch`:

```
try {
  something();
}
/* istanbul ignore next */
catch(e) {
  // should never happen
}
```
2025-04-09 16:24:20 +00:00
Yuji Sugiura ca8f174579 refactor(codegen): Do not print useless comma for TSEnumMember (#10213)
Current output:

```ts
enum X {A,B,}
//         ^
```

With this PR: 

```ts
enum X {A,B}
```
2025-04-04 14:44:31 +08:00
Boshen 418cfafba7 fix(parser): handle asi for declare module "foo"; (#10010)
fixes #10000
2025-03-29 14:32:09 +00:00
Dunqing 2326cefac8 feat(parser): apply pure to argument of unary expression (#9530)
Follow-up #9424
2025-03-04 06:13:22 +00:00
Boshen 9c6ae9f871 fix(parser): @__NO_SIDE_EFFECTS only affects const variable decl (#9517) 2025-03-03 14:58:11 +00:00
Boshen b7d5513410 fix(parser): parse @__NO_SIDE_EFFECTS__ between export default and async function (#9514) 2025-03-03 22:39:24 +08:00