Async error handler: dispatch Eval_error to VM handler_stack in resume_vm
When an error occurs during resumed VM execution (after perform/hs-wait), resume_vm now checks the VM's handler_stack. If a handler exists (from a compiled guard form's OP_PUSH_HANDLER), it unwinds frames and jumps to the catch block — exactly like OP_RAISE. This enables try/catch across async perform/resume boundaries. The guard form compiles to OP_PUSH_HANDLER which lives on the vm struct and survives across setTimeout-based async resume. Previously, errors during resume escaped to the JS console as unhandled exceptions. Also restored guard in the test runner (was cek-try which doesn't survive async) and restored error-throwing assertions in run-action. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -852,10 +852,26 @@ let resume_vm vm result =
|
||||
| None ->
|
||||
push vm result);
|
||||
(try run vm
|
||||
with VmSuspended _ as e ->
|
||||
(* Re-suspension during resume: the VM hit another perform.
|
||||
The new VmSuspended carries the current VM state. *)
|
||||
raise e);
|
||||
with
|
||||
| VmSuspended _ as e ->
|
||||
(* Re-suspension during resume: the VM hit another perform. *)
|
||||
raise e
|
||||
| Eval_error msg ->
|
||||
(* Error during resumed execution. If the VM has a handler on its
|
||||
handler_stack, dispatch to it (same as OP_RAISE). This enables
|
||||
try/catch across async perform/resume boundaries — the handler
|
||||
was pushed before the perform and survives on the vm struct. *)
|
||||
(match vm.handler_stack with
|
||||
| entry :: rest ->
|
||||
vm.handler_stack <- rest;
|
||||
while List.length vm.frames > entry.h_frame_depth do
|
||||
match vm.frames with _ :: fs -> vm.frames <- fs | [] -> ()
|
||||
done;
|
||||
vm.sp <- entry.h_sp;
|
||||
entry.h_frame.ip <- entry.h_catch_ip;
|
||||
push vm (String msg);
|
||||
run vm
|
||||
| [] -> raise (Eval_error msg)));
|
||||
(* Clear reuse_stack — any entries here are stale from the original
|
||||
suspension and don't apply to the current state. The VM just
|
||||
completed its execution successfully. *)
|
||||
|
||||
Reference in New Issue
Block a user