HS: test runner — auto-unwrap shim for new WASM kernel ABI
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 26s

Post-JIT-Phase-1 OCaml kernels return atomic values (number, string,
boolean, nil) as opaque handles {_type, __sx_handle} instead of plain
JS values. The 23 K.eval call sites in hs-run-filtered.js were written
against the pre-rewrite ABI and expect plain values.

Add a wrapper at boot that auto-unwraps via K.stringify when the result
is a handle. No-op on the legacy kernel (handles don't appear, so the
check falls through). Forward-compatible: when the new WASM is the
default, the shim transparently restores test compatibility.

Note: This unblocks future browser-WASM rollout of JIT Phase 1. A
separate issue (Set-append size regression — Expected 3, got 4 on
test 27) in newer architecture-branch kernel changes still blocks the
WASM rollout; the test tree continues to pin the pre-merge WASM until
that regression is identified and fixed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-11 20:30:32 +00:00
parent 30a7dd2108
commit 6e997e9382

View File

@@ -14,6 +14,28 @@ const SX_DIR = path.join(WASM_DIR, 'sx');
eval(fs.readFileSync(path.join(WASM_DIR, 'sx_browser.bc.js'), 'utf8'));
const K = globalThis.SxKernel;
// Auto-unwrap shim: the post-JIT-Phase-1 kernel returns numbers, strings,
// booleans, and nil as opaque value handles ({_type, __sx_handle}). Tests
// expect plain JS values from K.eval like the pre-rewrite kernel did. Wrap
// once at boot rather than touching all 23 K.eval call sites.
if (K && typeof K.eval === 'function' && K.stringify) {
const _kEval = K.eval.bind(K);
K.eval = function(expr) {
const r = _kEval(expr);
if (r && typeof r === 'object' && typeof r._type === 'string') {
switch (r._type) {
case 'number': { const s = K.stringify(r); const n = Number(s);
return Number.isInteger(n) || /^-?\d+$/.test(s) ? n : (Number.isNaN(n) ? r : n); }
case 'string': return K.stringify(r);
case 'boolean': return K.stringify(r) === 'true';
case 'nil': return null;
default: return r; // list/dict/symbol — leave as handle
}
}
return r;
};
}
// Step limit API — exposed from OCaml kernel
const STEP_LIMIT = parseInt(process.env.HS_STEP_LIMIT || '1000000');