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
- 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]>
72 lines
3.5 KiB
JavaScript
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`,
|
|
};
|