pcbjam/site/public/gerber-demo
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Viktor Vaczi 9c475a804e jspi cleanup: remove the asyncify-era residue — dead code, conditionals, pipeline scaffolding, stale prose
The runtime is JSPI-only; this removes everything that still pretended
otherwise. Three exhaustive sweeps (C++/JS+build+CI/tests+docs) drove
the inventory; every deletion verified by grep closure + full gates.

Broken-right-now fixes:
- deploy-staging.yml passed the retired opt_level input — the workflow
  could not even start. Removed.
- env.sh carried dead exports with a live -sASYNCIFY=1 inside
  (WASM_LDFLAGS/PTHREAD_LDFLAGS, zero consumers). Removed; the
  WASM_LEGACY_EXCEPTIONS rationale rewritten to the real reason.
- docker/build.sh exported PCBJAM_ASYNC_BACKEND (read nowhere). Gone.

Dead weight removed:
- binaryen submodule (nothing builds or invokes it), wasm-opt-bench
  workflow + scripts/bench/, get-wasm-opt.sh, diagnostics.js (242 lines
  of Asyncify-API-only code), the KICAD_PIPELINE background-postprocess
  scaffolding (existed to parallelize the deleted wasm-opt phase; the
  postprocess is a seconds-long node script and now runs inline),
  build-monitor's dead asyncify rows, sched-context orphan build
  output, dead .gitignore entries, the .jspi-assets spike dir (the two
  wf-result research JSONs moved to docs/features/async/migration-evidence/).
- bindings: fiber_park.h + its 12 embind registrations (broken-if-
  called under JSPI), the kicadOpenFileStart/OPEN_JOB starter route,
  main_stack_runner.h + 5 includes, the always-null context-sleep weak
  hook in nanosleep_yield.c.
- shim: the backend field (installed-flag idempotency instead),
  noteContextWait (dead both sides), the __wxAsyncifyDump alias (+ the
  WasmTool fallback and string-dump normalize branch).
- web: the emscripten-6-ignored mainScriptUrlOrBlob option in boot.ts
  (gerber-demo keeps it: it loads the deployed CDN release, which
  predates emscripten 6 — noted inline).

Conditionals: all 'backend === jspi' checks reduced to scheduler-
presence checks; races_quiescent re-keyed from Asyncify.state (vacuous)
to real backlog quiescence (resumeReady/mutatorQueue — NOT _windowLive,
which is the probing activation's own window by definition).

Renames (identifiers only, no file renames): ASYNC_LINK_FLAGS→
JSPI_LINK_FLAGS and Makefile ASYNC_LDFLAGS→JSPI_LDFLAGS,
kicadCollabFiberBusy→kicadCollabBusy (embind + web + tests),
collab_common.h fiber*→apply*/coroutine naming, asyncifySignatures→
wasmTrapSignatures (lists byte-identical).

Tests: the two remaining vacuous [wx-asyncify]/fiber-resume-refused
asserts re-keyed to live JSPI beacons; eeschema-load's failure message
no longer sends the developer to a deleted script; wait-beacons' dead
families/parser deleted; lane-0 legacy-glue guards removed (lane 0 is
unconstructible); the embind test.fail re-gated with the JSPI reason
(plain embind invokers cannot suspend — verified still failing);
lint-determinism now scans tests/jspi (166 files clean);
eeschema-collab local-move gated to chromium (~50% flaky on FF even
solo; pcbnew twin covers both engines).

Docs: DEBUG.md rewritten as the JSPI debugging guide; build.md
describes the single-phase build; docs/features/async/README.md
banner-marked historical and repointed at the NEW
23-jspi-runtime.md (current architecture: export census, turnstile,
libcontext ownership + refusal contract, embind call shapes, the
em-pthread service-wrapper trick, exception policy, known gaps).

Gates on the cleaned tree: test:e2e 725 passed / 0 failed (after the
quiescence-probe fix; the 3 other reds were verified contention flakes
solo-green or the documented FF gate), web 76/0, jspi 18/18 both
engines, vitest 295/295 + 17/17, all lints green, live-app census
clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016X9eh1s5sTx1o9Em9KBuwR
2026-08-14 09:25:32 +02:00
..
board feat: lazily-loaded Gerber viewer demo in the blog, served from R2 2026-06-17 10:28:06 +02:00
boot.js jspi cleanup: remove the asyncify-era residue — dead code, conditionals, pipeline scaffolding, stale prose 2026-08-14 09:25:32 +02:00
index.html feat: lazily-loaded Gerber viewer demo in the blog, served from R2 2026-06-17 10:28:06 +02:00
poster.png feat: lazily-loaded Gerber viewer demo in the blog, served from R2 2026-06-17 10:28:06 +02:00
README.md feat(site): move the marketing site from Vercel to Cloudflare Pages 2026-07-27 13:41:51 +02:00

Gerber viewer demo

KiCad's gerbview compiled to WebAssembly, embedded (lazily) in the landing page and the blog post. Click → it streams the WASM and renders the bundled tiny_tapeout board in-browser.

The WASM is not kept here — boot.js loads it from the versioned CDN (cdn.pcbjam.com), the same artifacts the demo/app deploy publishes. It resolves gerbview's immutable, content-addressed folder at runtime from the release manifest, so this page always shows the latest deployed gerbview with no manual sync:

manifest-latest.json  ->  { tag }
manifest-<tag>.json   ->  tools.gerbview -> <ver>
base = https://cdn.pcbjam.com/wasm/gerbview/<ver>

See docs/features/demo-deploy/0001-wasm-cdn-versioning.md (in pcbjam-private) for the CDN layout, manifest shapes, and header matrix.

Files here (site/public/gerber-demo/)

Path What it does
index.html The iframe/standalone target — minimal page with the #main-window / #window-container the WASM needs.
boot.js Boot harness: resolves gerbview's CDN folder from the manifest, configures Emscripten Module, seeds KiCad config, preloads the board into MEMFS, auto-opens it via Module.arguments, and injects wx.js → wx-dom.js → gerbview.js from the CDN.
board/ The tiny_tapeout Gerber layers (committed) the demo opens.
poster.png Static fallback shown to browsers that can't run the live viewer.

The folder is cross-origin to this page (which is COEP require-corp); the CDN sends Cross-Origin-Resource-Policy: cross-origin + Access-Control-Allow-Origin: *, and the cross-origin pthread worker is loaded via a same-origin blob: importScripts shim (new Worker(<cross-origin URL>) is a SecurityError). This mirrors the standalone editor's web/standalone/src/wasm/boot.ts.

Path What it does
src/sections/GerberDemoSection.astro The landing-page showcase: a poster + launch button that opens /gerber-demo/ in a new tab (the landing itself is not cross-origin isolated).
src/components/GerberDemo.astro The blog embed: lazy click-to-load iframe, cross-origin-isolation reload guard, feature-detect + poster fallback.
astro.config.mjs + src/middleware.ts Dev cross-origin-isolation headers (COOP/COEP require-corp).
public/_headers Prod COOP/COEP on Cloudflare Pages, scoped to the blog post + /gerber-demo/ routes (both URL forms of the post).

Dev overrides

boot.js reads query params so you can point it elsewhere without a rebuild:

Param Effect
?tag=<tag> Pin a specific release instead of following manifest-latest.json.
?cdn=<root> Swap the CDN root (e.g. a local mirror serving manifest-*.json + gerbview/<ver>/).
?base=<folder> Use a tool folder verbatim (e.g. a fresh local build) — skips manifest resolution.

The live viewer needs SharedArrayBuffer + WebGL2 (Chrome/Edge/Firefox, Safari 15.2+); other browsers get poster.png.

Updating KICAD_VERSION_DIR

boot.js seeds KiCad config under a version dir (currently "10.0") to suppress the first-run wizard. It must match the deployed build's GetMajorMinorVersion(). If a future deploy bumps KiCad's major.minor, update the KICAD_VERSION_DIR constant in boot.js (same coupling as web/standalone/src/wasm/constants.ts).