| Filename | Latest commit message | Latest commit date |
|---|---|---|
THE BUG IS FIXED. tests/kicad/quasimodal-strand.spec.ts flips from a test.fail() pin to a plain green regression test: 3/3 runs closed=true dialogs=0 refused-resumes=0 (was closed=false dialogs=1 refused-resumes=1 on every run). Mechanism: a quasi-modal's nested event loop parked on the TOOL COROUTINE's stack, which suspends the fiber's body where the fiber layer cannot see it — so the stale-fiber guard quarantined the fiber and then refused its own resume, the dispatch guard was never released, and every click after that was deferred forever. Bouncing the nested loop onto the main stack leaves the coroutine suspended the legitimate way (a recorded fiber swap), so nothing is quarantined and nothing is refused. Layering, so this is not a pile of WASM ifdefs in KiCad: - wx (3d37db3bf1) owns the POLICY and the hook; it must not know what a coroutine is. - wasm/bindings/main_stack_runner.h is the only place that may know both sides: it finds the frame's TOOL_MANAGER and bounces via RunMainStack. Header-only and self-installing, so no build-script change; included by every editor's binding TU. - KiCad gets ONE ifdef-free method (2c777efede), needed only because TOOL_STATE is opaque outside TOOL_MANAGER. libcontext and dialog_shim are untouched — an earlier draft edited both and was reverted. This also reframes the remaining plan: the doc-19 class is closed WITHOUT migrating tool coroutines onto scheduler contexts. Note it does not make the wait a context yield — waits still park in place, just never on a coroutine stack. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TEHGiiXMShNXbBr7gSJ7iz |
||
| .. | ||
| bindings | ||
| cli | ||
| cmake | ||
| editor | ||
| gl1 | ||
| kiplatform | ||
| ngspice-service | ||
| occ-service | ||
| shims | ||
| stubs | ||
| tools | ||
| README.md | ||
WASM Compatibility Layer
This directory contains WASM-specific implementations that allow KiCad to run in a web browser while keeping our KiCad fork as close to upstream as possible.
Principle
Instead of patching KiCad source files, we:
- Provide alternative implementations for platform-specific code (kiplatform)
- Stub out libraries/features that can't work in the browser (libgit2, curl, nng, scripting, 3D viewer, ...)
- Expose KiCad to JavaScript via Embind bindings
- Override host package detection during cross-compilation (cmake find-modules)
The KiCad-side hooks for this are small if(EMSCRIPTEN) branches in KiCad's own
CMakeLists that pull sources from this directory — see "How it's wired" below.
Directory Structure
wasm/
├── README.md # This file
├── kiplatform/ # Platform abstraction implementations (compiled into KiCad)
│ ├── app.cpp # App lifecycle (paths, startup)
│ ├── drivers.cpp # GPU detection (returns "WebGL")
│ ├── environment.cpp # Environment variables
│ ├── io.cpp # File I/O (WASM virtual filesystem)
│ ├── policy.cpp # Security policy (always permissive)
│ ├── secrets.cpp # Credential storage
│ ├── sysinfo.cpp # System information
│ ├── printing.cpp # Print support (browser print())
│ └── ui.cpp # UI helpers
├── bindings/ # Embind bindings exposing each app to JavaScript
│ ├── pcbnew_embind.cpp
│ ├── eeschema_embind.cpp
│ ├── pl_editor_embind.cpp
│ └── calculator_embind.cpp
├── stubs/ # Stub implementations + header shims for unavailable deps
│ ├── *.c / *.cpp # libgit2, curl, nng, scripting, 3D viewer, frame stubs, ...
│ ├── char_traits_uint16_workaround.h
│ └── GL/ nng/ ngspice/ # Header stubs found via include paths
└── cmake/ # CMake find-module overrides for cross-compilation
└── Find*.cmake / Use*.cmake
How it's wired
kiplatform — compiled into KiCad
The kiplatform/*.cpp files are added directly to KiCad's kiplatform library by an
if(EMSCRIPTEN) branch in kicad/libs/kiplatform/CMakeLists.txt, which references
them as ${PROJECT_SOURCE_DIR}/../wasm/kiplatform/*.cpp. There is no separate
libkiplatform_wasm.a.
stubs — compiled by the build script and KiCad CMakeLists
scripts/kicad/build-kicad-target.sh compiles the C stubs (libgit2_stub.c,
curl_stub.c, nng_stub.c) and force-includes char_traits_uint16_workaround.h.
App-specific *_frame_stub.cpp / *_scripting_stub.cpp are picked up per app, and
the remaining *_stub.cpp files are pulled in by if(EMSCRIPTEN) branches in the
KiCad fork's own CMakeLists. Header stubs under GL/, nng/, ngspice/ are resolved
via include paths.
bindings — per app
build-kicad-target.sh compiles wasm/bindings/<app>_embind.cpp for the app being
built (apps without an embind file get an empty placeholder object).
cmake — module path
build-kicad-target.sh passes -DCMAKE_MODULE_PATH="${PROJECT_ROOT}/wasm/cmake" so
the WASM find-module stubs override host package detection.
Coroutine/fiber support is not in this directory — it comes from the KiCad fork's
kicad/thirdparty/libcontext/libcontext.cpp(LIBCONTEXT_PLATFORM_wasm32). The GLU tesselator comes fromkicad/libs/kimath/glu_tess/glu_tess_impl.cpp.
Adding New Implementations
- Create the implementation file in the appropriate directory (
kiplatform/,stubs/,bindings/). - Wire it in: a stub C file goes in
build-kicad-target.sh; a kiplatform/app source goes in the relevantif(EMSCRIPTEN)branch of the KiCad-side CMakeLists. - Ensure the header interface matches KiCad's expected interface.
- Test with a minimal build before full integration.