// The side table a page keeps its frames' bindings in (WAI browser-sink §9.2), held to the // sequences of live-conformance/browser (`node --test web/room/binding.test.mjs`). The page runs // the same sequences in the browser; here the frames and decoders are stand-in objects. import test from "node:test"; import assert from "node:assert/strict"; import fs from "node:fs"; import { fileURLToPath } from "node:url"; import { runSequence, SideTable, chainToken } from "./binding.js"; const corpus = JSON.parse(fs.readFileSync(fileURLToPath(new URL("../../../../../../wai/live-conformance/browser/vectors.json", import.meta.url)), "utf8")); // The bindings in the sequences are valid: their canonical form is their members in §7.1's order. const canonicalOf = (b) => JSON.stringify({ alg: b.alg, digest: b.digest, ...(b.receipt ? { receipt: b.receipt } : {}), tier: b.tier }); for (const c of corpus.tables) { test(`side table: ${c.name}`, () => { const got = runSequence(c.bound, c.ops, canonicalOf); assert.deepEqual(got, c.result); }); } test("a frame object is unbound until a decoder's output attaches an entry, and a struck entry binds nothing", () => { const t = new SideTable(4); const d = {}; const f = { timestamp: 5 }; assert.equal(SideTable.of(f), null); t.chunk(d, 5, { binding: "b" }); t.chunk(d, 5, { binding: "c" }); assert.equal(t.output(d, f), null); assert.deepEqual(t.refusals, [{ at: 1, reason: "binding_ambiguous" }]); // A binding that depends on the frame is computed when the frame is output. t.chunk(d, 6, { binding: (fr) => `tier-of-${fr.timestamp}` }); assert.equal(t.output(d, { timestamp: 6 }).binding, "tier-of-6"); }); test("chain admissions read as §10's tokens", () => { assert.equal(chainToken("linked"), "linked"); assert.equal(chainToken("already"), "linked"); assert.equal(chainToken("anchor"), "anchor"); assert.equal(chainToken("held:parent_not_held"), "held"); assert.equal(chainToken("refused:chain_break"), "refused"); assert.equal(chainToken(undefined), "held"); });