WIP: IO suspension diagnosis — call-lambda CALL_PRIM converts VmSuspended→Eval_error

Root cause found: when the click handler calls run-all → for-each → callback → hs-wait → perform,
the perform raises VmSuspended. But the call path goes through sx_apply_cek
(from the call-lambda CALL_PRIM) which converts VmSuspended → CekPerformRequest.
The inner CEK context has no IO handler, so it raises "IO suspension in non-IO context"
instead of propagating the suspension to the outer context.

Fix needed: either (a) make sx_apply_cek NOT convert VmSuspended when in a context
that supports IO suspension, or (b) ensure the inner CEK from call-lambda propagates
perform as a suspension state rather than erroring.

Debug logging still present in sx_browser.ml (js_to_value traces).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-16 16:14:20 +00:00
parent 98fbd5cf40
commit 133edd4c5e
2 changed files with 14 additions and 3 deletions

View File

@@ -57,6 +57,7 @@
var obj = args[0], method = args[1];
var callArgs = [];
for (var i = 2; i < args.length; i++) callArgs.push(args[i]);
if (method === "addEventListener") console.log("[host-call] addEventListener args:", callArgs.map(a => typeof a === "function" ? "fn:" + (a.__host_callback ? "HOST_CB" : "other") : typeof a));
if (obj == null) {
// Global function call
var fn = typeof globalThis !== "undefined" ? globalThis[method] : window[method];
@@ -157,12 +158,16 @@
if (typeof fn === "function") return fn;
// SX callable (has __sx_handle) — wrap as JS function
if (fn && fn.__sx_handle !== undefined) {
return function() {
var wrappedFn = function() {
var a = Array.prototype.slice.call(arguments);
console.log("[host-callback] FIRED handle=" + fn.__sx_handle);
var r = K.callFn(fn, a);
console.log("[host-callback] callFn returned suspended=" + !!(r && r.suspended));
if (window._driveAsync) window._driveAsync(r);
return r;
};
wrappedFn.__host_callback = true;
return wrappedFn;
}
return function() {};
});