summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibWeb
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2022-10-17 14:41:50 +0200
committerAndreas Kling <kling@serenityos.org>2022-10-20 15:16:23 +0200
commit268b9c5d904e41ba901c9fce556a5be1d5fea228 (patch)
tree3162ca508db6480fef8729482dabb43c7eb5c4fe /Userland/Libraries/LibWeb
parent83c5ff57d8dfaad4652cd94df834b08d6cdc3db3 (diff)
downloadserenity-268b9c5d904e41ba901c9fce556a5be1d5fea228.zip
LibWeb: Make the layout tree GC-allocated
This removes a set of complex reference cycles between DOM, layout tree and browsing context. It also makes lifetimes much easier to reason about, as the DOM and layout trees are now free to keep each other alive.
Diffstat (limited to 'Userland/Libraries/LibWeb')
-rw-r--r--Userland/Libraries/LibWeb/DOM/Document.cpp8
-rw-r--r--Userland/Libraries/LibWeb/DOM/Document.h2
-rw-r--r--Userland/Libraries/LibWeb/DOM/Element.cpp36
-rw-r--r--Userland/Libraries/LibWeb/DOM/Element.h10
-rw-r--r--Userland/Libraries/LibWeb/DOM/Node.cpp9
-rw-r--r--Userland/Libraries/LibWeb/DOM/Node.h5
-rw-r--r--Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp14
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLBRElement.cpp4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLBRElement.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLImageElement.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp10
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLInputElement.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLLabelElement.cpp4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLLabelElement.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLProgressElement.cpp4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLProgressElement.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/BlockContainer.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/Box.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/BreakNode.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/ButtonBox.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/CanvasBox.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/CheckBox.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/FormAssociatedLabelableNode.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/FrameBox.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/ImageBox.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/InitialContainingBlock.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/InlineNode.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/Label.cpp3
-rw-r--r--Userland/Libraries/LibWeb/Layout/Label.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/LabelableNode.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/LayoutPosition.cpp2
-rw-r--r--Userland/Libraries/LibWeb/Layout/LayoutPosition.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/ListItemBox.cpp8
-rw-r--r--Userland/Libraries/LibWeb/Layout/ListItemBox.h8
-rw-r--r--Userland/Libraries/LibWeb/Layout/ListItemMarkerBox.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/Node.cpp28
-rw-r--r--Userland/Libraries/LibWeb/Layout/Node.h18
-rw-r--r--Userland/Libraries/LibWeb/Layout/Progress.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/RadioButton.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/ReplacedBox.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/SVGBox.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/SVGGeometryBox.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/SVGGraphicsBox.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/SVGSVGBox.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/TableBox.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/TableCellBox.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/TableRowBox.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/TableRowGroupBox.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/TextNode.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp54
-rw-r--r--Userland/Libraries/LibWeb/Layout/TreeBuilder.h4
-rw-r--r--Userland/Libraries/LibWeb/Page/EventHandler.cpp2
-rw-r--r--Userland/Libraries/LibWeb/Painting/PaintableBox.cpp6
-rw-r--r--Userland/Libraries/LibWeb/SVG/SVGClipPathElement.cpp2
-rw-r--r--Userland/Libraries/LibWeb/SVG/SVGClipPathElement.h2
-rw-r--r--Userland/Libraries/LibWeb/SVG/SVGDefsElement.cpp2
-rw-r--r--Userland/Libraries/LibWeb/SVG/SVGDefsElement.h2
-rw-r--r--Userland/Libraries/LibWeb/SVG/SVGGElement.cpp4
-rw-r--r--Userland/Libraries/LibWeb/SVG/SVGGElement.h2
-rw-r--r--Userland/Libraries/LibWeb/SVG/SVGGeometryElement.cpp4
-rw-r--r--Userland/Libraries/LibWeb/SVG/SVGGeometryElement.h2
-rw-r--r--Userland/Libraries/LibWeb/SVG/SVGSVGElement.cpp4
-rw-r--r--Userland/Libraries/LibWeb/SVG/SVGSVGElement.h2
-rw-r--r--Userland/Libraries/LibWeb/TreeNode.h112
71 files changed, 257 insertions, 206 deletions
diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp
index fc9afb9496..7f64a17337 100644
--- a/Userland/Libraries/LibWeb/DOM/Document.cpp
+++ b/Userland/Libraries/LibWeb/DOM/Document.cpp
@@ -683,7 +683,7 @@ void Document::tear_down_layout_tree()
// Gather up all the layout nodes in a vector and detach them from parents
// while the vector keeps them alive.
- NonnullRefPtrVector<Layout::Node> layout_nodes;
+ Vector<JS::Handle<Layout::Node>> layout_nodes;
m_layout_root->for_each_in_inclusive_subtree([&](auto& layout_node) {
layout_nodes.append(layout_node);
@@ -691,8 +691,8 @@ void Document::tear_down_layout_tree()
});
for (auto& layout_node : layout_nodes) {
- if (layout_node.parent())
- layout_node.parent()->remove_child(layout_node);
+ if (layout_node->parent())
+ layout_node->parent()->remove_child(*layout_node);
}
m_layout_root = nullptr;
@@ -816,7 +816,7 @@ void Document::update_layout()
if (!m_layout_root) {
m_next_layout_node_serial_id = 0;
Layout::TreeBuilder tree_builder;
- m_layout_root = static_ptr_cast<Layout::InitialContainingBlock>(tree_builder.build(*this));
+ m_layout_root = verify_cast<Layout::InitialContainingBlock>(*tree_builder.build(*this));
}
Layout::LayoutState layout_state;
diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h
index 8762b61ae5..1ba0988cb6 100644
--- a/Userland/Libraries/LibWeb/DOM/Document.h
+++ b/Userland/Libraries/LibWeb/DOM/Document.h
@@ -469,7 +469,7 @@ private:
JS::GCPtr<HTML::Window> m_window;
- RefPtr<Layout::InitialContainingBlock> m_layout_root;
+ JS::GCPtr<Layout::InitialContainingBlock> m_layout_root;
Optional<Color> m_link_color;
Optional<Color> m_active_link_color;
diff --git a/Userland/Libraries/LibWeb/DOM/Element.cpp b/Userland/Libraries/LibWeb/DOM/Element.cpp
index 319ec1c721..ac4e6c7f71 100644
--- a/Userland/Libraries/LibWeb/DOM/Element.cpp
+++ b/Userland/Libraries/LibWeb/DOM/Element.cpp
@@ -75,6 +75,8 @@ void Element::visit_edges(Cell::Visitor& visitor)
visitor.visit(m_inline_style.ptr());
visitor.visit(m_class_list.ptr());
visitor.visit(m_shadow_root.ptr());
+ for (auto& pseudo_element_layout_node : m_pseudo_element_nodes)
+ visitor.visit(pseudo_element_layout_node);
}
// https://dom.spec.whatwg.org/#dom-element-getattribute
@@ -272,7 +274,7 @@ bool Element::has_class(FlyString const& class_name, CaseSensitivity case_sensit
}
}
-RefPtr<Layout::Node> Element::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
+JS::GCPtr<Layout::Node> Element::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
{
if (local_name() == "noscript" && document().is_scripting_enabled())
return nullptr;
@@ -281,41 +283,41 @@ RefPtr<Layout::Node> Element::create_layout_node(NonnullRefPtr<CSS::StylePropert
return create_layout_node_for_display_type(document(), display, move(style), this);
}
-RefPtr<Layout::Node> Element::create_layout_node_for_display_type(DOM::Document& document, CSS::Display const& display, NonnullRefPtr<CSS::StyleProperties> style, Element* element)
+JS::GCPtr<Layout::Node> Element::create_layout_node_for_display_type(DOM::Document& document, CSS::Display const& display, NonnullRefPtr<CSS::StyleProperties> style, Element* element)
{
if (display.is_table_inside())
- return adopt_ref(*new Layout::TableBox(document, element, move(style)));
+ return document.heap().allocate_without_realm<Layout::TableBox>(document, element, move(style));
if (display.is_list_item())
- return adopt_ref(*new Layout::ListItemBox(document, element, move(style)));
+ return document.heap().allocate_without_realm<Layout::ListItemBox>(document, element, move(style));
if (display.is_table_row())
- return adopt_ref(*new Layout::TableRowBox(document, element, move(style)));
+ return document.heap().allocate_without_realm<Layout::TableRowBox>(document, element, move(style));
if (display.is_table_cell())
- return adopt_ref(*new Layout::TableCellBox(document, element, move(style)));
+ return document.heap().allocate_without_realm<Layout::TableCellBox>(document, element, move(style));
if (display.is_table_row_group() || display.is_table_header_group() || display.is_table_footer_group())
- return adopt_ref(*new Layout::TableRowGroupBox(document, element, move(style)));
+ return document.heap().allocate_without_realm<Layout::TableRowGroupBox>(document, element, move(style));
if (display.is_table_column() || display.is_table_column_group() || display.is_table_caption()) {
// FIXME: This is just an incorrect placeholder until we improve table layout support.
- return adopt_ref(*new Layout::BlockContainer(document, element, move(style)));
+ return document.heap().allocate_without_realm<Layout::BlockContainer>(document, element, move(style));
}
if (display.is_inline_outside()) {
if (display.is_flow_root_inside())
- return adopt_ref(*new Layout::BlockContainer(document, element, move(style)));
+ return document.heap().allocate_without_realm<Layout::BlockContainer>(document, element, move(style));
if (display.is_flow_inside())
- return adopt_ref(*new Layout::InlineNode(document, element, move(style)));
+ return document.heap().allocate_without_realm<Layout::InlineNode>(document, element, move(style));
if (display.is_flex_inside())
- return adopt_ref(*new Layout::BlockContainer(document, element, move(style)));
+ return document.heap().allocate_without_realm<Layout::BlockContainer>(document, element, move(style));
dbgln_if(LIBWEB_CSS_DEBUG, "FIXME: Support display: {}", display.to_string());
- return adopt_ref(*new Layout::InlineNode(document, element, move(style)));
+ return document.heap().allocate_without_realm<Layout::InlineNode>(document, element, move(style));
}
if (display.is_flow_inside() || display.is_flow_root_inside() || display.is_flex_inside() || display.is_grid_inside())
- return adopt_ref(*new Layout::BlockContainer(document, element, move(style)));
+ return document.heap().allocate_without_realm<Layout::BlockContainer>(document, element, move(style));
TODO();
}
@@ -709,14 +711,14 @@ void Element::children_changed()
set_needs_style_update(true);
}
-void Element::set_pseudo_element_node(Badge<Layout::TreeBuilder>, CSS::Selector::PseudoElement pseudo_element, RefPtr<Layout::Node> pseudo_element_node)
+void Element::set_pseudo_element_node(Badge<Layout::TreeBuilder>, CSS::Selector::PseudoElement pseudo_element, JS::GCPtr<Layout::Node> pseudo_element_node)
{
- m_pseudo_element_nodes[to_underlying(pseudo_element)] = pseudo_element_node->make_weak_ptr();
+ m_pseudo_element_nodes[to_underlying(pseudo_element)] = pseudo_element_node;
}
-RefPtr<Layout::Node> Element::get_pseudo_element_node(CSS::Selector::PseudoElement pseudo_element) const
+JS::GCPtr<Layout::Node> Element::get_pseudo_element_node(CSS::Selector::PseudoElement pseudo_element) const
{
- return m_pseudo_element_nodes[to_underlying(pseudo_element)].strong_ref();
+ return m_pseudo_element_nodes[to_underlying(pseudo_element)];
}
void Element::clear_pseudo_element_nodes(Badge<Layout::TreeBuilder>)
diff --git a/Userland/Libraries/LibWeb/DOM/Element.h b/Userland/Libraries/LibWeb/DOM/Element.h
index 95cb80dbfa..6265b1b80c 100644
--- a/Userland/Libraries/LibWeb/DOM/Element.h
+++ b/Userland/Libraries/LibWeb/DOM/Element.h
@@ -142,15 +142,15 @@ public:
JS::NonnullGCPtr<Geometry::DOMRect> get_bounding_client_rect() const;
JS::NonnullGCPtr<Geometry::DOMRectList> get_client_rects() const;
- virtual RefPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>);
+ virtual JS::GCPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>);
virtual void did_receive_focus() { }
virtual void did_lose_focus() { }
- static RefPtr<Layout::Node> create_layout_node_for_display_type(DOM::Document&, CSS::Display const&, NonnullRefPtr<CSS::StyleProperties>, Element*);
+ static JS::GCPtr<Layout::Node> create_layout_node_for_display_type(DOM::Document&, CSS::Display const&, NonnullRefPtr<CSS::StyleProperties>, Element*);
- void set_pseudo_element_node(Badge<Layout::TreeBuilder>, CSS::Selector::PseudoElement, RefPtr<Layout::Node>);
- RefPtr<Layout::Node> get_pseudo_element_node(CSS::Selector::PseudoElement) const;
+ void set_pseudo_element_node(Badge<Layout::TreeBuilder>, CSS::Selector::PseudoElement, JS::GCPtr<Layout::Node>);
+ JS::GCPtr<Layout::Node> get_pseudo_element_node(CSS::Selector::PseudoElement) const;
void clear_pseudo_element_nodes(Badge<Layout::TreeBuilder>);
void serialize_pseudo_elements_as_json(JsonArraySerializer<StringBuilder>& children_array) const;
@@ -188,7 +188,7 @@ private:
Vector<FlyString> m_classes;
- Array<WeakPtr<Layout::Node>, CSS::Selector::PseudoElementCount> m_pseudo_element_nodes;
+ Array<JS::GCPtr<Layout::Node>, CSS::Selector::PseudoElementCount> m_pseudo_element_nodes;
};
template<>
diff --git a/Userland/Libraries/LibWeb/DOM/Node.cpp b/Userland/Libraries/LibWeb/DOM/Node.cpp
index 7e4e83c23f..d073346ed2 100644
--- a/Userland/Libraries/LibWeb/DOM/Node.cpp
+++ b/Userland/Libraries/LibWeb/DOM/Node.cpp
@@ -92,6 +92,8 @@ void Node::visit_edges(Cell::Visitor& visitor)
visitor.visit(m_previous_sibling.ptr());
visitor.visit(m_child_nodes);
+ visitor.visit(m_layout_node);
+
for (auto& registered_observer : m_registered_observer_list)
visitor.visit(registered_observer);
}
@@ -823,11 +825,16 @@ bool Node::is_editable() const
return parent() && parent()->is_editable();
}
-void Node::set_layout_node(Badge<Layout::Node>, Layout::Node* layout_node) const
+void Node::set_layout_node(Badge<Layout::Node>, JS::NonnullGCPtr<Layout::Node> layout_node)
{
m_layout_node = layout_node;
}
+void Node::detach_layout_node(Badge<DOM::Document>)
+{
+ m_layout_node = nullptr;
+}
+
EventTarget* Node::get_parent(Event const&)
{
// FIXME: returns the node’s assigned slot, if node is assigned, and node’s parent otherwise.
diff --git a/Userland/Libraries/LibWeb/DOM/Node.h b/Userland/Libraries/LibWeb/DOM/Node.h
index cf2ad07a03..9e048a6892 100644
--- a/Userland/Libraries/LibWeb/DOM/Node.h
+++ b/Userland/Libraries/LibWeb/DOM/Node.h
@@ -156,7 +156,8 @@ public:
Painting::PaintableBox const* paint_box() const;
Painting::Paintable const* paintable() const;
- void set_layout_node(Badge<Layout::Node>, Layout::Node*) const;
+ void set_layout_node(Badge<Layout::Node>, JS::NonnullGCPtr<Layout::Node>);
+ void detach_layout_node(Badge<DOM::Document>);
virtual bool is_child_allowed(Node const&) const { return true; }
@@ -623,7 +624,7 @@ protected:
virtual void visit_edges(Cell::Visitor&) override;
JS::GCPtr<Document> m_document;
- mutable WeakPtr<Layout::Node> m_layout_node;
+ JS::GCPtr<Layout::Node> m_layout_node;
NodeType m_type { NodeType::INVALID };
bool m_needs_style_update { false };
bool m_child_needs_style_update { false };
diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp
index 4f8cd120d5..c713467031 100644
--- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp
+++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp
@@ -503,7 +503,7 @@ String BrowsingContext::selected_text() const
auto selection = layout_root->selection().normalized();
- if (selection.start().layout_node == selection.end().layout_node) {
+ if (selection.start().layout_node.ptr() == selection.end().layout_node) {
if (!is<Layout::TextNode>(*selection.start().layout_node))
return "";
return verify_cast<Layout::TextNode>(*selection.start().layout_node).text_for_rendering().substring(selection.start().index_in_node, selection.end().index_in_node - selection.start().index_in_node);
@@ -518,7 +518,7 @@ String BrowsingContext::selected_text() const
// Middle nodes
layout_node = layout_node->next_in_pre_order();
- while (layout_node && layout_node != selection.end().layout_node) {
+ while (layout_node && layout_node.ptr() != selection.end().layout_node) {
if (is<Layout::TextNode>(*layout_node))
builder.append(verify_cast<Layout::TextNode>(*layout_node).text_for_rendering());
else if (is<Layout::BreakNode>(*layout_node) || is<Layout::BlockContainer>(*layout_node))
@@ -528,7 +528,7 @@ String BrowsingContext::selected_text() const
}
// End node
- VERIFY(layout_node == selection.end().layout_node);
+ VERIFY(layout_node.ptr() == selection.end().layout_node);
if (is<Layout::TextNode>(*layout_node)) {
auto& text = verify_cast<Layout::TextNode>(*layout_node).text_for_rendering();
builder.append(text.substring(0, selection.end().index_in_node));
@@ -573,7 +573,13 @@ void BrowsingContext::select_all()
last_layout_node_index_in_node = text_for_rendering.length() - 1;
}
- layout_root->set_selection({ { first_layout_node, 0 }, { last_layout_node, last_layout_node_index_in_node } });
+ auto start = Layout::LayoutPosition {
+ JS::make_handle(const_cast<Layout::Node*>(first_layout_node)), 0
+ };
+ auto end = Layout::LayoutPosition {
+ JS::make_handle(const_cast<Layout::Node*>(last_layout_node)), last_layout_node_index_in_node
+ };
+ layout_root->set_selection({ move(start), move(end) });
}
void BrowsingContext::register_viewport_client(ViewportClient& client)
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBRElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLBRElement.cpp
index cd9f46b889..3dc799c88b 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLBRElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLBRElement.cpp
@@ -18,9 +18,9 @@ HTMLBRElement::HTMLBRElement(DOM::Document& document, DOM::QualifiedName qualifi
HTMLBRElement::~HTMLBRElement() = default;
-RefPtr<Layout::Node> HTMLBRElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
+JS::GCPtr<Layout::Node> HTMLBRElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
{
- return adopt_ref(*new Layout::BreakNode(document(), *this, move(style)));
+ return heap().allocate_without_realm<Layout::BreakNode>(document(), *this, move(style));
}
}
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBRElement.h b/Userland/Libraries/LibWeb/HTML/HTMLBRElement.h
index 9b02c1d0e7..d3c8af7440 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLBRElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLBRElement.h
@@ -16,7 +16,7 @@ class HTMLBRElement final : public HTMLElement {
public:
virtual ~HTMLBRElement() override;
- virtual RefPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
+ virtual JS::GCPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
private:
HTMLBRElement(DOM::Document&, DOM::QualifiedName);
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp
index 54217cf542..9ec5a469a2 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp
@@ -78,9 +78,9 @@ void HTMLCanvasElement::set_height(unsigned value)
reset_context_to_default_state();
}
-RefPtr<Layout::Node> HTMLCanvasElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
+JS::GCPtr<Layout::Node> HTMLCanvasElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
{
- return adopt_ref(*new Layout::CanvasBox(document(), *this, move(style)));
+ return heap().allocate_without_realm<Layout::CanvasBox>(document(), *this, move(style));
}
HTMLCanvasElement::HasOrCreatedContext HTMLCanvasElement::create_2d_context()
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.h b/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.h
index 084e6e3487..c9eba32067 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.h
@@ -42,7 +42,7 @@ private:
virtual void visit_edges(Cell::Visitor&) override;
- virtual RefPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
+ virtual JS::GCPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
enum class HasOrCreatedContext {
No,
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp
index 006640eabc..c3d171b55d 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp
@@ -22,9 +22,9 @@ HTMLIFrameElement::HTMLIFrameElement(DOM::Document& document, DOM::QualifiedName
HTMLIFrameElement::~HTMLIFrameElement() = default;
-RefPtr<Layout::Node> HTMLIFrameElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
+JS::GCPtr<Layout::Node> HTMLIFrameElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
{
- return adopt_ref(*new Layout::FrameBox(document(), *this, move(style)));
+ return heap().allocate_without_realm<Layout::FrameBox>(document(), *this, move(style));
}
void HTMLIFrameElement::parse_attribute(FlyString const& name, String const& value)
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.h b/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.h
index d7aba28e14..dd2aff3736 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.h
@@ -16,7 +16,7 @@ class HTMLIFrameElement final : public BrowsingContextContainer {
public:
virtual ~HTMLIFrameElement() override;
- virtual RefPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
+ virtual JS::GCPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#will-lazy-load-element-steps
bool will_lazy_load_element() const;
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp
index 1c14c29ee0..0d4ff16141 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp
@@ -85,9 +85,9 @@ void HTMLImageElement::parse_attribute(FlyString const& name, String const& valu
}
}
-RefPtr<Layout::Node> HTMLImageElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
+JS::GCPtr<Layout::Node> HTMLImageElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
{
- return adopt_ref(*new Layout::ImageBox(document(), *this, move(style), m_image_loader));
+ return heap().allocate_without_realm<Layout::ImageBox>(document(), *this, move(style), m_image_loader);
}
Gfx::Bitmap const* HTMLImageElement::bitmap() const
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h
index 803ee9f339..3353a259b9 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h
@@ -50,7 +50,7 @@ private:
void animate();
- virtual RefPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
+ virtual JS::GCPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
ImageLoader m_image_loader;
};
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp
index 3a613bb1af..e287da7387 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp
@@ -51,21 +51,21 @@ void HTMLInputElement::visit_edges(Cell::Visitor& visitor)
visitor.visit(m_selected_files);
}
-RefPtr<Layout::Node> HTMLInputElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
+JS::GCPtr<Layout::Node> HTMLInputElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
{
if (type_state() == TypeAttributeState::Hidden)
return nullptr;
if (type_state() == TypeAttributeState::SubmitButton || type_state() == TypeAttributeState::Button || type_state() == TypeAttributeState::ResetButton || type_state() == TypeAttributeState::FileUpload)
- return adopt_ref(*new Layout::ButtonBox(document(), *this, move(style)));
+ return heap().allocate_without_realm<Layout::ButtonBox>(document(), *this, move(style));
if (type_state() == TypeAttributeState::Checkbox)
- return adopt_ref(*new Layout::CheckBox(document(), *this, move(style)));
+ return heap().allocate_without_realm<Layout::CheckBox>(document(), *this, move(style));
if (type_state() == TypeAttributeState::RadioButton)
- return adopt_ref(*new Layout::RadioButton(document(), *this, move(style)));
+ return heap().allocate_without_realm<Layout::RadioButton>(document(), *this, move(style));
- return adopt_ref(*new Layout::BlockContainer(document(), this, move(style)));
+ return heap().allocate_without_realm<Layout::BlockContainer>(document(), this, move(style));
}
void HTMLInputElement::set_checked(bool checked, ChangeSource change_source)
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h
index b04c6ef58c..b77c6cbc9e 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h
@@ -48,7 +48,7 @@ class HTMLInputElement final
public:
virtual ~HTMLInputElement() override;
- virtual RefPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
+ virtual JS::GCPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
enum class TypeAttributeState {
#define __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(_, state) state,
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.cpp
index db4a4a86ff..940d880007 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.cpp
@@ -18,9 +18,9 @@ HTMLLabelElement::HTMLLabelElement(DOM::Document& document, DOM::QualifiedName q
HTMLLabelElement::~HTMLLabelElement() = default;
-RefPtr<Layout::Node> HTMLLabelElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
+JS::GCPtr<Layout::Node> HTMLLabelElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
{
- return adopt_ref(*new Layout::Label(document(), this, move(style)));
+ return heap().allocate_without_realm<Layout::Label>(document(), this, move(style));
}
}
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.h b/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.h
index e322245cb5..9fd742fbb5 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.h
@@ -16,7 +16,7 @@ class HTMLLabelElement final : public HTMLElement {
public:
virtual ~HTMLLabelElement() override;
- virtual RefPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
+ virtual JS::GCPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
String for_() const { return attribute(HTML::AttributeNames::for_); }
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp
index b90a79ff08..7eecba0673 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp
@@ -39,7 +39,7 @@ String HTMLObjectElement::data() const
return document().parse_url(data).to_string();
}
-RefPtr<Layout::Node> HTMLObjectElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
+JS::GCPtr<Layout::Node> HTMLObjectElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
{
switch (m_representation) {
case Representation::Children:
@@ -49,7 +49,7 @@ RefPtr<Layout::Node> HTMLObjectElement::create_layout_node(NonnullRefPtr<CSS::St
return nullptr;
case Representation::Image:
if (m_image_loader.has_value() && m_image_loader->has_image())
- return adopt_ref(*new Layout::ImageBox(document(), *this, move(style), *m_image_loader));
+ return heap().allocate_without_realm<Layout::ImageBox>(document(), *this, move(style), *m_image_loader);
break;
default:
break;
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h
index 5788f85a07..a2b02b2f63 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h
@@ -46,7 +46,7 @@ public:
private:
HTMLObjectElement(DOM::Document&, DOM::QualifiedName);
- virtual RefPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
+ virtual JS::GCPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
bool has_ancestor_media_element_or_object_element_not_showing_fallback_content() const;
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.cpp
index d52a7aa1fa..69a42f9d11 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.cpp
@@ -23,11 +23,11 @@ HTMLProgressElement::HTMLProgressElement(DOM::Document& document, DOM::Qualified
HTMLProgressElement::~HTMLProgressElement() = default;
-RefPtr<Layout::Node> HTMLProgressElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
+JS::GCPtr<Layout::Node> HTMLProgressElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
{
if (style->appearance().value_or(CSS::Appearance::Auto) == CSS::Appearance::None)
return HTMLElement::create_layout_node(style);
- return adopt_ref(*new Layout::Progress(document(), *this, move(style)));
+ return heap().allocate_without_realm<Layout::Progress>(document(), *this, move(style));
}
bool HTMLProgressElement::using_system_appearance() const
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.h b/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.h
index e806f685af..414769514b 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.h
@@ -16,7 +16,7 @@ class HTMLProgressElement final : public HTMLElement {
public:
virtual ~HTMLProgressElement() override;
- virtual RefPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
+ virtual JS::GCPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
double value() const;
void set_value(double);
diff --git a/Userland/Libraries/LibWeb/Layout/BlockContainer.h b/Userland/Libraries/LibWeb/Layout/BlockContainer.h
index 0735a45553..4f89a7659b 100644
--- a/Userland/Libraries/LibWeb/Layout/BlockContainer.h
+++ b/Userland/Libraries/LibWeb/Layout/BlockContainer.h
@@ -13,6 +13,8 @@ namespace Web::Layout {
// https://www.w3.org/TR/css-display/#block-container
class BlockContainer : public Box {
+ JS_CELL(BlockContainer, Box);
+
public:
BlockContainer(DOM::Document&, DOM::Node*, NonnullRefPtr<CSS::StyleProperties>);
BlockContainer(DOM::Document&, DOM::Node*, CSS::ComputedValues);
diff --git a/Userland/Libraries/LibWeb/Layout/Box.h b/Userland/Libraries/LibWeb/Layout/Box.h
index a064d909c8..67cbe50573 100644
--- a/Userland/Libraries/LibWeb/Layout/Box.h
+++ b/Userland/Libraries/LibWeb/Layout/Box.h
@@ -18,6 +18,8 @@ struct LineBoxFragmentCoordinate {
};
class Box : public NodeWithStyleAndBoxModelMetrics {
+ JS_CELL(Box, NodeWithStyleAndBoxModelMetrics);
+
public:
Painting::PaintableBox const* paint_box() const;
diff --git a/Userland/Libraries/LibWeb/Layout/BreakNode.h b/Userland/Libraries/LibWeb/Layout/BreakNode.h
index 320f442722..f3c814b3ae 100644
--- a/Userland/Libraries/LibWeb/Layout/BreakNode.h
+++ b/Userland/Libraries/LibWeb/Layout/BreakNode.h
@@ -12,6 +12,8 @@
namespace Web::Layout {
class BreakNode final : public NodeWithStyleAndBoxModelMetrics {
+ JS_CELL(BreakNode, NodeWithStyleAndBoxModelMetrics);
+
public:
BreakNode(DOM::Document&, HTML::HTMLBRElement&, NonnullRefPtr<CSS::StyleProperties>);
virtual ~BreakNode() override;
diff --git a/Userland/Libraries/LibWeb/Layout/ButtonBox.h b/Userland/Libraries/LibWeb/Layout/ButtonBox.h
index d80278e202..c1b0c1f106 100644
--- a/Userland/Libraries/LibWeb/Layout/ButtonBox.h
+++ b/Userland/Libraries/LibWeb/Layout/ButtonBox.h
@@ -12,6 +12,8 @@
namespace Web::Layout {
class ButtonBox : public FormAssociatedLabelableNode {
+ JS_CELL(ButtonBox, FormAssociatedLabelableNode);
+
public:
ButtonBox(DOM::Document&, HTML::HTMLInputElement&, NonnullRefPtr<CSS::StyleProperties>);
virtual ~ButtonBox() override;
diff --git a/Userland/Libraries/LibWeb/Layout/CanvasBox.h b/Userland/Libraries/LibWeb/Layout/CanvasBox.h
index 29da272193..89ec2c3da1 100644
--- a/Userland/Libraries/LibWeb/Layout/CanvasBox.h
+++ b/Userland/Libraries/LibWeb/Layout/CanvasBox.h
@@ -12,6 +12,8 @@
namespace Web::Layout {
class CanvasBox : public ReplacedBox {
+ JS_CELL(CanvasBox, ReplacedBox);
+
public:
CanvasBox(DOM::Document&, HTML::HTMLCanvasElement&, NonnullRefPtr<CSS::StyleProperties>);
virtual ~CanvasBox() override;
diff --git a/Userland/Libraries/LibWeb/Layout/CheckBox.h b/Userland/Libraries/LibWeb/Layout/CheckBox.h
index b6046f9de0..a43911cad3 100644
--- a/Userland/Libraries/LibWeb/Layout/CheckBox.h
+++ b/Userland/Libraries/LibWeb/Layout/CheckBox.h
@@ -12,6 +12,8 @@
namespace Web::Layout {
class CheckBox : public FormAssociatedLabelableNode {
+ JS_CELL(CheckBox, FormAssociatedLabelableNode);
+
public:
CheckBox(DOM::Document&, HTML::HTMLInputElement&, NonnullRefPtr<CSS::StyleProperties>);
virtual ~CheckBox() override;
diff --git a/Userland/Libraries/LibWeb/Layout/FormAssociatedLabelableNode.h b/Userland/Libraries/LibWeb/Layout/FormAssociatedLabelableNode.h
index 8aacbaf93a..44ee62981f 100644
--- a/Userland/Libraries/LibWeb/Layout/FormAssociatedLabelableNode.h
+++ b/Userland/Libraries/LibWeb/Layout/FormAssociatedLabelableNode.h
@@ -14,6 +14,8 @@
namespace Web::Layout {
class FormAssociatedLabelableNode : public LabelableNode {
+ JS_CELL(FormAssociatedLabelableNode, LabelableNode);
+
public:
const HTML::FormAssociatedElement& dom_node() const { return dynamic_cast<const HTML::FormAssociatedElement&>(LabelableNode::dom_node()); }
HTML::FormAssociatedElement& dom_node() { return dynamic_cast<HTML::FormAssociatedElement&>(LabelableNode::dom_node()); }
diff --git a/Userland/Libraries/LibWeb/Layout/FrameBox.h b/Userland/Libraries/LibWeb/Layout/FrameBox.h
index 96c6efdae3..2fd465213b 100644
--- a/Userland/Libraries/LibWeb/Layout/FrameBox.h
+++ b/Userland/Libraries/LibWeb/Layout/FrameBox.h
@@ -12,6 +12,8 @@
namespace Web::Layout {
class FrameBox final : public ReplacedBox {
+ JS_CELL(FrameBox, ReplacedBox);
+
public:
FrameBox(DOM::Document&, DOM::Element&, NonnullRefPtr<CSS::StyleProperties>);
virtual ~FrameBox() override;
diff --git a/Userland/Libraries/LibWeb/Layout/ImageBox.h b/Userland/Libraries/LibWeb/Layout/ImageBox.h
index 138cb507b8..9887312702 100644
--- a/Userland/Libraries/LibWeb/Layout/ImageBox.h
+++ b/Userland/Libraries/LibWeb/Layout/ImageBox.h
@@ -15,6 +15,8 @@ namespace Web::Layout {
class ImageBox
: public ReplacedBox
, public HTML::BrowsingContext::ViewportClient {
+ JS_CELL(ImageBox, ReplacedBox);
+
public:
ImageBox(DOM::Document&, DOM::Element&, NonnullRefPtr<CSS::StyleProperties>, ImageLoader const&);
virtual ~ImageBox() override;
diff --git a/Userland/Libraries/LibWeb/Layout/InitialContainingBlock.h b/Userland/Libraries/LibWeb/Layout/InitialContainingBlock.h
index 200fe63dae..10c5f75074 100644
--- a/Userland/Libraries/LibWeb/Layout/InitialContainingBlock.h
+++ b/Userland/Libraries/LibWeb/Layout/InitialContainingBlock.h
@@ -13,6 +13,8 @@
namespace Web::Layout {
class InitialContainingBlock final : public BlockContainer {
+ JS_CELL(InitialContainingBlock, BlockContainer);
+
public:
explicit InitialContainingBlock(DOM::Document&, NonnullRefPtr<CSS::StyleProperties>);
virtual ~InitialContainingBlock() override;
diff --git a/Userland/Libraries/LibWeb/Layout/InlineNode.h b/Userland/Libraries/LibWeb/Layout/InlineNode.h
index bf5f35552b..e670180e93 100644
--- a/Userland/Libraries/LibWeb/Layout/InlineNode.h
+++ b/Userland/Libraries/LibWeb/Layout/InlineNode.h
@@ -11,6 +11,8 @@
namespace Web::Layout {
class InlineNode : public NodeWithStyleAndBoxModelMetrics {
+ JS_CELL(InlineNode, NodeWithStyleAndBoxModelMetrics);
+
public:
InlineNode(DOM::Document&, DOM::Element*, NonnullRefPtr<CSS::StyleProperties>);
virtual ~InlineNode() override;
diff --git a/Userland/Libraries/LibWeb/Layout/Label.cpp b/Userland/Libraries/LibWeb/Layout/Label.cpp
index fc8ef56649..7cffc25ae4 100644
--- a/Userland/Libraries/LibWeb/Layout/Label.cpp
+++ b/Userland/Libraries/LibWeb/Layout/Label.cpp
@@ -38,9 +38,6 @@ void Label::handle_mouseup_on_label(Badge<Painting::TextPaintable>, Gfx::IntPoin
if (!m_tracking_mouse || button != GUI::MouseButton::Primary)
return;
- // NOTE: Changing the checked state of the DOM node may run arbitrary JS, which could disappear this node.
- NonnullRefPtr protect = *this;
-
if (auto* control = labeled_control(); control) {
bool is_inside_control = enclosing_int_rect(control->paint_box()->absolute_rect()).contains(position);
bool is_inside_label = enclosing_int_rect(paint_box()->absolute_rect()).contains(position);
diff --git a/Userland/Libraries/LibWeb/Layout/Label.h b/Userland/Libraries/LibWeb/Layout/Label.h
index 5cee1a986c..3723719046 100644
--- a/Userland/Libraries/LibWeb/Layout/Label.h
+++ b/Userland/Libraries/LibWeb/Layout/Label.h
@@ -12,6 +12,8 @@
namespace Web::Layout {
class Label final : public BlockContainer {
+ JS_CELL(Label, BlockContainer);
+
public:
Label(DOM::Document&, HTML::HTMLLabelElement*, NonnullRefPtr<CSS::StyleProperties>);
virtual ~Label() override;
diff --git a/Userland/Libraries/LibWeb/Layout/LabelableNode.h b/Userland/Libraries/LibWeb/Layout/LabelableNode.h
index 6c579783c9..28f566b8dd 100644
--- a/Userland/Libraries/LibWeb/Layout/LabelableNode.h
+++ b/Userland/Libraries/LibWeb/Layout/LabelableNode.h
@@ -12,6 +12,8 @@
namespace Web::Layout {
class LabelableNode : public ReplacedBox {
+ JS_CELL(LabelableNode, ReplacedBox);
+
public:
Painting::LabelablePaintable* paintable();
Painting::LabelablePaintable const* paintable() const;
diff --git a/Userland/Libraries/LibWeb/Layout/LayoutPosition.cpp b/Userland/Libraries/LibWeb/Layout/LayoutPosition.cpp
index aeb4163f8d..a44cc343e7 100644
--- a/Userland/Libraries/LibWeb/Layout/LayoutPosition.cpp
+++ b/Userland/Libraries/LibWeb/Layout/LayoutPosition.cpp
@@ -23,7 +23,7 @@ LayoutRange LayoutRange::normalized() const
{
if (!is_valid())
return {};
- if (m_start.layout_node == m_end.layout_node) {
+ if (m_start.layout_node.ptr() == m_end.layout_node.ptr()) {
if (m_start.index_in_node < m_end.index_in_node)
return *this;
return { m_end, m_start };
diff --git a/Userland/Libraries/LibWeb/Layout/LayoutPosition.h b/Userland/Libraries/LibWeb/Layout/LayoutPosition.h
index 7ab85c4a07..755e6dd01a 100644
--- a/Userland/Libraries/LibWeb/Layout/LayoutPosition.h
+++ b/Userland/Libraries/LibWeb/Layout/LayoutPosition.h
@@ -16,7 +16,7 @@ namespace Web::Layout {
class Node;
struct LayoutPosition {
- RefPtr<Node> layout_node;
+ JS::Handle<Layout::Node> layout_node;
int index_in_node { 0 };
DOM::Position to_dom_position() const;
diff --git a/Userland/Libraries/LibWeb/Layout/ListItemBox.cpp b/Userland/Libraries/LibWeb/Layout/ListItemBox.cpp
index 4ac9ccb430..29f7035039 100644
--- a/Userland/Libraries/LibWeb/Layout/ListItemBox.cpp
+++ b/Userland/Libraries/LibWeb/Layout/ListItemBox.cpp
@@ -17,7 +17,13 @@ ListItemBox::ListItemBox(DOM::Document& document, DOM::Element* element, Nonnull
ListItemBox::~ListItemBox() = default;
-void ListItemBox::set_marker(RefPtr<ListItemMarkerBox> marker)
+void ListItemBox::visit_edges(Cell::Visitor& visitor)
+{
+ Base::visit_edges(visitor);
+ visitor.visit(m_marker);
+}
+
+void ListItemBox::set_marker(JS::GCPtr<ListItemMarkerBox> marker)
{
m_marker = move(marker);
}
diff --git a/Userland/Libraries/LibWeb/Layout/ListItemBox.h b/Userland/Libraries/LibWeb/Layout/ListItemBox.h
index b285e2b0df..d3b79f3e3d 100644
--- a/Userland/Libraries/LibWeb/Layout/ListItemBox.h
+++ b/Userland/Libraries/LibWeb/Layout/ListItemBox.h
@@ -12,6 +12,8 @@
namespace Web::Layout {
class ListItemBox final : public BlockContainer {
+ JS_CELL(ListItemBox, BlockContainer);
+
public:
ListItemBox(DOM::Document&, DOM::Element*, NonnullRefPtr<CSS::StyleProperties>);
virtual ~ListItemBox() override;
@@ -20,10 +22,12 @@ public:
DOM::Element const& dom_node() const { return static_cast<DOM::Element const&>(*BlockContainer::dom_node()); }
ListItemMarkerBox const* marker() const { return m_marker; }
- void set_marker(RefPtr<ListItemMarkerBox>);
+ void set_marker(JS::GCPtr<ListItemMarkerBox>);
private:
- RefPtr<ListItemMarkerBox> m_marker;
+ virtual void visit_edges(Cell::Visitor&) override;
+
+ JS::GCPtr<ListItemMarkerBox> m_marker;
};
}
diff --git a/Userland/Libraries/LibWeb/Layout/ListItemMarkerBox.h b/Userland/Libraries/LibWeb/Layout/ListItemMarkerBox.h
index 647f4a7f20..170a620d89 100644
--- a/Userland/Libraries/LibWeb/Layout/ListItemMarkerBox.h
+++ b/Userland/Libraries/LibWeb/Layout/ListItemMarkerBox.h
@@ -12,6 +12,8 @@
namespace Web::Layout {
class ListItemMarkerBox final : public Box {
+ JS_CELL(ListItemMarkerBox, Box);
+
public:
explicit ListItemMarkerBox(DOM::Document&, CSS::ListStyleType, size_t index, NonnullRefPtr<CSS::StyleProperties>);
virtual ~ListItemMarkerBox() override;
diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp
index 4a0838af27..778e3cf4a9 100644
--- a/Userland/Libraries/LibWeb/Layout/Node.cpp
+++ b/Userland/Libraries/LibWeb/Layout/Node.cpp
@@ -15,24 +15,26 @@
#include <LibWeb/Layout/Node.h>
#include <LibWeb/Layout/TextNode.h>
#include <LibWeb/Platform/FontPlugin.h>
-#include <typeinfo>
namespace Web::Layout {
Node::Node(DOM::Document& document, DOM::Node* node)
- : m_dom_node(node ? node : &document)
+ : m_dom_node(node ? *node : document)
, m_anonymous(node == nullptr)
{
m_serial_id = document.next_layout_node_serial_id({});
if (node)
- node->set_layout_node({}, this);
+ node->set_layout_node({}, *this);
}
-Node::~Node()
+Node::~Node() = default;
+
+void Node::visit_edges(Cell::Visitor& visitor)
{
- if (!is_anonymous() && m_dom_node->layout_node() == this)
- m_dom_node->set_layout_node({}, nullptr);
+ Base::visit_edges(visitor);
+ visitor.visit(m_dom_node);
+ TreeNode::visit_edges(visitor);
}
// https://www.w3.org/TR/css-display-3/#out-of-flow
@@ -558,16 +560,10 @@ bool Node::is_root_element() const
return is<HTML::HTMLHtmlElement>(*dom_node());
}
-String Node::class_name() const
-{
- auto const* mangled_name = typeid(*this).name();
- return demangle({ mangled_name, strlen(mangled_name) });
-}
-
String Node::debug_description() const
{
StringBuilder builder;
- builder.append(class_name().substring_view(13));
+ builder.append(class_name());
if (dom_node()) {
builder.appendff("<{}>", dom_node()->node_name());
if (dom_node()->is_element()) {
@@ -604,13 +600,13 @@ bool Node::is_inline_block() const
return display.is_inline_outside() && display.is_flow_root_inside();
}
-NonnullRefPtr<NodeWithStyle> NodeWithStyle::create_anonymous_wrapper() const
+JS::NonnullGCPtr<NodeWithStyle> NodeWithStyle::create_anonymous_wrapper() const
{
- auto wrapper = adopt_ref(*new BlockContainer(const_cast<DOM::Document&>(document()), nullptr, m_computed_values.clone_inherited_values()));
+ auto wrapper = heap().allocate_without_realm<BlockContainer>(const_cast<DOM::Document&>(document()), nullptr, m_computed_values.clone_inherited_values());
static_cast<CSS::MutableComputedValues&>(wrapper->m_computed_values).set_display(CSS::Display(CSS::Display::Outside::Block, CSS::Display::Inside::Flow));
wrapper->m_font = m_font;
wrapper->m_line_height = m_line_height;
- return wrapper;
+ return *wrapper;
}
void Node::set_paintable(RefPtr<Painting::Paintable> paintable)
diff --git a/Userland/Libraries/LibWeb/Layout/Node.h b/Userland/Libraries/LibWeb/Layout/Node.h
index e8ca0bfe1b..b3a044d3f8 100644
--- a/Userland/Libraries/LibWeb/Layout/Node.h
+++ b/Userland/Libraries/LibWeb/Layout/Node.h
@@ -31,7 +31,12 @@ enum class LayoutMode {
IntrinsicSizing,
};
-class Node : public TreeNode<Node> {
+class Node
+ : public JS::Cell
+ , public TreeNode<Node>
+ , public Weakable<Node> {
+ JS_CELL(Node, JS::Cell);
+
public:
virtual ~Node();
@@ -61,7 +66,6 @@ public:
bool is_root_element() const;
- String class_name() const;
String debug_description() const;
bool has_style() const { return m_has_style; }
@@ -140,10 +144,12 @@ public:
protected:
Node(DOM::Document&, DOM::Node*);
+ virtual void visit_edges(Cell::Visitor&) override;
+
private:
friend class NodeWithStyle;
- JS::Handle<DOM::Node> m_dom_node;
+ JS::NonnullGCPtr<DOM::Node> m_dom_node;
RefPtr<Painting::Paintable> m_paintable;
size_t m_serial_id { 0 };
@@ -159,6 +165,8 @@ private:
};
class NodeWithStyle : public Node {
+ JS_CELL(NodeWithStyle, Node);
+
public:
virtual ~NodeWithStyle() override = default;
@@ -171,7 +179,7 @@ public:
Vector<CSS::BackgroundLayerData> const& background_layers() const { return computed_values().background_layers(); }
const CSS::AbstractImageStyleValue* list_style_image() const { return m_list_style_image; }
- NonnullRefPtr<NodeWithStyle> create_anonymous_wrapper() const;
+ JS::NonnullGCPtr<NodeWithStyle> create_anonymous_wrapper() const;
protected:
NodeWithStyle(DOM::Document&, DOM::Node*, NonnullRefPtr<CSS::StyleProperties>);
@@ -185,6 +193,8 @@ private:
};
class NodeWithStyleAndBoxModelMetrics : public NodeWithStyle {
+ JS_CELL(NodeWithStyleAndBoxModelMetrics, NodeWithStyle);
+
public:
BoxModelMetrics& box_model() { return m_box_model; }
BoxModelMetrics const& box_model() const { return m_box_model; }
diff --git a/Userland/Libraries/LibWeb/Layout/Progress.h b/Userland/Libraries/LibWeb/Layout/Progress.h
index 0f26ae6142..a55ed6860b 100644
--- a/Userland/Libraries/LibWeb/Layout/Progress.h
+++ b/Userland/Libraries/LibWeb/Layout/Progress.h
@@ -12,6 +12,8 @@
namespace Web::Layout {
class Progress : public LabelableNode {
+ JS_CELL(Progress, LabelableNode);
+
public:
Progress(DOM::Document&, HTML::HTMLProgressElement&, NonnullRefPtr<CSS::StyleProperties>);
virtual ~Progress() override;
diff --git a/Userland/Libraries/LibWeb/Layout/RadioButton.h b/Userland/Libraries/LibWeb/Layout/RadioButton.h
index 9be341f00a..bf30e2dde3 100644
--- a/Userland/Libraries/LibWeb/Layout/RadioButton.h
+++ b/Userland/Libraries/LibWeb/Layout/RadioButton.h
@@ -12,6 +12,8 @@
namespace Web::Layout {
class RadioButton final : public FormAssociatedLabelableNode {
+ JS_CELL(RadioButton, FormAssociatedLabelableNode);
+
public:
RadioButton(DOM::Document&, HTML::HTMLInputElement&, NonnullRefPtr<CSS::StyleProperties>);
virtual ~RadioButton() override;
diff --git a/Userland/Libraries/LibWeb/Layout/ReplacedBox.h b/Userland/Libraries/LibWeb/Layout/ReplacedBox.h
index 28032d5aa8..f2bfa4a3cd 100644
--- a/Userland/Libraries/LibWeb/Layout/ReplacedBox.h
+++ b/Userland/Libraries/LibWeb/Layout/ReplacedBox.h
@@ -12,6 +12,8 @@
namespace Web::Layout {
class ReplacedBox : public Box {
+ JS_CELL(ReplacedBox, Box);
+
public:
ReplacedBox(DOM::Document&, DOM::Element&, NonnullRefPtr<CSS::StyleProperties>);
virtual ~ReplacedBox() override;
diff --git a/Userland/Libraries/LibWeb/Layout/SVGBox.h b/Userland/Libraries/LibWeb/Layout/SVGBox.h
index 30caf476d3..69bd821279 100644
--- a/Userland/Libraries/LibWeb/Layout/SVGBox.h
+++ b/Userland/Libraries/LibWeb/Layout/SVGBox.h
@@ -13,6 +13,8 @@
namespace Web::Layout {
class SVGBox : public Box {
+ JS_CELL(SVGBox, Box);
+
public:
SVGBox(DOM::Document&, SVG::SVGElement&, NonnullRefPtr<CSS::StyleProperties>);
virtual ~SVGBox() override = default;
diff --git a/Userland/Libraries/LibWeb/Layout/SVGGeometryBox.h b/Userland/Libraries/LibWeb/Layout/SVGGeometryBox.h
index 0da419179b..d5a009c891 100644
--- a/Userland/Libraries/LibWeb/Layout/SVGGeometryBox.h
+++ b/Userland/Libraries/LibWeb/Layout/SVGGeometryBox.h
@@ -12,6 +12,8 @@
namespace Web::Layout {
class SVGGeometryBox final : public SVGGraphicsBox {
+ JS_CELL(SVGGeometryBox, SVGGraphicsBox);
+
public:
SVGGeometryBox(DOM::Document&, SVG::SVGGeometryElement&, NonnullRefPtr<CSS::StyleProperties>);
virtual ~SVGGeometryBox() override = default;
diff --git a/Userland/Libraries/LibWeb/Layout/SVGGraphicsBox.h b/Userland/Libraries/LibWeb/Layout/SVGGraphicsBox.h
index efa4333239..1411ef93dd 100644
--- a/Userland/Libraries/LibWeb/Layout/SVGGraphicsBox.h
+++ b/Userland/Libraries/LibWeb/Layout/SVGGraphicsBox.h
@@ -13,6 +13,8 @@
namespace Web::Layout {
class SVGGraphicsBox : public SVGBox {
+ JS_CELL(SVGGraphicsBox, SVGBox);
+
public:
SVGGraphicsBox(DOM::Document&, SVG::SVGGraphicsElement&, NonnullRefPtr<CSS::StyleProperties>);
virtual ~SVGGraphicsBox() override = default;
diff --git a/Userland/Libraries/LibWeb/Layout/SVGSVGBox.h b/Userland/Libraries/LibWeb/Layout/SVGSVGBox.h
index 55d4967c41..ee681c23c1 100644
--- a/Userland/Libraries/LibWeb/Layout/SVGSVGBox.h
+++ b/Userland/Libraries/LibWeb/Layout/SVGSVGBox.h
@@ -12,6 +12,8 @@
namespace Web::Layout {
class SVGSVGBox final : public ReplacedBox {
+ JS_CELL(SVGSVGBox, ReplacedBox);
+
public:
SVGSVGBox(DOM::Document&, SVG::SVGSVGElement&, NonnullRefPtr<CSS::StyleProperties>);
virtual ~SVGSVGBox() override = default;
diff --git a/Userland/Libraries/LibWeb/Layout/TableBox.h b/Userland/Libraries/LibWeb/Layout/TableBox.h
index 8fd3b9aba8..fbe3371d0c 100644
--- a/Userland/Libraries/LibWeb/Layout/TableBox.h
+++ b/Userland/Libraries/LibWeb/Layout/TableBox.h
@@ -11,6 +11,8 @@
namespace Web::Layout {
class TableBox final : public Layout::BlockContainer {
+ JS_CELL(TableBox, BlockContainer);
+
public:
TableBox(DOM::Document&, DOM::Element*, NonnullRefPtr<CSS::StyleProperties>);
TableBox(DOM::Document&, DOM::Element*, CSS::ComputedValues);
diff --git a/Userland/Libraries/LibWeb/Layout/TableCellBox.h b/Userland/Libraries/LibWeb/Layout/TableCellBox.h
index 3662c62fa0..b63d8c5b1e 100644
--- a/Userland/Libraries/LibWeb/Layout/TableCellBox.h
+++ b/Userland/Libraries/LibWeb/Layout/TableCellBox.h
@@ -11,6 +11,8 @@
namespace Web::Layout {
class TableCellBox final : public BlockContainer {
+ JS_CELL(TableCellBox, BlockContainer);
+
public:
TableCellBox(DOM::Document&, DOM::Element*, NonnullRefPtr<CSS::StyleProperties>);
TableCellBox(DOM::Document&, DOM::Element*, CSS::ComputedValues);
diff --git a/Userland/Libraries/LibWeb/Layout/TableRowBox.h b/Userland/Libraries/LibWeb/Layout/TableRowBox.h
index e7f6b1f783..26c7f6de7d 100644
--- a/Userland/Libraries/LibWeb/Layout/TableRowBox.h
+++ b/Userland/Libraries/LibWeb/Layout/TableRowBox.h
@@ -11,6 +11,8 @@
namespace Web::Layout {
class TableRowBox final : public Box {
+ JS_CELL(TableRowBox, Box);
+
public:
TableRowBox(DOM::Document&, DOM::Element*, NonnullRefPtr<CSS::StyleProperties>);
TableRowBox(DOM::Document&, DOM::Element*, CSS::ComputedValues);
diff --git a/Userland/Libraries/LibWeb/Layout/TableRowGroupBox.h b/Userland/Libraries/LibWeb/Layout/TableRowGroupBox.h
index 46ac7f4997..923c662f47 100644
--- a/Userland/Libraries/LibWeb/Layout/TableRowGroupBox.h
+++ b/Userland/Libraries/LibWeb/Layout/TableRowGroupBox.h
@@ -11,6 +11,8 @@
namespace Web::Layout {
class TableRowGroupBox final : public BlockContainer {
+ JS_CELL(TableRowGroupBox, BlockContainer);
+
public:
TableRowGroupBox(DOM::Document&, DOM::Element*, NonnullRefPtr<CSS::StyleProperties>);
virtual ~TableRowGroupBox() override;
diff --git a/Userland/Libraries/LibWeb/Layout/TextNode.h b/Userland/Libraries/LibWeb/Layout/TextNode.h
index 128f80b893..e13ca54272 100644
--- a/Userland/Libraries/LibWeb/Layout/TextNode.h
+++ b/Userland/Libraries/LibWeb/Layout/TextNode.h
@@ -15,6 +15,8 @@ namespace Web::Layout {
class LineBoxFragment;
class TextNode : public Node {
+ JS_CELL(TextNode, Node);
+
public:
TextNode(DOM::Document&, DOM::Text&);
virtual ~TextNode() override;
diff --git a/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp b/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp
index ac86d9ddc6..e4c7ceb04b 100644
--- a/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp
+++ b/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp
@@ -31,7 +31,7 @@ TreeBuilder::TreeBuilder() = default;
static bool has_inline_or_in_flow_block_children(Layout::Node const& layout_node)
{
- for (auto const* child = layout_node.first_child(); child; child = child->next_sibling()) {
+ for (auto child = layout_node.first_child(); child; child = child->next_sibling()) {
if (child->is_inline())
return true;
if (!child->is_floating() && !child->is_absolutely_positioned())
@@ -44,7 +44,7 @@ static bool has_in_flow_block_children(Layout::Node const& layout_node)
{
if (layout_node.children_are_inline())
return false;
- for (auto const* child = layout_node.first_child(); child; child = child->next_sibling()) {
+ for (auto child = layout_node.first_child(); child; child = child->next_sibling()) {
if (child->is_inline())
continue;
if (!child->is_floating() && !child->is_absolutely_positioned())
@@ -95,15 +95,15 @@ static Layout::Node& insertion_parent_for_block_node(Layout::NodeWithStyle& layo
// Parent block has inline-level children (our siblings).
// First move these siblings into an anonymous wrapper block.
- NonnullRefPtrVector<Layout::Node> children;
- while (RefPtr<Layout::Node> child = layout_parent.first_child()) {
+ Vector<JS::Handle<Layout::Node>> children;
+ while (JS::GCPtr<Layout::Node> child = layout_parent.first_child()) {
layout_parent.remove_child(*child);
- children.append(child.release_nonnull());
+ children.append(*child);
}
layout_parent.append_child(layout_parent.create_anonymous_wrapper());
layout_parent.set_children_are_inline(false);
for (auto& child : children) {
- layout_parent.last_child()->append_child(child);
+ layout_parent.last_child()->append_child(*child);
}
layout_parent.last_child()->set_children_are_inline(true);
// Then it's safe to insert this block into parent.
@@ -166,10 +166,10 @@ void TreeBuilder::create_pseudo_element_if_needed(DOM::Element& element, CSS::Se
// FIXME: Handle images, and multiple values
if (pseudo_element_content.type == CSS::ContentData::Type::String) {
auto* text = document.heap().allocate<DOM::Text>(document.realm(), document, pseudo_element_content.data);
- auto text_node = adopt_ref(*new TextNode(document, *text));
+ auto text_node = document.heap().allocate_without_realm<Layout::TextNode>(document, *text);
text_node->set_generated(true);
push_parent(verify_cast<NodeWithStyle>(*pseudo_element_node));
- insert_node_into_inline_or_block_ancestor(text_node, text_node->display(), AppendOrPrepend::Append);
+ insert_node_into_inline_or_block_ancestor(*text_node, text_node->display(), AppendOrPrepend::Append);
pop_parent();
} else {
TODO();
@@ -195,7 +195,7 @@ void TreeBuilder::create_layout_tree(DOM::Node& dom_node, TreeBuilder::Context&
auto& document = dom_node.document();
auto& style_computer = document.style_computer();
- RefPtr<Layout::Node> layout_node;
+ JS::GCPtr<Layout::Node> layout_node;
RefPtr<CSS::StyleProperties> style;
CSS::Display display;
@@ -211,12 +211,12 @@ void TreeBuilder::create_layout_tree(DOM::Node& dom_node, TreeBuilder::Context&
} else if (is<DOM::Document>(dom_node)) {
style = style_computer.create_document_style();
display = style->display();
- layout_node = adopt_ref(*new Layout::InitialContainingBlock(static_cast<DOM::Document&>(dom_node), *style));
+ layout_node = document.heap().allocate_without_realm<Layout::InitialContainingBlock>(static_cast<DOM::Document&>(dom_node), *style);
} else if (is<DOM::Text>(dom_node)) {
- layout_node = adopt_ref(*new Layout::TextNode(document, static_cast<DOM::Text&>(dom_node)));
+ layout_node = document.heap().allocate_without_realm<Layout::TextNode>(document, static_cast<DOM::Text&>(dom_node));
display = CSS::Display(CSS::Display::Outside::Inline, CSS::Display::Inside::Flow);
} else if (is<DOM::ShadowRoot>(dom_node)) {
- layout_node = adopt_ref(*new Layout::BlockContainer(document, &static_cast<DOM::ShadowRoot&>(dom_node), CSS::ComputedValues {}));
+ layout_node = document.heap().allocate_without_realm<Layout::BlockContainer>(document, &static_cast<DOM::ShadowRoot&>(dom_node), CSS::ComputedValues {});
display = CSS::Display(CSS::Display::Outside::Block, CSS::Display::Inside::FlowRoot);
}
@@ -256,10 +256,10 @@ void TreeBuilder::create_layout_tree(DOM::Node& dom_node, TreeBuilder::Context&
auto& element = static_cast<DOM::Element&>(dom_node);
int child_index = layout_node->parent()->index_of_child<ListItemBox>(*layout_node).value();
auto marker_style = style_computer.compute_style(element, CSS::Selector::PseudoElement::Marker);
- auto list_item_marker = adopt_ref(*new ListItemMarkerBox(document, layout_node->computed_values().list_style_type(), child_index + 1, *marker_style));
+ auto list_item_marker = document.heap().allocate_without_realm<ListItemMarkerBox>(document, layout_node->computed_values().list_style_type(), child_index + 1, *marker_style);
static_cast<ListItemBox&>(*layout_node).set_marker(list_item_marker);
element.set_pseudo_element_node({}, CSS::Selector::PseudoElement::Marker, list_item_marker);
- layout_node->append_child(move(list_item_marker));
+ layout_node->append_child(*list_item_marker);
}
if (is<HTML::HTMLProgressElement>(dom_node)) {
@@ -287,7 +287,7 @@ void TreeBuilder::create_layout_tree(DOM::Node& dom_node, TreeBuilder::Context&
}
}
-RefPtr<Node> TreeBuilder::build(DOM::Node& dom_node)
+JS::GCPtr<Layout::Node> TreeBuilder::build(DOM::Node& dom_node)
{
VERIFY(dom_node.is_document());
@@ -333,7 +333,7 @@ void TreeBuilder::remove_irrelevant_boxes(NodeWithStyle& root)
{
// The following boxes are discarded as if they were display:none:
- NonnullRefPtrVector<Node> to_remove;
+ Vector<JS::Handle<Node>> to_remove;
// Children of a table-column.
for_each_in_tree_with_internal_display<CSS::Display::Internal::TableColumn>(root, [&](Box& table_column) {
@@ -358,7 +358,7 @@ void TreeBuilder::remove_irrelevant_boxes(NodeWithStyle& root)
// - whose immediate sibling, if any, is a table-non-root box
for (auto& box : to_remove)
- box.parent()->remove_child(box);
+ box->parent()->remove_child(*box);
}
static bool is_table_track(CSS::Display display)
@@ -424,18 +424,18 @@ static bool is_ignorable_whitespace(Layout::Node const& node)
template<typename Matcher, typename Callback>
static void for_each_sequence_of_consecutive_children_matching(NodeWithStyle& parent, Matcher matcher, Callback callback)
{
- NonnullRefPtrVector<Node> sequence;
+ Vector<JS::Handle<Node>> sequence;
auto sequence_is_all_ignorable_whitespace = [&]() -> bool {
for (auto& node : sequence) {
- if (!is_ignorable_whitespace(node))
+ if (!is_ignorable_whitespace(*node))
return false;
}
return true;
};
Node* next_sibling = nullptr;
- for (auto* child = parent.first_child(); child; child = next_sibling) {
+ for (auto child = parent.first_child(); child; child = next_sibling) {
next_sibling = child->next_sibling();
if (matcher(*child)) {
sequence.append(*child);
@@ -452,21 +452,21 @@ static void for_each_sequence_of_consecutive_children_matching(NodeWithStyle& pa
}
template<typename WrapperBoxType>
-static void wrap_in_anonymous(NonnullRefPtrVector<Node>& sequence, Node* nearest_sibling)
+static void wrap_in_anonymous(Vector<JS::Handle<Node>>& sequence, Node* nearest_sibling)
{
VERIFY(!sequence.is_empty());
- auto& parent = *sequence.first().parent();
+ auto& parent = *sequence.first()->parent();
auto computed_values = parent.computed_values().clone_inherited_values();
static_cast<CSS::MutableComputedValues&>(computed_values).set_display(WrapperBoxType::static_display());
- auto wrapper = adopt_ref(*new WrapperBoxType(parent.document(), nullptr, move(computed_values)));
+ auto wrapper = parent.heap().template allocate_without_realm<WrapperBoxType>(parent.document(), nullptr, move(computed_values));
for (auto& child : sequence) {
- parent.remove_child(child);
- wrapper->append_child(child);
+ parent.remove_child(*child);
+ wrapper->append_child(*child);
}
if (nearest_sibling)
- parent.insert_before(move(wrapper), *nearest_sibling);
+ parent.insert_before(*wrapper, *nearest_sibling);
else
- parent.append_child(move(wrapper));
+ parent.append_child(*wrapper);
}
void TreeBuilder::generate_missing_child_wrappers(NodeWithStyle& root)
diff --git a/Userland/Libraries/LibWeb/Layout/TreeBuilder.h b/Userland/Libraries/LibWeb/Layout/TreeBuilder.h
index f3b844b240..0c0c238ad4 100644
--- a/Userland/Libraries/LibWeb/Layout/TreeBuilder.h
+++ b/Userland/Libraries/LibWeb/Layout/TreeBuilder.h
@@ -17,7 +17,7 @@ class TreeBuilder {
public:
TreeBuilder();
- RefPtr<Layout::Node> build(DOM::Node&);
+ JS::GCPtr<Layout::Node> build(DOM::Node&);
private:
struct Context {
@@ -47,7 +47,7 @@ private:
void insert_node_into_inline_or_block_ancestor(Layout::Node&, CSS::Display, AppendOrPrepend);
void create_pseudo_element_if_needed(DOM::Element&, CSS::Selector::PseudoElement, AppendOrPrepend);
- RefPtr<Layout::Node> m_layout_root;
+ JS::GCPtr<Layout::Node> m_layout_root;
Vector<Layout::NodeWithStyle&> m_ancestor_stack;
};
diff --git a/Userland/Libraries/LibWeb/Page/EventHandler.cpp b/Userland/Libraries/LibWeb/Page/EventHandler.cpp
index f60d7c624b..a5ed478ced 100644
--- a/Userland/Libraries/LibWeb/Page/EventHandler.cpp
+++ b/Userland/Libraries/LibWeb/Page/EventHandler.cpp
@@ -637,7 +637,7 @@ bool EventHandler::handle_keydown(KeyCode key, unsigned modifiers, u32 code_poin
if (!document->layout_node())
return false;
- NonnullRefPtr<Layout::InitialContainingBlock> layout_root = *document->layout_node();
+ JS::NonnullGCPtr<Layout::InitialContainingBlock> layout_root = *document->layout_node();
if (key == KeyCode::Key_Tab) {
if (modifiers & KeyModifier::Mod_Shift)
diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp
index 34d56620a0..c9326e047e 100644
--- a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp
+++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp
@@ -71,6 +71,12 @@ Gfx::FloatPoint PaintableBox::effective_offset() const
{
Gfx::FloatPoint offset;
if (m_containing_line_box_fragment.has_value()) {
+
+ // FIXME: This is a hack to deal with situations where the layout tree has been garbage collected.
+ // We could avoid this by making the paintable tree garbage collected as well.
+ if (!containing_block() || !containing_block()->paint_box())
+ return offset;
+
auto const& fragment = containing_block()->paint_box()->line_boxes()[m_containing_line_box_fragment->line_box_index].fragments()[m_containing_line_box_fragment->fragment_index];
offset = fragment.offset();
} else {
diff --git a/Userland/Libraries/LibWeb/SVG/SVGClipPathElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGClipPathElement.cpp
index 34642e5eec..c7127dff91 100644
--- a/Userland/Libraries/LibWeb/SVG/SVGClipPathElement.cpp
+++ b/Userland/Libraries/LibWeb/SVG/SVGClipPathElement.cpp
@@ -19,7 +19,7 @@ SVGClipPathElement::~SVGClipPathElement()
{
}
-RefPtr<Layout::Node> SVGClipPathElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties>)
+JS::GCPtr<Layout::Node> SVGClipPathElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties>)
{
return nullptr;
}
diff --git a/Userland/Libraries/LibWeb/SVG/SVGClipPathElement.h b/Userland/Libraries/LibWeb/SVG/SVGClipPathElement.h
index 8a76da5aae..36712c18b4 100644
--- a/Userland/Libraries/LibWeb/SVG/SVGClipPathElement.h
+++ b/Userland/Libraries/LibWeb/SVG/SVGClipPathElement.h
@@ -16,7 +16,7 @@ class SVGClipPathElement final : public SVGElement {
public:
virtual ~SVGClipPathElement();
- virtual RefPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
+ virtual JS::GCPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
private:
SVGClipPathElement(DOM::Document&, DOM::QualifiedName);
diff --git a/Userland/Libraries/LibWeb/SVG/SVGDefsElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGDefsElement.cpp
index 4d4a8dfaa6..86e7d87ff0 100644
--- a/Userland/Libraries/LibWeb/SVG/SVGDefsElement.cpp
+++ b/Userland/Libraries/LibWeb/SVG/SVGDefsElement.cpp
@@ -19,7 +19,7 @@ SVGDefsElement::~SVGDefsElement()
{
}
-RefPtr<Layout::Node> SVGDefsElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties>)
+JS::GCPtr<Layout::Node> SVGDefsElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties>)
{
return nullptr;
}
diff --git a/Userland/Libraries/LibWeb/SVG/SVGDefsElement.h b/Userland/Libraries/LibWeb/SVG/SVGDefsElement.h
index 68e521b5e9..ddb2eeb437 100644
--- a/Userland/Libraries/LibWeb/SVG/SVGDefsElement.h
+++ b/Userland/Libraries/LibWeb/SVG/SVGDefsElement.h
@@ -16,7 +16,7 @@ class SVGDefsElement final : public SVGGraphicsElement {
public:
virtual ~SVGDefsElement();
- virtual RefPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
+ virtual JS::GCPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
private:
SVGDefsElement(DOM::Document&, DOM::QualifiedName);
diff --git a/Userland/Libraries/LibWeb/SVG/SVGGElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGGElement.cpp
index 20601ea4a8..25fdd0beee 100644
--- a/Userland/Libraries/LibWeb/SVG/SVGGElement.cpp
+++ b/Userland/Libraries/LibWeb/SVG/SVGGElement.cpp
@@ -16,9 +16,9 @@ SVGGElement::SVGGElement(DOM::Document& document, DOM::QualifiedName qualified_n
{
}
-RefPtr<Layout::Node> SVGGElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
+JS::GCPtr<Layout::Node> SVGGElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
{
- return adopt_ref(*new Layout::SVGGraphicsBox(document(), *this, move(style)));
+ return heap().allocate_without_realm<Layout::SVGGraphicsBox>(document(), *this, move(style));
}
}
diff --git a/Userland/Libraries/LibWeb/SVG/SVGGElement.h b/Userland/Libraries/LibWeb/SVG/SVGGElement.h
index a2609680ca..825983c2dc 100644
--- a/Userland/Libraries/LibWeb/SVG/SVGGElement.h
+++ b/Userland/Libraries/LibWeb/SVG/SVGGElement.h
@@ -16,7 +16,7 @@ class SVGGElement final : public SVGGraphicsElement {
public:
virtual ~SVGGElement() override = default;
- virtual RefPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
+ virtual JS::GCPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
private:
SVGGElement(DOM::Document&, DOM::QualifiedName);
diff --git a/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.cpp
index 2c56eadce2..974f966797 100644
--- a/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.cpp
+++ b/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.cpp
@@ -16,9 +16,9 @@ SVGGeometryElement::SVGGeometryElement(DOM::Document& document, DOM::QualifiedNa
set_prototype(&Bindings::cached_web_prototype(realm(), "SVGGeometryElement"));
}
-RefPtr<Layout::Node> SVGGeometryElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
+JS::GCPtr<Layout::Node> SVGGeometryElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
{
- return adopt_ref(*new Layout::SVGGeometryBox(document(), *this, move(style)));
+ return heap().allocate_without_realm<Layout::SVGGeometryBox>(document(), *this, move(style));
}
float SVGGeometryElement::get_total_length()
diff --git a/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.h b/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.h
index 70d48b7669..bf01c92a93 100644
--- a/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.h
+++ b/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.h
@@ -16,7 +16,7 @@ class SVGGeometryElement : public SVGGraphicsElement {
WEB_PLATFORM_OBJECT(SVGGeometryElement, SVGGraphicsElement);
public:
- virtual RefPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
+ virtual JS::GCPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
virtual Gfx::Path& get_path() = 0;
diff --git a/Userland/Libraries/LibWeb/SVG/SVGSVGElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGSVGElement.cpp
index 640b4d7edc..24a34d343d 100644
--- a/Userland/Libraries/LibWeb/SVG/SVGSVGElement.cpp
+++ b/Userland/Libraries/LibWeb/SVG/SVGSVGElement.cpp
@@ -23,9 +23,9 @@ SVGSVGElement::SVGSVGElement(DOM::Document& document, DOM::QualifiedName qualifi
set_prototype(&Bindings::cached_web_prototype(realm(), "SVGSVGElement"));
}
-RefPtr<Layout::Node> SVGSVGElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
+JS::GCPtr<Layout::Node> SVGSVGElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
{
- return adopt_ref(*new Layout::SVGSVGBox(document(), *this, move(style)));
+ return heap().allocate_without_realm<Layout::SVGSVGBox>(document(), *this, move(style));
}
void SVGSVGElement::apply_presentational_hints(CSS::StyleProperties& style) const
diff --git a/Userland/Libraries/LibWeb/SVG/SVGSVGElement.h b/Userland/Libraries/LibWeb/SVG/SVGSVGElement.h
index c3518e09b3..92835066e7 100644
--- a/Userland/Libraries/LibWeb/SVG/SVGSVGElement.h
+++ b/Userland/Libraries/LibWeb/SVG/SVGSVGElement.h
@@ -16,7 +16,7 @@ class SVGSVGElement final : public SVGGraphicsElement {
WEB_PLATFORM_OBJECT(SVGSVGElement, SVGGraphicsElement);
public:
- virtual RefPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
+ virtual JS::GCPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
virtual void apply_presentational_hints(CSS::StyleProperties&) const override;
diff --git a/Userland/Libraries/LibWeb/TreeNode.h b/Userland/Libraries/LibWeb/TreeNode.h
index 1972c4fd05..74d7a94d40 100644
--- a/Userland/Libraries/LibWeb/TreeNode.h
+++ b/Userland/Libraries/LibWeb/TreeNode.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@@ -7,54 +7,27 @@
#pragma once
#include <AK/Assertions.h>
-#include <AK/NonnullRefPtr.h>
#include <AK/TypeCasts.h>
-#include <AK/Weakable.h>
+#include <LibJS/Heap/GCPtr.h>
#include <LibWeb/Forward.h>
namespace Web {
template<typename T>
-class TreeNode : public Weakable<T> {
+class TreeNode {
public:
- void ref()
- {
- VERIFY(!m_in_removed_last_ref);
- if constexpr (!IsBaseOf<DOM::Node, T>) {
- // NOTE: DOM::Document is allowed to survive with 0 ref count, if one of its descendant nodes are alive.
- VERIFY(m_ref_count);
- }
- ++m_ref_count;
- }
-
- void unref()
- {
- VERIFY(!m_in_removed_last_ref);
- VERIFY(m_ref_count);
- if (!--m_ref_count) {
- if constexpr (IsBaseOf<DOM::Node, T>) {
- m_in_removed_last_ref = true;
- static_cast<T*>(this)->removed_last_ref();
- } else {
- delete static_cast<T*>(this);
- }
- return;
- }
- }
- int ref_count() const { return m_ref_count; }
-
T* parent() { return m_parent; }
- const T* parent() const { return m_parent; }
+ T const* parent() const { return m_parent; }
bool has_children() const { return m_first_child; }
T* next_sibling() { return m_next_sibling; }
T* previous_sibling() { return m_previous_sibling; }
T* first_child() { return m_first_child; }
T* last_child() { return m_last_child; }
- const T* next_sibling() const { return m_next_sibling; }
- const T* previous_sibling() const { return m_previous_sibling; }
- const T* first_child() const { return m_first_child; }
- const T* last_child() const { return m_last_child; }
+ T const* next_sibling() const { return m_next_sibling; }
+ T const* previous_sibling() const { return m_previous_sibling; }
+ T const* first_child() const { return m_first_child; }
+ T const* last_child() const { return m_last_child; }
size_t child_count() const
{
@@ -75,7 +48,7 @@ public:
return nullptr;
}
- const T* child_at_index(int index) const
+ T const* child_at_index(int index) const
{
return const_cast<TreeNode*>(this)->child_at_index(index);
}
@@ -90,7 +63,7 @@ public:
return index;
}
- Optional<size_t> index_of_child(const T& search_child)
+ Optional<size_t> index_of_child(T const& search_child)
{
VERIFY(search_child.parent() == this);
size_t index = 0;
@@ -106,7 +79,7 @@ public:
}
template<typename ChildType>
- Optional<size_t> index_of_child(const T& search_child)
+ Optional<size_t> index_of_child(T const& search_child)
{
VERIFY(search_child.parent() == this);
size_t index = 0;
@@ -130,12 +103,12 @@ public:
bool is_following(TreeNode const&) const;
- void append_child(NonnullRefPtr<T> node);
- void prepend_child(NonnullRefPtr<T> node);
- void insert_before(NonnullRefPtr<T> node, RefPtr<T> child);
- void remove_child(NonnullRefPtr<T> node);
+ void append_child(JS::NonnullGCPtr<T> node);
+ void prepend_child(JS::NonnullGCPtr<T> node);
+ void insert_before(JS::NonnullGCPtr<T> node, JS::GCPtr<T> child);
+ void remove_child(JS::NonnullGCPtr<T> node);
- bool is_child_allowed(const T&) const { return true; }
+ bool is_child_allowed(T const&) const { return true; }
T* next_in_pre_order()
{
@@ -230,7 +203,7 @@ public:
template<typename Callback>
IterationDecision for_each_in_inclusive_subtree(Callback callback) const
{
- if (callback(static_cast<const T&>(*this)) == IterationDecision::Break)
+ if (callback(static_cast<T const&>(*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)
@@ -254,7 +227,7 @@ public:
template<typename U, typename Callback>
IterationDecision for_each_in_inclusive_subtree_of_type(Callback callback)
{
- if (is<U>(static_cast<const T&>(*this))) {
+ if (is<U>(static_cast<T const&>(*this))) {
if (callback(static_cast<U&>(*this)) == IterationDecision::Break)
return IterationDecision::Break;
}
@@ -268,8 +241,8 @@ public:
template<typename U, typename Callback>
IterationDecision for_each_in_inclusive_subtree_of_type(Callback callback) const
{
- if (is<U>(static_cast<const T&>(*this))) {
- if (callback(static_cast<const U&>(*this)) == IterationDecision::Break)
+ if (is<U>(static_cast<T const&>(*this))) {
+ if (callback(static_cast<U const&>(*this)) == IterationDecision::Break)
return IterationDecision::Break;
}
for (auto* child = first_child(); child; child = child->next_sibling()) {
@@ -348,7 +321,7 @@ public:
}
template<typename U>
- const U* next_sibling_of_type() const
+ U const* next_sibling_of_type() const
{
return const_cast<TreeNode*>(this)->template next_sibling_of_type<U>();
}
@@ -364,7 +337,7 @@ public:
}
template<typename U>
- const U* previous_sibling_of_type() const
+ U const* previous_sibling_of_type() const
{
return const_cast<TreeNode*>(this)->template previous_sibling_of_type<U>();
}
@@ -380,13 +353,13 @@ public:
}
template<typename U>
- const U* first_child_of_type() const
+ U const* first_child_of_type() const
{
return const_cast<TreeNode*>(this)->template first_child_of_type<U>();
}
template<typename U>
- const U* last_child_of_type() const
+ U const* last_child_of_type() const
{
return const_cast<TreeNode*>(this)->template last_child_of_type<U>();
}
@@ -418,7 +391,7 @@ public:
}
template<typename U>
- const U* first_ancestor_of_type() const
+ U const* first_ancestor_of_type() const
{
return const_cast<TreeNode*>(this)->template first_ancestor_of_type<U>();
}
@@ -442,25 +415,21 @@ public:
return false;
}
- ~TreeNode()
- {
- VERIFY(!m_parent);
- T* next_child = nullptr;
- for (auto* child = m_first_child; child; child = next_child) {
- next_child = child->m_next_sibling;
- child->m_parent = nullptr;
- child->unref();
- }
- }
+ ~TreeNode() = default;
protected:
TreeNode() = default;
- bool m_deletion_has_begun { false };
- bool m_in_removed_last_ref { false };
+ void visit_edges(JS::Cell::Visitor& visitor)
+ {
+ visitor.visit(m_parent);
+ visitor.visit(m_first_child);
+ visitor.visit(m_last_child);
+ visitor.visit(m_next_sibling);
+ visitor.visit(m_previous_sibling);
+ }
private:
- int m_ref_count { 1 };
T* m_parent { nullptr };
T* m_first_child { nullptr };
T* m_last_child { nullptr };
@@ -469,7 +438,7 @@ private:
};
template<typename T>
-inline void TreeNode<T>::remove_child(NonnullRefPtr<T> node)
+inline void TreeNode<T>::remove_child(JS::NonnullGCPtr<T> node)
{
VERIFY(node->m_parent == this);
@@ -488,12 +457,10 @@ inline void TreeNode<T>::remove_child(NonnullRefPtr<T> node)
node->m_next_sibling = nullptr;
node->m_previous_sibling = nullptr;
node->m_parent = nullptr;
-
- node->unref();
}
template<typename T>
-inline void TreeNode<T>::append_child(NonnullRefPtr<T> node)
+inline void TreeNode<T>::append_child(JS::NonnullGCPtr<T> node)
{
VERIFY(!node->m_parent);
@@ -507,11 +474,10 @@ inline void TreeNode<T>::append_child(NonnullRefPtr<T> node)
m_last_child = node.ptr();
if (!m_first_child)
m_first_child = m_last_child;
- [[maybe_unused]] auto& rc = node.leak_ref();
}
template<typename T>
-inline void TreeNode<T>::insert_before(NonnullRefPtr<T> node, RefPtr<T> child)
+inline void TreeNode<T>::insert_before(JS::NonnullGCPtr<T> node, JS::GCPtr<T> child)
{
if (!child)
return append_child(move(node));
@@ -531,11 +497,10 @@ inline void TreeNode<T>::insert_before(NonnullRefPtr<T> node, RefPtr<T> child)
child->m_previous_sibling = node;
node->m_parent = static_cast<T*>(this);
- [[maybe_unused]] auto& rc = node.leak_ref();
}
template<typename T>
-inline void TreeNode<T>::prepend_child(NonnullRefPtr<T> node)
+inline void TreeNode<T>::prepend_child(JS::NonnullGCPtr<T> node)
{
VERIFY(!node->m_parent);
@@ -550,7 +515,6 @@ inline void TreeNode<T>::prepend_child(NonnullRefPtr<T> node)
if (!m_last_child)
m_last_child = m_first_child;
node->inserted_into(static_cast<T&>(*this));
- [[maybe_unused]] auto& rc = node.leak_ref();
static_cast<T*>(this)->children_changed();
}