commit 8b732c4b790bfb729475ddba1dc36a4fd235a5ba
parent 87c14abb1108fe5c19344d2939887bfdf5d9f83b
Author: Jan-Niklas Jaeschke <jjaschke@mozilla.com>
Date: Tue, 28 Oct 2025 17:18:26 +0000
Bug 1970123, part 8 - Navigation API: Call precommit handlers in #inner-navigate-event-firing. r=dom-core,smaug
Differential Revision: https://phabricator.services.mozilla.com/D270185
Diffstat:
2 files changed, 49 insertions(+), 2 deletions(-)
diff --git a/dom/events/NavigateEvent.h b/dom/events/NavigateEvent.h
@@ -109,6 +109,11 @@ class NavigateEvent final : public Event {
MOZ_CAN_RUN_SCRIPT
void Finish(bool aDidFulfill);
+ nsTArray<RefPtr<NavigationPrecommitHandler>>&
+ NavigationPrecommitHandlerList() {
+ return mNavigationPrecommitHandlerList;
+ }
+
void PerformSharedChecks(ErrorResult& aRv);
private:
diff --git a/dom/navigation/Navigation.cpp b/dom/navigation/Navigation.cpp
@@ -6,6 +6,7 @@
#include "mozilla/dom/Navigation.h"
+#include "NavigationPrecommitController.h"
#include "fmt/format.h"
#include "jsapi.h"
#include "mozilla/CycleCollectedJSContext.h"
@@ -1661,8 +1662,49 @@ bool Navigation::InnerFireNavigateEvent(
RefPtr scope = MakeRefPtr<NavigationWaitForAllScope>(this, apiMethodTracker,
event, aDestination);
// Step 30
- scope->CommitNavigateEvent(aNavigationType);
-
+ if (event->NavigationPrecommitHandlerList().IsEmpty()) {
+ LOG_FMTD("No precommit handlers, committing directly");
+ scope->CommitNavigateEvent(aNavigationType);
+ } else {
+ LOG_FMTD("Running {} precommit handlers",
+ event->NavigationPrecommitHandlerList().Length());
+ // Step 31.1
+ RefPtr precommitController =
+ new NavigationPrecommitController(event, globalObject);
+ // Step 31.2
+ nsTArray<RefPtr<Promise>> precommitPromiseList;
+ // Step 31.3
+ for (auto& handler : event->NavigationPrecommitHandlerList().Clone()) {
+ // Step 31.3.1
+ RefPtr promise = MOZ_KnownLive(handler)->Call(*precommitController);
+ if (promise) {
+ precommitPromiseList.AppendElement(promise);
+ }
+ }
+ // Step 31.4
+ Promise::WaitForAll(
+ globalObject, precommitPromiseList,
+ [weakScope = WeakPtr(scope),
+ aNavigationType](const Span<JS::Heap<JS::Value>>&)
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY_LAMBDA {
+ // If weakScope is null we've been cycle collected
+ if (!weakScope) {
+ return;
+ }
+ RefPtr scope = weakScope.get();
+ scope->CommitNavigateEvent(aNavigationType);
+ },
+ [weakScope = WeakPtr(scope)](JS::Handle<JS::Value> aRejectionReason)
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY_LAMBDA {
+ // If weakScope is null we've been cycle collected
+ if (!weakScope) {
+ return;
+ }
+ RefPtr scope = weakScope.get();
+ scope->ProcessNavigateEventHandlerFailure(aRejectionReason);
+ },
+ scope);
+ }
// Step 32 and 33
return event->InterceptionState() == NavigateEvent::InterceptionState::None;
}