Skip to content

fix(transformer/typescript): rewrite extensions in dynamic import() expressions#20121

Merged
Dunqing merged 4 commits intooxc-project:mainfrom
sverrejoh:fix/rewrite-extensions-dynamic-import
Mar 12, 2026
Merged

fix(transformer/typescript): rewrite extensions in dynamic import() expressions#20121
Dunqing merged 4 commits intooxc-project:mainfrom
sverrejoh:fix/rewrite-extensions-dynamic-import

Conversation

@sverrejoh
Copy link
Contributor

Closes #20120

rewriteImportExtensions was not handling dynamic import() expressions, only static import/export declarations. TypeScript's rewriteRelativeImportExtensions handles both (via visitImportOrRequireCall in the ESNext module transformer).

The fix adds enter_import_expression visitors at three levels of the transformer dispatch chain. When the import() source is a string literal, it is rewritten the same way as static imports. Non-literal sources (e.g., import(variable)) are left unchanged.

Test fixtures added for both "rewrite" and "remove" modes covering dynamic imports.

Disclosure: AI-assisted (Claude). All changes reviewed and tested by the contributor.

Copilot AI review requested due to automatic review settings March 8, 2026 17:57
@github-actions github-actions bot added A-transformer Area - Transformer / Transpiler C-bug Category - Bug labels Mar 8, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes TypeScript’s rewriteImportExtensions transformer option to also rewrite file extensions inside dynamic import() expressions (when the import source is a literal), matching TypeScript’s behavior more closely and addressing #20120.

Changes:

  • Add enter_import_expression traversal hooks through the transformer dispatch chain so dynamic import() sources can be rewritten.
  • Extend the TypeScript rewrite-extensions visitor to rewrite ImportExpression string-literal sources.
  • Add/extend conformance fixtures for both "rewrite" and "remove" modes covering dynamic imports.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tasks/transform_conformance/tests/babel-preset-typescript/test/fixtures/rewriteImportExtensions/input.ts New fixture input covering static + dynamic import extension rewriting cases.
tasks/transform_conformance/tests/babel-preset-typescript/test/fixtures/rewriteImportExtensions/output.js New expected output asserting dynamic import() literals are rewritten in "rewrite" mode.
tasks/transform_conformance/tests/babel-preset-typescript/test/fixtures/rewriteImportExtensions/options.json New fixture options enabling rewriteImportExtensions: "rewrite".
tasks/transform_conformance/tests/babel-preset-typescript/test/fixtures/removeImportExtensions/input.ts Extend existing fixture input to include dynamic imports for "remove" mode.
tasks/transform_conformance/tests/babel-preset-typescript/test/fixtures/removeImportExtensions/output.js Extend expected output to assert dynamic import() literals are rewritten in "remove" mode.
crates/oxc_transformer/src/typescript/rewrite_extensions.rs Implement rewriting for ImportExpression when the source is a string literal.
crates/oxc_transformer/src/typescript/mod.rs Forward enter_import_expression to the rewrite-extensions sub-transform when enabled.
crates/oxc_transformer/src/lib.rs Forward enter_import_expression from the top-level transformer into the TypeScript preset.

Copy link
Member

@Dunqing Dunqing left a comment

Choose a reason for hiding this comment

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

looks good!

@codspeed-hq
Copy link

codspeed-hq bot commented Mar 9, 2026

Merging this PR will not alter performance

✅ 40 untouched benchmarks
⏩ 16 skipped benchmarks1


Comparing sverrejoh:fix/rewrite-extensions-dynamic-import (731aff4) with main (a1031cb)2

Open in CodSpeed

Footnotes

  1. 16 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on main (fe3b32e) during the generation of this report, so a1031cb was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

…terals in dynamic import()

TypeScript's `isStringLiteralLike` includes `NoSubstitutionTemplateLiteral`,
so `import(`./a.ts`)` is also rewritten by tsc. Match that behavior.
@sverrejoh
Copy link
Contributor Author

looks good!

I can address the template string concern from copilot above. Noticed that TypeScript also supports this.

Sverre Johansen added 2 commits March 9, 2026 10:23
`Atom<'_>` implements `Copy`, so `.clone()` triggers clippy::clone_on_copy.
@sverrejoh
Copy link
Contributor Author

@Dunqing I can revert the import bare template change hand handle that in a followup, if you think that's cleaner.

TypeScript and babel supports this in the later versons, but they also now support falling back to a runtime helper for importing substitution template strings via a runtime helper. I could tackle that in a followup too.

Copy link
Member

@Dunqing Dunqing left a comment

Choose a reason for hiding this comment

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

Great

@Dunqing Dunqing merged commit 1ff5c1d into oxc-project:main Mar 12, 2026
27 of 28 checks passed
Boshen added a commit that referenced this pull request Mar 14, 2026
### 🚀 Features

- e7163b6 ecmascript: Add known-globals to side-effect-free property
reads (#20212) (Dunqing)
- 139ab68 ecmascript: Add `property_write_side_effects` to
`MayHaveSideEffectsContext` (#20217) (Dunqing)

### 🐛 Bug Fixes

- 78c264a parser: Fix conditional expressions with arrow-function
alternates in TS (#20356) (camc314)
- 5c97b14 minifier: Recognize object spread of object literals as
side-effect-free (#20299) (Boshen)
- 1ff5c1d transformer/typescript: Rewrite extensions in dynamic
`import()` expressions (#20121) (Sverre Johansen)
- 1c07b3b diagnostics: Handle `WouldBlock` in stdout writes to prevent
panic (#20295) (Boshen)
- ade14d4 ecmascript: Enhance side-effect detection for classes,
TypedArrays, computed members, and spread (#20213) (Dunqing)

### ⚡ Performance

- 5474d0a semantic: V8-style walk-up reference resolution (#20292)
(Boshen)

### 📚 Documentation

- e4aa5b5 parser/napi, linter/plugins: Add JSDoc comments to raw
transfer constants (#20286) (overlookmotel)

Co-authored-by: Boshen <1430279+Boshen@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-transformer Area - Transformer / Transpiler C-bug Category - Bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

rewriteImportExtensions does not rewrite dynamic import() expressions

3 participants