Skip to content

docs: document ensure_lazy_module_initialization_order in code-splitting design doc#8931

Merged
graphite-app[bot] merged 1 commit intomainfrom
03-27-docs_ensure_lazy_module_initialization_order
Mar 28, 2026
Merged

docs: document ensure_lazy_module_initialization_order in code-splitting design doc#8931
graphite-app[bot] merged 1 commit intomainfrom
03-27-docs_ensure_lazy_module_initialization_order

Conversation

@IWANABETHATGUY
Copy link
Copy Markdown
Member

@IWANABETHATGUY IWANABETHATGUY commented Mar 27, 2026

Summary

  • Adds a new Lazy Module Initialization Order section to meta/design/code-splitting.md documenting the ensure_lazy_module_initialization_order pass
  • Explains the problem: when wrapped CJS init calls are split across different unwrapped ESM modules, the default placement can produce incorrect initialization order (with a concrete example based on [Bug]: Runtime error when using rolldown to build a page using tinymce #5531)
  • Documents the 6-step algorithm, the js_import_order DFS helper, and the insert_map/remove_map output consumed by the finalizer
  • Extends the pipeline diagram to show post-ChunkGraph processing steps (compute_cross_chunk_links, ensure_lazy_module_initialization_order, on_demand_wrapping, merge_cjs_namespace)
  • Updates the key files list to include linking_metadata.rs

Test plan

  • Read through the updated design doc for accuracy and clarity
  • No code changes — documentation only

🤖 Generated with Claude Code

Copy link
Copy Markdown
Member Author


How to use the Graphite Merge Queue

Add 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.

@netlify
Copy link
Copy Markdown

netlify bot commented Mar 27, 2026

Deploy Preview for rolldown-rs canceled.

Name Link
🔨 Latest commit 6ab459a
🔍 Latest deploy log https://app.netlify.com/projects/rolldown-rs/deploys/69c7397593e9bb00080d8610

@IWANABETHATGUY IWANABETHATGUY changed the title docs: ensure_lazy_module_initialization_order docs: document ensure_lazy_module_initialization_order in code-splitting design doc Mar 27, 2026
@IWANABETHATGUY IWANABETHATGUY force-pushed the 03-27-docs_ensure_lazy_module_initialization_order branch from b588da1 to 01051fe Compare March 27, 2026 06:13
@IWANABETHATGUY IWANABETHATGUY marked this pull request as ready for review March 27, 2026 06:39
@IWANABETHATGUY IWANABETHATGUY requested a review from hyf0 March 27, 2026 06:40
@IWANABETHATGUY IWANABETHATGUY force-pushed the 03-27-docs_ensure_lazy_module_initialization_order branch from 01051fe to 4e48cf5 Compare March 27, 2026 07:53
@IWANABETHATGUY IWANABETHATGUY force-pushed the 03-27-docs_ensure_lazy_module_initialization_order branch from 4e48cf5 to 5d00745 Compare March 27, 2026 18:02
@graphite-app
Copy link
Copy Markdown
Contributor

graphite-app bot commented Mar 28, 2026

Merge activity

graphite-app bot pushed a commit that referenced this pull request Mar 28, 2026
…d is skipped (#8934)

When a PR only touches files outside the `node-changes` path filter (e.g. `meta/**`), `build-rolldown-ubuntu` is skipped and never uploads the native artifact — causing `vite-test-ubuntu` to fail unconditionally on the download step with `Artifact not found for name: rolldown-native-ubuntu-latest`.

## Change

Added the same `if` guard that already exists on the **Run Vite Tests** step to the **Download Native Rolldown Build** step in `vite-test-ubuntu`:

```yaml
- name: Download Native Rolldown Build
  if: ${{ needs.changes.outputs.node-changes == 'true' }}   # ← added
  uses: actions/download-artifact@...
  with:
    name: rolldown-native-ubuntu-latest
    path: ./packages
```

Other potentially affected jobs (`node-validation`, `vite-test-windows`) are already protected — `node-validation` by a job-level `if`, and `vite-test-windows` by its `github.ref_name == 'main'` gate.

<!-- START COPILOT ORIGINAL PROMPT -->

<details>

<summary>Original prompt</summary>

## Problem

The `vite-test-ubuntu` job (and potentially similar jobs) in `.github/workflows/ci.yml` fails when a PR only modifies files that don't match the `node-changes` path filter (e.g., doc-only changes under `meta/`).

Here's the chain of events:
1. A PR with no `node-changes` (e.g. only `meta/**` files changed) causes `needs.changes.outputs.node-changes == 'false'`.
2. `build-rolldown-ubuntu` calls `reusable-native-build.yml` with `changed: false`, which has `if: ${{ inputs.changed }}` — so the build job is **skipped** and **no artifact is uploaded**.
3. `vite-test-ubuntu` is still triggered (intentionally, for status checks), but it unconditionally runs the `Download Native Rolldown Build` step:
   ```yaml
   - name: Download Native Rolldown Build
     uses: actions/download-artifact@3e5f45b # v8.0.1
     with:
       name: rolldown-native-ubuntu-latest
       path: ./packages
   ```
   This fails with:
   > `Unable to download artifact(s): Artifact not found for name: rolldown-native-ubuntu-latest`

Note that the `Run Vite Tests` step already has the correct guard (`if: ${{ needs.changes.outputs.node-changes == 'true' }}`), but the **download step does not**.

## Fix

In `.github/workflows/ci.yml`, add `if: ${{ needs.changes.outputs.node-changes == 'true' }}` to **all** `Download Native Rolldown Build` steps that are gated on `build-rolldown-ubuntu` being skippable. Specifically, audit and fix:

- `vite-test-ubuntu` → `Download Native Rolldown Build` step (line ~200)
- `node-validation` → `Download Native Rolldown Build` step (line ~310)

Check if any other jobs in the same file have the same pattern (unconditional artifact download but the upstream build can be skipped) and fix those too.

The pattern to apply is consistent with how `Run Vite Tests` already works:
```yaml
- name: Download Native Rolldown Build
  if: ${{ needs.changes.outputs.node-changes == 'true' }}
  uses: actions/download-artifact@3e5f45b # v8.0.1
  with:
    name: rolldown-native-ubuntu-latest
    path: ./packages
```

The fix should be minimal �� only add the missing `if:` conditions to the download steps. Do not restructure jobs or change any other logic.

The following is the prior conversation context from the user's chat exploration (may be truncated):

User: Do you know why the CI is failed? Don't write code https://github.com/rolldown/rolldown/actions/runs/23636641529/job/68847218961?pr=8931

Assistant: The CI failed due to a **missing artifact**. Here's the root cause:

> `Unable to download artifact(s): Artifact not found for name: rolldown-native-ubuntu-latest`

### What happened

This job tried to **download a pre-built native artifact** named `rolldown-native-ubuntu-latest` that was supposed to have been uploaded by an earlier job in the same workflow run (`run-id: 23636641529`). That artifact was never found.

### Likely reasons

1. **The upstream build job failed or was skipped** — The job that was supposed to compile and upload `rolldown-native-ubuntu-latest` either failed before uploading, was cancelled, or was skipped entirely. This is the most common cause.
2. **Artifact upload used an incompatible version** — The error message hints that a version mismatch between `upload-artifact` and `download-artifact` actions could cause this, though this is less likely if the workflow hasn't changed recently.
3. **The artifact expired** — Unlikely here since this is a fresh run, but artifacts do have a retention period.

### How to confirm

Check the other jobs in the same workflow run (`run-id: 23636641529`) — specifically the job responsible for building and uploading `rolldown-native-ubuntu-latest`. If that job failed or was skipped, it explains why this download job couldn't find the artifact.

User: Hot to fix it?

Assistant: Now I have the full picture. Here's a clear explanation:

---

## Root Cause

The failing job tried to download the `rolldown-native-ubuntu-latest` artifact, but **that artifact was never uploaded** — because the `build-rolldown-ubuntu` job was **skipped**.

Here's why it was skipped, tracing the logic:

### 1. `build-rolldown-ubuntu` is skipped when `node-changes == false`

In `reusable-native-build.yml` (line 18):
```yaml
if: ${{ inputs.changed }}
```
The build job only runs if `changed` is `true`. The `changed` input is passed as:
```yaml
changed: ${{ needs.changes.outputs.node-changes == 'true' }}
```

### 2. Your PR only modifies a Markdown doc file

PR #8931 only changes `meta/design/code-splitting.md`. Looking at the `node-changes` path filter in `ci.yml`:

```yaml
node-changes:
  - *rust-changes   # .github/workflows/**, crates/**, Cargo.toml, etc.
  - 'packages/**'
  - 'examples/**'
  - 'scripts/**'
  - 'package.json'
  - 'justfile'
  - 'rollup'
```

`meta/**` is **not included** in this list. So the `changes` job outputs `node-changes == false`, `build-rolldown-ubuntu` is skipped, **no artifact is uploaded**, and t...

</details>

<!-- START COPILOT CODING AGENT SUFFIX -->

*This pull request was created from Copilot chat.*
>

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 Send tasks to Copilot coding agent from [Slack](https://gh.io/cca-slack-docs) and [Teams](https://gh.io/cca-teams-docs) to turn conversations into code. Copilot posts an update in your thread when it's finished.
…ing design doc (#8931)

## Summary

- Adds a new **Lazy Module Initialization Order** section to `meta/design/code-splitting.md` documenting the `ensure_lazy_module_initialization_order` pass
- Explains the problem: when wrapped CJS init calls are split across different unwrapped ESM modules, the default placement can produce incorrect initialization order (with a concrete example based on #5531)
- Documents the 6-step algorithm, the `js_import_order` DFS helper, and the `insert_map`/`remove_map` output consumed by the finalizer
- Extends the pipeline diagram to show post-ChunkGraph processing steps (`compute_cross_chunk_links`, `ensure_lazy_module_initialization_order`, `on_demand_wrapping`, `merge_cjs_namespace`)
- Updates the key files list to include `linking_metadata.rs`

## Test plan

- [x] Read through the updated design doc for accuracy and clarity
- [x] No code changes — documentation only

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@graphite-app graphite-app bot force-pushed the 03-27-docs_ensure_lazy_module_initialization_order branch from 5d00745 to 6ab459a Compare March 28, 2026 02:14
@graphite-app graphite-app bot merged commit 6ab459a into main Mar 28, 2026
30 checks passed
@graphite-app graphite-app bot deleted the 03-27-docs_ensure_lazy_module_initialization_order branch March 28, 2026 02:15
This was referenced Apr 1, 2026
shulaoda added a commit that referenced this pull request Apr 1, 2026
## [1.0.0-rc.13] - 2026-04-01

### 🚀 Features

- add friendly error for unloadable virtual modules (#8955) by @sapphi-red
- better error message for unsupported CSS error (#8911) by @sapphi-red

### 🐛 Bug Fixes

- prevent chunk merging from leaking entry side effects (#8979) by @IWANABETHATGUY
- correct inlining based on module's def format and esModule flag (#8975) by @h-a-n-a
- generate init calls for excluded re-exports in strict execution order (#8858) by @IWANABETHATGUY
- consistent order for `meta.chunks` in `renderChunk` hook (#8956) by @sapphi-red
- subpath imports in glob imports failing to find files (#8885) by @kalvenschraut
- browser: bundle binding types in dts output (#8930) by @nyan-left
- ci: guard artifact download step in `vite-test-ubuntu` when build is skipped (#8934) by @Copilot
- track CJS re-export import records to fix inline const and tree-shaking (#8925) by @h-a-n-a
- use ImportKind::Import for common-chunk root computation (#8899) by @IWANABETHATGUY
- watch: clear emitted_filenames between rebuilds (#8914) by @IWANABETHATGUY
- ci: cache esbuild snapshots to avoid 429 rate limiting (#8921) by @IWANABETHATGUY
- always check circular deps in chunk optimizer (#8915) by @IWANABETHATGUY
- don't mark calls to reassigned bindings as pure (#8917) by @IWANABETHATGUY
- magic-string: throw TypeError for non-string content args (#8905) by @IWANABETHATGUY
- magic-string: add split-point validation and overwrite/update options (#8904) by @IWANABETHATGUY

### 🚜 Refactor

- pre-compute has_side_effects on ChunkCandidate (#8981) by @IWANABETHATGUY
- cleanup and simplify in dynamic_import.rs (#8927) by @ulrichstark
- rename came_from_cjs to came_from_commonjs for consistency (#8938) by @IWANABETHATGUY
- inline `create_ecma_view` return destructuring and remove redundant binding (#8932) by @shulaoda

### 📚 Documentation

- document ensure_lazy_module_initialization_order in code-splitting design doc (#8931) by @IWANABETHATGUY

### 🧪 Testing

- add regression test for runtime helper circular dependency (#8958) by @h-a-n-a
- enable 8 previously-skipped MagicString remove tests (#8945) by @IWANABETHATGUY
- add test for why PureAnnotation is needed in execution order check (#8933) by @IWANABETHATGUY

### ⚙️ Miscellaneous Tasks

- add `@emnapi/runtime` and `@emnapi/core` as direct deps of `@rolldown/browser` (#8978) by @Copilot
- deps: update dependency vite-plus to v0.1.15 (#8970) by @renovate[bot]
- deps: update dependency oxfmt to ^0.43.0 (#8969) by @renovate[bot]
- deps: upgrade oxc to 0.123.0 (#8967) by @shulaoda
- justfile: deduplicate update-submodule as alias of setup-submodule (#8968) by @shulaoda
- deps: update rollup submodule for tests to v4.60.1 (#8965) by @sapphi-red
- deps: update test262 submodule for tests (#8966) by @sapphi-red
- remove unused `type-check` scripts (#8957) by @sapphi-red
- deps: update actions/cache action to v5 (#8953) by @renovate[bot]
- deps: update npm packages to v6 (major) (#8954) by @renovate[bot]
- deps: update npm packages (#8948) by @renovate[bot]
- deps: update rust crates (#8949) by @renovate[bot]
- deps: update github-actions (#8947) by @renovate[bot]
- deps: update napi (#8943) by @renovate[bot]
- deps: update dependency rolldown-plugin-dts to ^0.23.0 (#8944) by @renovate[bot]
- regenerate testing snapshots (#8928) by @ulrichstark
- deps: update dependency rust to v1.94.1 (#8923) by @renovate[bot]

### ❤️ New Contributors

* @kalvenschraut made their first contribution in [#8885](#8885)
* @nyan-left made their first contribution in [#8930](#8930)

Co-authored-by: shulaoda <[email protected]>
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.

2 participants