Lights up the Phase A WebShell on the C-hard pipeline (vendor/skia-
safe-op + crates/wasm-libc-shim, wired in the previous two commits)
so `cargo build --target wasm32-unknown-unknown --features skia`
followed by `wasm-bindgen --target web` produces a browser-loadable
ES module with 0 env.* imports.
What's added:
- WebBackend (src/backend/mod.rs): impl RenderBackend over a
skia-safe raster N32_PREMUL surface; presents each frame to the
host <canvas> via image_snapshot → read_pixels → ImageData →
put_image_data. end_frame surfaces present errors via
last_present_error / take_present_error so a stale failure does
not leak into a subsequent successful frame
- skia_wasm.rs: thin make_raster_surface helper so swapping in a
GPU GrContext (Phase A round 2) is a self-contained change
- mount(canvas_id) entry: locates the host <canvas>, builds a
WebBackend, paints the Phase A red-rect demo synchronously,
propagates any present error as a JsValue exception
- smoke/step-1b.html: manual smoke harness that mounts the shell
and surfaces a structured diagnostic (with regression-mode
LinkError messaging + rebuild instructions) if loading fails
- extern crate wasm_libc_shim as _; in lib.rs to keep the shim's
no_mangle symbols from being dead-code-eliminated
- .gitignore for wasm-bindgen pkg/ output
Cargo.toml feature wiring:
- default = ["web"] keeps the kickoff §1.2 wasm32-clean compile
guard CI green (stub mount, no skia)
- skia = ["dep:skia-safe", "wasm-libc-shim"] opts into the real
WebBackend + raster paint loop; the shim dep is target-gated
so only wasm32-unknown-unknown actually pulls it in
- wasm-bindgen = "=0.2.117" pinned (last release that compiles
on Rust 1.85; bump alongside the toolchain in a future commit)
Verified end-to-end:
- `cargo build … --features skia --release` green
- `wasm-bindgen --target web` produces ../pkg/*.{js,_bg.wasm}
- WebAssembly.Module.imports() returns 22 imports, all from
./openpencil_shell_web_bg.js; 0 env.* imports
- post `wasm-opt -Oz`: 1542 KiB raw / 599 KiB gzip — within
spec §6 ceiling (≤ 1024 KiB gzip)
- the kickoff §1.2 wasm32-clean compile guard still passes
(`cargo check … --no-default-features --features web`)
Browser-side manual smoke (Phase E) is still TODO; the bundle is
structurally LinkError-free but a human still needs to confirm the
red rect actually paints in Safari / Chrome / Firefox before the
sub-phase can be marked complete.
Step 1b §3.2 P0.5B Run path, sub-phase C-hard.2.
78 lines
2.8 KiB
TOML
78 lines
2.8 KiB
TOML
[package]
|
|
name = "openpencil-shell-web"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
rust-version.workspace = true
|
|
license.workspace = true
|
|
description = "OpenPencil shell — wasm32-unknown-unknown web bundle entry (Step 1b §1.2, C-hard pipeline)"
|
|
|
|
[lib]
|
|
name = "openpencil_shell_web"
|
|
path = "src/lib.rs"
|
|
crate-type = ["cdylib", "rlib"]
|
|
|
|
[dependencies]
|
|
openpencil-shell-core = { path = "../openpencil-shell-core", version = "0.1.0" }
|
|
# Step 1b §3.6: handwritten DOM mirror consumes accesskit::TreeUpdate (0.24).
|
|
accesskit = "0.24"
|
|
console_error_panic_hook = "0.1"
|
|
js-sys = "0.3"
|
|
# Pin to 0.2.117 — last wasm-bindgen-cli release compatible with the
|
|
# workspace's Rust 1.85 toolchain. Newer 0.2.120+ requires rustc 1.86.
|
|
# When the workspace bumps Rust, raise this bound.
|
|
wasm-bindgen = "=0.2.117"
|
|
|
|
# Step 1b §2.2 (post C-hard.2 lock-in 2026-05-09): wasm32-unknown-unknown
|
|
# via the vendor/skia-safe-op fork + crates/wasm-libc-shim. Optional dep
|
|
# behind the `skia` feature so `cargo check --target wasm32-unknown-
|
|
# unknown --no-default-features --features web` (the kickoff §1.2
|
|
# wasm32-clean CI baseline) still compile-checks without pulling skia
|
|
# — that path uses the stub mount entry. Phase A and onward opt in via
|
|
# `--features skia` to get the real WebBackend + raster paint loop.
|
|
[dependencies.skia-safe]
|
|
version = "0.97.0"
|
|
default-features = false
|
|
features = ["binary-cache", "textlayout"]
|
|
optional = true
|
|
|
|
# C-hard.2 libc/libcxx/libm shim — only linked when targeting
|
|
# wasm32-unknown-unknown with the `skia` feature on. The crate's lib.rs
|
|
# guards every symbol with `cfg(all(target_arch = "wasm32", target_os
|
|
# = "unknown"))` so native builds (where this would conflict with the
|
|
# host C runtime) link an empty crate.
|
|
[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
|
|
wasm-libc-shim = { path = "../wasm-libc-shim", optional = true }
|
|
|
|
[dependencies.web-sys]
|
|
version = "0.3"
|
|
features = [
|
|
"CanvasRenderingContext2d",
|
|
"CompositionEvent",
|
|
"console",
|
|
"Document",
|
|
"Element",
|
|
"Event",
|
|
"EventTarget",
|
|
"FocusEvent",
|
|
"HtmlCanvasElement",
|
|
"HtmlElement",
|
|
"ImageData",
|
|
"KeyboardEvent",
|
|
"PointerEvent",
|
|
"WheelEvent",
|
|
"Window",
|
|
]
|
|
|
|
[features]
|
|
# `web` keeps the kickoff §1.2 wasm32-unknown-unknown CI baseline green —
|
|
# the crate compile-checks as a wasm32-clean stub without pulling skia.
|
|
default = ["web"]
|
|
web = []
|
|
# `skia` opts into the Phase A WebBackend (skia-safe + raster surface).
|
|
# When the cargo target is wasm32-unknown-unknown the build also links
|
|
# the libc/libcxx/libm shim crate so the bundle is runtime-loadable.
|
|
# Native targets resolve the target-conditional shim dep to nothing.
|
|
skia = ["dep:skia-safe", "wasm-libc-shim"]
|
|
# Internal feature toggled on by `skia` to flip the cfg-target dep.
|
|
wasm-libc-shim = ["dep:wasm-libc-shim"]
|