Skip to content

fix: boot early only on ready, not on an answer from the whole archive - #33

Merged
alekswebnet merged 1 commit into
mainfrom
fix/early-boot-whole-download
Oct 14, 2026
Merged

alekswebnet merged 1 commit into
mainfrom
fix/early-boot-whole-download

Conversation

@alekswebnet

Copy link
Copy Markdown
Contributor

Closes #32.

On a host without Range, the element boots early only when the worker answers ready: true. Before, it booted on any answer that didn't say ready: false. That included the answer the worker gives once the download is whole: from the central directory, with no ready and no dependency walk. So the frame could boot before the final index had attached the library bundle, and the runtime got a 404 for the missing library.json.

Change

packages/player/src/h5p-offline-player.ts, in downloadAndIndex:

-          if (reply.ok && reply.type === 'indexed' && reply.ready !== false) {
+          if (reply.ok && reply.type === 'indexed' && reply.ready === true) {

partial and ready entered the protocol together (10137a1, 2026-09-28), so every worker that can say a partial index is ready says so with true. The final deep index, which runs anyway once the download ends, supplies the libraries and boots the frame.

Evidence

Each probe was 30 plays of the unpaced /no-range/needs-dependency.h5p with libraries, each under its own URL (temporary probe, not committed):

WebKit Chromium
Before 1, 2 and 1 failures in 30 (three runs) 0 in 30
Instrumented before every play booted on a reply with partial and ready both undefined
After 0 in 30, three runs 0 in 30

A content-only export from a host without Range was never exposed: 0 failures in 10 per engine on the old code, with the same states as the fix. The plain index refuses a package missing a library its h5p.json declares, so there's nothing to boot on. Only packages whose own libraries need one they don't carry are affected, which is #18's case.

Test

libraries.test.ts gains "boots a whole download only after the final index has supplied what its libraries need". It pins the states of the unpaced load: probing → downloading → indexing → downloading → indexing → ready, with indexing between the package's download and the bundle's. On the old condition the element had already booted, so the bundle's downloading merged into the package's and the test fails deterministically (checked as a control), not 1 time in 30.

Testing

Run Result
Player browser suite, Chromium (with browser-emulated) 171/171
Same, WebKit / Firefox 167/167 each
Player unit tests 306/306
Typecheck clean

AGENTS.md: the early-boot paragraph under the dependency walk invariant now covers this.

Release

Player patch, 0.9.4. The runtime and embed don't change. Embed 0.6.2 accepts ^0.9.3, so a player domain gets this when its site is written again.

🤖 Generated with Claude Code

On a host without Range the element indexes on every progress report and
boots early when the answer allows. Only a partial index carries `ready`,
decided by the dependency walk; once the download is whole the worker answers
from the central directory with no `ready` and no walk, and the element booted
on that answer because it checked `ready !== false`. The runtime then raced the
library bundle's attachment for the missing library.json: 1 or 2 plays in 30
failed in WebKit. Any answer but `ready: true` now waits for the final index.

Closes #32.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@alekswebnet alekswebnet self-assigned this Oct 14, 2026
@alekswebnet
alekswebnet merged commit 8c22ff8 into main Oct 14, 2026
8 checks passed
@alekswebnet
alekswebnet deleted the fix/early-boot-whole-download branch October 15, 2026 17:07
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.

Early boot on a host without Range can still race the library bundle

1 participant