You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Bug]: advancedChunks + CJS + includeDependenciesRecursively: false → cross-chunk wrapped-ESM init cycle (init_X is not a function); strictExecutionOrder does not help #9887
THROW includeDependenciesRecursively:false -> init_dep is not a function
THROW includeDependenciesRecursively:false + strictExecutionOrder:true -> init_dep is not a function
OK includeDependenciesRecursively:true (control)
What is expected?
Importing the entry runs without error (as it does with includeDependenciesRecursively: true), or rolldown errors at build time instead of emitting code that throws at runtime.
What is actually happening?
TypeError: init_dep is not a function at load.
The hub chunk imports init_dep from the dep chunk and calls it eagerly at module-eval time, but dep imports extend back from the hub chunk, so the two chunks form an import cycle and hub runs before dep has assigned var init_dep = __esmMin(...). The import binding is present — the wrapper is simply called before it is initialized:
// hub chunk (generated)import{nasinit_dep,rasuseDep}from"./dep.js";varrequire_interop=/* @__PURE__ */__commonJSMin((()=>{init_shared();init_dep();// <-- init_dep is still undefined here}));
...
require_interop();init_dep();
Notes:
output.strictExecutionOrder: true does not fix this variant. It changes the emitted output but the cycle and the premature call remain. (As a control, strictExecutionOrder: truedoes fix the simpler CJS + advancedChunks order bug in [Bug]: incorrect execution order with CJS + advancedChunks #7449.)
includeDependenciesRecursively: true (the default) fixes it — the dependency is pulled into the dependent's chunk, so no cross-chunk cycle forms.
Not a regression. Reproduces on rolldown 1.0.2, 1.0.3, 1.1.0, 1.1.1, and 1.1.2 (latest).
Minimal trigger (each ingredient is necessary — removing any one makes the output correct):
a CJS module that require()s the ESM modules (forces __esmMin wrapping + an eager init call);
advancedChunks groups that place a dependency in a different chunk than a module that depends back into the first chunk (a cross-chunk cycle);
includeDependenciesRecursively: false;
an eager init at module-eval time (here, the CJS require_*()).
The namespace-import shape is not required (named imports reproduce it too).
This is the same failure class as #7449 (incorrect execution order with CJS + advancedChunks) and #8803 / #9630, but specifically the case the documented strictExecutionOrder workaround (#8803) does not cover, because includeDependenciesRecursively: false forces the cross-chunk cycle. includeDependenciesRecursively: false is a meaningful real-world setting (it improves vendor-chunk content/hash stability), so a manual-chunking config with any CJS dependency in a cycle can hit silent, runtime-only breakage with no working escape hatch.
Minimum bar would be to error at build time rather than emit code that throws at load. Filing separately from #7449 since the workaround gap is specific to includeDependenciesRecursively: false; happy to fold it into #7449 if preferred.
Reproduction link or steps
A REPL link can't carry the
advancedChunksconfig, and this bug requires it, so here is a self-contained copy-paste reproduction.package.json{ "name": "repro", "private": true, "type": "module", "devDependencies": { "rolldown": "1.1.2" } }shared.jsdep.jsinterop.cjshub.jsmain.jsbuild.mjsRun:
Output (rolldown 1.1.2):
What is expected?
Importing the entry runs without error (as it does with
includeDependenciesRecursively: true), or rolldown errors at build time instead of emitting code that throws at runtime.What is actually happening?
TypeError: init_dep is not a functionat load.The
hubchunk importsinit_depfrom thedepchunk and calls it eagerly at module-eval time, butdepimportsextendback from thehubchunk, so the two chunks form an import cycle andhubruns beforedephas assignedvar init_dep = __esmMin(...). The import binding is present — the wrapper is simply called before it is initialized:Notes:
output.strictExecutionOrder: truedoes not fix this variant. It changes the emitted output but the cycle and the premature call remain. (As a control,strictExecutionOrder: truedoes fix the simpler CJS +advancedChunksorder bug in [Bug]: incorrect execution order with CJS + advancedChunks #7449.)includeDependenciesRecursively: true(the default) fixes it — the dependency is pulled into the dependent's chunk, so no cross-chunk cycle forms.Minimal trigger (each ingredient is necessary — removing any one makes the output correct):
require()s the ESM modules (forces__esmMinwrapping + an eager init call);advancedChunksgroups that place a dependency in a different chunk than a module that depends back into the first chunk (a cross-chunk cycle);includeDependenciesRecursively: false;require_*()).The namespace-import shape is not required (named imports reproduce it too).
System Info
Any additional comments?
This is the same failure class as #7449 (incorrect execution order with CJS + advancedChunks) and #8803 / #9630, but specifically the case the documented
strictExecutionOrderworkaround (#8803) does not cover, becauseincludeDependenciesRecursively: falseforces the cross-chunk cycle.includeDependenciesRecursively: falseis a meaningful real-world setting (it improves vendor-chunk content/hash stability), so a manual-chunking config with any CJS dependency in a cycle can hit silent, runtime-only breakage with no working escape hatch.Minimum bar would be to error at build time rather than emit code that throws at load. Filing separately from #7449 since the workaround gap is specific to
includeDependenciesRecursively: false; happy to fold it into #7449 if preferred.