فهرست منبع

LibWeb: Implement NavigateEvent AOs that are called during event firing

The potentially scroll/focus and finish AOs are called by the inner
navigate event firing algorithm. Implement them beforehand to make the
diff look pretty :^).
Andrew Kaster 1 سال پیش
والد
کامیت
2a24dda44d

+ 87 - 0
Userland/Libraries/LibWeb/HTML/NavigateEvent.cpp

@@ -14,7 +14,9 @@
 #include <LibWeb/DOM/AbortController.h>
 #include <LibWeb/DOM/AbortController.h>
 #include <LibWeb/DOM/AbortSignal.h>
 #include <LibWeb/DOM/AbortSignal.h>
 #include <LibWeb/DOM/Document.h>
 #include <LibWeb/DOM/Document.h>
+#include <LibWeb/HTML/Focus.h>
 #include <LibWeb/HTML/NavigateEvent.h>
 #include <LibWeb/HTML/NavigateEvent.h>
+#include <LibWeb/HTML/Navigation.h>
 #include <LibWeb/HTML/NavigationDestination.h>
 #include <LibWeb/HTML/NavigationDestination.h>
 #include <LibWeb/XHR/FormData.h>
 #include <LibWeb/XHR/FormData.h>
 
 
@@ -196,4 +198,89 @@ void NavigateEvent::process_scroll_behavior()
     }
     }
 }
 }
 
 
+// https://html.spec.whatwg.org/multipage/nav-history-apis.html#potentially-process-scroll-behavior
+void NavigateEvent::potentially_process_scroll_behavior()
+{
+    // 1. Assert: event's interception state is "committed" or "scrolled".
+    VERIFY(m_interception_state != InterceptionState::Committed && m_interception_state != InterceptionState::Scrolled);
+
+    // 2. If event's interception state is "scrolled", then return.
+    if (m_interception_state == InterceptionState::Scrolled)
+        return;
+
+    // 3. If event's scroll behavior is "manual", then return.
+    // NOTE: If it was left as null, then we treat that as "after-transition", and continue onward.
+    if (m_scroll_behavior == Bindings::NavigationScrollBehavior::Manual)
+        return;
+
+    // 4. Process scroll behavior given event.
+    process_scroll_behavior();
+}
+
+// https://html.spec.whatwg.org/multipage/nav-history-apis.html#potentially-reset-the-focus
+void NavigateEvent::potentially_reset_the_focus()
+{
+    // 1. Assert: event's interception state is "committed" or "scrolled".
+    VERIFY(m_interception_state == InterceptionState::Committed || m_interception_state == InterceptionState::Scrolled);
+
+    // 2. Let navigation be event's relevant global object's navigation API.
+    auto& relevant_global_object = verify_cast<Window>(HTML::relevant_global_object(*this));
+    auto navigation = relevant_global_object.navigation();
+
+    // 3. Let focusChanged be navigation's focus changed during ongoing navigation.
+    auto focus_changed = navigation->focus_changed_during_ongoing_navigation();
+
+    // 4. Set navigation's focus changed during ongoing navigation to false.
+    navigation->set_focus_changed_during_ongoing_navigation(false);
+
+    // 5. If focusChanged is true, then return.
+    if (focus_changed)
+        return;
+
+    // 6. If event's focus reset behavior is "manual", then return.
+    // NOTE: If it was left as null, then we treat that as "after-transition", and continue onward.
+    if (m_focus_reset_behavior == Bindings::NavigationFocusReset::Manual)
+        return;
+
+    // 7. Let document be event's relevant global object's associated Document.
+    auto& document = relevant_global_object.associated_document();
+
+    // 8. FIXME: Let focusTarget be the autofocus delegate for document.
+    JS::GCPtr<DOM::Node> focus_target = nullptr;
+
+    // 9. If focusTarget is null, then set focusTarget to document's body element.
+    if (focus_target == nullptr)
+        focus_target = document.body();
+
+    // 10. If focusTarget is null, then set focusTarget to document's document element.
+    if (focus_target == nullptr)
+        focus_target = document.document_element();
+
+    // FIXME: 11. Run the focusing steps for focusTarget, with document's viewport as the fallback target.
+    run_focusing_steps(focus_target, nullptr);
+
+    // FIXME: 12. Move the sequential focus navigation starting point to focusTarget.
+}
+
+// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigateevent-finish
+void NavigateEvent::finish(bool did_fulfill)
+{
+    // 1. Assert: event's interception state is not "intercepted" or "finished".
+    VERIFY(m_interception_state != InterceptionState::Intercepted && m_interception_state != InterceptionState::Finished);
+
+    // 2. If event's interception state is "none", then return.
+    if (m_interception_state == InterceptionState::None)
+        return;
+
+    // 3. Potentially reset the focus given event.
+    potentially_reset_the_focus();
+
+    // 4. If didFulfill is true, then potentially process scroll behavior given event.
+    if (did_fulfill)
+        potentially_process_scroll_behavior();
+
+    // 5. Set event's interception state to "finished".
+    m_interception_state = InterceptionState::Finished;
+}
+
 }
 }

+ 4 - 0
Userland/Libraries/LibWeb/HTML/NavigateEvent.h

@@ -64,6 +64,8 @@ public:
 
 
     JS::NonnullGCPtr<DOM::AbortController> abort_controller() const { return *m_abort_controller; }
     JS::NonnullGCPtr<DOM::AbortController> abort_controller() const { return *m_abort_controller; }
 
 
+    void finish(bool did_fulfill);
+
 private:
 private:
     NavigateEvent(JS::Realm&, FlyString const& event_name, NavigateEventInit const& event_init);
     NavigateEvent(JS::Realm&, FlyString const& event_name, NavigateEventInit const& event_init);
 
 
@@ -72,6 +74,8 @@ private:
 
 
     WebIDL::ExceptionOr<void> perform_shared_checks();
     WebIDL::ExceptionOr<void> perform_shared_checks();
     void process_scroll_behavior();
     void process_scroll_behavior();
+    void potentially_process_scroll_behavior();
+    void potentially_reset_the_focus();
 
 
     // https://html.spec.whatwg.org/multipage/nav-history-apis.html#concept-navigateevent-interception-state
     // https://html.spec.whatwg.org/multipage/nav-history-apis.html#concept-navigateevent-interception-state
     enum class InterceptionState {
     enum class InterceptionState {

+ 4 - 1
Userland/Libraries/LibWeb/HTML/Navigation.h

@@ -110,9 +110,12 @@ public:
 
 
     virtual ~Navigation() override;
     virtual ~Navigation() override;
 
 
-    // Internal Getters
+    // Internal Getters/Setters
     JS::GCPtr<NavigateEvent> ongoing_navigate_event() const { return m_ongoing_navigate_event; }
     JS::GCPtr<NavigateEvent> ongoing_navigate_event() const { return m_ongoing_navigate_event; }
 
 
+    bool focus_changed_during_ongoing_navigation() const { return m_focus_changed_during_ongoing_navigation; }
+    void set_focus_changed_during_ongoing_navigation(bool b) { m_focus_changed_during_ongoing_navigation = b; }
+
 private:
 private:
     explicit Navigation(JS::Realm&);
     explicit Navigation(JS::Realm&);