open-standards/joule-code/joule-code-rs/crates/joule-moq-web/web/binding/sink.js
Transaction Science c18ee6a7c8
Some checks failed
joule-code conformance gate / joule-moq-relay, its own energy on a counter (macos) (push) Successful in 50s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Has been cancelled
joule-moq-web browser client / joule-moq-web · does this change touch it (push) Successful in 36s
wai-app and Create / wai-app · does this change touch it (push) Successful in 34s
wai-fleet service / does this change touch it (push) Successful in 35s
wai-ledger service / does this change touch it (push) Successful in 36s
WAI Studio / does this change touch it (push) Successful in 31s
wai-fleet service / service · macos (push) Successful in 1m10s
wai-ledger service / service · macos (push) Successful in 1m46s
wai-app and Create / wai-app · Create, browser end-to-end (macos) (push) Successful in 5m23s
WAI Studio / Studio in Chromium and Firefox · macos (push) Successful in 7m36s
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (push) Successful in 12s
joule-code conformance gate / Build + round-trip C1-C4 vectors (push) Successful in 2m28s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (push) Successful in 16m14s
wai-app and Create / wai-app · tests, clippy, the line language's verifier (linux) (push) Successful in 42s
WAI Studio / the catalogue's actions, the unit tests and the core · linux (push) Successful in 1m47s
wai-ledger service / service · linux (push) Successful in 3m34s
wai-fleet service / service · linux (push) Successful in 4m25s
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (push) Successful in 2m50s
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (push) Successful in 6m55s
WAI Studio / Studio in WebKit · linux (push) Successful in 16m42s
joule-code conformance gate / joule-moq-relay, every target (push) Successful in 3m41s
joule-code conformance gate / joule-moq-ingest, every target (push) Successful in 6m10s
The browser sink corpus run by a page in a browser through wai conform, its record signed and admitted
- joule-moq-web's web/binding/sink.html answers each call of live-conformance/browser with
  wai-live-web's wasm build and the page's own side table (web/room/binding.js), each answer one
  JSON text in RFC 8785 form; e2e/conform_sink.mjs drives it in a browser and is the HTTP adapter
  of wai conform sink --suite browser. With --wai it runs the runner itself, the record named for
  the page and the browser's version, and admits it with wai verify --conformant.
- Run on the build host in its installed browser (156.0.8078.80, headless): 110 of 110 cases,
  conformant, admitted. Planted (--plant: frames the page shows as refused answered verified):
  106 of 110, failing at frames/object_refused among four, and its record refused at admission
  rule 2.
- e2e/run.sh runs both as its conform step (joule-moq-web.yml), the planted record's refusal
  checked too.
- wai-breaking.yml: the relay's --version for the record drops the comma after the number.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-08 16:43:30 -05:00

72 lines
3.5 KiB
JavaScript

// WAI's browser sink (extensions/browser-sink.md) in this page, as `wai conform sink --suite
// browser` holds a sink to its corpus (live-conformance/browser, §12): each call is given with
// its answer withheld, and the page answers it with its own code, the normative parts by
// wai-live-web's wasm (`routeReport`, `chooseReport`, `evaluateConstraints`, `readBinding`,
// `frameTier`, `frameState`) and the side table by the page's own JavaScript
// (web/room/binding.js, `runSequence`). The answer is an object of the members the corpus states
// for the call's family, written as one JSON text in RFC 8785 form and a line feed.
//
// e2e/conform_sink.mjs drives this page in a browser and serves its answers to `wai conform`.
// Everything it reads is on `window.waiBrowserSink`: `ready` (a promise), `answer(call)` and
// `version`.
import initWai, * as wai from "../pkg/wai_live_web.js";
import { runSequence } from "../room/binding.js";
const parse = (s) => JSON.parse(s);
const text = (v) => JSON.stringify(v);
// A binding's canonical form (§7.1), as the page writes it into the side table.
const canonicalOf = (b) => parse(wai.readBinding(text(b))).canonical;
// The page's answer to one call: the members the corpus states for its family.
export function answer(call) {
switch (call.call) {
case "routes": {
const r = parse(wai.routeReport(text(call.report)));
return r.outcome === "routed" ? { outcome: r.outcome, reason: null, table: r.table } : { outcome: r.outcome, reason: r.reason, table: null };
}
case "choices": {
const c = parse(wai.chooseReport(text(call.report)));
if (c.outcome !== "chosen") return { outcome: c.outcome, reason: c.reason, table: null, choices: null };
const r = parse(wai.routeReport(text(call.report)));
return { outcome: c.outcome, reason: null, table: r.outcome === "routed" ? r.table : null, choices: c.choices };
}
case "constraints": {
const e = parse(wai.evaluateConstraints(text(call.sets), text(call.params)));
return { outcome: e.outcome, reason: e.reason };
}
case "bindings": {
const b = parse(wai.readBinding(text(call.value)));
return b.outcome === "read" ? { outcome: b.outcome, reason: null, canonical: b.canonical, tier: b.tier } : { outcome: b.outcome, reason: b.reason, canonical: null, tier: null };
}
case "frame_tiers":
return { tier: wai.frameTier(call.route, call.route_tier, call.format_null, call.altered) };
case "frames":
return { result: parse(wai.frameState(text(call.binding), call.object, call.chain, call.provenance)) };
case "tables":
return { result: runSequence(call.bound, call.ops, canonicalOf) };
default:
throw new Error(`${call.call}: no call of this sink`);
}
}
// RFC 8785: no insignificant whitespace, members sorted by their names' UTF-16 code units
// (JavaScript's own order of strings), and numbers and strings as ECMAScript writes them.
export function jcs(v) {
if (v === null || typeof v !== "object") {
if (typeof v === "number" && !Number.isFinite(v)) throw new Error(`${v}: a number RFC 8785 does not write`);
if (v === undefined) throw new Error("undefined: not a JSON value");
return JSON.stringify(v);
}
if (Array.isArray(v)) return `[${v.map(jcs).join(",")}]`;
return `{${Object.keys(v).filter((k) => v[k] !== undefined).sort().map((k) => `${JSON.stringify(k)}:${jcs(v[k])}`).join(",")}}`;
}
const ready = initWai().then(() => true);
window.waiBrowserSink = {
ready,
version: navigator.userAgent,
answer: (call) => `${jcs(answer(call))}\n`,
};