feat: add swipl-web-no-data build variant (external wasm, no data) - #1203
Draft
jeswr wants to merge 1 commit into
Draft
feat: add swipl-web-no-data build variant (external wasm, no data)#1203jeswr wants to merge 1 commit into
jeswr wants to merge 1 commit into
Conversation
Adds the missing cell of the build matrix: an external, streamable .wasm (like swipl-web) with no .data file and no base64 embedding (like swipl-bundle-no-data). Boots from a saved state only. - docker/swipl-web-no-data.cmake: new Emscripten link target appended to swipl-devel's EmscriptenTargets.cmake at image build time; guarded so it no-ops if swipl-devel ships the target upstream. - package.json: extract the new artifacts from the build container. - dist/loadImageWeb.ts: loadImageDefault-style helper for the variant. - tests: node + puppeteer smoke tests that boot from a qsave image and assert only the .wasm is fetched (never a .data). - nodejs.yml: cache key now also hashes docker/*, so Docker build changes (including this one) invalidate cached artifacts. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
What
Adds the missing cell of the build matrix:
swipl-web-no-data— an external, streamable.wasm(likeswipl-web) with no.datafile and no base64 embedding (likeswipl-bundle-no-data)..data(1.6 MB)swipl-web.wasm(streamable)swipl-bundleswipl-bundle-no-dataswipl-web-no-data(this PR).wasm(streamable)Like
swipl-bundle-no-data, the new variant ships no Prolog library, so it must boot from a saved state (-x image.pvm, see "Generating an Image" in the README). For embedders that already boot from an image (e.g. eye-js, see eyereasoner/eye-js#1957), this is the smallest and best-cacheable way to deliver SWI-Prolog: the browser can compile the wasm withWebAssembly.instantiateStreamingwhile it downloads, and cache it independently of application JS.How
The three existing variants are link targets defined in swipl-devel's
cmake/EmscriptenTargets.cmake; this repo's Docker build just compiles them anddocker cps the artifacts out. The new target is the cross product of flags that already exist there:WASM_DIST_LINK_FLAGSwithout--preload-file(drops the.dataand the file-packager glue) and without-s SINGLE_FILE(keeps the wasm external).docker/swipl-web-no-data.cmake(new): the link target, reusingWASM_DIST_LINK_FLAGS/SWIPL_SRC/PREJS/POSTJSfromEmscriptenTargets.cmake. Guarded withif(NOT TARGET ...)so it becomes a no-op if swipl-devel ships the target upstream one day (happy to file it there as a follow-up).docker/Dockerfile: appends the snippet to swipl-devel'sEmscriptenTargets.cmakeafter checkout. Appending (rather than a context patch) keeps working acrossSWIPL_COMMITbumps from the update workflow.package.json: two newbuild:wasm-docker:extract:*entries copyswipl-web-no-data.js/swipl-web-no-data.wasmout of the container (picked up automatically byrun-s build:wasm-docker:extract:*).dist/swipl/swipl-web-no-data.d.ts,dist/loadImageWeb.ts: typings + aloadImageDefault-style helper bound to the new variant.tests/node.js: boots the new variant from aqsave_programimage and asserts the answer is produced, that only the.wasmis located (never a.data), and that the glue contains no data-preload reference.tests/browser.js+examples/browser-no-data.html: same end-to-end in Puppeteer, asserting via the network log thatswipl-web-no-data.wasmis fetched and no.datarequest is ever made..github/workflows/nodejs.yml: the build cache key now also hashesdocker/*. This is needed for this PR (otherwise CI restores the cacheddist/swipland never builds the new artifacts) and fixes a latent issue where Dockerfile changes did not invalidate the artifact cache.Wire sizes
Measured on the published swipl-wasm 8.0.3 artifacts (brotli
-q 11, via Node'szlib):swipl-web.wasmswipl-web.jsswipl-web.dataswipl-bundle-no-data.jsswipl-bundle.jsExpected for
swipl-web-no-data(estimate — the artifacts are produced by CI, see below): the.wasmlinks from the same objects with the same codegen flags, so ~2.09 MB raw / ~0.60 MB brotli; the glue is theswipl-webglue minus the file-packager block, ~146 KB raw / ~33 KB brotli (measured on an emulation, see below). Total ~0.64 MB brotli + the application's own.pvmimage, versus ~1.60 MB forswipl-webtoday (which unconditionally drags the.data) and 1.40 MB forswipl-bundle.Against
swipl-bundle-no-data(~0.65 MB) the byte win is small — the real difference is delivery quality: streaming wasm compile instead of parsing 2.5 MB of JavaScript and base64-decoding the wasm out of it, plus the.wasmbeing separately cacheable.One cost to be aware of: the npm tarball grows by roughly the new
swipl-web-no-data.js+swipl-web-no-data.wasm(~2.3 MB raw). The new.wasmshould be functionally identical toswipl-web.wasm(only the packaging flags differ), so if tarball size matters we could later dedupe by shipping only the glue and defaultinglocateFiletoswipl-web.wasm— kept out of this PR to avoid coupling the variants.Validation status
Build config authored but NOT validated in the author's environment — needs CI to produce/verify the artifacts. I could not run the emsdk Docker build on the machine this was authored on (2-core box, insufficient disk headroom). What was validated locally:
swipl-web.jsglue and removing the file-packager IIFE (precisely the code that--preload-fileadds) yields a glue that boots-x image.pvmfrom aqsave_program/1image with onlyswipl-web.wasmever located — no.datarequest — and answers queries correctly (current_prolog_flag(version, 100110)). This is the exact shape of glue Emscripten emits without--preload-file.npm run tscandnpm run lintpass.Because the cache key changes, this PR's CI run performs a full Docker build and then runs the new tests against the freshly built artifacts — that run is the authoritative validation. Note the full-build path failed transiently on 2 July (
zlib.netdownload flaked on thefix/update-emsdk-v6.0.2branch); the URL responds again, so a re-run should suffice if it recurs. If it keeps flaking, switching the Dockerfile tohttps://github.com/madler/zlib/releases/download/v$ZLIB_VERSION/zlib-$ZLIB_VERSION.tar.gzwould be a robust follow-up.Review timing: This draft was prepared with Claude; I (@jeswr) will personally review it before it progresses. I'm currently batching a lot of work in flight, so expect active review Wednesday–Friday (8–10 July).