WASM kernel fixes: parse, env sync, iterative CEK, click delegation

Browser kernel:
- Add `parse` native fn (matches server: unwrap single, list for multiple)
- Restore env==global_env guard on _env_bind_hook (let bindings must not
  leak to _vm_globals — caused JIT CSSX "Not callable: nil" errors)
- Add _env_bind_hook call in env_set_id so set! mutations sync to VM globals
- Fire _vm_global_set_hook from OP_DEFINE so VM defines sync back to CEK env

CEK evaluator:
- Replace recursive cek_run with iterative while loop using sx_truthy
  (previous attempt used strict Bool true matching, broke in wasm_of_ocaml)
- Remove dead cek_run_iterative function

Web modules:
- Remove find-matching-route and parse-route-pattern stubs from
  boot-helpers.sx that shadowed real implementations from router.sx
- Sync boot-helpers.sx to dist/static dirs for bytecode compilation

Platform (sx-platform.js):
- Set data-sx-ready attribute after boot completes (was only in boot-init
  which sx-platform.js doesn't call — it steps through boot manually)
- Add document-level click delegation for a[sx-get] links as workaround
  for bytecoded bind-event not attaching per-element listeners (VM closure
  issue under investigation — bind-event runs but dom-add-listener calls
  don't result in addEventListener)

Tests:
- New test_kernel.js: 24 tests covering env sync, parse, route matching,
  host FFI/preventDefault, deep recursion
- New navigation test: "sx-get link fetches SX not HTML and preserves layout"
  (currently catches layout breakage after SPA swap — known issue)

Known remaining issues:
- JIT CSSX failures: closure-captured variables resolve to nil in VM bytecode
- SPA content swap via execute-request breaks page layout
- Bytecoded bind-event doesn't attach per-element addEventListener (root
  cause unknown — when listen-target guard appears to block despite element
  being valid)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-30 13:33:13 +00:00
parent 03c2115f0d
commit b274e428eb
37 changed files with 335 additions and 77 deletions

View File

@@ -434,6 +434,33 @@
})
.catch(function(e) { console.warn("[sx] popstate fetch error:", e); });
});
// Event delegation for sx-get links — bytecoded bind-event doesn't
// attach per-element listeners (VM closure issue), so catch clicks
// at the document level and route through the SX engine.
document.addEventListener("click", function(e) {
var el = e.target.closest("a[sx-get]");
if (!el) return;
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
e.preventDefault();
var url = el.getAttribute("href") || el.getAttribute("sx-get");
// Push URL first (execute-request doesn't handle URL updates)
if (el.getAttribute("sx-push-url")) {
history.pushState({}, "", url);
}
// Store the element reference for SX to pick up
window.__sxClickEl = el;
try {
K.eval('(execute-request (host-global "__sxClickEl") nil nil)');
} catch(ex) {
console.warn("[sx] click delegation error:", ex);
location.href = el.href;
}
delete window.__sxClickEl;
});
// Signal boot complete
document.documentElement.setAttribute("data-sx-ready", "true");
document.dispatchEvent(new CustomEvent("sx:boot-done"));
console.log("[sx] boot done");
}
}