From bac2fc2daaa5e0e4ae3e64b70b746cc703c54f21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Thu, 12 Mar 2026 22:58:00 +0100 Subject: [PATCH 1/3] fix(web): support structuredClone for DOMException Uses the cloneable resource registry to enable structured cloning of DOMException objects. Serializes message, name, and stack; code is derived from name on deserialization. Co-Authored-By: Claude Opus 4.6 --- ext/web/01_dom_exception.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/ext/web/01_dom_exception.js b/ext/web/01_dom_exception.js index d654d07317f7ea..7a868a4abace80 100644 --- a/ext/web/01_dom_exception.js +++ b/ext/web/01_dom_exception.js @@ -7,7 +7,7 @@ /// /// -import { primordials } from "ext:core/mod.js"; +import { core, primordials } from "ext:core/mod.js"; const { Error, ErrorPrototype, @@ -137,6 +137,12 @@ class DOMException { error[_name] = name; error[_code] = code; error[webidl.brand] = webidl.brand; + error[core.hostObjectBrand] = () => ({ + type: "DOMException", + message, + name, + stack: error.stack, + }); return error; } @@ -217,4 +223,18 @@ for (let i = 0; i < entries.length; ++i) { ObjectDefineProperty(DOMException.prototype, key, desc); } +core.registerCloneableResource("DOMException", (data) => { + const ex = new DOMException(data.message, data.name); + if (data.stack !== undefined) { + ObjectDefineProperty(ex, "stack", { + __proto__: null, + value: data.stack, + configurable: true, + writable: true, + enumerable: false, + }); + } + return ex; +}); + export { DOMException, DOMExceptionPrototype }; From baa07c47c75d596d94243813aa7f1e4046f49177 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Fri, 13 Mar 2026 08:52:35 +0100 Subject: [PATCH 2/3] fix: update WPT expectations for DOMException structuredClone Mark newly passing tests: DOMException cloning, stream error propagation with DOMException, and unclonable object errors. Co-Authored-By: Claude Opus 4.6 --- tests/wpt/runner/expectations/html.json | 4 +--- tests/wpt/runner/expectations/streams.json | 15 +++------------ 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/tests/wpt/runner/expectations/html.json b/tests/wpt/runner/expectations/html.json index 70937b21810306..83c8246f4b5bf9 100644 --- a/tests/wpt/runner/expectations/html.json +++ b/tests/wpt/runner/expectations/html.json @@ -1154,9 +1154,7 @@ "ImageData object can be cloned", "ImageData expandos are not cloned", "Document objects cannot be cloned", - "URIError objects from other realms are treated as URIError", - "DOMException objects can be cloned", - "DOMException objects created by the UA can be cloned" + "URIError objects from other realms are treated as URIError" ] } }, diff --git a/tests/wpt/runner/expectations/streams.json b/tests/wpt/runner/expectations/streams.json index af6adac3f9ffba..b516b975739a5c 100644 --- a/tests/wpt/runner/expectations/streams.json +++ b/tests/wpt/runner/expectations/streams.json @@ -184,15 +184,10 @@ "readable-stream.html": { "expectedFailures": [ "cancel should be propagated to the original", - "cancel should abort a pending read()", - "transferring a non-serializable chunk should error both sides" - ] - }, - "reason.html": { - "expectedFailures": [ - "DOMException errors should be preserved" + "cancel should abort a pending read()" ] }, + "reason.html": true, "service-worker.https.html": false, "shared-worker.html": false, "transform-stream-members.any.html": true, @@ -204,10 +199,6 @@ ] }, "worker.html": true, - "writable-stream.html": { - "expectedFailures": [ - "writing a unclonable object should error the stream" - ] - } + "writable-stream.html": true } } From bd667fb529d264aaf615d556a93868e9afb7b53c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Fri, 13 Mar 2026 08:59:50 +0100 Subject: [PATCH 3/3] fix: make hostObjectBrand non-enumerable on DOMException MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same fix as CryptoKey — prevents deepStrictEqual from comparing the closure instances. Co-Authored-By: Claude Opus 4.6 --- ext/web/01_dom_exception.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/ext/web/01_dom_exception.js b/ext/web/01_dom_exception.js index 7a868a4abace80..f50ebac2e37122 100644 --- a/ext/web/01_dom_exception.js +++ b/ext/web/01_dom_exception.js @@ -137,11 +137,17 @@ class DOMException { error[_name] = name; error[_code] = code; error[webidl.brand] = webidl.brand; - error[core.hostObjectBrand] = () => ({ - type: "DOMException", - message, - name, - stack: error.stack, + ObjectDefineProperty(error, core.hostObjectBrand, { + __proto__: null, + value: () => ({ + type: "DOMException", + message, + name, + stack: error.stack, + }), + enumerable: false, + configurable: false, + writable: false, }); return error;