Skip to content

fix(cli): rewrite import extensions in transpile output - #36403

Open
rathodkunj2005 wants to merge 6 commits into
denoland:mainfrom
rathodkunj2005:fix/transpile-import-extensions
Open

rathodkunj2005 wants to merge 6 commits into
denoland:mainfrom
rathodkunj2005:fix/transpile-import-extensions

Conversation

@rathodkunj2005

Copy link
Copy Markdown
Contributor

Closes #36399.

Summary

  • Rewrite TypeScript extensions in static imports, re-exports, and string-literal dynamic imports during deno transpile (.ts/.tsx → .js, .mts → .mjs, .cts → .cjs).
  • Preserve query/hash suffixes, declaration-file specifiers, non-TypeScript specifiers, and ordinary string literals.
  • Add focused unit coverage for extension mapping and a spec regression covering static imports, re-exports, dynamic imports, and literal lookalikes.

Verification

  • cargo check -p deno
  • ./tools/format.js --check cli/tools/transpile.rs cli/tools/transpile/import_extensions.rs tests/specs/transpile/__test__.jsonc tests/specs/transpile/import_extensions.ts tests/specs/transpile/check_import_extensions.ts tests/specs/transpile/rewrite_import_extensions_emit.out
  • rustc --edition=2024 --test cli/tools/transpile/import_extensions.rs -o /tmp/import_extensions_test && /tmp/import_extensions_test (2 passed)

AI assistance was used to investigate the issue and implement this change; I reviewed the resulting code and tests.

Comment thread cli/tools/transpile.rs Resolved

@bartlomieju bartlomieju left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Fixes #36399 and matches what the docs promise. The parse_module_with_post_process + VisitMut approach is the right hook, and clearing raw so the new value is what gets emitted is the easy thing to get wrong.

I pushed one fix: rewrite was matching on the extension alone, so it also rewrote specifiers that don't point at anything deno transpile emits — https://deno.land/x/foo/mod.ts became .../mod.js, and likewise for npm:/jsr:/bare/absolute specifiers. That turns a working import into a 404. It now only rewrites ./ and ../ specifiers, which is both what the docs describe ("./foo.ts → ./foo.js") and what tsc's rewriteRelativeImportExtensions does. Added unit coverage for the non-relative cases.

Two non-blocking nits:

  • check_import_extensions.ts prints a single true/false, so a failure gives no clue which specifier didn't get rewritten. assertEquals on the emitted text, or a few asserts, would make CI failures diagnosable.
  • The stray export {}; in the middle of that file isn't doing anything — the top-level await already makes it a module.

The test node_compat failure looks unrelated to this change. LGTM.

@rathodkunj2005

Copy link
Copy Markdown
Contributor Author

Thanks — addressed both review comments in 182fbcf.

What changed:

  • Added .jsx -> .js import specifier rewriting alongside the existing .tsx mapping.
  • Handled TsImportEquals external module references such as import helper = require("./helper.cts").
  • Extended the rewrite_import_extensions spec fixture to cover both cases.

Verification run locally:

  • cargo fmt --check ✅
  • git diff --check ✅
  • cargo check -p deno --lib ✅
  • cargo test --bin deno spec::transpile::rewrite_import_extensions was attempted, but the checkout ran out of disk space while compiling dependencies (No space left on device) before the test binary could finish building.

@rathodkunj2005

Copy link
Copy Markdown
Contributor Author

Follow-up: fixed the formatter failure from the new view.jsx fixture in d9a6834 (missing trailing newline). Verified with:

  • deno fmt --check cli/tools/transpile.rs cli/tools/transpile/import_extensions.rs tests/specs/transpile/__test__.jsonc tests/specs/transpile/check_import_extensions.ts tests/specs/transpile/import_extensions.ts tests/specs/transpile/view.jsx ✅
  • cargo fmt --check ✅
  • git diff --check ✅

@CLAassistant

CLAassistant commented Sep 23, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deno transpile doesn't change import extensions from ".ts" to ".js"

3 participants