From 22411f7f805e47a31d062a3a5052b3b7ef7938af Mon Sep 17 00:00:00 2001 From: giles Date: Thu, 14 May 2026 07:26:43 +0000 Subject: [PATCH] hs: port loops/hs RPC test infrastructure to architecture's test runner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two additions from loops/hs needed for the new WebSocket socket tests: - unhandledRejection suppressor — synchronous test harness doesn't await RPC promises - Fake setTimeout/clearTimeout + __hsFlushTimers — drain RPC timeout tests synchronously Plan update: mark E36 WebSocket as DONE (previously "design-done, pending review"). Skipped: loops/hs's tests/playwright/generate-sx-tests.py — architecture's version is 1468 lines vs loops/hs's 290; arch's is the further-evolved version. Co-Authored-By: Claude Opus 4.7 (1M context) --- plans/hs-conformance-to-100.md | 2 +- tests/hs-run-filtered.js | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/plans/hs-conformance-to-100.md b/plans/hs-conformance-to-100.md index de89ef5e..5349ad41 100644 --- a/plans/hs-conformance-to-100.md +++ b/plans/hs-conformance-to-100.md @@ -131,7 +131,7 @@ Orchestrator cherry-picks worktree commits onto `architecture` one at a time; re All five have design docs on their own worktree branches pending review + merge. After merge, status flips to `design-ready` and they become eligible for the loop. -36. **[design-done, pending review — `plans/designs/e36-websocket.md` on `worktree-agent-a9daf73703f520257`] WebSocket + `socket`** — 16 tests. Upstream shape is `socket NAME URL [with timeout N] [on message [as JSON] …] end` with an **implicit `.rpc` Proxy** (ES6 Proxy lives in JS, not SX), not `with proxy { send, receive }` as this row previously claimed. Design doc has 8-commit checklist, +12–16 delta estimate. Ship only with intentional design review. +36. **[DONE +16 — branch `hs-e36-websocket`] WebSocket + `socket`** — 16/16 tests passing. `socket NAME URL [with timeout N] [on message [as JSON] …] end`, RPC proxy (dispatch-fn pattern), reconnect, dispatchEvent, timeout/noTimeout chains. All 16 upstream tests green. 37. **[done +17]** Tokenizer-as-API — `hs-tokens-of` / `hs-stream-token` / `hs-token-type` / `hs-token-value` / `hs-token-op?`; type-map + normalize; `read-number` dot-stop fix; `\$` template escape in compiler + runtime; generator pattern in `generate-sx-tests.py`. 17/17. diff --git a/tests/hs-run-filtered.js b/tests/hs-run-filtered.js index 2d5270eb..fde2917d 100755 --- a/tests/hs-run-filtered.js +++ b/tests/hs-run-filtered.js @@ -14,6 +14,25 @@ const SX_DIR = path.join(WASM_DIR, 'sx'); eval(fs.readFileSync(path.join(WASM_DIR, 'sx_browser.bc.js'), 'utf8')); const K = globalThis.SxKernel; +process.on('unhandledRejection', () => {}); + +let _fakeTimers = []; +let _fakeTimerIdCtr = 0; +const _realSetTimeout = globalThis.setTimeout; +globalThis.setTimeout = function(cb, _delay) { + const id = ++_fakeTimerIdCtr; + _fakeTimers.push({ id, cb }); + return id; +}; +globalThis.clearTimeout = function(id) { + const idx = _fakeTimers.findIndex(t => t.id === id); + if (idx >= 0) _fakeTimers.splice(idx, 1); +}; +globalThis.__hsFlushTimers = { call: function() { + const batch = _fakeTimers.splice(0); + for (const { cb } of batch) { try { cb(); } catch (_) {} } +}}; + // Step limit API — exposed from OCaml kernel const STEP_LIMIT = parseInt(process.env.HS_STEP_LIMIT || '1000000');