Skip to content

Fix Safari: strip dead worker-entry export that breaks shell boot#838

Merged
brandonpayton merged 1 commit into
mainfrom
emdash/deployed-kandelo-not-loading-in-safari-1bm33
Jul 3, 2026
Merged

Fix Safari: strip dead worker-entry export that breaks shell boot#838
brandonpayton merged 1 commit into
mainfrom
emdash/deployed-kandelo-not-loading-in-safari-1bm33

Conversation

@brandonpayton

Copy link
Copy Markdown
Member

Problem

The deployed browser demos (https://automattic.github.io/kandelo/) never finish booting in Safari/WebKit — the shell freezes at instantiating kernel... with no console error. Chromium and Firefox are unaffected. It only reproduces in the production build, so it's invisible on the Vite dev server (which is why it couldn't be reproduced locally at first).

Root cause

Rolldown (Vite 8's bundler) synthesizes a dead export { … } on the kernel/process worker entry chunks. The source has no such export and nothing imports it — but its presence makes WebKit evaluate the type:"module" worker twice:

  1. Evaluation feat: centralized multi-process kernel #1 handles init, sets initReady = true, posts ready.
  2. Evaluation fix: dispatch_channel_syscall build errors #2 re-runs the module top level and reinstalls self.onmessage, bound to a fresh module state whose initReady is false — shadowing feat: centralized multi-process kernel #1's handler.

kernel.init() then sends register_lazy_files / register_lazy_archives and waits for an ack. Those are now handled by the uninitialized handler, which parks them in its !initReady pending queue and never replies. kernel.init() never resolves → the machine never boots.

Fix

A worker-build Vite plugin (dropWorkerEntryExports) strips the dead trailing export { … } from worker entry chunks at renderChunk, so the worker is a single-evaluation module on every engine.

The "proper" lever — preserveEntrySignatures: false — has no effect here: rolldown-vite (Vite 8 / rolldown 1.0.3) doesn't thread that option into the worker build (byte-identical output). There's an inline, dated note to revisit and drop this plugin once it does.

Verification

Reproduced and verified on real Safari 26.5 (via safaridriver) and Playwright WebKit, against a production build served exactly like GitHub Pages (service worker injects COOP/COEP, no direct headers):

Build real Safari WebKit (run echo) Chromium
Baseline (unfixed) ❌ hang at "instantiating kernel..."
Fixed ✅ boots ✅ boots + runs command ✅ boots + runs command

Confirmed the rebuilt worker chunks (kernel worker and nested process worker) no longer contain any export, and the command-run test proves the nested process worker still spawns.

Scope

One file: apps/browser-demos/vite.config.ts. No runtime/kernel/ABI changes.

🤖 Generated with Claude Code

The browser demos never finish booting in Safari/WebKit — the shell
freezes at "instantiating kernel..." with no error. Chromium and Firefox
are fine, and it only reproduces in the production build, so it is invisible
on the Vite dev server.

Root cause: rolldown (Vite 8's bundler) synthesizes a dead `export { … }` on
the kernel/process worker entry chunks. The source has no such export and
nothing imports it. But its presence makes WebKit evaluate the `type:"module"`
worker TWICE: the second (uninitialized) evaluation reinstalls `self.onmessage`
bound to a fresh module state whose `initReady` is false, shadowing the first
evaluation's handler. The kernel worker posts `ready`, but the main thread's
follow-up `register_lazy_files`/`register_lazy_archives` requests are then
handled by the uninitialized handler, which parks them in its pending queue and
never acks — so `kernel.init()` never resolves and the machine never boots.

Fix: a worker-build Vite plugin (`dropWorkerEntryExports`) strips the dead
trailing `export { … }` from worker entry chunks at `renderChunk`, making the
worker a single-evaluation module on every engine. The "proper" lever,
`preserveEntrySignatures: false`, has no effect here — rolldown-vite does not
thread it into the worker build (see the inline note to revisit).

Verified on real Safari 26.5 (via safaridriver) and Playwright WebKit against a
production build served like GitHub Pages (service worker injects COOP/COEP):
baseline hangs, fixed build boots and runs a shell command. No Chromium
regression.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot enabled auto-merge (squash) July 3, 2026 16:13
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

prepare-merge: runtime/materialization tests passed against the synthetic PR merge; package staging and durable package publishing were skipped. merge-gate=success posted on PR HEAD and squash auto-merge enabled.

@brandonpayton brandonpayton disabled auto-merge July 3, 2026 16:57
@brandonpayton brandonpayton merged commit bec8a43 into main Jul 3, 2026
108 of 112 checks passed
@brandonpayton brandonpayton deleted the emdash/deployed-kandelo-not-loading-in-safari-1bm33 branch July 3, 2026 16:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant