Fix WASM trampoline stub + event-bridge host-get

- sx_browser.ml: use Sx_ref.trampoline instead of Sx_runtime.trampoline
  (the stub was a no-op, causing cek-call to return unresolved Thunks).
  Fixes resource island promise resolution — promises now resolve and
  update signals correctly.

- event-bridge island: use host-get instead of get for event-detail,
  since WASM kernel returns JS host handles for CustomEvent detail
  objects, not native SX dicts.

- Mark event-bridge and isomorphic-nav as test.fixme (deeper issues
  remain: event handler swap! doesn't propagate to DOM; header island
  inside #main-panel swap boundary needs structural layout change).

99 passed, 2 skipped, 0 failed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-28 09:33:20 +00:00
parent 07fabeb4ed
commit 919ce927b1
7 changed files with 9 additions and 10 deletions

View File

@@ -257,7 +257,7 @@ let api_eval_vm src_js =
let compile_fn = match Hashtbl.find_opt _vm_globals "compile-module" with
| Some v -> v
| None -> env_get global_env "compile-module" in
let code_val = Sx_runtime.trampoline (Sx_runtime.sx_call compile_fn [List exprs]) in
let code_val = Sx_ref.trampoline (Sx_runtime.sx_call compile_fn [List exprs]) in
let code = Sx_vm.code_from_value code_val in
let result = Sx_vm.execute_module code _vm_globals in
(* Sync VM globals → CEK env so subsequent eval() calls see defines *)
@@ -457,7 +457,7 @@ let () =
match args with
| [f; a] when is_callable f ->
let arg_list = match a with List l -> l | Nil -> [] | v -> [v] in
Sx_runtime.trampoline (Sx_runtime.sx_call f arg_list)
Sx_ref.trampoline (Sx_runtime.sx_call f arg_list)
| [f; _] -> raise (Eval_error ("cek-call: not callable: " ^ type_of f))
| _ -> raise (Eval_error "cek-call: expected (fn args)"));
@@ -675,13 +675,13 @@ let () =
match args with
| [f; a; _] | [f; a] when is_callable f ->
let arg_list = match a with List l -> l | Nil -> [] | v -> [v] in
Sx_runtime.trampoline (Sx_runtime.sx_call f arg_list)
Sx_ref.trampoline (Sx_runtime.sx_call f arg_list)
| _ -> raise (Eval_error "call-lambda: expected (fn args env?)"));
bind "cek-call" (fun args ->
match args with
| [f; a] when is_callable f ->
let arg_list = match a with List l -> l | Nil -> [] | v -> [v] in
Sx_runtime.trampoline (Sx_runtime.sx_call f arg_list)
Sx_ref.trampoline (Sx_runtime.sx_call f arg_list)
| [f; _] -> raise (Eval_error ("cek-call: not callable: " ^ type_of f))
| _ -> raise (Eval_error "cek-call: expected (fn args)"));
bind "cek-eval" (fun args ->

View File

@@ -1792,7 +1792,7 @@
blake2_js_for_wasm_create: blake2_js_for_wasm_create};
}
(globalThis))
({"link":[["runtime-0db9b496",0],["prelude-d7e4b000",0],["stdlib-23ce0836",[]],["sx-64e6b16e",[2]],["jsoo_runtime-f96b44a8",[2]],["js_of_ocaml-651f6707",[2,4]],["dune__exe__Sx_browser-490a8e59",[2,3,5]],["std_exit-10fb8830",[2]],["start-80fdb768",0]],"generated":(b=>{var
({"link":[["runtime-0db9b496",0],["prelude-d7e4b000",0],["stdlib-23ce0836",[]],["sx-64e6b16e",[2]],["jsoo_runtime-f96b44a8",[2]],["js_of_ocaml-651f6707",[2,4]],["dune__exe__Sx_browser-2ac146e9",[2,3,5]],["std_exit-10fb8830",[2]],["start-80fdb768",0]],"generated":(b=>{var
c=b,a=b?.module?.export||b;return{"env":{"caml_ba_kind_of_typed_array":()=>{throw new
Error("caml_ba_kind_of_typed_array not implemented")},"caml_exn_with_js_backtrace":()=>{throw new
Error("caml_exn_with_js_backtrace not implemented")},"caml_int64_create_lo_mi_hi":()=>{throw new

View File

@@ -523,7 +523,7 @@
(on-event el "inbox:message"
(fn (e)
(swap! messages (fn (old)
(append old (get (event-detail e) "text"))))))))))))
(append old (host-get (event-detail e) "text"))))))))))))
(div :ref container-ref
(p :class "text-xs font-semibold text-stone-500 mb-2" "Event Bridge Demo")
(p :class "text-sm text-stone-600 mb-2"

View File

@@ -233,7 +233,7 @@ test.describe('Reactive island interactions', () => {
});
test.fixme('event-bridge: sender triggers receiver update', async ({ page }) => {
// BUG: on-event listener via schedule-idle + container-ref not receiving CustomEvents from data-sx-emit buttons
// BUG: on-event handler receives CustomEvent but swap!/signal update doesn't propagate to DOM
await page.goto(BASE_URL + '/sx/(geography.(reactive.(examples.event-bridge-demo)))', { waitUntil: 'networkidle' });
await page.waitForTimeout(2000);
@@ -269,8 +269,7 @@ test.describe('Reactive island interactions', () => {
}
});
test.fixme('resource: shows loading then data', async ({ page }) => {
// BUG: resource promise never resolves in WASM kernel — host-await/promise-then callback not firing
test('resource: shows loading then data', async ({ page }) => {
await page.goto(BASE_URL + '/sx/(geography.(reactive.(examples.resource)))', { waitUntil: 'networkidle' });
await page.waitForTimeout(2000);

View File

@@ -177,7 +177,7 @@ test.describe('Isomorphic SSR', () => {
});
test.fixme('navigation preserves header island state', async ({ page }) => {
// BUG: header island color resets after SPA nav — signals re-initialized instead of preserved
// BUG: header island inside #main-panel swap boundary — needs structural layout change or store-based state
await page.goto(BASE_URL + '/sx/', { waitUntil: 'networkidle' });
// Wait for header island to hydrate