open-standards/wai/wai-vector/wasm/build-pkg.sh
Transaction Science 5189e5f50b wai-vector: the wasm exports and the three-engine browser leg (D7-8)
- wai/wai-vector/wasm: the sink's exports (wv_alloc, wv_free, wv_open,
  wv_close, wv_render, wv_out_ptr, wv_out_len, wv_sha256, wv_cost,
  wv_transcript, wv_projection), no_std with its own allocator, built for
  wasm32v1-none so the module is WebAssembly 1.0 only; check-mvp.mjs refuses
  any post-1.0 feature, and fails on the wasm32-unknown-unknown build.
- build-pkg.sh: the package a page serves.
- browser/: a harness that renders every listed frame of every vector in
  Chromium, WebKit and Firefox, hashes it in the page twice, re-hashes sampled
  frames in Node, recomputes the arithmetic vectors and authoring forms, and
  compares each a11y payload's transcript and projections with its text record.
  A missing engine fails the run.
- wai-vector.yml: the browser job, in a Playwright container pinned by digest,
  on the linux runner.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 02:44:44 -04:00

71 lines
3.4 KiB
Shell
Executable file

#!/usr/bin/env bash
# The package a site serves under /wai/pkg-vector/: the sink of wai.graphics.vector as
# one WebAssembly module, wai_vector.wasm, which a page instantiates with no imports
# and no glue script.
#
# bash wai/wai-vector/wasm/build-pkg.sh [<out-dir>]
#
# Writes <out-dir>/wai_vector.wasm (default wai/wai-vector/wasm/dist/pkg-vector, which
# git ignores) and prints its size and SHA-256.
#
# The module is WebAssembly 1.0 and nothing later: no SIMD, no threads, no bulk
# memory, no sign-extension operators, no saturating conversions, no reference types,
# no multi-value. That is enforced twice.
#
# 1. By the target. The module is built for wasm32v1-none, whose precompiled core
# and alloc are themselves WebAssembly 1.0. Those of wasm32-unknown-unknown are
# not: they use bulk memory, sign extension and reference types, and the linker
# carries what they use into any module linked against them, whatever
# -C target-cpu or -C target-feature the build passes. That target has no std, so
# the crate is no_std with its own allocator (src/heap.rs).
# 2. By reading the result. check-mvp.mjs decodes the module that was built: every
# section, type, segment and instruction must be 1.0's; and, as a package, it
# must have no imports, no exported function with a 64-bit parameter or result,
# no floating point, and exactly the exported functions listed below. The build
# fails otherwise, and leaves no module in <out-dir>.
#
# The crate is built without its default feature, so the module has the sink's
# exports and not the recomputation of the conformance vectors.
#
# The same source gives different module bytes on different hosts, so the SHA-256
# printed here names this build and not the source. What every host's build has in
# common is what it computes: the frames of wai/vector-conformance, checked in three
# browser engines by wai/wai-vector/browser/run.mjs.
#
# Needs bash, cargo with the wasm32v1-none target (rustup target add wasm32v1-none)
# and node >= 18.
set -euo pipefail
if [ $# -gt 1 ]; then
echo "usage: bash build-pkg.sh [<out-dir>]" >&2
exit 2
fi
CRATE="$(cd "$(dirname "$0")" && pwd -P)"
OUT="${1:-$CRATE/dist/pkg-vector}"
# The package's exported functions. A function added to the sink is added here.
FUNCTIONS=wv_add_set,wv_alloc,wv_close,wv_cost,wv_free,wv_open,wv_out_len,wv_out_ptr,wv_projection,wv_render,wv_sha256,wv_transcript
for t in cargo node; do
command -v "$t" >/dev/null || { echo "pkg-vector: needs $t" >&2; exit 1; }
done
mkdir -p "$OUT"
OUT="$(cd "$OUT" && pwd -P)"
rm -f "$OUT/wai_vector.wasm"
cd "$CRATE"
# Asked of the toolchain this crate builds with, before anything is built.
LIBDIR="$(rustc --print target-libdir --target wasm32v1-none 2>/dev/null || true)"
if [ -z "$LIBDIR" ] || [ ! -d "$LIBDIR" ]; then
echo "pkg-vector: this toolchain has no wasm32v1-none target (rustup target add wasm32v1-none)" >&2
exit 1
fi
cargo build --locked --release --target wasm32v1-none --no-default-features
TARGET_DIR="$(cargo metadata --locked --format-version 1 --no-deps \
| node -e 'let s = ""; process.stdin.on("data", (d) => { s += d; }).on("end", () => console.log(JSON.parse(s).target_directory));')"
BUILT="$TARGET_DIR/wasm32v1-none/release/wai_vector_wasm.wasm"
[ -f "$BUILT" ] || { echo "pkg-vector: the build left no $BUILT" >&2; exit 1; }
node "$CRATE/check-mvp.mjs" "$BUILT" --package --functions "$FUNCTIONS"
cp "$BUILT" "$OUT/wai_vector.wasm"
echo "pkg-vector: $OUT/wai_vector.wasm"