summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2022-10-17 11:06:50 +0200
committerAndreas Kling <kling@serenityos.org>2022-10-20 15:16:23 +0200
commit83c5ff57d8dfaad4652cd94df834b08d6cdc3db3 (patch)
treeb9341fb9edd8e1426461c5ace56cf97a7f80e352
parent2898701459a3966b3e973823706142ebbc287ae9 (diff)
downloadserenity-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.
-rw-r--r--Userland/Libraries/LibWeb/DOM/Document.cpp12
-rw-r--r--Userland/Libraries/LibWeb/DOM/Document.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp92
-rw-r--r--Userland/Libraries/LibWeb/HTML/BrowsingContext.h91
-rw-r--r--Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.cpp8
-rw-r--r--Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/BrowsingContextGroup.cpp18
-rw-r--r--Userland/Libraries/LibWeb/HTML/BrowsingContextGroup.h12
-rw-r--r--Userland/Libraries/LibWeb/HTML/NavigationParams.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/Scripting/Environments.cpp1
-rw-r--r--Userland/Libraries/LibWeb/HTML/Scripting/Environments.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/SessionHistoryEntry.h4
-rw-r--r--Userland/Libraries/LibWeb/Page/Page.cpp12
-rw-r--r--Userland/Libraries/LibWeb/Page/Page.h7
-rw-r--r--Userland/Libraries/LibWeb/Painting/LabelablePaintable.cpp2
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);
}