LibWeb/HTML: Implement NavigationTransition committed promise

This commit is contained in:
Sam Atkins 2025-12-04 16:21:03 +00:00
parent 945c4ca5b3
commit 4fb28539a9
Notes: github-actions[bot] 2025-12-05 09:21:16 +00:00
4 changed files with 27 additions and 9 deletions

View file

@ -806,7 +806,8 @@ void Navigation::abort_a_navigate_event(GC::Ref<NavigateEvent> event, GC::Ref<We
if (!m_transition)
return;
// FIXME: 8. Reject navigation's transition's committed promise with error.
// 8. Reject navigation's transition's committed promise with error.
WebIDL::reject_promise(realm(), m_transition->committed(), reason);
// 9. Reject navigation's transition's finished promise with reason.
WebIDL::reject_promise(realm(), m_transition->finished(), reason);
@ -1127,13 +1128,17 @@ bool Navigation::inner_navigate_event_firing_algorithm(
// navigation type: navigationType
// from entry: fromNHE
// destination: event's destination
// FIXME: committed promise: a new promise created in navigation's relevant realm
// committed promise: a new promise created in navigation's relevant realm
// finished promise: a new promise created in navigation's relevant realm
m_transition = NavigationTransition::create(realm, navigation_type, *from_nhe, event->destination(), WebIDL::create_promise(realm));
m_transition = NavigationTransition::create(realm, navigation_type, *from_nhe, event->destination(), WebIDL::create_promise(realm), WebIDL::create_promise(realm));
// 5. Mark as handled navigation's transition's finished promise.
WebIDL::mark_promise_as_handled(*m_transition->finished());
// AD-HOC: The current spec has changed significantly from what we implement here, but marks the committed
// promise as handled at the equivalent place.
WebIDL::mark_promise_as_handled(*m_transition->committed());
// 6. If navigationType is "traverse", then set navigation's suppress normal scroll restoration during ongoing navigation to true.
// NOTE: If event's scroll behavior was set to "after-transition", then scroll restoration will happen as part of finishing
// the relevant NavigateEvent. Otherwise, there will be no scroll restoration. That is, no navigation which is intercepted

View file

@ -17,16 +17,17 @@ namespace Web::HTML {
GC_DEFINE_ALLOCATOR(NavigationTransition);
GC::Ref<NavigationTransition> NavigationTransition::create(JS::Realm& realm, Bindings::NavigationType navigation_type, GC::Ref<NavigationHistoryEntry> from_entry, GC::Ref<NavigationDestination> destination, GC::Ref<WebIDL::Promise> finished_promise)
GC::Ref<NavigationTransition> NavigationTransition::create(JS::Realm& realm, Bindings::NavigationType navigation_type, GC::Ref<NavigationHistoryEntry> from_entry, GC::Ref<NavigationDestination> destination, GC::Ref<WebIDL::Promise> committed_promise, GC::Ref<WebIDL::Promise> finished_promise)
{
return realm.create<NavigationTransition>(realm, navigation_type, from_entry, destination, finished_promise);
return realm.create<NavigationTransition>(realm, navigation_type, from_entry, destination, committed_promise, finished_promise);
}
NavigationTransition::NavigationTransition(JS::Realm& realm, Bindings::NavigationType navigation_type, GC::Ref<NavigationHistoryEntry> from_entry, GC::Ref<NavigationDestination> destination, GC::Ref<WebIDL::Promise> finished_promise)
NavigationTransition::NavigationTransition(JS::Realm& realm, Bindings::NavigationType navigation_type, GC::Ref<NavigationHistoryEntry> from_entry, GC::Ref<NavigationDestination> destination, GC::Ref<WebIDL::Promise> committed_promise, GC::Ref<WebIDL::Promise> finished_promise)
: Bindings::PlatformObject(realm)
, m_navigation_type(navigation_type)
, m_from_entry(from_entry)
, m_destination(destination)
, m_committed_promise(committed_promise)
, m_finished_promise(finished_promise)
{
}
@ -44,6 +45,7 @@ void NavigationTransition::visit_edges(JS::Cell::Visitor& visitor)
Base::visit_edges(visitor);
visitor.visit(m_from_entry);
visitor.visit(m_destination);
visitor.visit(m_committed_promise);
visitor.visit(m_finished_promise);
}

View file

@ -17,7 +17,7 @@ class NavigationTransition : public Bindings::PlatformObject {
GC_DECLARE_ALLOCATOR(NavigationTransition);
public:
[[nodiscard]] static GC::Ref<NavigationTransition> create(JS::Realm&, Bindings::NavigationType, GC::Ref<NavigationHistoryEntry>, GC::Ref<NavigationDestination>, GC::Ref<WebIDL::Promise>);
[[nodiscard]] static GC::Ref<NavigationTransition> create(JS::Realm&, Bindings::NavigationType, GC::Ref<NavigationHistoryEntry>, GC::Ref<NavigationDestination>, GC::Ref<WebIDL::Promise> committed, GC::Ref<WebIDL::Promise> finished);
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigationtransition-navigationtype
Bindings::NavigationType navigation_type() const
@ -40,6 +40,13 @@ public:
return m_destination;
}
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigationtransition-committed
GC::Ref<WebIDL::Promise> committed() const
{
// The committed getter steps are to return this's committed promise.
return m_committed_promise;
}
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigationtransition-finished
GC::Ref<WebIDL::Promise> finished() const
{
@ -50,7 +57,7 @@ public:
virtual ~NavigationTransition() override;
private:
NavigationTransition(JS::Realm&, Bindings::NavigationType, GC::Ref<NavigationHistoryEntry>, GC::Ref<NavigationDestination>, GC::Ref<WebIDL::Promise>);
NavigationTransition(JS::Realm&, Bindings::NavigationType, GC::Ref<NavigationHistoryEntry>, GC::Ref<NavigationDestination>, GC::Ref<WebIDL::Promise> committed, GC::Ref<WebIDL::Promise> finished);
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(JS::Cell::Visitor&) override;
@ -67,6 +74,10 @@ private:
// Each NavigationTransition has an associated destination, which is a NavigationDestination.
GC::Ref<NavigationDestination> m_destination;
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#concept-navigationtransition-committedc
// Each NavigationTransition has an associated committed promise, which is a promise.
GC::Ref<WebIDL::Promise> m_committed_promise;
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#concept-navigationtransition-finished
// Each NavigationTransition has an associated finished promise, which is a promise.
GC::Ref<WebIDL::Promise> m_finished_promise;

View file

@ -8,6 +8,6 @@ interface NavigationTransition {
readonly attribute NavigationType navigationType;
readonly attribute NavigationHistoryEntry from;
readonly attribute NavigationDestination to;
// FIXME: readonly attribute Promise<undefined> committed;
readonly attribute Promise<undefined> committed;
readonly attribute Promise<undefined> finished;
};