[Web] Publish the browser host runtime as @kandelo/web - #1242
Draft
mho22 wants to merge 3 commits into
Draft
Conversation
Contributor
Phase B-1 matrix build status —
|
| Package | Arch | Status | Sha |
|---|---|---|---|
| icu | wasm32 | failed | — |
| libcurl | wasm32 | failed | — |
| libcxx | wasm32 | failed | — |
| libcxx | wasm64 | failed | — |
| libiconv | wasm32 | failed | — |
| libpng | wasm32 | failed | — |
| libxml2 | wasm32 | failed | — |
| libzip | wasm32 | failed | — |
| openssl | wasm32 | failed | — |
| openssl | wasm64 | failed | — |
| sqlite | wasm32 | failed | — |
| sqlite | wasm64 | failed | — |
| zlib | wasm32 | failed | — |
| zlib | wasm64 | failed | — |
| bc | wasm32 | failed | — |
| bzip2 | wasm32 | failed | — |
| coreutils | wasm32 | failed | — |
| cpython | wasm32 | failed | — |
| curl | wasm32 | failed | — |
| dash | wasm32 | failed | — |
| diffutils | wasm32 | failed | — |
| dinit | wasm32 | failed | — |
| erlang | wasm32 | failed | — |
| fbdoom | wasm32 | failed | — |
| file | wasm32 | failed | — |
| findutils | wasm32 | failed | — |
| gawk | wasm32 | failed | — |
| git | wasm32 | failed | — |
| grep | wasm32 | failed | — |
| gzip | wasm32 | failed | — |
| homebrew-bootstrap | wasm32 | failed | — |
| kandelo-sdk | wasm32 | failed | — |
| kernel | wasm32 | failed | — |
| less | wasm32 | failed | — |
| lsof | wasm32 | failed | — |
| m4 | wasm32 | failed | — |
| make | wasm32 | failed | — |
| mariadb | wasm32 | failed | — |
| mariadb | wasm64 | failed | — |
| modeset | wasm32 | failed | — |
| msmtpd | wasm32 | failed | — |
| nano | wasm32 | failed | — |
| ncurses | wasm32 | failed | — |
| netcat | wasm32 | failed | — |
| nginx | wasm32 | failed | — |
| php | wasm32 | failed | — |
| posix-utils-lite | wasm32 | failed | — |
| ruby | wasm32 | failed | — |
| sed | wasm32 | failed | — |
| shell | wasm32 | failed | — |
| spidermonkey | wasm32 | failed | — |
| tar | wasm32 | failed | — |
| unzip | wasm32 | failed | — |
| userspace | wasm32 | failed | — |
| vim | wasm32 | failed | — |
| wget | wasm32 | failed | — |
| xz | wasm32 | failed | — |
| zip | wasm32 | failed | — |
| zstd | wasm32 | failed | — |
| bash | wasm32 | failed | — |
| lamp | wasm32 | failed | — |
| mariadb-test | wasm32 | failed | — |
| mariadb-vfs | wasm32 | failed | — |
| mariadb-vfs | wasm64 | failed | — |
| nethack | wasm32 | failed | — |
| nginx-php-vfs | wasm32 | failed | — |
| nginx-vfs | wasm32 | failed | — |
| node | wasm32 | failed | — |
| redis-vfs | wasm32 | failed | — |
| spidermonkey-node | wasm32 | failed | — |
| vim-browser-bundle | wasm32 | failed | — |
| wordpress | wasm32 | failed | — |
| nethack-browser-bundle | wasm32 | failed | — |
| node-vfs | wasm32 | failed | — |
| rootfs | wasm32 | failed | — |
Auto-generated; replaced on each push. Raw data in the publish-status workflow artifact.
Move the two `?worker&url` worker-entry imports from browser-kernel-host.ts into the new browser-kernel-assets.ts so a package build can swap that module while the repository keeps consuming it through Vite. The BrowserKernelAssets interface stays in browser-kernel-host.ts so type graphs never load the Vite-coupled module. BrowserKernel gains opt-in exposeHostFs: the kernel worker reports the VFS SharedArrayBuffer at boot and BrowserKernel.hostFs serves a synchronous main-thread filesystem view over the same bytes. It stays off by default and the reference is released in destroy(), preserving the WebKit image-switch reclaim behavior. spawnFromVfs now defaults stdin to an immediate EOF for non-PTY spawns, matching boot(), spawn(), and NodeKernelHost.spawnProgram. Without the default, a VFS-spawned program that reads fd 0 (php does at startup) retried readv(0) forever in the browser.
A downstream browser project that embeds the Kandelo kernel today
has to vendor host/src or carry a git submodule. web-libs/kandelo-web
ships BrowserKernel, the VFS backends and image helpers, and a
binaries loader as a code-only npm package, so a separate browser
IDE can depend on the browser host runtime like any other package.
The package ships no Wasm: the loader fetches ABI-verified
kernel/rootfs/program binaries from a Kandelo binaries release at
runtime and resolves a relative baseUrl (the same-origin proxy
pattern for GitHub's CORS-less release CDN) against the page URL.
Every ABI constant derives from the generated
host/src/generated/abi.ts, so a kernel ABI bump cannot leave the
package stale.
The tsdown build swaps the Vite-coupled assets module and the lazy
default-artifacts module for package-local replacements, emits each
worker entry as a single self-contained file, and fails if any
import other than the lazy Node-only import("net") survives. dist
invariants are enforced by test/dist-contract.test.ts, which builds
with the package's own tsdown devDependency, so the vitest suite
installs the package's node modules and the suite-runner fixture
provisions the directory.
The root package.json gains pack:web. That manifest is a declared
build input of the VFS-shaped packages, so
packages/registry/program-packages.json is regenerated.
apps/browser-demos imports BrowserKernel, MemoryFileSystem, and writeVfsFile from @kandelo/web through a repository alias in browserRepositoryAliases(), exercising the package entry from source in every demo page while published consumers get the bundled dist.
mho22
force-pushed
the
explore-npm-packaging
branch
from
August 11, 2026 18:59
445c919 to
fcee6b1
Compare
mho22
marked this pull request as ready for review
August 12, 2026 14:24
mho22
marked this pull request as draft
August 12, 2026 14:25
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A downstream browser project that embeds the Kandelo kernel today has to vendor
host/srcor carry a git submodule. There is no supported way to depend on the browser host runtime as an ordinary npm dependency, so a separate browser IDE cannot pick up kernel, host, or ABI updates through normal package management.This change adds
web-libs/kandelo-web, an npm package that ships the browser host runtime as code-only artifacts. The package shipsBrowserKernel, the VFS backends and image helpers, and a binaries loader. It ships no Wasm: the loader fetches ABI-verified kernel/rootfs/program binaries from a Kandelo binaries release at runtime, and every ABI constant derives from the generatedhost/src/generated/abi.ts, so a kernel ABI bump cannot leave the package stale.What changed
The branch is three commits.
[Host] Decouple BrowserKernel from Vite-only worker asset imports. The two Vite-only
?worker&urlworker-entry imports move frombrowser-kernel-host.tsinto the newbrowser-kernel-assets.ts. The package build (tsdown/rolldown) swaps that module and the lazy default-artifacts module for package-local replacements; the repository keeps consuming them through Vite unchanged. TheBrowserKernelAssetsinterface lives inbrowser-kernel-host.tsso type graphs never load the Vite-coupled module.BrowserKernelgains opt-inexposeHostFs: the kernel worker reports the VFSSharedArrayBufferat boot andBrowserKernel.hostFsgives the main thread a synchronous filesystem view over the same bytes; it stays off by default and the reference is released indestroy(), preserving the WebKit image-switch reclaim behavior.BrowserKernel.spawnFromVfsnow defaults stdin to an immediate EOF for non-PTY spawns, matchingboot(),spawn(), andNodeKernelHost.spawnProgram— without the default, a VFS-spawned program that reads fd 0 (php does at startup) retriedreadv(0)forever in the browser.[Web] Publish the browser host runtime as @kandelo/web. The package build emits each worker entry as a single self-contained file with all dependencies bundled, because consumers copy them as
new URL(...)assets where bare imports cannot resolve;deps.onlyImportfails the build if any import other than the lazy Node-onlyimport("net")survives. dist invariants are enforced byweb-libs/kandelo-web/test/dist-contract.test.ts, which builds with the package's own tsdown devDependency, soci-run-test-suite.shinstalls the package's node modules for the vitest suite and the suite-runner groups-test fixture provisions the directory. The package loader resolves a relativebaseUrl(the same-origin proxy pattern for GitHub's CORS-less release CDN) against the page URL before deriving archive URLs. The rootpackage.jsongainspack:web; that manifest is a declared build input of the VFS-shaped packages, sopackages/registry/program-packages.jsonis regenerated.[Demos] Consume BrowserKernel through @kandelo/web.
apps/browser-demosimportsBrowserKernelfrom@kandelo/webthrough a repository alias inbrowserRepositoryAliases(), dogfooding the package entry from source.Validation
examples/scratch-consumeracceptance harness printsACCEPTANCE PASSEDin cross-origin-isolated headless Chromium: it fetches the binaries-abi-v42 release, boots the kernel, runs/usr/bin/php -v, and round-trips a file through main-threadhostFs.hostFswrite grew the VFSSharedArrayBufferin place 49 MB -> 154 MB and a kernel-side php process read correct bytes through the grown region.git.wasmthrough the packaged import in the Vite dev server.