From 0e9f6d428b6e9dc6cf2038971c5828ccbabc6243 Mon Sep 17 00:00:00 2001 From: Eduardo Speroni Date: Thu, 5 Nov 2026 15:55:51 -0300 Subject: [PATCH 1/2] test: assert a caller-set DOMException stack survives structuredClone --- .../src/main/assets/app/tests/testRuntimeImplementedAPIs.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test-app/app/src/main/assets/app/tests/testRuntimeImplementedAPIs.js b/test-app/app/src/main/assets/app/tests/testRuntimeImplementedAPIs.js index 27b784df2..c17807cb8 100644 --- a/test-app/app/src/main/assets/app/tests/testRuntimeImplementedAPIs.js +++ b/test-app/app/src/main/assets/app/tests/testRuntimeImplementedAPIs.js @@ -64,9 +64,12 @@ describe("DOMException canary", function () { }); it("serializes through structuredClone on this runtime", function () { - var clone = structuredClone(new DOMException("x", "AbortError")); + var original = new DOMException("x", "AbortError"); + original.stack = "DOMException stack sentinel"; + var clone = structuredClone(original); expect(clone instanceof DOMException).toBe(true); expect(clone.name).toBe("AbortError"); + expect(clone.stack).toBe("DOMException stack sentinel"); }); it("clones the isolate's first DOMException even when a getter creates it mid-clone", function (done) { From b5b3f89006f2783a1440767ce04c60687ff8670b Mon Sep 17 00:00:00 2001 From: Eduardo Speroni Date: Thu, 5 Nov 2026 15:55:57 -0300 Subject: [PATCH 2/2] fix(worker): open a handle scope per delivered message, and wait for the fourth reply in the on()+once() spec --- test-app/app/src/main/assets/app/tests/testMessaging.js | 7 ++++--- test-app/runtime/src/main/cpp/WorkerEvents.cpp | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/test-app/app/src/main/assets/app/tests/testMessaging.js b/test-app/app/src/main/assets/app/tests/testMessaging.js index c06a46037..faa6cfe2d 100644 --- a/test-app/app/src/main/assets/app/tests/testMessaging.js +++ b/test-app/app/src/main/assets/app/tests/testMessaging.js @@ -155,10 +155,11 @@ describe("Messaging runtime edges", function () { var got = []; worker.on("message", function (value) { got.push(value); - if (got.length === 3) { + if (got.length === 4) { setTimeout(function () { - // Three messages: the once() registration fires only - // for the first, the on() one for all three. + // Three messages: the on() registration fires for all + // three, the once() one only for the first. The settle + // window catches a fifth reply. expect(got).toEqual([1, 2, 3, 4]); worker.terminate(); done(); diff --git a/test-app/runtime/src/main/cpp/WorkerEvents.cpp b/test-app/runtime/src/main/cpp/WorkerEvents.cpp index 978aeb014..7ed146b52 100644 --- a/test-app/runtime/src/main/cpp/WorkerEvents.cpp +++ b/test-app/runtime/src/main/cpp/WorkerEvents.cpp @@ -62,6 +62,9 @@ void WorkerEvents::Init(Local context) { void WorkerEvents::EmitMessage(Isolate* isolate, Local receiver, const std::shared_ptr& message) { + // Callers drain a whole batch under one scope; without this the handles of + // every message in the batch stay alive until the batch ends. + HandleScope handleScope(isolate); auto* state = RuntimeState::For(isolate); if (state == nullptr || state->emitMessage.IsEmpty()) { return;