Parcourir la source

LibWeb: Update session history when `History` entry is pushed/replaced

With this change `shared_history_push_replace_state()` starts to
actually add/replace session history entry.
Aliaksandr Kalenik il y a 1 an
Parent
commit
7cdbd59e92

+ 0 - 0
Tests/LibWeb/Text/expected/navigation/history-pushstate-iframe.txt


+ 1 - 0
Tests/LibWeb/Text/expected/navigation/history-pushstate.txt

@@ -0,0 +1 @@
+  history object length has changed by 1

+ 20 - 0
Tests/LibWeb/Text/input/navigation/history-pushstate-iframe.html

@@ -0,0 +1,20 @@
+<script src="../include.js"></script>
+<script>
+    try {
+        const initialHistoryLength = window.history.length;
+
+        history.pushState({}, "hello", "history-pushstate-iframe.html#hello");
+
+        if (window.self !== window.top) {
+            parent.postMessage(
+                "history object length has changed by " +
+                    (window.history.length - initialHistoryLength),
+                "*"
+            );
+        } else {
+            test(() => {});
+        }
+    } catch (e) {
+        if (window.self !== window.top) parent.postMessage("ERROR:" + e, "*");
+    }
+</script>

+ 23 - 0
Tests/LibWeb/Text/input/navigation/history-pushstate.html

@@ -0,0 +1,23 @@
+<script src="../include.js"></script>
+<iframe id="testIframe" src="about:blank"></iframe>
+<script>
+    asyncTest(async done => {
+        const iframe = document.getElementById("testIframe");
+
+        function navigateIframe(src) {
+            return new Promise(resolve => {
+                iframe.addEventListener("load", () => {
+                    resolve();
+                });
+                iframe.src = src;
+            });
+        }
+
+        window.addEventListener("message", event => {
+            println(event.data);
+            done();
+        });
+
+        await navigateIframe("./history-pushstate-iframe.html");
+    }); 
+</script>

+ 9 - 8
Userland/Libraries/LibWeb/HTML/History.cpp

@@ -38,17 +38,17 @@ void History::visit_edges(Cell::Visitor& visitor)
 }
 
 // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate
+// The pushState(data, unused, url) method steps are to run the shared history push/replace state steps given this, data, url, and "push".
 WebIDL::ExceptionOr<void> History::push_state(JS::Value data, String const&, Optional<String> const& url)
 {
-    // NOTE: The second parameter of this function is intentionally unused.
-    return shared_history_push_replace_state(data, url, IsPush::Yes);
+    return shared_history_push_replace_state(data, url, HistoryHandlingBehavior::Push);
 }
 
 // https://html.spec.whatwg.org/multipage/history.html#dom-history-replacestate
+// The replaceState(data, unused, url) method steps are to run the shared history push/replace state steps given this, data, url, and "replace".
 WebIDL::ExceptionOr<void> History::replace_state(JS::Value data, String const&, Optional<String> const& url)
 {
-    // NOTE: The second parameter of this function is intentionally unused.
-    return shared_history_push_replace_state(data, url, IsPush::No);
+    return shared_history_push_replace_state(data, url, HistoryHandlingBehavior::Replace);
 }
 
 // https://html.spec.whatwg.org/multipage/history.html#dom-history-length
@@ -145,7 +145,7 @@ bool can_have_its_url_rewritten(DOM::Document const& document, AK::URL const& ta
 }
 
 // https://html.spec.whatwg.org/multipage/history.html#shared-history-push/replace-state-steps
-WebIDL::ExceptionOr<void> History::shared_history_push_replace_state(JS::Value value, Optional<String> const& url, IsPush)
+WebIDL::ExceptionOr<void> History::shared_history_push_replace_state(JS::Value value, Optional<String> const& url, HistoryHandlingBehavior history_handling)
 {
     // 1. Let document be history's associated Document.
     auto& document = m_associated_document;
@@ -188,10 +188,11 @@ WebIDL::ExceptionOr<void> History::shared_history_push_replace_state(JS::Value v
     ///          with navigationType set to historyHandling, isSameDocument set to true, destinationURL set to newURL,
     //           and classicHistoryAPIState set to serializedData.
     // FIXME: 9. If continue is false, then return.
-    // FIXME: 10. Run the URL and history update steps given document and newURL, with serializedData set to
-    //            serializedData and historyHandling set to historyHandling.
 
-    dbgln("FIXME: Implement shared_history_push_replace_state.");
+    // 10. Run the URL and history update steps given document and newURL, with serializedData set to
+    //     serializedData and historyHandling set to historyHandling.
+    perform_url_and_history_update_steps(document, new_url, history_handling);
+
     return {};
 }
 

+ 2 - 5
Userland/Libraries/LibWeb/HTML/History.h

@@ -8,6 +8,7 @@
 #pragma once
 
 #include <LibWeb/Bindings/PlatformObject.h>
+#include <LibWeb/HTML/HistoryHandlingBehavior.h>
 #include <LibWeb/WebIDL/ExceptionOr.h>
 
 namespace Web::HTML {
@@ -36,11 +37,7 @@ private:
     virtual void initialize(JS::Realm&) override;
     virtual void visit_edges(Cell::Visitor&) override;
 
-    enum class IsPush {
-        No,
-        Yes,
-    };
-    WebIDL::ExceptionOr<void> shared_history_push_replace_state(JS::Value data, Optional<String> const& url, IsPush is_push);
+    WebIDL::ExceptionOr<void> shared_history_push_replace_state(JS::Value data, Optional<String> const& url, HistoryHandlingBehavior);
 
     JS::NonnullGCPtr<DOM::Document> m_associated_document;
 };