// Checks the browser sink's advertised capability menu against the registry: // every string `known_capabilities()` returns is a registered payload or // companion capability whose status is `registered` (no candidate, SPEC §5), as // both the wasm build's own registry (`isCandidate`, `isRegistered`) and the // committed export wai/registry/capabilities.json say. // // node verify_menu.mjs [path/to/wai_web.js] [path/to/capabilities.json] // The package path is relative to this directory (as in the other verify scripts); // the export path is relative to the working directory (default: this tree's). // Exit 0 iff every check holds. import { readFileSync } from 'node:fs'; import { dirname, resolve } from 'node:path'; import { fileURLToPath, pathToFileURL } from 'node:url'; const here = dirname(fileURLToPath(import.meta.url)); const pkg = resolve(here, process.argv[2] ?? './pkg-node/wai_web.js'); const exportPath = process.argv[3] ? resolve(process.argv[3]) : resolve(here, '../../registry/capabilities.json'); const wai = await import(pathToFileURL(pkg).href); const registry = new Map(JSON.parse(readFileSync(exportPath, 'utf8')).capabilities.map((c) => [c.capability, c])); let pass = true; const fail = (msg) => { pass = false; console.log(`FAIL ${msg}`); }; const menu = Array.from(wai.known_capabilities()); if (menu.length === 0) fail('the menu is empty'); for (const cap of menu) { const r = registry.get(cap); if (!r) { fail(`${cap}: not in ${exportPath}`); continue; } if (!['payload', 'companion'].includes(r.kind)) fail(`${cap}: kind ${r.kind}, not a payload or companion capability`); if (r.status !== 'registered') fail(`${cap}: status ${r.status} — a candidate must not be advertised`); if (wai.isCandidate(cap)) fail(`${cap}: the wasm registry calls it a candidate`); if (!wai.isRegistered(cap)) fail(`${cap}: the wasm registry does not register it`); } // The wasm build's registry agrees with the export on every candidate. for (const [cap, r] of registry) { if (['payload', 'companion'].includes(r.kind) && wai.isCandidate(cap) !== (r.status === 'candidate')) { fail(`${cap}: isCandidate disagrees with the export (${r.status})`); } } console.log(pass ? `PASS the browser menu is registered and names no candidate` : '\n✗ the browser menu disagrees with the registry'); process.exit(pass ? 0 : 1);