fix: transform non-static dynamic imports when dynamicImportInCjs is false#7823
Conversation
How to use the Graphite Merge QueueAdd the label graphite: merge-when-ready to this PR to add it to the merge queue. You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
✅ Deploy Preview for rolldown-rs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
Pull request overview
This PR fixes a bug where non-static dynamic imports like import(foo) or imports with @vite-ignore comments were not being transformed to require() calls in CJS output format when dynamicImportInCjs is false.
Key changes:
- Tracks statement indices for non-static/ignored dynamic imports during AST scanning
- Transforms them to
Promise.resolve().then(() => __toESM(require(...)))in the module finalizer - Ensures the
__toESMruntime helper is properly registered for these transformations
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| crates/rolldown_common/src/ecmascript/ecma_view.rs | Adds non_static_dynamic_import_stmt_idxs field to track statements with non-static dynamic imports |
| crates/rolldown/src/ast_scanner/mod.rs | Adds non_static_dynamic_import_stmt_idxs field to ScanResult struct |
| crates/rolldown/src/ast_scanner/impl_visit.rs | Records statement indices when encountering non-static or @vite-ignore dynamic imports in CJS format |
| crates/rolldown/src/module_finalizers/mod.rs | Transforms non-static dynamic imports to Promise.resolve().then(() => __toESM(require(...))) |
| crates/rolldown/src/stages/link_stage/reference_needed_symbols.rs | Registers __toESM runtime helper dependency for non-static dynamic import statements |
| crates/rolldown/src/ecmascript/ecma_module_view_factory.rs | Passes non_static_dynamic_import_stmt_idxs from scan result to ecma view |
| crates/rolldown/src/module_loader/runtime_module_task.rs | Initializes non_static_dynamic_import_stmt_idxs as empty vec for runtime module |
| crates/rolldown/tests/rolldown/cjs_compat/dynamic_import_in_cjs_non_static/* | Test case verifying the transformation of non-static dynamic imports |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
crates/rolldown/src/stages/link_stage/reference_needed_symbols.rs
Outdated
Show resolved
Hide resolved
Benchmarks Rust
|
3d183c3 to
d71a062
Compare
dynamicImportInCjs is false
Merge activity
|
…s `false` (#7823) Related to #7784 Previously, non-static dynamic imports like `import(foo)` or imports with `@vite-ignore` comment were not being transformed to require() calls in CJS output format when dynamicImportInCjs was false. This change: - Tracks statement indices for non-static/ignored dynamic imports - Transforms them to `Promise.resolve().then(() => __toESM(require(...)))` - Ensures __toESM runtime helper is properly included
d71a062 to
ca701f2
Compare
## [1.0.0-beta.60] - 2026-01-14 ### 💥 BREAKING CHANGES - tsconfig: enable auto-discovery by default (#7817) by @shulaoda ### 🚀 Features - distinguish transformer diagnostics from parse errors (#7872) by @shulaoda - emit transformer warnings instead of ignoring them (#7850) by @shulaoda - node: add `output.codeSplitting` option and deprecate `output.advancedChunks` (#7855) by @hyf0 - nativeMagicString reset (#7828) by @IWANABETHATGUY - nativeMagicString lastChar (#7819) by @IWANABETHATGUY - dev/lazy: inject lazy compilation runtime automatically (#7816) by @hyf0 - nativeMagicString snip (#7818) by @IWANABETHATGUY - nativeMagicString construct with options (#7814) by @IWANABETHATGUY - nativeMagicString clone (#7813) by @IWANABETHATGUY - nativeMagicString `insert` (#7812) by @IWANABETHATGUY - nativeMagicString `slice` (#7807) by @IWANABETHATGUY - nativeMagicString trim methods (#7800) by @IWANABETHATGUY - make closeBundle hook receive the last error (#7278) by @Copilot ### 🐛 Bug Fixes - when package only contains export default, cjsDefault didn't resolve correctly (#7873) by @IWANABETHATGUY - inline __name calls for default exports (#7862) by @IWANABETHATGUY - improve variable renaming to avoid unnecessary shadowing in nested scopes (#7859) by @IWANABETHATGUY - use correct index when inserting keepNames statements during export default transformation (#7853) by @IWANABETHATGUY - transform non-static dynamic imports when `dynamicImportInCjs` is `false` (#7823) by @shulaoda - dev/lazy: should include imported and non-executed modules in the patch (#7815) by @hyf0 - set ExportsKind to Esm when json is none object literal (#7808) by @IWANABETHATGUY - nativeMagicString move api (#7796) by @IWANABETHATGUY - remove unnecessary exports after merging into commong and user defined entry (#7789) by @IWANABETHATGUY - use output.name instead of chunk.name in mixed export warning (#7788) by @Copilot ### 🚜 Refactor - generalize ParseError to OxcError with dynamic EventKind (#7868) by @shulaoda - rust: rename `advanced_chunks` to `manual_code_splitting` (#7856) by @hyf0 - string_wizard error hanlding (#7830) by @IWANABETHATGUY - remove `experimental.disableLiveBindings` option (#7820) by @sapphi-red - node/test: run fixture tests in concurrent (#7790) by @hyf0 - move ConfigExport and RolldownOptionsFunction types to define-config (#7799) by @shulaoda - cli: validate config after resolving and improve error message (#7798) by @shulaoda ### 📚 Documentation - rebrand (#7670) by @yyx990803 - fix incorrect default value for propertyReadSideEffects (#7847) by @Copilot - remove options pages and redirect to reference pages (#7834) by @sapphi-red - options: inline types to option property pages (#7831) by @sapphi-red - options: port checks.pluginTimings content from options page to reference page (#7832) by @sapphi-red - options: use `@linkcode` where possible (#7824) by @sapphi-red - options: port content from options page to reference page (#7822) by @sapphi-red - options: add descriptions for output options (#7821) by @sapphi-red - options: add description for input options (#7802) by @sapphi-red - options: add description for `checks.*` (#7801) by @sapphi-red - apis: add hook graph (#7671) by @sapphi-red ### 🧪 Testing - add all valid combination of chunk exports related test (#7851) by @IWANABETHATGUY - enable MagicString test after api return type alignment (#7797) by @IWANABETHATGUY - init magic-string test (#7794) by @IWANABETHATGUY ### ⚙️ Miscellaneous Tasks - vite-tests: configure git user for rebase operation (#7875) by @shulaoda - rolldown_binding: remove v3 native plugins (#7837) by @shulaoda - rolldown_binding: allow crate-type as lib (#7866) by @Brooooooklyn - README.md: adjust position and size of rolldown logo (#7861) by @hyf0 - deps: update test262 submodule for tests (#7857) by @sapphi-red - deps: update oxc to v0.108.0 (#7845) by @renovate[bot] - deps: update dependency oxlint to v1.39.0 (#7849) by @renovate[bot] - deps: update dependency oxfmt to ^0.24.0 (#7844) by @renovate[bot] - deps: update npm packages (#7841) by @renovate[bot] - deps: update rust crates (#7839) by @renovate[bot] - deps: update github-actions (#7840) by @renovate[bot] - use workspace edition for all crates (#7829) by @IWANABETHATGUY - deps: update dependency oxlint-tsgolint to v0.11.0 (#7827) by @renovate[bot] - deps: update napi to v3.8.2 (#7810) by @renovate[bot] - remove outdated snapshot files (#7806) by @shulaoda - deps: update crate-ci/typos action to v1.42.0 (#7792) by @renovate[bot] Co-authored-by: shulaoda <[email protected]>

Related to #7784
Previously, non-static dynamic imports like
import(foo)or imports with@vite-ignorecomment were not being transformed to require() calls in CJS output format when dynamicImportInCjs was false.This change:
Promise.resolve().then(() => __toESM(require(...)))