Skip to content

fix(packages/codegen): print matching quoted import names as identifiers - #26404

Merged
graphite-app[bot] merged 1 commit into
mainfrom
codex/js-codegen-quoted-import-names
Sep 7, 2026
Merged

graphite-app[bot] merged 1 commit into
mainfrom
codex/js-codegen-quoted-import-names

Conversation

@camc314

@camc314 camc314 commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Oxc codegen npm package emits invalid JavaScript when a quoted imported name matches its local binding. The printer compares the decoded names and omits the alias, but leaves the imported name quoted. A quoted import name requires an explicit as binding.

For this valid input:

import { "foo" as foo } from "m";

The JavaScript printer previously emitted:

import { "foo" } from "m";

It now prints the matching local binding as identifier shorthand:

import { foo } from "m";

printImportDeclaration checks for a string-literal imported name whose decoded value equals the local binding name before printing the imported name. In that case, it prints the local identifier directly, including its source-map mapping. The local binding already supplies a valid identifier, so this requires neither a separate identifier-validity check nor an AST mutation.

Comparing the decoded value also handles escaped and Unicode import names:

// Input
import { "a\u0062" as ab } from "m";
import { "π" as π } from "m";

// Output
import { ab } from "m";
import { π } from "m";

Declaration-level and inline TypeScript type imports use the same shorthand:

// Input
import type { "Foo" as Foo } from "m";
import { type "Bar" as Bar } from "m";

// Output
import type { Foo } from "m";
import { type Bar } from "m";

Quoted names that differ from their local bindings retain their quotes and aliases, including "foo-bar" as foo, "" as foo, and "default" as foo. Ordinary identifier imports keep their existing shorthand behavior. The correction applies to both the ordinary and source-map-enabled builds and brings the JavaScript printer in line with the Rust codegen fix in #26386.

Copilot AI lite review requested due to automatic review settings September 7, 2026 14:55
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 7, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-07T14:59:13.339479Z ea5bae1 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions github-actions Bot added the A-codegen Area - Code Generation label Sep 7, 2026
@camc314 camc314 changed the title fix(codegen): print matching quoted import names as identifiers in JS printer fix(packages/codegen): print matching quoted import names as identifiers Sep 7, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The change is small, localized to import-specifier printing, and is covered by new fixtures exercised by the existing fixtures conformance test harness.

Pull request overview

Fixes JavaScript/TypeScript codegen output for import specifiers where the imported name is a string literal whose decoded value matches the local binding, ensuring the printer emits valid shorthand identifier imports (and correct source-map mappings) instead of an invalid quoted name without an as clause.

Changes:

  • Update printImportDeclaration to detect imported: Literal where imported.value === local.name and print the local identifier directly (shorthand form).
  • Add new JS/TS fixture inputs covering quoted import names (including escaped and Unicode forms) and TS type import variants.
File summaries
File Description
packages/codegen/src-js/print/module.ts Prints local identifier shorthand when a quoted imported name’s decoded value matches the local binding, avoiding invalid import { "x" } output.
packages/codegen/test/fixtures/quoted-import-names.js Adds JS fixture coverage for quoted import names that should (and should not) collapse to shorthand.
packages/codegen/test/fixtures/quoted-import-names.ts Adds TS fixture coverage for declaration-level and inline type imports with quoted import names.
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

@camc314 camc314 added the 0-merge Merge with Graphite Merge Queue label Sep 7, 2026
@camc314 camc314 self-assigned this Sep 7, 2026

camc314 commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

Merge activity

…ers (#26404)

Oxc codegen npm package emits invalid JavaScript when a quoted imported name matches its local binding. The printer compares the decoded names and omits the alias, but leaves the imported name quoted. A quoted import name requires an explicit `as` binding.

For this valid input:

```js
import { "foo" as foo } from "m";
```

The JavaScript printer previously emitted:

```js
import { "foo" } from "m";
```

It now prints the matching local binding as identifier shorthand:

```js
import { foo } from "m";
```

`printImportDeclaration` checks for a string-literal imported name whose decoded value equals the local binding name before printing the imported name. In that case, it prints the local identifier directly, including its source-map mapping. The local binding already supplies a valid identifier, so this requires neither a separate identifier-validity check nor an AST mutation.

Comparing the decoded value also handles escaped and Unicode import names:

```js
// Input
import { "a\u0062" as ab } from "m";
import { "π" as π } from "m";

// Output
import { ab } from "m";
import { π } from "m";
```

Declaration-level and inline TypeScript type imports use the same shorthand:

```ts
// Input
import type { "Foo" as Foo } from "m";
import { type "Bar" as Bar } from "m";

// Output
import type { Foo } from "m";
import { type Bar } from "m";
```

Quoted names that differ from their local bindings retain their quotes and aliases, including `"foo-bar" as foo`, `"" as foo`, and `"default" as foo`. Ordinary identifier imports keep their existing shorthand behavior. The correction applies to both the ordinary and source-map-enabled builds and brings the JavaScript printer in line with the Rust codegen fix in #26386.
@graphite-app
graphite-app Bot force-pushed the codex/js-codegen-quoted-import-names branch from ea5bae1 to 6e15ad5 Compare September 7, 2026 15:28
@graphite-app
graphite-app Bot merged commit 6e15ad5 into main Sep 7, 2026
31 checks passed
@graphite-app graphite-app Bot removed the 0-merge Merge with Graphite Merge Queue label Sep 7, 2026
@graphite-app
graphite-app Bot deleted the codex/js-codegen-quoted-import-names branch September 7, 2026 15:33
graphite-app Bot pushed a commit that referenced this pull request Sep 14, 2026
### 🚀 Features

- ca649e0 ecma: Define math constants as known globals and resolve their types (#26585) (Armano)
- 9ef028c codegen: Add `ascii_only` option (#25994) (Samuel Attard)
- 80a76a0 minifier: Negate binary comparison for `typeof x < 'u'` (#26367) (Armano)

### 🐛 Bug Fixes

- 8ca76da parser: Reject `accessor` modifiers on methods (#26617) (camc314)
- 1916f31 parser: Reject `readonly` modifier on constructors (#26612) (camc314)
- 1c42008 parser: Handle escaped let in for loops (#26583) (camc314)
- d21d5cf parser: Recognize annotated empty arrows in conditionals (#26537) (camc314)
- d7713ad parser: Classify Unicode line breaks in block comments (#26536) (camc314)
- 75cd919 transformer: Preserve receivers in private optional chains (#26535) (camc314)
- b32d25d parser: Reject escaped import-phase keywords (#26534) (camc314)
- 47b8311 parser: Recognize contextual binding names in type lookaheads (#26532) (camc314)
- d6b6705 parser: Require arrow separator in TypeScript function types (#26529) (camc314)
- e98beef parser: Disambiguate await using in for initializers (#26527) (camc314)
- 92afee6 parser: Allow parenthesized JSX comma expressions with preserve_parens=false (#26524) (camc314)
- 31508b1 parser: Reject return types on constructor overloads (#26523) (camc314)
- a091fc4 parser: Validate await context for await using declarations (#26495) (camc314)
- 5501e86 parser: Disallow in expressions in using for-loop initializers (#26490) (camc314)
- c8e5fa7 parser: Allow escaped type names in import and export specifiers (#26487) (camc314)
- 2dcee2f parser: Reject async modifiers on class fields (#26486) (camc314)
- 973d58e parser: Require comma after TypeScript this parameter (#26480) (camc314)
- 32d00c5 codegen: Preserve instantiation expression precedence (#26424) (camc314)
- cfa47ab parser: Allow `in` expressions in class static blocks (#26423) (camc314)
- 5986187 packages/codegen: Preserve private-in right operand precedence (#26420) (camc314)
- f8e6c6c packages/codegen: Preserve in restriction through yield arguments (#26421) (camc314)
- d61e3bf parser: Validate TS named tuple rest elements (#26419) (camc314)
- ae6c386 codegen: Preserve in restriction through yield arguments (#26413) (camc314)
- 42ac916 codegen: Preserve private-in right operand precedence (#26411) (camc314)
- 10521b2 parser: Allow escaped type default import bindings (#26409) (camc314)
- 72cb5e3 parser: Reject rest parameters in getters (#26400) (camc314)
- 6e15ad5 packages/codegen: Print matching quoted import names as identifiers (#26404) (camc314)
- bbbb4bc packages/codegen: Preserve private-in left operand precedence (#26403) (camc314)
- a111b5b packages/codegen: Print accessibility modifiers before abstract (#26402) (camc314)
- 4e76602 parser: Allow `in` in arrow block bodies within `for` initializers (#26395) (camc314)
- b20fc19 parser: Reject partially parenthesized mixed coalesce expressions (#26394) (camc314)

### ⚡ Performance

- 1f902a6 isolated_declarations: Key scope maps by `Ident` (#26380) (Dunqing)
- a242469 minfiier: Reduce allocs when creating indirect access (#26601) (Armano)
- 5b4787f minifier: Update chain expressions in place (#26544) (Armano)
- 0bc1661 minifier: Try merging before creating new expression statements (#26556) (Armano)
- c78d707 minifier: Process newly created stmt in handle_if_statement (#26541) (Armano)
- 029c84b minfier: Update expressions in place when substituting alternate syntax (#26460) (Armano)
- d198982 codegen: Outline postfix source mapping work (#26450) (camc314)
- 53f006e ecmascript: Format small integer literals with itoa (#26446) (camc314)
- 8bfb8c0 codegen: Avoid duplicate sourcemap name lookups (#26441) (camc314)

### 📚 Documentation

- 38533ac ast: Move type annotation span comment to span field (#26522) (camc314)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-codegen Area - Code Generation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Sponsor
SponsoredKunjungi sekarang
Promo