Skip to content

Commit 786f663

Browse files
Dunqingclaude
andcommitted
docs: clarify why external filtering only applies to dynamic imports
User-defined and emitted entries are already guaranteed non-external by `load_entry_module()` which rejects them with `entry_cannot_be_external`. Added inline comment and updated design doc to explain this invariant. Co-Authored-By: Claude Opus 4.6 <[email protected]>
1 parent 552b889 commit 786f663

File tree

2 files changed

+5
-1
lines changed

2 files changed

+5
-1
lines changed

crates/rolldown/src/module_loader/module_loader.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,10 @@ impl<'a, Fs: FileSystem + Clone + 'static> ModuleLoader<'a, Fs> {
458458
if let Some(usage) = dynamic_import_rec_exports_usage.remove(&rec_idx) {
459459
dynamic_import_exports_usage_pairs.push((idx, usage));
460460
}
461+
// External modules are excluded here to preserve the bit-position-to-ChunkIdx
462+
// invariant in code splitting. User-defined and emitted entries are already
463+
// guaranteed non-external by `load_entry_module()` which rejects them with
464+
// `entry_cannot_be_external`.
461465
if matches!(raw_rec.kind, ImportKind::DynamicImport)
462466
&& !is_external
463467
&& !user_defined_entry_ids.contains(&idx)

meta/design/code-splitting.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ entry_index 2 → plugin.js → bit 2 → ChunkIdx(2)
7676

7777
Dynamic imports are treated as entry points — they get bit positions and entry chunks just like static entries. This matches Rollup and esbuild behavior: a dynamic `import()` creates a new loading boundary, so the imported module needs its own chunk (or must be merged into an existing one).
7878

79-
External modules are filtered out at the source — they never appear in `link_output.entries`. This is done in `module_loader.rs` where dynamic imports are collected as entry points: external modules are excluded from `dynamic_import_entry_ids`. This matches esbuild's approach where external modules never enter the entry list, and ensures that **bit positions directly equal chunk indices**`ChunkIdx::from_raw(bit_position)` is always valid.
79+
External modules are filtered out at the source — they never appear in `link_output.entries`. This is done in `module_loader.rs` where dynamic imports are collected as entry points: external modules are excluded from `dynamic_import_entry_ids`. User-defined and emitted entries are also safe because `load_entry_module()` rejects external resolutions with `entry_cannot_be_external`. This matches esbuild's approach where external modules never enter the entry list, and ensures that **bit positions directly equal chunk indices**`ChunkIdx::from_raw(bit_position)` is always valid.
8080

8181
See #8595 for the bug that motivated this filtering.
8282

0 commit comments

Comments
 (0)