Hyperscript examples working: toggle, bounce, count clicks

- sx_browser.ml: restore VmSuspended handler in api_call_fn with
  make_js_callFn_suspension for IO suspension chains (wait, fetch)
- runtime.sx: delete host-get stub that shadowed platform native —
  hs-toggle-class! now uses real FFI host-get for classList access

All three live demo examples work:
  Toggle Color — classList.toggle on click
  Bounce — add .animate-bounce, wait 1s suspend, remove
  Count Clicks — increment @data-count, put into innerHTML

4/4 bytecode regression tests pass (was 0/4 without VmSuspended).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-09 21:04:45 +00:00
parent c6df054957
commit de9ab4ca07
7 changed files with 253 additions and 117 deletions

View File

@@ -487,12 +487,35 @@ let api_register_native name_js callback_js =
Hashtbl.replace _vm_globals name v;
Js.Unsafe.inject Js.null
let rec make_js_callFn_suspension request vm =
let obj = Js.Unsafe.obj [||] in
Js.Unsafe.set obj (Js.string "suspended") (Js.Unsafe.inject Js._true);
Js.Unsafe.set obj (Js.string "request") (value_to_js request);
Js.Unsafe.set obj (Js.string "resume") (Js.wrap_callback (fun result_js ->
let result = js_to_value result_js in
try
let v = Sx_vm.resume_vm vm result in
sync_vm_to_env ();
value_to_js v
with
| Sx_vm.VmSuspended (req2, vm2) ->
Js.Unsafe.inject (make_js_callFn_suspension req2 vm2)
| Eval_error msg ->
ignore (Js.Unsafe.meth_call
(Js.Unsafe.get Js.Unsafe.global (Js.string "console"))
"error" [| Js.Unsafe.inject (Js.string ("[sx] resume: " ^ msg)) |]);
Js.Unsafe.inject Js.null));
obj
let api_call_fn fn_js args_js =
try
let fn = js_to_value fn_js in
let args = Array.to_list (Array.map js_to_value (Js.to_array (Js.Unsafe.coerce args_js))) in
return_via_side_channel (value_to_js (call_sx_fn fn args))
with
| Sx_vm.VmSuspended (request, vm) ->
sync_vm_to_env ();
Js.Unsafe.inject (make_js_callFn_suspension request vm)
| Eval_error msg ->
ignore (Js.Unsafe.meth_call
(Js.Unsafe.get Js.Unsafe.global (Js.string "console"))