diff options
author | Andreas Kling <kling@serenityos.org> | 2022-10-17 11:06:50 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-10-20 15:16:23 +0200 |
commit | 83c5ff57d8dfaad4652cd94df834b08d6cdc3db3 (patch) | |
tree | b9341fb9edd8e1426461c5ace56cf97a7f80e352 | |
parent | 2898701459a3966b3e973823706142ebbc287ae9 (diff) | |
download | serenity-83c5ff57d8dfaad4652cd94df834b08d6cdc3db3.zip |
LibWeb: Make BrowsingContext GC-allocated
(And BrowsingContextGroup had to come along for the ride as well.)
This solves a number of nasty reference cycles between browsing
contexts, history items, and their documents.
15 files changed, 225 insertions, 44 deletions
diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index 54f6156796..fc9afb9496 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -79,7 +79,7 @@ namespace Web::DOM { // https://html.spec.whatwg.org/multipage/origin.html#obtain-browsing-context-navigation -static NonnullRefPtr<HTML::BrowsingContext> obtain_a_browsing_context_to_use_for_a_navigation_response( +static JS::NonnullGCPtr<HTML::BrowsingContext> obtain_a_browsing_context_to_use_for_a_navigation_response( HTML::BrowsingContext& browsing_context, HTML::SandboxingFlagSet sandbox_flags, HTML::CrossOriginOpenerPolicy navigation_coop, @@ -130,7 +130,7 @@ JS::NonnullGCPtr<Document> Document::create_and_initialize(Type type, String con // given navigationParams's browsing context, navigationParams's final sandboxing flag set, // navigationParams's cross-origin opener policy, and navigationParams's COOP enforcement result. auto browsing_context = obtain_a_browsing_context_to_use_for_a_navigation_response( - navigation_params.browsing_context, + *navigation_params.browsing_context, navigation_params.final_sandboxing_flag_set, navigation_params.cross_origin_opener_policy, navigation_params.coop_enforcement_result); @@ -330,6 +330,8 @@ void Document::visit_edges(Cell::Visitor& visitor) visitor.visit(m_pending_parsing_blocking_script.ptr()); visitor.visit(m_history.ptr()); + visitor.visit(m_browsing_context); + visitor.visit(m_applets); visitor.visit(m_anchors); visitor.visit(m_images); @@ -2051,10 +2053,10 @@ HTML::PolicyContainer Document::policy_container() const } // https://html.spec.whatwg.org/multipage/browsers.html#list-of-the-descendant-browsing-contexts -Vector<NonnullRefPtr<HTML::BrowsingContext>> Document::list_of_descendant_browsing_contexts() const +Vector<JS::Handle<HTML::BrowsingContext>> Document::list_of_descendant_browsing_contexts() const { // 1. Let list be an empty list. - Vector<NonnullRefPtr<HTML::BrowsingContext>> list; + Vector<JS::Handle<HTML::BrowsingContext>> list; // 2. For each browsing context container container, // whose nested browsing context is non-null and whose shadow-including root is d, in shadow-including tree order: @@ -2063,7 +2065,7 @@ Vector<NonnullRefPtr<HTML::BrowsingContext>> Document::list_of_descendant_browsi // of this document's browsing context. if (browsing_context()) { browsing_context()->for_each_in_subtree([&](auto& context) { - list.append(context); + list.append(JS::make_handle(const_cast<HTML::BrowsingContext&>(context))); return IterationDecision::Continue; }); } diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index c8417fd514..8762b61ae5 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -416,7 +416,7 @@ public: HTML::PolicyContainer policy_container() const; // https://html.spec.whatwg.org/multipage/browsers.html#list-of-the-descendant-browsing-contexts - Vector<NonnullRefPtr<HTML::BrowsingContext>> list_of_descendant_browsing_contexts() const; + Vector<JS::Handle<HTML::BrowsingContext>> list_of_descendant_browsing_contexts() const; // https://html.spec.whatwg.org/multipage/window-object.html#discard-a-document void discard(); diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp index 93b6ed21eb..4f8cd120d5 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp @@ -92,21 +92,21 @@ HTML::Origin determine_the_origin(BrowsingContext const& browsing_context, Optio } // https://html.spec.whatwg.org/multipage/browsers.html#creating-a-new-top-level-browsing-context -NonnullRefPtr<BrowsingContext> BrowsingContext::create_a_new_top_level_browsing_context(Web::Page& page) +JS::NonnullGCPtr<BrowsingContext> BrowsingContext::create_a_new_top_level_browsing_context(Web::Page& page) { // 1. Let group be the result of creating a new browsing context group. auto group = BrowsingContextGroup::create_a_new_browsing_context_group(page); // 2. Return group's browsing context set[0]. - return *group->browsing_context_set().begin(); + return *(*group->browsing_context_set().begin()); } // https://html.spec.whatwg.org/multipage/browsers.html#creating-a-new-browsing-context -NonnullRefPtr<BrowsingContext> BrowsingContext::create_a_new_browsing_context(Page& page, JS::GCPtr<DOM::Document> creator, JS::GCPtr<DOM::Element> embedder, BrowsingContextGroup&) +JS::NonnullGCPtr<BrowsingContext> BrowsingContext::create_a_new_browsing_context(Page& page, JS::GCPtr<DOM::Document> creator, JS::GCPtr<DOM::Element> embedder, BrowsingContextGroup&) { // 1. Let browsingContext be a new browsing context. BrowsingContextContainer* container = (embedder && is<BrowsingContextContainer>(*embedder)) ? static_cast<BrowsingContextContainer*>(embedder.ptr()) : nullptr; - auto browsing_context = adopt_ref(*new BrowsingContext(page, container)); + auto browsing_context = Bindings::main_thread_vm().heap().allocate_without_realm<BrowsingContext>(page, container); // 2. Let unsafeContextCreationTime be the unsafe shared current time. [[maybe_unused]] auto unsafe_context_creation_time = HighResolutionTime::unsafe_shared_current_time(); @@ -125,7 +125,7 @@ NonnullRefPtr<BrowsingContext> BrowsingContext::create_a_new_browsing_context(Pa SandboxingFlagSet sandbox_flags; // 5. Let origin be the result of determining the origin given browsingContext, about:blank, sandboxFlags, and browsingContext's creator origin. - auto origin = determine_the_origin(browsing_context, AK::URL("about:blank"), sandbox_flags, browsing_context->m_creator_origin); + auto origin = determine_the_origin(*browsing_context, AK::URL("about:blank"), sandbox_flags, browsing_context->m_creator_origin); // FIXME: 6. Let permissionsPolicy be the result of creating a permissions policy given browsingContext and origin. [PERMISSIONSPOLICY] @@ -240,7 +240,7 @@ NonnullRefPtr<BrowsingContext> BrowsingContext::create_a_new_browsing_context(Pa document->completely_finish_loading(); // 24. Return browsingContext. - return browsing_context; + return *browsing_context; } BrowsingContext::BrowsingContext(Page& page, HTML::BrowsingContextContainer* container) @@ -261,6 +261,22 @@ BrowsingContext::BrowsingContext(Page& page, HTML::BrowsingContextContainer* con BrowsingContext::~BrowsingContext() = default; +void BrowsingContext::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + + for (auto& entry : m_session_history) + visitor.visit(entry.document); + visitor.visit(m_container); + visitor.visit(m_window_proxy); + visitor.visit(m_group); + visitor.visit(m_parent); + visitor.visit(m_first_child); + visitor.visit(m_last_child); + visitor.visit(m_next_sibling); + visitor.visit(m_previous_sibling); +} + void BrowsingContext::did_edit(Badge<EditEventHandler>) { reset_cursor_blink_cycle(); @@ -446,7 +462,7 @@ Gfx::IntRect BrowsingContext::to_top_level_rect(Gfx::IntRect const& a_rect) Gfx::IntPoint BrowsingContext::to_top_level_position(Gfx::IntPoint const& a_position) { auto position = a_position; - for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) { + for (auto ancestor = parent(); ancestor; ancestor = ancestor->parent()) { if (ancestor->is_top_level()) break; if (!ancestor->container()) @@ -657,7 +673,7 @@ BrowsingContext* BrowsingContext::choose_a_browsing_context(StringView name, boo // name, a browsing context current, and a boolean noopener are as follows: // 1. Let chosen be null. - BrowsingContext* chosen = nullptr; + JS::GCPtr<BrowsingContext> chosen = nullptr; // FIXME: 2. Let windowType be "existing or none". @@ -672,7 +688,7 @@ BrowsingContext* BrowsingContext::choose_a_browsing_context(StringView name, boo // set chosen to current's parent browsing context, if any, and current // otherwise. if (name.equals_ignoring_case("_parent"sv)) { - if (auto* parent = this->parent()) + if (auto parent = this->parent()) chosen = parent; else chosen = this; @@ -872,13 +888,13 @@ void BrowsingContext::remove() VERIFY(group()); // 2. Let group be browsingContext's group. - NonnullRefPtr<BrowsingContextGroup> group = *this->group(); + JS::NonnullGCPtr<BrowsingContextGroup> group = *this->group(); // 3. Set browsingContext's group to null. set_group(nullptr); // 4. Remove browsingContext from group's browsing context set. - group->browsing_context_set().remove(*this); + group->browsing_context_set().remove(this); // 5. If group's browsing context set is empty, then remove group from the user agent's browsing context group set. // NOTE: This is done by ~BrowsingContextGroup() when the refcount reaches 0. @@ -1281,7 +1297,7 @@ Vector<JS::Handle<DOM::Document>> BrowsingContext::document_family() const for (auto& entry : m_session_history) { if (!entry.document) continue; - if (documents.set(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& document : context->document_family()) { @@ -1367,4 +1383,56 @@ void BrowsingContext::close() discard(); } +void BrowsingContext::append_child(JS::NonnullGCPtr<BrowsingContext> child) +{ + VERIFY(!child->m_parent); + + if (m_last_child) + m_last_child->m_next_sibling = child; + child->m_previous_sibling = m_last_child; + child->m_parent = this; + m_last_child = child; + if (!m_first_child) + m_first_child = m_last_child; +} + +void BrowsingContext::remove_child(JS::NonnullGCPtr<BrowsingContext> child) +{ + VERIFY(child->m_parent.ptr() == this); + + if (m_first_child == child) + m_first_child = child->m_next_sibling; + + if (m_last_child == child) + m_last_child = child->m_previous_sibling; + + if (child->m_next_sibling) + child->m_next_sibling->m_previous_sibling = child->m_previous_sibling; + + if (child->m_previous_sibling) + child->m_previous_sibling->m_next_sibling = child->m_next_sibling; + + child->m_next_sibling = nullptr; + child->m_previous_sibling = nullptr; + child->m_parent = nullptr; +} + +JS::GCPtr<BrowsingContext> BrowsingContext::first_child() const +{ + return m_first_child; +} +JS::GCPtr<BrowsingContext> BrowsingContext::next_sibling() const +{ + return m_next_sibling; +} + +bool BrowsingContext::is_ancestor_of(BrowsingContext const& other) const +{ + for (auto ancestor = other.parent(); ancestor; ancestor = ancestor->parent()) { + if (ancestor == this) + return true; + } + return false; +} + } diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.h b/Userland/Libraries/LibWeb/HTML/BrowsingContext.h index 34b2d920a8..6fb9e8617f 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.h +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.h @@ -13,6 +13,7 @@ #include <LibGfx/Bitmap.h> #include <LibGfx/Rect.h> #include <LibGfx/Size.h> +#include <LibJS/Heap/Cell.h> #include <LibWeb/DOM/Position.h> #include <LibWeb/HTML/BrowsingContextContainer.h> #include <LibWeb/HTML/HistoryHandlingBehavior.h> @@ -26,13 +27,83 @@ namespace Web::HTML { -class BrowsingContext : public TreeNode<BrowsingContext> { +class BrowsingContext final + : public JS::Cell + , public Weakable<BrowsingContext> { + JS_CELL(BrowsingContext, JS::Cell); + public: - static NonnullRefPtr<BrowsingContext> create_a_new_browsing_context(Page&, JS::GCPtr<DOM::Document> creator, JS::GCPtr<DOM::Element> embedder, BrowsingContextGroup&); - static NonnullRefPtr<BrowsingContext> create_a_new_top_level_browsing_context(Page&); + static JS::NonnullGCPtr<BrowsingContext> create_a_new_browsing_context(Page&, JS::GCPtr<DOM::Document> creator, JS::GCPtr<DOM::Element> embedder, BrowsingContextGroup&); + static JS::NonnullGCPtr<BrowsingContext> create_a_new_top_level_browsing_context(Page&); ~BrowsingContext(); + JS::GCPtr<BrowsingContext> parent() const { return m_parent; } + void append_child(JS::NonnullGCPtr<BrowsingContext>); + void remove_child(JS::NonnullGCPtr<BrowsingContext>); + JS::GCPtr<BrowsingContext> first_child() const; + JS::GCPtr<BrowsingContext> next_sibling() const; + + bool is_ancestor_of(BrowsingContext const&) const; + + template<typename Callback> + IterationDecision for_each_in_inclusive_subtree(Callback callback) const + { + if (callback(*this) == IterationDecision::Break) + return IterationDecision::Break; + for (auto child = first_child(); child; child = child->next_sibling()) { + if (child->for_each_in_inclusive_subtree(callback) == IterationDecision::Break) + return IterationDecision::Break; + } + return IterationDecision::Continue; + } + + template<typename Callback> + IterationDecision for_each_in_inclusive_subtree(Callback callback) + { + if (callback(*this) == IterationDecision::Break) + return IterationDecision::Break; + for (auto child = first_child(); child; child = child->next_sibling()) { + if (child->for_each_in_inclusive_subtree(callback) == IterationDecision::Break) + return IterationDecision::Break; + } + return IterationDecision::Continue; + } + + template<typename Callback> + void for_each_child(Callback callback) const + { + for (auto node = first_child(); node; node = node->next_sibling()) + callback(*node); + } + + template<typename Callback> + void for_each_child(Callback callback) + { + for (auto node = first_child(); node; node = node->next_sibling()) + callback(*node); + } + + template<typename Callback> + IterationDecision for_each_in_subtree(Callback callback) const + { + for (auto child = first_child(); child; child = child->next_sibling()) { + if (child->for_each_in_inclusive_subtree(callback) == IterationDecision::Break) + return IterationDecision::Break; + } + return IterationDecision::Continue; + } + + template<typename Callback> + IterationDecision for_each_in_subtree(Callback callback) + { + for (auto child = first_child(); child; child = child->next_sibling()) { + if (child->for_each_in_inclusive_subtree(callback) == IterationDecision::Break) + return IterationDecision::Break; + } + return IterationDecision::Continue; + } + class ViewportClient { public: virtual ~ViewportClient() = default; @@ -178,6 +249,8 @@ public: private: explicit BrowsingContext(Page&, HTML::BrowsingContextContainer*); + virtual void visit_edges(Cell::Visitor&) override; + void reset_cursor_blink_cycle(); void scroll_offset_did_change(); @@ -204,12 +277,12 @@ private: // https://html.spec.whatwg.org/multipage/browsers.html#creator-origin Optional<HTML::Origin> m_creator_origin; - WeakPtr<HTML::BrowsingContextContainer> m_container; + JS::GCPtr<HTML::BrowsingContextContainer> m_container; Gfx::IntSize m_size; Gfx::IntPoint m_viewport_scroll_offset; // https://html.spec.whatwg.org/multipage/browsers.html#browsing-context - JS::Handle<HTML::WindowProxy> m_window_proxy; + JS::GCPtr<HTML::WindowProxy> m_window_proxy; DOM::Position m_cursor_position; RefPtr<Platform::Timer> m_cursor_blink_timer; @@ -221,10 +294,16 @@ private: String m_name; // https://html.spec.whatwg.org/multipage/browsers.html#tlbc-group - RefPtr<BrowsingContextGroup> m_group; + JS::GCPtr<BrowsingContextGroup> m_group; // https://html.spec.whatwg.org/multipage/interaction.html#system-visibility-state VisibilityState m_system_visibility_state { VisibilityState::Hidden }; + + JS::GCPtr<BrowsingContext> m_parent; + JS::GCPtr<BrowsingContext> m_first_child; + JS::GCPtr<BrowsingContext> m_last_child; + JS::GCPtr<BrowsingContext> m_next_sibling; + JS::GCPtr<BrowsingContext> m_previous_sibling; }; HTML::Origin determine_the_origin(BrowsingContext const& browsing_context, Optional<AK::URL> url, SandboxingFlagSet sandbox_flags, Optional<HTML::Origin> invocation_origin); diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.cpp b/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.cpp index 135662d4d1..1b22820814 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.cpp +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.cpp @@ -31,6 +31,12 @@ BrowsingContextContainer::BrowsingContextContainer(DOM::Document& document, DOM: BrowsingContextContainer::~BrowsingContextContainer() = default; +void BrowsingContextContainer::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_nested_browsing_context); +} + // https://html.spec.whatwg.org/multipage/browsers.html#creating-a-new-nested-browsing-context void BrowsingContextContainer::create_new_nested_browsing_context() { @@ -142,7 +148,7 @@ void BrowsingContextContainer::shared_attribute_processing_steps_for_iframe_and_ // 3. If there exists an ancestor browsing context of element's nested browsing context // whose active document's URL, ignoring fragments, is equal to url, then return. if (m_nested_browsing_context) { - for (auto* ancestor = m_nested_browsing_context->parent(); ancestor; ancestor = ancestor->parent()) { + for (auto ancestor = m_nested_browsing_context->parent(); ancestor; ancestor = ancestor->parent()) { VERIFY(ancestor->active_document()); if (ancestor->active_document()->url().equals(url, AK::URL::ExcludeFragment::Yes)) return; diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.h b/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.h index f950d9960e..5adcb8daed 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.h +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.h @@ -31,6 +31,8 @@ public: protected: BrowsingContextContainer(DOM::Document&, DOM::QualifiedName); + virtual void visit_edges(Cell::Visitor&) override; + // https://html.spec.whatwg.org/multipage/iframe-embed-object.html#shared-attribute-processing-steps-for-iframe-and-frame-elements void shared_attribute_processing_steps_for_iframe_and_frame(bool initial_insertion); @@ -39,7 +41,7 @@ protected: void create_new_nested_browsing_context(); - RefPtr<BrowsingContext> m_nested_browsing_context; + JS::GCPtr<BrowsingContext> m_nested_browsing_context; private: virtual bool is_browsing_context_container() const override { return true; } diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContextGroup.cpp b/Userland/Libraries/LibWeb/HTML/BrowsingContextGroup.cpp index bb2161b8dc..6df63342a5 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContextGroup.cpp +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContextGroup.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <LibWeb/Bindings/MainThreadVM.h> #include <LibWeb/HTML/BrowsingContext.h> #include <LibWeb/HTML/BrowsingContextGroup.h> @@ -27,21 +28,28 @@ BrowsingContextGroup::~BrowsingContextGroup() user_agent_browsing_context_group_set().remove(this); } +void BrowsingContextGroup::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + for (auto& context : m_browsing_context_set) + visitor.visit(context); +} + // https://html.spec.whatwg.org/multipage/browsers.html#creating-a-new-browsing-context-group -NonnullRefPtr<BrowsingContextGroup> BrowsingContextGroup::create_a_new_browsing_context_group(Web::Page& page) +JS::NonnullGCPtr<BrowsingContextGroup> BrowsingContextGroup::create_a_new_browsing_context_group(Web::Page& page) { // 1. Let group be a new browsing context group. // 2. Append group to the user agent's browsing context group set. - auto group = adopt_ref(*new BrowsingContextGroup(page)); + auto group = Bindings::main_thread_vm().heap().allocate_without_realm<BrowsingContextGroup>(page); // 3. Let browsingContext be the result of creating a new browsing context with null, null, and group. - auto browsing_context = BrowsingContext::create_a_new_browsing_context(page, nullptr, nullptr, group); + auto browsing_context = BrowsingContext::create_a_new_browsing_context(page, nullptr, nullptr, *group); // 4. Append browsingContext to group. group->append(move(browsing_context)); // 5. Return group. - return group; + return *group; } // https://html.spec.whatwg.org/multipage/browsers.html#bcg-append @@ -50,7 +58,7 @@ void BrowsingContextGroup::append(BrowsingContext& browsing_context) VERIFY(browsing_context.is_top_level()); // 1. Append browsingContext to group's browsing context set. - m_browsing_context_set.set(browsing_context); + m_browsing_context_set.set(&browsing_context); // 2. Set browsingContext's group to group. browsing_context.set_group(this); diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContextGroup.h b/Userland/Libraries/LibWeb/HTML/BrowsingContextGroup.h index 2e0c08b4a4..f172c1616e 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContextGroup.h +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContextGroup.h @@ -8,14 +8,16 @@ #include <AK/HashMap.h> #include <AK/NonnullRefPtr.h> -#include <AK/RefCounted.h> +#include <LibJS/Heap/Cell.h> #include <LibWeb/Forward.h> namespace Web::HTML { -class BrowsingContextGroup : public RefCounted<BrowsingContextGroup> { +class BrowsingContextGroup final : public JS::Cell { + JS_CELL(BrowsingContextGroup, JS::Cell); + public: - static NonnullRefPtr<BrowsingContextGroup> create_a_new_browsing_context_group(Page&); + static JS::NonnullGCPtr<BrowsingContextGroup> create_a_new_browsing_context_group(Page&); ~BrowsingContextGroup(); Page* page() { return m_page; } @@ -30,8 +32,10 @@ public: private: explicit BrowsingContextGroup(Web::Page&); + virtual void visit_edges(Cell::Visitor&) override; + // https://html.spec.whatwg.org/multipage/browsers.html#browsing-context-group-set - OrderedHashTable<NonnullRefPtr<BrowsingContext>> m_browsing_context_set; + OrderedHashTable<BrowsingContext*> m_browsing_context_set; WeakPtr<Page> m_page; }; diff --git a/Userland/Libraries/LibWeb/HTML/NavigationParams.h b/Userland/Libraries/LibWeb/HTML/NavigationParams.h index 629360235a..45855b2625 100644 --- a/Userland/Libraries/LibWeb/HTML/NavigationParams.h +++ b/Userland/Libraries/LibWeb/HTML/NavigationParams.h @@ -47,7 +47,7 @@ struct NavigationParams { Optional<Environment> reserved_environment; // the browsing context to be navigated (or discarded, if a browsing context group switch occurs) - NonnullRefPtr<HTML::BrowsingContext> browsing_context; + JS::Handle<HTML::BrowsingContext> browsing_context; // a history handling behavior HistoryHandlingBehavior history_handling { HistoryHandlingBehavior::Default }; diff --git a/Userland/Libraries/LibWeb/HTML/Scripting/Environments.cpp b/Userland/Libraries/LibWeb/HTML/Scripting/Environments.cpp index c0baaa30a4..28ccf88260 100644 --- a/Userland/Libraries/LibWeb/HTML/Scripting/Environments.cpp +++ b/Userland/Libraries/LibWeb/HTML/Scripting/Environments.cpp @@ -32,6 +32,7 @@ EnvironmentSettingsObject::~EnvironmentSettingsObject() void EnvironmentSettingsObject::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); + visitor.visit(target_browsing_context); for (auto& promise : m_about_to_be_notified_rejected_promises_list) visitor.visit(promise); } diff --git a/Userland/Libraries/LibWeb/HTML/Scripting/Environments.h b/Userland/Libraries/LibWeb/HTML/Scripting/Environments.h index bdc56a116f..f846f30218 100644 --- a/Userland/Libraries/LibWeb/HTML/Scripting/Environments.h +++ b/Userland/Libraries/LibWeb/HTML/Scripting/Environments.h @@ -33,7 +33,7 @@ struct Environment { Origin top_level_origin; // https://html.spec.whatwg.org/multipage/webappapis.html#concept-environment-target-browsing-context - RefPtr<BrowsingContext> target_browsing_context; + JS::GCPtr<BrowsingContext> target_browsing_context; // FIXME: An active service worker https://html.spec.whatwg.org/multipage/webappapis.html#concept-environment-active-service-worker diff --git a/Userland/Libraries/LibWeb/HTML/SessionHistoryEntry.h b/Userland/Libraries/LibWeb/HTML/SessionHistoryEntry.h index 1ef72d1e71..493e151da5 100644 --- a/Userland/Libraries/LibWeb/HTML/SessionHistoryEntry.h +++ b/Userland/Libraries/LibWeb/HTML/SessionHistoryEntry.h @@ -30,7 +30,7 @@ struct SessionHistoryEntry { AK::URL url; // document, a Document or null - WeakPtr<DOM::Document> document; + JS::GCPtr<DOM::Document> document; // serialized state, which is serialized state or null, initially null Optional<String> serialized_state; @@ -49,7 +49,7 @@ struct SessionHistoryEntry { // FIXME: persisted user state, which is implementation-defined, initially null // NOTE: This is where we could remember the state of form controls, for example. - WeakPtr<BrowsingContext> original_source_browsing_context; + JS::GCPtr<BrowsingContext> original_source_browsing_context; }; } diff --git a/Userland/Libraries/LibWeb/Page/Page.cpp b/Userland/Libraries/LibWeb/Page/Page.cpp index e8bd7f75dd..864ed57b71 100644 --- a/Userland/Libraries/LibWeb/Page/Page.cpp +++ b/Userland/Libraries/LibWeb/Page/Page.cpp @@ -13,7 +13,7 @@ namespace Web { Page::Page(PageClient& client) : m_client(client) { - m_top_level_browsing_context = HTML::BrowsingContext::create_a_new_top_level_browsing_context(*this); + m_top_level_browsing_context = JS::make_handle(*HTML::BrowsingContext::create_a_new_top_level_browsing_context(*this)); } Page::~Page() = default; @@ -95,4 +95,14 @@ bool Page::handle_keyup(KeyCode key, unsigned modifiers, u32 code_point) return focused_context().event_handler().handle_keyup(key, modifiers, code_point); } +HTML::BrowsingContext& Page::top_level_browsing_context() +{ + return *m_top_level_browsing_context; +} + +HTML::BrowsingContext const& Page::top_level_browsing_context() const +{ + return *m_top_level_browsing_context; +} + } diff --git a/Userland/Libraries/LibWeb/Page/Page.h b/Userland/Libraries/LibWeb/Page/Page.h index 5bf6251d81..e1a1376ea6 100644 --- a/Userland/Libraries/LibWeb/Page/Page.h +++ b/Userland/Libraries/LibWeb/Page/Page.h @@ -17,6 +17,7 @@ #include <LibGfx/Forward.h> #include <LibGfx/Palette.h> #include <LibGfx/StandardCursor.h> +#include <LibJS/Heap/Handle.h> #include <LibWeb/CSS/PreferredColorScheme.h> #include <LibWeb/Forward.h> #include <LibWeb/Loader/FileRequest.h> @@ -36,8 +37,8 @@ public: PageClient& client() { return m_client; } PageClient const& client() const { return m_client; } - HTML::BrowsingContext& top_level_browsing_context() { return *m_top_level_browsing_context; } - HTML::BrowsingContext const& top_level_browsing_context() const { return *m_top_level_browsing_context; } + HTML::BrowsingContext& top_level_browsing_context(); + HTML::BrowsingContext const& top_level_browsing_context() const; HTML::BrowsingContext& focused_context(); HTML::BrowsingContext const& focused_context() const { return const_cast<Page*>(this)->focused_context(); } @@ -74,7 +75,7 @@ public: private: PageClient& m_client; - RefPtr<HTML::BrowsingContext> m_top_level_browsing_context; + JS::Handle<HTML::BrowsingContext> m_top_level_browsing_context; WeakPtr<HTML::BrowsingContext> m_focused_context; // FIXME: Enable this by default once CORS preflight checks are supported. diff --git a/Userland/Libraries/LibWeb/Painting/LabelablePaintable.cpp b/Userland/Libraries/LibWeb/Painting/LabelablePaintable.cpp index 74ce00c66d..66f469215f 100644 --- a/Userland/Libraries/LibWeb/Painting/LabelablePaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/LabelablePaintable.cpp @@ -83,7 +83,7 @@ void LabelablePaintable::handle_associated_label_mouseup(Badge<Layout::Label>) { // NOTE: Handling the click may run arbitrary JS, which could disappear this node. NonnullRefPtr protected_this = *this; - NonnullRefPtr protected_browsing_context = browsing_context(); + JS::NonnullGCPtr protected_browsing_context { browsing_context() }; set_being_pressed(false); } |