Skip to content

strictExecutionOrder / onDemandWrapping: follow-up ledger #10294

Description

@hyfdev

Follow-up ledger for the strictExecutionOrder / onDemandWrapping work after #10104. This body is the single tracking surface, ordered by priority; the two older comments are superseded and minimized (their full audit details remain expandable).

P0 — correctness, likely to hit real projects

P1 — output shape (this issue's original scope)

  • Fold the runtime chunk back after order lowering. ensure_runtime_module_for_order_wraps unconditionally evicts a co-hosted runtime; re-run the merge proof with the post-lowering consumer set (OrderWrapState already carries each wrap's helper demand). Acceptance: issues/9463 inlines the runtime into common~a~b~shared in both cells. Anchors: issues/9463, issues/9463_plain_group, issues/9463_three_entries, strict_execution_order/concatenate_basic. fix(code-splitting): fold the runtime chunk back after order lowering #10414
  • Avoid the dynamic-entry facade when the same-chunk collapse can carry the trigger. create_order_wrap_entry_facades splits unconditionally; either emit the init through the shared esm_init_target view or skip the facade when the entry init is a noop with no transitive targets. Acceptance: issues/9463 wrap-all loses the shared.js facade chunk. Anchors: manual_group_phantom_dynamic, mixed_static_dynamic_same_target, issues/9463, issues/9463_plain_group, chunk_merging/dynamic_entry_merged_in_user_defined_entry. fix(code-splitting): avoid the dynamic-entry facade when the same-chunk collapse carries the trigger #10433
  • dynamicImports metadata records module_to_chunk[importee] while the finalizer rewrites via entry_module_to_entry_chunk (compute_cross_chunk_links.rs:358) — after a facade split, modulepreload-style consumers and devtools get the wrong direct edge. Verify whether Vite modulepreload is affected; if yes, promote to P0. Fix: record entry_module_to_entry_chunk with a module_to_chunk fallback. fix(code-splitting): align dynamicImports metadata with the rewritten import() specifier #10430
  • Add single-chunk strict coverage for a dynamic import of a wrapped module, e.g. strict_execution_order/single_chunk_dynamic_import_wrapped_module with IIFE and UMD variants.

Reference regression case: crates/rolldown/tests/rolldown/issues/9463 (cargo test -p rolldown --test integration -- 9463); pre-rewrite 3-chunk baseline fb81314, post-#10104 topology at 220783a (4/5 chunks). The full 94/94 snapshot audit trail lives in the minimized comments.

P2 — quick wins

  • Strict-gate the add_wrapped_esm_init_targets_for_static_member_reads Emit call site (esm_init_obligations.rs:359) — flag-off builds currently pay it for ns.x-only bindings of cross-chunk importees. The per-module member-read index can come later.
  • Warn when experimental.onDemandWrapping is set without output.strictExecutionOrder (silent no-op today), and reconcile the @hidden marker with the two public docs recommending the option by name.
  • Regenerate topics/generated_code/symbols_ns2/artifacts.snap in an environment that resolves assert, or pin the fixture's resolution — currently causes spurious local snapshot drift.

P3 — machinery follow-ups (opportunistic)

Correctness-adjacent corners:

  • restore_order_wrap_entry_facades un-tombstones every matching facade but wires only the first (order_wrapping.rs:389); two emitFile calls for one module break — only un-tombstone the facade actually re-pointed.
  • required_runtime_helpers() folds all overlays while live_symbols() gates on live importers (order_wrap_state.rs:33) — can define a __reExport nobody calls (bloat-only today); gate the fold the same way.

Perf (strict-only):

  • Gate TopLevelImportReadDetector (ast_scanner/impl_visit.rs:98) on onDemandWrapping too — wrap-all pays a per-module walk for a bit only on-demand analysis reads.
  • Skip building dynamic_target_modules_by_chunk in create_order_wrap_entry_facades under wrap-all.

Maintainability:

  • Route every "is this statement rendered?" read through one accessor (stmt_info_included OR forces_runtime_stmt) — the fix(code-splitting): deconflict force-included runtime helper statements #10336 deconflict miss is the failure mode this prevents.
  • Deduplicate: the export-star WrapKind::Esm arm vs wrapped_esm_init_call_expr (module_finalizers/mod.rs:1753); runtime-chunk minting and the "rolldown-runtime" literal (three sites, one naming warning); the duplicated 16-line order_live_symbols block (keep the second recompute — merge_cjs_namespace links canonical refs between the two).
  • Sweep the dormant concatenation model: ConcatenateWrappedModuleKind, Chunk::module_groups, the unreachable format/esm.rs:225 arm, and the dead disabled-splitting overlay arm (order_wrap_state.rs:536).
  • Unify the plan-member filters between real lowering (order_wrapping.rs:558) and the fixpoint probe (order_analysis.rs:553).
  • Comment in ast_scanner/impl_visit.rs that the scanner reads an output option — a footgun once scan caching across outputs lands.
  • Nits: use chunk_is_live() at detect_ineffective_dynamic_imports.rs:18 / order_wrapping.rs:272; ReexportRetentionEvidence → bool; drop write-only OrderSyntheticStmt.chunk/.owner; restore the internal-docs comment above trace_action_chunks_infos.

Moved out / resolved

Metadata

Metadata

Assignees

Type

No type

Fields

Priority

None yet

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions