Two research dossiers under docs/features: - async/: Asyncify currData contention — the clipboard crash and post-idle tool hang as one disease (single global suspension slot, three producers), asyncify internals walkthroughs, prior art, arbiter designs A/B. - wasm-exceptions/: -fexceptions vs -fwasm-exceptions — measured invoke-driven share of the asyncify tax on pcbnew (59% raw / 64% gzip; download 64.5->36 MB if migrated), KiCad dialog-in-catch audit (85 direct / 93 review of 636, catch_audit.py included), binaryen toolchain status (partial EH support since v125; TryTable unsupported), and a catch-arm-hoisting pre-pass design that would obsolete the KiCad-side refactor. Cross-linked with the parked KICAD_WASM_EH end-to-end experiment (docs/wasm-exceptions-experiment.md). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
5.7 KiB
5.7 KiB
03 — Toolchain compatibility status (verified 2026-06-10/11)
The compatibility matrix
| Combination | Status |
|---|---|
ASYNCIFY=1 + -fexceptions (ours today) |
Supported; the expensive-but-working baseline |
ASYNCIFY=1 + -fwasm-exceptions |
emcc emits a warning, not an error ("Parts of the program that mix ASYNCIFY and exceptions will not compile"); Binaryen support is partial — everything except unwinding from inside a catch arm (see 05) |
SUPPORT_LONGJMP=emscripten + -fwasm-exceptions |
Hard error in emcc; wasm-EH pairs with SUPPORT_LONGJMP=wasm (automatic default) |
JSPI (-sJSPI) + -fwasm-exceptions |
Compatible (JSPI doesn't transform the wasm) — but fibers do not exist under JSPI (Asyncify.setDataHeader is not a function, emscripten #18180), and KiCad tools are fibers → JSPI stays closed for us |
Mixing -fexceptions and -fwasm-exceptions objects at link |
Not supported; produces inconsistent internal state (emscripten #20165, #18500) — flag flip must be uniform across wx + kicad + test apps |
Binaryen history (the part that moved since our earlier research)
- Partial asyncify+wasm-EH support merged upstream 2025-11-19, commit
ad13362b"Add partial support for -fwasm-exceptions in Asyncify (#5343) (#5475)" — these are the caiiiycuk PRs from 2022/2023 (the author previously maintained thecaiiiycuk/binaryen-fwasm-exceptionsfork). Shipped in binaryen v125 (released the same day). Upstream is at v130 (2026-06-01). - The merge is +114 lines in
src/passes/Asyncify.cppplus 1,139 lines of lit tests (asyncify_pass-arg=asyncify-eh*.wast): Try-body traversal + an asserts-mode tripwire. Details and the remaining hole in05-asyncify-fork-design.md. - Notable gaps in current main: the documented
asyncify-ignore-unwind-from-catchpass-arg is not consumed anywhere in the code (dead docs);TryTable(standardized exnref EH encoding) is entirely unsupported by the pass; tail calls remain fatal. - Tracking issue for full support: WebAssembly/binaryen #4470 (open).
Our local toolchain
- emsdk-bundled
wasm-opt: v121 (version_121-72-g7353da707) — verified 612 commits behind the EH merge. We do not have even the partial support locally. - This only matters for the post-link step:
scripts/common/apply-asyncify.shresolves its binary viascripts/common/get-wasm-opt.sh, so a newer/patched wasm-opt can be slotted in for asyncify alone, without touching the emsdk compiler side. (apply-finalize.shkeeps using the emsdkwasm-emscripten-finalize; cross-version binary compatibility at the .wasm level is fine.) - The compiler side (LLVM emitting wasm-EH instructions) has been mature for years; the emcc warning about ASYNCIFY=1 is expected and survivable once the Binaryen side is fixed.
setjmp/longjmp inventory (often raised as a blocker — it is not)
- KiCad: zero direct
setjmp/libpng usage outsidethirdparty/(andthirdparty/does not bundle libpng). All image I/O goes throughwxImage. - wxWidgets bundles
png,jpeg,tiff,zlib. Both libpng'spngerror.cand wx's own PNG handler use the classic pattern (src/common/imagpng.cpp:319/:527setjmp,:204longjmp); libjpeg's error manager likewise. - Today this rides JS-based SjLj (default
SUPPORT_LONGJMP=emscripten, invoke machinery). Under wasm-EH it becomesSUPPORT_LONGJMP=wasmautomatically, no source changes. Constraints don't bite: setjmp is not called from C++ catch clauses there, and the PNG/JPEG decode paths never suspend (pure computation → never asyncify-instrumented → the unwind-from-catch limitation cannot arise in them).
The parked end-to-end experiment (2026-06-11) — what it taught us
A parallel session actually built pcbnew with wasm-EH end-to-end
(docs/wasm-exceptions-experiment.md; full plumbing patch in its appendix, gated behind
KICAD_WASM_EH=1). Findings that supersede/extend the matrix above:
- Working flag set:
-fwasm-exceptions -sSUPPORT_LONGJMP=wasm -sWASM_LEGACY_EXCEPTIONS=0, uniformly on every compile and link (deps incl. boost/cairo/harfbuzz, wx, kicad). - Result: links clean, raw pcbnew 92 MB (vs 338 MB post-asyncify pre-O2 today), zero
invoke_*/dynCall— corroborates this dossier's measurements from the compiler side. - Blocker #1 (before the catch issue ever arises): emscripten 4.0.2's LLVM emits an
invalid
br_table(label arity mismatch) in OpenCASCADE (ShapeUpgrade_SplitSurface::Build) under wasm-EH — module malformed at the source; no Binaryen can fix it. Resume = emsdk bump (5.0.7+), then full clean rebuild (~2.5–3 h). - Encoding wrinkle: 4.0.2's legacy encoding output failed Binaryen parsing
(
popping from empty stack), forcingWASM_LEGACY_EXCEPTIONS=0(exnref). But the asyncify pass has zeroTryTablesupport (05 §2) — so after the emsdk bump, the encoding decision forks the asyncify work: legacy → v125 partial support + the catch-arm-hoisting pre-pass; exnref → TryTable support + exnref spilling (05 §new-EH). - Ops gotchas recorded there: deps scripts skip-if-stamped (flag changes don't trigger
rebuilds —
undefined symbol: emscripten_longjmpfrom stalelibcairo.a); CI already self-builds Binaryen v130 for the post-link chain; build-time payoff is also large (the ~52 min-O2pass shrinks with the module).
Browser support notes
wasm-EH (legacy encoding) is supported across modern Chrome/Firefox/Safari. One watch item
from research: a Safari 26.0 regression crashing -fwasm-exceptions apps at startup was
reported September 2025 (emscripten #25365) — re-check status at migration time.