The browser builds run on every engine: memory64 lowered at link, relaxed SIMD out, the Safari gates gone - #4051
Conversation
45e7f69 to
91bd3e7
Compare
There was a problem hiding this comment.
🟡 Changes recommended
site-dasllama/test_metadata.py’s new cross-origin subresource assertion misclassifies same-origin relative URLs as cross-origin, making the test incorrectly fail on valid markup changes.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
This PR updates the web/wasm toolchain and both daslang.io + dasllama.io site surfaces so the compiled browser artifacts run on Safari/iOS by linking wasm64 builds with memory lowered to wasm32 at link time (-sMEMORY64=2) and by removing +relaxed-simd, while also aligning cross-origin isolation (COOP/COEP) behavior and removing browser-feature gating.
Changes:
- Switch wasm64 link paths to
-sMEMORY64=2(keep 8-byte pointers, lower memory to 32-bit at link) and drop+relaxed-simdfrom the wasm target feature string (plus codegen/cache version bumps). - Remove memory64/Safari gating across the playground UI, examples page, service worker, and Playwright tests; update dasllama.io Caddy snippet + deploy script to enforce COEP
require-corp. - Add/adjust tests and documentation to lock in invariants (no memory64 gates, no relaxed-simd, cross-origin subresources require
crossoriginunderrequire-corp).
File summaries
| File | Description |
|---|---|
| web/examples/ui/src/main.js | Removes memory64 probe gating for enabling the wasm engine; relies on build service availability only. |
| web/examples/ui/REVIEW.md | Updates checklist language for how this UI is deployed/staged and what validation must be stated. |
| web/CMakeLists.txt | Changes wasm64 link flag to -sMEMORY64=2 and documents the “compile=1/link=2” approach. |
| utils/internal/dasllama-ladder/REVIEW.md | Tightens operational rules around Caddy snippet truth + COEP must be require-corp. |
| utils/internal/dasllama-ladder/README.md | Documents why /examples/* needs COOP/COEP and how deploy reconciles the header block. |
| utils/internal/dasllama-ladder/dasllama-deploy.sh | Makes caddy_apply replace /examples/* header block when it differs (not just insert if missing). |
| utils/internal/dasllama-ladder/caddy.snippet | Switches /examples/* COEP from credentialless to require-corp. |
| utils/daspkg/REVIEW.md | Clarifies review requirements for changes on the wasm release path and clarg doc consistency. |
| utils/daspkg/README.md | Updates --wasm description to reflect link-time lowering and broader browser support. |
| utils/daspkg/commands.das | Switches wasm release link flags to -sMEMORY64=2 and updates documentation comments. |
| tests/jit_tests/wasm_idot_lowering.das | Adds a test that inspects emitted object “target_features” to ensure no relaxed-simd and simd128 present. |
| src/builtin/module_jit.cpp | Updates link_wasm to pass -sMEMORY64=2 when targeting wasm64. |
| skills/daspkg.md | Updates daspkg skill docs to describe link-time lowering and removal of relaxed SIMD for WebKit reach. |
| site/tests/playground/REVIEW.md | Adds rule: tests must not skip/branch by browser-engine capability; stub build service instead. |
| site/tests/playground/engine-toggle.spec.js | Removes memory64-based test.skip gates now that artifacts should run on all engines. |
| site/REVIEW.md | Updates review rules for Playwright run statements and sample coverage wording. |
| site/playground/index.html | Removes “memory64-only registration” claim from COI service worker comment. |
| site/files/examples.js | Removes wasm64 detection; switches to “compiled by default, ?force=interp for QA” and renames flags to compiledOnly. |
| site/examples/_interp.html | Updates comment to reflect ?force=interp rather than a required Safari fallback. |
| site/examples.html | Removes “memory64-only registration” claim from COI service worker comment. |
| site/coi-serviceworker.js | Removes memory64 registration gate so /examples and /playground isolate on every engine (with require-corp on WebKit). |
| site/_news/2026-09-16-the-browser-examples-now-run-on-safari-too.md | Adds daslang.io news stub announcing Safari/iOS support for compiled examples. |
| site-dasllama/test_metadata.py | Updates shell invariants (no memory64 gates, isolation probe ordering) and adds COEP/crossorigin checks. |
| site-dasllama/serve.py | Mirrors vhost change: sends COEP require-corp for /examples/ in local preview server. |
| site-dasllama/REVIEW.md | Strengthens rules around not weakening metadata/shell assertions in test_metadata.py. |
| site-dasllama/examples.html | Updates example cards to “any current browser” and replaces wasm64 tags/wording with wasm. |
| site-dasllama/_news/2026-09-16-every-browser.md | Adds dasllama.io news post explaining the change (lowered memory + relaxed SIMD removed). |
| modules/dasLLVM/REVIEW.md | Clarifies review requirements for cross-target branches and feature-set changes. |
| modules/dasLLVM/daslib/llvm_jit_run.das | Updates LLVM_JIT_EMITTER_HASH to match emitter source changes. |
| modules/dasLLVM/daslib/llvm_jit_plan.das | Bumps LLVM_JIT_CODEGEN_VERSION to invalidate cached codegen artifacts after feature-string change. |
| modules/dasLLVM/daslib/llvm_jit_common.das | Drops +relaxed-simd from wasm_target_features(). |
| modules/dasLLVM/ARCHITECTURE_TARGET_FEATURES.md | Updates architecture rationale to remove relaxed-simd for WebKit reach and explain consequences. |
| modules/dasLLAMA/REVIEW.md | Minor checklist wording updates (PERF ledger rule and followup naming). |
| modules/dasLLAMA/PERF_LEDGER.md | Adds a landed entry documenting the relaxed-simd removal and reach/perf implications. |
| examples/REVIEW.md | Broadens rule: all files in a folder with web_shell.html answer to dasLLAMA review rules. |
| examples/dasLLAMA/storywish/web_shell.html | Removes memory64 probe; adds crossorigin="anonymous" to analytics script; gates only on isolation. |
| examples/dasLLAMA/storyteller/web_shell.html | Same: remove memory64 gate; add crossorigin="anonymous" to analytics script; isolation-only gating. |
| examples/dasLLAMA/parrot/web_shell.html | Same: remove memory64 gate; add crossorigin="anonymous" to analytics script; isolation-only gating. |
| examples/dasLLAMA/REVIEW.md | Updates browser-example rules (input handling, canvas sizing, and forbids wasm feature probes for gating). |
| doc/source/reference/utils/daspkg.rst | Updates docs for --wasm option to reflect link-time lowering. |
| CHANGELIST.md | Adds an entry describing “Every browser” milestone and the main technical shifts. |
| .github/workflows/REVIEW.md | Clarifies what counts as weakening a per-PR check and notes provisioning steps vs checks. |
| .github/workflows/pages.yml | Removes Node setup step and updates deployment/build comments to match lowered wasm64 behavior. |
Review details
- Files reviewed: 43/43 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
91bd3e7 to
cb8d81a
Compare
There was a problem hiding this comment.
🔵 Needs a closer look
It changes the wasm link ABI/feature set and cross-origin isolation behavior across build tooling, runtime linkage, deployment scripts, and both sites, so it needs final human review despite no specific defects found in the reviewed diffs.
Review details
- Files reviewed: 43/43 changed files
- Comments generated: 0 new
- Review effort level: Lite
…axed SIMD out, the Safari gates gone Every compiled web artifact stays a wasm64 cross-compile inside - host and target pointer widths match, so the baked layouts stay honest - and now links -sMEMORY64=2: the objects and archives keep their 8-byte pointers, the JS boundary still passes them as BigInt, and Binaryen lowers the memory itself to 32-bit, so an engine without memory64 runs the module. WebKit is that engine, on every Mac, iPhone and iPad. daspkg release wasm, dasLLVM's link_wasm (the playground's module rail) and the web tree all say so in one place each. +relaxed-simd leaves the wasm feature string. WebKit implements none of the relaxed opcodes, and the feature put f32x4.relaxed_max - the backend's lowering of an nnan vector max, which sec.12 believed it never emitted - into every release, so Safari refused the whole module at validation once memory64 was out of the way. The one thing the feature bought, f32x4.relaxed_madd, costs nothing to lose: Pocket TTS on the storywish page reads the same real-time factor (0.167-0.171) with and without it. The codegen version moves so no cached object keeps the old string. The gates that named memory64 are gone: the three dasllama.io shells, the daslang.io examples page and its coi service worker, the playground's engine radio and its tests, and the node 24 step pages.yml needed only because a true memory64 module refuses node 22. dasllama.io's /examples/* sends COEP require-corp, the one value WebKit implements; the analytics script, the only cross-origin subresource, loads with crossorigin since its host allows CORS. test_metadata.py now fails a shell that names memory64 or Safari. Both sites get a news post. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
cb8d81a to
bf86331
Compare
There was a problem hiding this comment.
🟡 Changes recommended
dasllama-deploy.sh’s new examples_block() parsing won’t terminate on indented } lines, which can make the snippet-vs-vhost comparison always differ and force unnecessary rewrites/reloads on every deploy run.
Get a fresh assessment by requesting another Copilot review.
Review details
- Files reviewed: 46/46 changed files
- Comments generated: 2
- Review effort level: Lite
behavior change: every compiled browser artifact now runs on Safari and iOS - after the merge the operator runs
dasllama-deploy.sh caddyon the dasllama.io box (the vhost's COEP value changes) androll_toolchain.sh --ref <merge sha>on zen4 (the playground's build host), or Safari visitors keep getting a module they cannot load.Why. The compiled browser builds were memory64 modules, and WebKit implements neither memory64 nor relaxed SIMD, so on every Mac, iPhone and iPad the dasllama.io examples showed a note and daslang.io's example cards fell back to the interpreter.
What changes.
-sMEMORY64=2: the objects and archives keep their 8-byte pointers, Binaryen lowers the memory to 32-bit, and the JS boundary keeps its BigInt pointers.+relaxed-simd, and the codegen version moves so no cached object keeps the old string./examples/*sends COEPrequire-corp, the one value WebKit implements, and the shells load the analytics script withcrossorigin.dasllama-deploy.sh caddynow replaces the vhost'sheader /examples/*block when its text differs from the snippet's, where it used to splice only an absent one.crossorigin, or acredentiallessCOEP in the snippet or the preview server; the wasm idot test reads the emitted object'starget_featuresand fails onrelaxed-simd. Both sites get a news post.Observable behavior.
MAXIMUM_MEMORY).Where to look. The link line in
utils/daspkg/commands.das,link_wasminsrc/builtin/module_jit.cpp,wasm_target_featuresinmodules/dasLLVM/daslib/llvm_jit_common.das, and the COEP switch inutils/internal/dasllama-ladder/caddy.snippet.Validation, claims, ledger
Validation
site-dasllama/serve.pywithrequire-corp: river_run and storywish run on the lowered, no-relaxed builds (the relaxed build was refused at validation onf32x4.relaxed_max, op 270, function 298). Chrome: river_run, storyteller, storywish and parrot (to the microphone gate) run; storywish maps its image in 17 ms, writes story 1 and reads it (dasLLAMA tts: ... rtf 0.167-0.171), the same figures as the relaxed build - the record is the PERF_LEDGER entry. iOS was not tried.dlim_configprobe ran under node 25 here. The removedsetup-nodestep gave the runner node 24; ubuntu-latest ships 22, which the module now accepts.daspkg build --wasmthendaspkg release wasmfor river_run, storyteller, storywish, parrot anddlim_configran on macOS (emsdk 5.0.7, the libc++ host fromweb/build_wasm_host.sh), and each artifact's memory is a 32-bit shared import with no relaxed-simd feature.-exe --jit-target=wasm64-unknown-emscripten --jit-runtime-lib, the C++link_wasm):fib_loopbuilds to a 32-bit-memory standalone module and prints under the playground's own WASI shim in node (exit 0).--jit-check-abiwas not run on a lowered bundle: the objects and archives keep every 8-byte layout the check reads, and only the memory index width changed.modules/dasLLVM/tests(green, 177 s),tests/jit_tests/wasm_idot_lowering.das(4 cells, the new target-features cell included) andcross_target_folds.das(green),utils/daspkg/test_daspkg.das(248 green),site-dasllama/test_metadata.py(11 green),examples/dasLLAMA/wasm/test_mint_models.py(green),tests-cpp-smallemitter pin (green with the newLLVM_JIT_EMITTER_HASH), lint on the changed.das/.md(0 issues). Negative controls run by the TDD audit: inverting a shell's isolation predicate passes the shell test (the predicate's truth is untested, its text is), re-adding a memory64 probe fails it.dasllama-deploy.sh caddy_apply's reconcile was exercised against a fake Caddyfile withcaddyandsystemctlstubbed: a differing block is replaced, a matching one left alone, an absent one inserted, the daslang.io vhost untouched; the box itself was not run.site/tests/playground/engine-toggle.spec.js: the six un-skipped tests stub the build service and instantiate no daslang runtime, so the per-PRplayground-e2e.ymllane runs them on this PR's head; no local WASM-staged run was made._site); the first proof is the deploy.[arch]citers of the two edited sections ofARCHITECTURE_TARGET_FEATURES.mdwere audited:wasm_target_featuresmatches sec.12 string for string, andidot_wasm_simd128/intrinsic_lattice_idotemit no relaxed opcode, so sec.9 still describes them.access-control-allow-origin: *with no CORP header, socrossoriginon the tag is what lets it load underrequire-corp.Claims - stated, not tested
examples.htmlcopy on dasllama.io ("any current browser") and both news posts describe the deploy that follows this merge; they were checked against the local builds above, not the deployed site.Not done
/files/script was declined here because it moves the shell test's needles and three shell rules with it - its own change.webkitproject insite/tests/playground/playwright.config.jswould makeengine-toggle.spec.jsthe distinguishing test.MAXIMUM_MEMORYstays emscripten's 2 GB default for a lowered build; raise it deliberately if a model set outgrows it.require-corpuntil they are self-hosted.link_wasmuntil the toolchain roll named at the top.