Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 045a0c6379ef4d428a45302fe0c95160d4cea9e8
      
https://github.com/WebKit/WebKit/commit/045a0c6379ef4d428a45302fe0c95160d4cea9e8
  Author: Chris Dumez <[email protected]>
  Date:   2026-08-25 (Tue, 25 Aug 2026)

  Changed paths:
    M LayoutTests/fast/storage/serialized-script-value.html
    M 
LayoutTests/imported/w3c/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/DOMException-custom-bindings.any-expected.txt
    M 
LayoutTests/imported/w3c/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/DOMException-custom-bindings.any.worker-expected.txt
    M 
LayoutTests/imported/w3c/web-platform-tests/html/infrastructure/safe-passing-of-structured-data/structured-cloning-error-stack-optional.sub.window-expected.txt
    A LayoutTests/js/dom/dom-exception-stack-expected.txt
    A LayoutTests/js/dom/dom-exception-stack.html
    M Source/JavaScriptCore/runtime/ErrorInstance.cpp
    M Source/JavaScriptCore/runtime/ErrorInstance.h
    M Source/JavaScriptCore/runtime/StructuredCloneTags.h
    M Source/WebCore/bindings/js/JSDOMWrapper.h
    M Source/WebCore/bindings/js/SerializedScriptValue.cpp

  Log Message:
  -----------
  DOMException should have a stack property, like other errors
https://bugs.webkit.org/show_bug.cgi?id=322388

Reviewed by Yusuke Suzuki.

The WebIDL web-platform-test "If the implementation has a stack property on
normal errors, it also does on DOMExceptions" was still failing after
318930@main. That test compares typeof new Error().stack against
typeof (new DOMException()).stack; we returned "string" for the former and
"undefined" for the latter. Firefox passes this test; Chrome fails it.

318930@main gave DOMException's JS wrapper the [[ErrorData]] internal slot by
making it a genuine JSC::ErrorInstance subclass, but deliberately opted out of
stack capture (StackTraceCapturePolicy::DoNotCapture) to keep the property set
byte-for-byte unchanged. Now that a DOMException really is an ErrorInstance,
there is no reason for it to be the one error in the engine without a stack, so
let it capture one like any other.

ErrorInstance's DoNotCapture policy had exactly one caller, so the enum is
replaced by a single named entry point, finishCreationForEmbedderError(), which
captures a stack trace but still adds no own "message" / "cause" properties.
JSDOMErrorWrapper calls it. "stack" (and WebKit's non-standard "line", "column"
and "sourceURL") then materialize lazily through the existing
materializeErrorInfoIfNeeded() path, so they are DontEnum and honour
Error.stackTraceLimit exactly as they do for a plain Error, and DOMException's
name/message continue to come from the WebIDL getters on the prototype rather
than from own properties. This also covers DOMException's subclasses
(WebTransportError, GPUPipelineError, RTCError, OverconstrainedError).

Giving DOMException a stack also stops WPT's
structured-cloning-error-stack-optional.sub.window.html from skipping its
DOMException cases, at which point it asserts that a clone reports the same
stack as the original. That failed, because dumpDOMException() serialized only
the name and message, so a clone reported the stack of whichever frame did the
deserializing. The four "web API-created DOMException" subtests were already
failing this way, since createDOMException() has always given engine-thrown
DOMExceptions a stack.

So serialize the line/column/sourceURL/stack alongside the name and message.
That needs wire format version 16, and the extra fields are read back behind a
version check so version 15 and earlier data still deserializes.
ErrorInstance::setErrorInfoForEmbedderError() replaces the stack trace captured
when the wrapper was created with the deserialized information, still leaving
the properties to materialize lazily, so a cloned DOMException and a cloned
Error behave the same way. All 20 subtests of that test pass now, up from 12.

createDOMException()'s addErrorInfo() call is now partly redundant, since
creating the wrapper on the preceding line already captures a stack trace, but
it is kept: it is what gives a "stack" of "" to exceptions created with no JS
frames on the stack, such as an asynchronous rejection. Dropping it made
WebGPU's mapping.spec.js fail its typeof ex.stack === 'string' assertion for
mapAsync rejections.

Two consequences worth noting. Surfacing a DOM exception to JS now pays for a
stack trace capture, the same cost `new Error()` already pays. And, as with 
every
serialization version bump, data written by this build cannot be read by older
versions of WebKit.

* LayoutTests/fast/storage/serialized-script-value.html: Bump the pinned wire
format version.
* 
LayoutTests/imported/w3c/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/DOMException-custom-bindings.any-expected.txt:
* 
LayoutTests/imported/w3c/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/DOMException-custom-bindings.any.worker-expected.txt:
* 
LayoutTests/imported/w3c/web-platform-tests/html/infrastructure/safe-passing-of-structured-data/structured-cloning-error-stack-optional.sub.window-expected.txt:
* LayoutTests/js/dom/dom-exception-stack.html: Added.
* LayoutTests/js/dom/dom-exception-stack-expected.txt: Added.
* Source/JavaScriptCore/runtime/ErrorInstance.cpp:
(JSC::ErrorInstance::finishCreationForEmbedderError):
(JSC::ErrorInstance::setErrorInfoForEmbedderError):
* Source/JavaScriptCore/runtime/ErrorInstance.h:
* Source/JavaScriptCore/runtime/StructuredCloneTags.h:
* Source/WebCore/bindings/js/JSDOMWrapper.h:
(WebCore::JSDOMErrorWrapper::finishCreation):
* Source/WebCore/bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneSerializer::dumpDOMException):
(WebCore::CloneDeserializer::readDOMException):

Canonical link: https://commits.webkit.org/319782@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to