Ver código fonte

LibWeb: Make SessionHistoryEntry GC-allocated

These will need to float around more than they're currently able to.
Put them on the GC heap to prepare for that.

Co-authored-by: Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
Andreas Kling 2 anos atrás
pai
commit
3b0e5a87db

+ 1 - 0
Userland/Libraries/LibWeb/CMakeLists.txt

@@ -337,6 +337,7 @@ set(SOURCES
     HTML/Scripting/ModuleScript.cpp
     HTML/Scripting/Script.cpp
     HTML/Scripting/WindowEnvironmentSettingsObject.cpp
+    HTML/SessionHistoryEntry.cpp
     HTML/Storage.cpp
     HTML/StructuredSerialize.cpp
     HTML/SubmitEvent.cpp

+ 1 - 0
Userland/Libraries/LibWeb/Forward.h

@@ -351,6 +351,7 @@ class PromiseRejectionEvent;
 class WorkerDebugConsoleClient;
 struct SandboxingFlagSet;
 struct SerializedFormData;
+struct SessionHistoryEntry;
 class Storage;
 class SubmitEvent;
 class TextMetrics;

+ 28 - 28
Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp

@@ -209,15 +209,15 @@ JS::NonnullGCPtr<BrowsingContext> BrowsingContext::create_a_new_browsing_context
     // FIXME: 21. If creator is non-null, then set document's policy container to a clone of creator's policy container.
 
     // 22. Append a new session history entry to browsingContext's session history whose URL is about:blank and document is document.
-    browsing_context->m_session_history.append(HTML::SessionHistoryEntry {
-        .url = AK::URL("about:blank"),
-        .document = document.ptr(),
-        .serialized_state = {},
-        .policy_container = {},
-        .scroll_restoration_mode = {},
-        .browsing_context_name = {},
-        .original_source_browsing_context = {},
-    });
+    auto new_entry = browsing_context->heap().allocate_without_realm<SessionHistoryEntry>();
+    new_entry->url = AK::URL("about:blank");
+    new_entry->document = document.ptr();
+    new_entry->serialized_state = {};
+    new_entry->policy_container = {};
+    new_entry->scroll_restoration_mode = {};
+    new_entry->browsing_context_name = {};
+    new_entry->original_source_browsing_context = {};
+    browsing_context->m_session_history.append(*new_entry);
 
     // 23. Completely finish loading document.
     document->completely_finish_loading();
@@ -249,7 +249,7 @@ void BrowsingContext::visit_edges(Cell::Visitor& visitor)
     Base::visit_edges(visitor);
 
     for (auto& entry : m_session_history)
-        visitor.visit(entry.document);
+        visitor.visit(entry);
     visitor.visit(m_container);
     visitor.visit(m_window_proxy);
     visitor.visit(m_opener_browsing_context);
@@ -774,8 +774,8 @@ bool BrowsingContext::still_on_its_initial_about_blank_document() const
     // if browsingContext's session history's size is 1
     // and browsingContext's session history[0]'s document's is initial about:blank is true.
     return m_session_history.size() == 1
-        && m_session_history[0].document
-        && m_session_history[0].document->is_initial_about_blank();
+        && m_session_history[0]->document
+        && m_session_history[0]->document->is_initial_about_blank();
 }
 
 DOM::Document const* BrowsingContext::active_document() const
@@ -1009,15 +1009,15 @@ WebIDL::ExceptionOr<void> BrowsingContext::navigate_to_a_fragment(AK::URL const&
     //    document is the current entry's document,
     //    policy container is the current entry's policy-container
     //    and scroll restoration mode is the current entry's scroll restoration mode.
-    m_session_history.append(SessionHistoryEntry {
-        .url = url,
-        .document = current_entry().document,
-        .serialized_state = {},
-        .policy_container = current_entry().policy_container,
-        .scroll_restoration_mode = current_entry().scroll_restoration_mode,
-        .browsing_context_name = {},
-        .original_source_browsing_context = {},
-    });
+    auto new_entry = heap().allocate_without_realm<SessionHistoryEntry>();
+    new_entry->url = url;
+    new_entry->document = current_entry().document;
+    new_entry->serialized_state = {};
+    new_entry->policy_container = current_entry().policy_container;
+    new_entry->scroll_restoration_mode = current_entry().scroll_restoration_mode;
+    new_entry->browsing_context_name = {};
+    new_entry->original_source_browsing_context = {};
+    m_session_history.append(*new_entry);
 
     // 4. Traverse the history to the new entry, with historyHandling set to historyHandling.
     //    This will scroll to the fragment given in what is now the document's URL.
@@ -1033,7 +1033,7 @@ WebIDL::ExceptionOr<void> BrowsingContext::navigate_to_a_fragment(AK::URL const&
 // https://html.spec.whatwg.org/multipage/browsing-the-web.html#traverse-the-history
 WebIDL::ExceptionOr<void> BrowsingContext::traverse_the_history(size_t entry_index, HistoryHandlingBehavior history_handling, bool explicit_history_navigation)
 {
-    auto* entry = &m_session_history[entry_index];
+    auto entry = m_session_history[entry_index];
 
     // 1. If entry's document is null, then:
     if (!entry->document) {
@@ -1152,7 +1152,7 @@ WebIDL::ExceptionOr<void> BrowsingContext::traverse_the_history(size_t entry_ind
         // FIXME: This is gnarly.
         m_session_history.remove(entry_index - 1);
         entry_index--;
-        entry = &m_session_history[entry_index];
+        entry = m_session_history[entry_index];
     }
 
     // 10. If entry's persisted user state is null, and its URL's fragment is non-null, then scroll to the fragment.
@@ -1260,11 +1260,11 @@ Vector<JS::Handle<DOM::Document>> BrowsingContext::document_family() const
 {
     HashTable<DOM::Document*> documents;
     for (auto& entry : m_session_history) {
-        if (!entry.document)
+        if (!entry->document)
             continue;
-        if (documents.set(const_cast<DOM::Document*>(entry.document.ptr())) == AK::HashSetResult::ReplacedExistingEntry)
+        if (documents.set(const_cast<DOM::Document*>(entry->document.ptr())) == AK::HashSetResult::ReplacedExistingEntry)
             continue;
-        for (auto& context : entry.document->list_of_descendant_browsing_contexts()) {
+        for (auto& context : entry->document->list_of_descendant_browsing_contexts()) {
             for (auto& document : context->document_family()) {
                 documents.set(document.ptr());
             }
@@ -1320,8 +1320,8 @@ void BrowsingContext::discard()
 
     // 1. Discard all Document objects for all the entries in browsingContext's session history.
     for (auto& entry : m_session_history) {
-        if (entry.document)
-            entry.document->discard();
+        if (entry->document)
+            entry->document->discard();
     }
 
     // AD-HOC:

+ 4 - 3
Userland/Libraries/LibWeb/HTML/BrowsingContext.h

@@ -210,8 +210,9 @@ public:
 
     JS::GCPtr<DOM::Node> currently_focused_area();
 
-    Vector<SessionHistoryEntry>& session_history() { return m_session_history; }
-    Vector<SessionHistoryEntry> const& session_history() const { return m_session_history; }
+    Vector<JS::NonnullGCPtr<SessionHistoryEntry>>& session_history() { return m_session_history; }
+    Vector<JS::NonnullGCPtr<SessionHistoryEntry>> const& session_history() const { return m_session_history; }
+
     size_t session_history_index() const { return *m_session_history_index; }
 
     // https://html.spec.whatwg.org/multipage/dom.html#still-on-its-initial-about:blank-document
@@ -284,7 +285,7 @@ private:
     Optional<size_t> m_session_history_index { 0 };
 
     // https://html.spec.whatwg.org/multipage/history.html#session-history
-    Vector<SessionHistoryEntry> m_session_history;
+    Vector<JS::NonnullGCPtr<SessionHistoryEntry>> m_session_history;
 
     // https://html.spec.whatwg.org/multipage/browsers.html#creator-url
     Optional<AK::URL> m_creator_url;

+ 1 - 1
Userland/Libraries/LibWeb/HTML/History.cpp

@@ -83,7 +83,7 @@ WebIDL::ExceptionOr<void> History::go(long delta = 0)
     if (next_entry_index < sessions.size()) {
         auto const& next_entry = sessions.at(next_entry_index);
         // FIXME: 4. Traverse the history by a delta with delta and document's browsing context.
-        browsing_context->loader().load(next_entry.url, FrameLoader::Type::Reload);
+        browsing_context->loader().load(next_entry->url, FrameLoader::Type::Reload);
     }
 
     return {};

+ 19 - 0
Userland/Libraries/LibWeb/HTML/SessionHistoryEntry.cpp

@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibWeb/DOM/Document.h>
+#include <LibWeb/HTML/SessionHistoryEntry.h>
+
+namespace Web::HTML {
+
+void SessionHistoryEntry::visit_edges(Cell::Visitor& visitor)
+{
+    Base::visit_edges(visitor);
+    visitor.visit(document);
+    visitor.visit(original_source_browsing_context);
+}
+
+}

+ 6 - 1
Userland/Libraries/LibWeb/HTML/SessionHistoryEntry.h

@@ -8,6 +8,7 @@
 
 #include <AK/URL.h>
 #include <AK/WeakPtr.h>
+#include <LibJS/Heap/Cell.h>
 #include <LibJS/Heap/GCPtr.h>
 #include <LibWeb/Forward.h>
 #include <LibWeb/HTML/PolicyContainers.h>
@@ -26,7 +27,11 @@ enum class ScrollRestorationMode {
 };
 
 // https://html.spec.whatwg.org/multipage/history.html#session-history-entry
-struct SessionHistoryEntry {
+struct SessionHistoryEntry final : public JS::Cell {
+    JS_CELL(SessionHistoryEntry, JS::Cell);
+
+    void visit_edges(Cell::Visitor&) override;
+
     // URL, a URL
     AK::URL url;