Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 37cfccb3c6c9ae9cc09b9d9908c190286ac2e858
      
https://github.com/WebKit/WebKit/commit/37cfccb3c6c9ae9cc09b9d9908c190286ac2e858
  Author: Kristian Monsen <[email protected]>
  Date:   2026-08-07 (Fri, 07 Aug 2026)

  Changed paths:
    A 
LayoutTests/navigation-api/navigation-navigate-state-clone-exception-crash-expected.txt
    A 
LayoutTests/navigation-api/navigation-navigate-state-clone-exception-crash.html
    A 
LayoutTests/navigation-api/navigation-reload-state-clone-exception-crash-expected.txt
    A 
LayoutTests/navigation-api/navigation-reload-state-clone-exception-crash.html
    M Source/WebCore/bindings/js/JSDOMPromiseDeferred.cpp

  Log Message:
  -----------
  Fix crash from double-consuming the pending exception in 
DeferredPromise::reject() during Navigation reload()/navigate() error handling
https://bugs.webkit.org/show_bug.cgi?id=321250
rdar://183911429

Reviewed by Rupin Mittal.

Navigation::createErrorResult() rejects both the committed and finished 
promises with the same Exception. When that exception carries 
ExceptionCode::ExistingExceptionError — the
sentinel meaning "the real JS exception is already sitting on the VM's 
exception scope" — DeferredPromise::reject() pulled the value straight off 
scope.exception() and called
scope.clearException() as a side effect. That works for the first reject() 
call, but clears the exception before the second call runs, so it finds nothing 
there: an assert in
debug/ASan builds, a null-pointer read of Exception::m_value in release builds 
— either way, a crash on every reload()/navigate() whose state argument throws 
during
structured-clone.

The fix reuses the exceptionObject out-parameter that's already threaded 
through both reject() calls (the same parameter the plain-ExceptionCode branch 
a few lines below already
uses to build the DOMException once and share it across calls). On the first 
call, if exceptionObject is still empty, it extracts the value from the 
exception scope, clears it, and
caches the result in exceptionObject; on the second call, exceptionObject is 
already populated, so it skips touching the exception scope entirely and just 
rejects with the cached
value. This matches the pattern already used elsewhere in Navigation.cpp 
(rejectFinishedPromise, which precomputes a DOMException once and passes it to 
both promise rejections),
and it satisfies the spec requirement that committed and finished reject with 
the identical error value — which a "swallow and fall back to a generic error" 
fix would not have.

Tests: navigation-api/navigation-navigate-state-clone-exception-crash.html
       navigation-api/navigation-reload-state-clone-exception-crash.html

* 
LayoutTests/navigation-api/navigation-navigate-state-clone-exception-crash-expected.txt:
 Added.
* 
LayoutTests/navigation-api/navigation-navigate-state-clone-exception-crash.html:
 Added.
* 
LayoutTests/navigation-api/navigation-reload-state-clone-exception-crash-expected.txt:
 Added.
* 
LayoutTests/navigation-api/navigation-reload-state-clone-exception-crash.html: 
Added.
* Source/WebCore/bindings/js/JSDOMPromiseDeferred.cpp:
(WebCore::DeferredPromise::reject):

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



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

Reply via email to