Fix bytecode when/do/perform: snapshot pending_cek in resume closure
Root cause: nested cek_call_or_suspend calls on the same VM (from synchronous callbacks like dom-listen firing handler immediately) overwrote pending_cek before the first resume ran. Fix: _vm_suspension_to_dict snapshots pending_cek at capture time and restores it in the resume closure before calling resume_vm. This ensures each suspension's CEK state is preserved regardless of nested overwrite. test_bytecode_repeat.js: 4/4 pass (was 3/4). Source: 6 suspensions ✓ Bytecode: 6 suspensions ✓ Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -814,12 +814,10 @@ and run vm =
|
||||
let resume_vm vm result =
|
||||
(match vm.pending_cek with
|
||||
| Some cek_state ->
|
||||
(* Resume the suspended CEK evaluation first *)
|
||||
vm.pending_cek <- None;
|
||||
let final = Sx_ref.cek_resume cek_state result in
|
||||
(match Sx_runtime.get_val final (String "phase") with
|
||||
| String "io-suspended" ->
|
||||
(* CEK suspended again — re-suspend the VM *)
|
||||
vm.pending_cek <- Some final;
|
||||
raise (VmSuspended (Sx_runtime.get_val final (String "request"), vm))
|
||||
| _ ->
|
||||
@@ -948,12 +946,18 @@ let () = _vm_call_closure_ref := (fun cl args -> call_closure_reuse cl args)
|
||||
let () = _vm_suspension_to_dict := (fun exn ->
|
||||
match exn with
|
||||
| VmSuspended (request, vm) ->
|
||||
(* Snapshot pending_cek NOW — a nested cek_call_or_suspend on the same VM
|
||||
may overwrite it before our resume function is called. *)
|
||||
let saved_cek = vm.pending_cek in
|
||||
let d = Hashtbl.create 3 in
|
||||
Hashtbl.replace d "__vm_suspended" (Bool true);
|
||||
Hashtbl.replace d "request" request;
|
||||
Hashtbl.replace d "resume" (NativeFn ("vm-resume", fun args ->
|
||||
match args with
|
||||
| [result] ->
|
||||
(* Restore the saved pending_cek before resuming — it may have been
|
||||
overwritten by a nested suspension on the same VM. *)
|
||||
vm.pending_cek <- saved_cek;
|
||||
(try resume_vm vm result
|
||||
with exn2 ->
|
||||
match !_vm_suspension_to_dict exn2 with
|
||||
|
||||
Reference in New Issue
Block a user