Skip to content

fix(code-splitting): gate entry facades on post-lowering import edges#10335

Draft
hyfdev wants to merge 2 commits into
mainfrom
codex/facade-gate-post-lowering-edges
Draft

fix(code-splitting): gate entry facades on post-lowering import edges#10335
hyfdev wants to merge 2 commits into
mainfrom
codex/facade-gate-post-lowering-edges

Conversation

@hyfdev

@hyfdev hyfdev commented Jul 17, 2026

Copy link
Copy Markdown
Member

Summary

The strict-order entry-facade gate decided whether to split an interop-wrapped entry into a facade using the pre-lowering chunk import edges. Lowering's own init_* forwarding can add the first cross-chunk edge into such an entry's chunk, and when that edge closes no cycle the fixpoint converges without revisiting the facade decision — so the gate never saw it. This routes the gate through the converged post-lowering edges instead, so an entry whose chunk is only reached by a lowering-added hop is still split. Over-approximation is the safe direction (more facades are always legal; wrap-all splits unconditionally).

Verified mechanism

  • create_order_wrap_entry_facades builds imported_chunks from analysis.import_edges (order_wrapping.rs:214), which analyze_execution_order set to the pre-lowering baseline and returned at the end.
  • The emergent-cycle fixpoint recomputes post_lowering_import_edges every round and threw them away after cycle detection. This captures the converged round's post_edges (the round where added == 0) and returns those as OrderAnalysis.import_edges.
  • create_order_wrap_entry_facades is the only consumer of that field (grep-verified); the wrap-all path builds empty edges and short-circuits (on_demand == false), so it is unchanged.

Behavior / snapshot impact

  • Full suite: zero existing snapshots change. Over-approximation added no facades to any existing fixture — no current fixture reaches an interop entry's chunk by an emergent-only edge, confirming the shape is novel.
  • One new fixture function/experimental/strict_execution_order/facade_gate_emergent_edge (on-demand): a CommonJS entry sec (WrapKind::Cjs) co-hosts the interop-wrapped t in group gs; an order-wrapped wrapper in chunk A carries a tree-shaken export * from './f.js' whose dropped f imports unused from t, so the excluded-statement metadata projects an init_t forward — a post-lowering A -> gs edge with no baseline counterpart.
    • Snapshot is the differentiator (verified against the unfixed base): with the pre-lowering gate, sec keeps its inline require_sec() trigger in the shared chunk (no sec2.js); with this fix the gate sees the emergent edge and splits sec into a facade (sec.js thin trigger + sec2.js impl). The only diff between the two builds is the added facade chunk.
    • Executes under node (_test.mjs): loading only the root does not run sec's program; loading sec directly runs it once.

Fixture outcome — constructibility verdict

The reviewer expected a directed fixture where "evaluating the importing chunk runs the whole entry program early." I could construct the facade-decision difference (above) but not an executable early-run, and the reason is structural — established over ≥7 distinct attempts (co-hosted order-wrapped target with a TLA entry, a CJS entry, and a plain entry; the excluded forwarder targeting the entry directly vs. a co-hosted module; single- vs. two-entry; TLA vs. CJS interop). A post-lowering-only edge (absent from the baseline) comes from exactly two sources:

  1. Excluded re-export hops (the named Hole-2 shape) — projection-only. The real lowering does not render the forward (Hole-2's own dist/a.js calls no init_t); it exists only in post_lowering_import_edges for cycle detection. So it never actually imports the entry's chunk at runtime — the facade the fix creates is a correct conservative guard, not a fix for a live crash.
  2. Eager re-export overlays (Hole-1) — rendered, but retaining the re-export requires the re-exported binding to be consumed, which itself creates a baseline edge into the target's chunk. So the gate already splits in that case, with or without the fix.

A rendered, baseline-invisible edge into an interop entry's chunk therefore does not appear constructible; the executable early-run is not reachable through the facade gate. The fixture pins the facade-gate behavior change directly (snapshot differentiator) and the fix stands as the correct over-approximation the review asked for. If a rendered path is later found, it converts straight into an executed assertion on this same fixture.

Validation

  • cargo test -p rolldown — 1872 passed (+1 new fixture, executed under node); only the 5 known environmental failures (cjs_module_lexer_compat ×3 + npm_packages/util_deprecate need pnpm install; test262_module_code needs the submodule). No existing snapshot changed (the local symbols_ns2 drift is pre-existing node_modules-resolution noise, reproducible with this change reverted, and is not committed).
  • cargo fmt --all --check — clean; cargo clippy -p rolldown --all-targets -- -D warnings — clean.

Follow-up to #10104; addresses item 1 of #10104 (comment)

@hyfdev
hyfdev force-pushed the codex/facade-gate-post-lowering-edges branch from 0688d2e to 1f73c9f Compare July 17, 2026 07:59
@hyfdev
hyfdev force-pushed the codex/flag-off-runtime-sweep-chunk-order branch from 39bb381 to 4957c8a Compare July 17, 2026 08:18
@hyfdev
hyfdev force-pushed the codex/facade-gate-post-lowering-edges branch from 1f73c9f to 4206c33 Compare July 17, 2026 08:18
@hyfdev
hyfdev force-pushed the codex/flag-off-runtime-sweep-chunk-order branch from 4957c8a to cbe7f25 Compare July 18, 2026 05:35
@hyfdev
hyfdev force-pushed the codex/facade-gate-post-lowering-edges branch from 4206c33 to 0f463fb Compare July 18, 2026 05:35
@hyfdev
hyfdev force-pushed the codex/flag-off-runtime-sweep-chunk-order branch from cbe7f25 to f8ec80d Compare July 18, 2026 05:48
@hyfdev
hyfdev force-pushed the codex/facade-gate-post-lowering-edges branch from 0f463fb to ea9b969 Compare July 18, 2026 05:48
@hyfdev
hyfdev force-pushed the codex/flag-off-runtime-sweep-chunk-order branch 3 times, most recently from 40e86d8 to 0f69617 Compare July 19, 2026 12:49
@graphite-app
graphite-app Bot force-pushed the codex/flag-off-runtime-sweep-chunk-order branch from 0f69617 to ab2a338 Compare July 19, 2026 15:25
Base automatically changed from codex/flag-off-runtime-sweep-chunk-order to main July 19, 2026 15:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant