From 268b9c5d904e41ba901c9fce556a5be1d5fea228 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 17 Oct 2022 14:41:50 +0200 Subject: [PATCH] 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. --- Userland/Libraries/LibWeb/DOM/Document.cpp | 8 +- Userland/Libraries/LibWeb/DOM/Document.h | 2 +- Userland/Libraries/LibWeb/DOM/Element.cpp | 36 +++--- Userland/Libraries/LibWeb/DOM/Element.h | 10 +- Userland/Libraries/LibWeb/DOM/Node.cpp | 9 +- Userland/Libraries/LibWeb/DOM/Node.h | 5 +- .../Libraries/LibWeb/HTML/BrowsingContext.cpp | 14 ++- .../Libraries/LibWeb/HTML/HTMLBRElement.cpp | 4 +- .../Libraries/LibWeb/HTML/HTMLBRElement.h | 2 +- .../LibWeb/HTML/HTMLCanvasElement.cpp | 4 +- .../Libraries/LibWeb/HTML/HTMLCanvasElement.h | 2 +- .../LibWeb/HTML/HTMLIFrameElement.cpp | 4 +- .../Libraries/LibWeb/HTML/HTMLIFrameElement.h | 2 +- .../LibWeb/HTML/HTMLImageElement.cpp | 4 +- .../Libraries/LibWeb/HTML/HTMLImageElement.h | 2 +- .../LibWeb/HTML/HTMLInputElement.cpp | 10 +- .../Libraries/LibWeb/HTML/HTMLInputElement.h | 2 +- .../LibWeb/HTML/HTMLLabelElement.cpp | 4 +- .../Libraries/LibWeb/HTML/HTMLLabelElement.h | 2 +- .../LibWeb/HTML/HTMLObjectElement.cpp | 4 +- .../Libraries/LibWeb/HTML/HTMLObjectElement.h | 2 +- .../LibWeb/HTML/HTMLProgressElement.cpp | 4 +- .../LibWeb/HTML/HTMLProgressElement.h | 2 +- .../Libraries/LibWeb/Layout/BlockContainer.h | 2 + Userland/Libraries/LibWeb/Layout/Box.h | 2 + Userland/Libraries/LibWeb/Layout/BreakNode.h | 2 + Userland/Libraries/LibWeb/Layout/ButtonBox.h | 2 + Userland/Libraries/LibWeb/Layout/CanvasBox.h | 2 + Userland/Libraries/LibWeb/Layout/CheckBox.h | 2 + .../Layout/FormAssociatedLabelableNode.h | 2 + Userland/Libraries/LibWeb/Layout/FrameBox.h | 2 + Userland/Libraries/LibWeb/Layout/ImageBox.h | 2 + .../LibWeb/Layout/InitialContainingBlock.h | 2 + Userland/Libraries/LibWeb/Layout/InlineNode.h | 2 + Userland/Libraries/LibWeb/Layout/Label.cpp | 3 - Userland/Libraries/LibWeb/Layout/Label.h | 2 + .../Libraries/LibWeb/Layout/LabelableNode.h | 2 + .../LibWeb/Layout/LayoutPosition.cpp | 2 +- .../Libraries/LibWeb/Layout/LayoutPosition.h | 2 +- .../Libraries/LibWeb/Layout/ListItemBox.cpp | 8 +- .../Libraries/LibWeb/Layout/ListItemBox.h | 8 +- .../LibWeb/Layout/ListItemMarkerBox.h | 2 + Userland/Libraries/LibWeb/Layout/Node.cpp | 28 ++--- Userland/Libraries/LibWeb/Layout/Node.h | 18 ++- Userland/Libraries/LibWeb/Layout/Progress.h | 2 + .../Libraries/LibWeb/Layout/RadioButton.h | 2 + .../Libraries/LibWeb/Layout/ReplacedBox.h | 2 + Userland/Libraries/LibWeb/Layout/SVGBox.h | 2 + .../Libraries/LibWeb/Layout/SVGGeometryBox.h | 2 + .../Libraries/LibWeb/Layout/SVGGraphicsBox.h | 2 + Userland/Libraries/LibWeb/Layout/SVGSVGBox.h | 2 + Userland/Libraries/LibWeb/Layout/TableBox.h | 2 + .../Libraries/LibWeb/Layout/TableCellBox.h | 2 + .../Libraries/LibWeb/Layout/TableRowBox.h | 2 + .../LibWeb/Layout/TableRowGroupBox.h | 2 + Userland/Libraries/LibWeb/Layout/TextNode.h | 2 + .../Libraries/LibWeb/Layout/TreeBuilder.cpp | 54 ++++----- .../Libraries/LibWeb/Layout/TreeBuilder.h | 4 +- .../Libraries/LibWeb/Page/EventHandler.cpp | 2 +- .../LibWeb/Painting/PaintableBox.cpp | 6 + .../LibWeb/SVG/SVGClipPathElement.cpp | 2 +- .../Libraries/LibWeb/SVG/SVGClipPathElement.h | 2 +- .../Libraries/LibWeb/SVG/SVGDefsElement.cpp | 2 +- .../Libraries/LibWeb/SVG/SVGDefsElement.h | 2 +- Userland/Libraries/LibWeb/SVG/SVGGElement.cpp | 4 +- Userland/Libraries/LibWeb/SVG/SVGGElement.h | 2 +- .../LibWeb/SVG/SVGGeometryElement.cpp | 4 +- .../Libraries/LibWeb/SVG/SVGGeometryElement.h | 2 +- .../Libraries/LibWeb/SVG/SVGSVGElement.cpp | 4 +- Userland/Libraries/LibWeb/SVG/SVGSVGElement.h | 2 +- Userland/Libraries/LibWeb/TreeNode.h | 112 ++++++------------ .../WebContent/ConnectionFromClient.cpp | 2 +- 72 files changed, 258 insertions(+), 207 deletions(-) diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index fc9afb9496d..7f64a173370 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_nodes; + Vector> 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(tree_builder.build(*this)); + m_layout_root = verify_cast(*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 8762b61ae54..1ba0988cb63 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -469,7 +469,7 @@ private: JS::GCPtr m_window; - RefPtr m_layout_root; + JS::GCPtr m_layout_root; Optional m_link_color; Optional m_active_link_color; diff --git a/Userland/Libraries/LibWeb/DOM/Element.cpp b/Userland/Libraries/LibWeb/DOM/Element.cpp index 319ec1c721f..ac4e6c7f71c 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 Element::create_layout_node(NonnullRefPtr style) +JS::GCPtr Element::create_layout_node(NonnullRefPtr style) { if (local_name() == "noscript" && document().is_scripting_enabled()) return nullptr; @@ -281,41 +283,41 @@ RefPtr Element::create_layout_node(NonnullRefPtr Element::create_layout_node_for_display_type(DOM::Document& document, CSS::Display const& display, NonnullRefPtr style, Element* element) +JS::GCPtr Element::create_layout_node_for_display_type(DOM::Document& document, CSS::Display const& display, NonnullRefPtr style, Element* element) { if (display.is_table_inside()) - return adopt_ref(*new Layout::TableBox(document, element, move(style))); + return document.heap().allocate_without_realm(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(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(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(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(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(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(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(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(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(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(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, CSS::Selector::PseudoElement pseudo_element, RefPtr pseudo_element_node) +void Element::set_pseudo_element_node(Badge, CSS::Selector::PseudoElement pseudo_element, JS::GCPtr 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 Element::get_pseudo_element_node(CSS::Selector::PseudoElement pseudo_element) const +JS::GCPtr 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) diff --git a/Userland/Libraries/LibWeb/DOM/Element.h b/Userland/Libraries/LibWeb/DOM/Element.h index 95cb80dbfa4..6265b1b80c9 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.h +++ b/Userland/Libraries/LibWeb/DOM/Element.h @@ -142,15 +142,15 @@ public: JS::NonnullGCPtr get_bounding_client_rect() const; JS::NonnullGCPtr get_client_rects() const; - virtual RefPtr create_layout_node(NonnullRefPtr); + virtual JS::GCPtr create_layout_node(NonnullRefPtr); virtual void did_receive_focus() { } virtual void did_lose_focus() { } - static RefPtr create_layout_node_for_display_type(DOM::Document&, CSS::Display const&, NonnullRefPtr, Element*); + static JS::GCPtr create_layout_node_for_display_type(DOM::Document&, CSS::Display const&, NonnullRefPtr, Element*); - void set_pseudo_element_node(Badge, CSS::Selector::PseudoElement, RefPtr); - RefPtr get_pseudo_element_node(CSS::Selector::PseudoElement) const; + void set_pseudo_element_node(Badge, CSS::Selector::PseudoElement, JS::GCPtr); + JS::GCPtr get_pseudo_element_node(CSS::Selector::PseudoElement) const; void clear_pseudo_element_nodes(Badge); void serialize_pseudo_elements_as_json(JsonArraySerializer& children_array) const; @@ -188,7 +188,7 @@ private: Vector m_classes; - Array, CSS::Selector::PseudoElementCount> m_pseudo_element_nodes; + Array, 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 7e4e83c23ff..d073346ed28 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) const +void Node::set_layout_node(Badge, JS::NonnullGCPtr layout_node) { m_layout_node = layout_node; } +void Node::detach_layout_node(Badge) +{ + 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 cf2ad07a03a..9e048a68927 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*) const; + void set_layout_node(Badge, JS::NonnullGCPtr); + void detach_layout_node(Badge); virtual bool is_child_allowed(Node const&) const { return true; } @@ -623,7 +624,7 @@ protected: virtual void visit_edges(Cell::Visitor&) override; JS::GCPtr m_document; - mutable WeakPtr m_layout_node; + JS::GCPtr 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 4f8cd120d50..c7134670315 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(*selection.start().layout_node)) return ""; return verify_cast(*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_node)) builder.append(verify_cast(*layout_node).text_for_rendering()); else if (is(*layout_node) || is(*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_node)) { auto& text = verify_cast(*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(first_layout_node)), 0 + }; + auto end = Layout::LayoutPosition { + JS::make_handle(const_cast(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 cd9f46b8896..3dc799c88bf 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 HTMLBRElement::create_layout_node(NonnullRefPtr style) +JS::GCPtr HTMLBRElement::create_layout_node(NonnullRefPtr style) { - return adopt_ref(*new Layout::BreakNode(document(), *this, move(style))); + return heap().allocate_without_realm(document(), *this, move(style)); } } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBRElement.h b/Userland/Libraries/LibWeb/HTML/HTMLBRElement.h index 9b02c1d0e72..d3c8af74405 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 create_layout_node(NonnullRefPtr) override; + virtual JS::GCPtr create_layout_node(NonnullRefPtr) override; private: HTMLBRElement(DOM::Document&, DOM::QualifiedName); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp index 54217cf542e..9ec5a469a25 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 HTMLCanvasElement::create_layout_node(NonnullRefPtr style) +JS::GCPtr HTMLCanvasElement::create_layout_node(NonnullRefPtr style) { - return adopt_ref(*new Layout::CanvasBox(document(), *this, move(style))); + return heap().allocate_without_realm(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 084e6e34877..c9eba32067f 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 create_layout_node(NonnullRefPtr) override; + virtual JS::GCPtr create_layout_node(NonnullRefPtr) override; enum class HasOrCreatedContext { No, diff --git a/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp index 006640eabc8..c3d171b55d4 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 HTMLIFrameElement::create_layout_node(NonnullRefPtr style) +JS::GCPtr HTMLIFrameElement::create_layout_node(NonnullRefPtr style) { - return adopt_ref(*new Layout::FrameBox(document(), *this, move(style))); + return heap().allocate_without_realm(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 d7aba28e145..dd2aff37365 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 create_layout_node(NonnullRefPtr) override; + virtual JS::GCPtr create_layout_node(NonnullRefPtr) 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 1c14c29ee07..0d4ff161417 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 HTMLImageElement::create_layout_node(NonnullRefPtr style) +JS::GCPtr HTMLImageElement::create_layout_node(NonnullRefPtr style) { - return adopt_ref(*new Layout::ImageBox(document(), *this, move(style), m_image_loader)); + return heap().allocate_without_realm(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 803ee9f339c..3353a259b97 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h @@ -50,7 +50,7 @@ private: void animate(); - virtual RefPtr create_layout_node(NonnullRefPtr) override; + virtual JS::GCPtr create_layout_node(NonnullRefPtr) override; ImageLoader m_image_loader; }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp index 3a613bb1af7..e287da73870 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 HTMLInputElement::create_layout_node(NonnullRefPtr style) +JS::GCPtr HTMLInputElement::create_layout_node(NonnullRefPtr 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(document(), *this, move(style)); if (type_state() == TypeAttributeState::Checkbox) - return adopt_ref(*new Layout::CheckBox(document(), *this, move(style))); + return heap().allocate_without_realm(document(), *this, move(style)); if (type_state() == TypeAttributeState::RadioButton) - return adopt_ref(*new Layout::RadioButton(document(), *this, move(style))); + return heap().allocate_without_realm(document(), *this, move(style)); - return adopt_ref(*new Layout::BlockContainer(document(), this, move(style))); + return heap().allocate_without_realm(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 b04c6ef58c7..b77c6cbc9e6 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 create_layout_node(NonnullRefPtr) override; + virtual JS::GCPtr create_layout_node(NonnullRefPtr) 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 db4a4a86fff..940d8800076 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 HTMLLabelElement::create_layout_node(NonnullRefPtr style) +JS::GCPtr HTMLLabelElement::create_layout_node(NonnullRefPtr style) { - return adopt_ref(*new Layout::Label(document(), this, move(style))); + return heap().allocate_without_realm(document(), this, move(style)); } } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.h b/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.h index e322245cb54..9fd742fbb57 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 create_layout_node(NonnullRefPtr) override; + virtual JS::GCPtr create_layout_node(NonnullRefPtr) 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 b90a79ff082..7eecba0673f 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 HTMLObjectElement::create_layout_node(NonnullRefPtr style) +JS::GCPtr HTMLObjectElement::create_layout_node(NonnullRefPtr style) { switch (m_representation) { case Representation::Children: @@ -49,7 +49,7 @@ RefPtr HTMLObjectElement::create_layout_node(NonnullRefPtrhas_image()) - return adopt_ref(*new Layout::ImageBox(document(), *this, move(style), *m_image_loader)); + return heap().allocate_without_realm(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 5788f85a078..a2b02b2f63f 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 create_layout_node(NonnullRefPtr) override; + virtual JS::GCPtr create_layout_node(NonnullRefPtr) 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 d52a7aa1fa7..69a42f9d11e 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 HTMLProgressElement::create_layout_node(NonnullRefPtr style) +JS::GCPtr HTMLProgressElement::create_layout_node(NonnullRefPtr 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(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 e806f685af4..414769514be 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 create_layout_node(NonnullRefPtr) override; + virtual JS::GCPtr create_layout_node(NonnullRefPtr) 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 0735a455535..4f89a7659b9 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); BlockContainer(DOM::Document&, DOM::Node*, CSS::ComputedValues); diff --git a/Userland/Libraries/LibWeb/Layout/Box.h b/Userland/Libraries/LibWeb/Layout/Box.h index a064d909c89..67cbe505731 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 320f4427226..f3c814b3ae5 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); virtual ~BreakNode() override; diff --git a/Userland/Libraries/LibWeb/Layout/ButtonBox.h b/Userland/Libraries/LibWeb/Layout/ButtonBox.h index d80278e2022..c1b0c1f1066 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); virtual ~ButtonBox() override; diff --git a/Userland/Libraries/LibWeb/Layout/CanvasBox.h b/Userland/Libraries/LibWeb/Layout/CanvasBox.h index 29da2721936..89ec2c3da1f 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); virtual ~CanvasBox() override; diff --git a/Userland/Libraries/LibWeb/Layout/CheckBox.h b/Userland/Libraries/LibWeb/Layout/CheckBox.h index b6046f9de0a..a43911cad3f 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); virtual ~CheckBox() override; diff --git a/Userland/Libraries/LibWeb/Layout/FormAssociatedLabelableNode.h b/Userland/Libraries/LibWeb/Layout/FormAssociatedLabelableNode.h index 8aacbaf93a9..44ee62981fe 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(LabelableNode::dom_node()); } HTML::FormAssociatedElement& dom_node() { return dynamic_cast(LabelableNode::dom_node()); } diff --git a/Userland/Libraries/LibWeb/Layout/FrameBox.h b/Userland/Libraries/LibWeb/Layout/FrameBox.h index 96c6efdae32..2fd465213bc 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); virtual ~FrameBox() override; diff --git a/Userland/Libraries/LibWeb/Layout/ImageBox.h b/Userland/Libraries/LibWeb/Layout/ImageBox.h index 138cb507b80..98873127021 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, ImageLoader const&); virtual ~ImageBox() override; diff --git a/Userland/Libraries/LibWeb/Layout/InitialContainingBlock.h b/Userland/Libraries/LibWeb/Layout/InitialContainingBlock.h index 200fe63dae0..10c5f750748 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); virtual ~InitialContainingBlock() override; diff --git a/Userland/Libraries/LibWeb/Layout/InlineNode.h b/Userland/Libraries/LibWeb/Layout/InlineNode.h index bf5f35552b6..e670180e938 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); virtual ~InlineNode() override; diff --git a/Userland/Libraries/LibWeb/Layout/Label.cpp b/Userland/Libraries/LibWeb/Layout/Label.cpp index fc8ef566493..7cffc25ae45 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, 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 5cee1a986c7..37237190469 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); virtual ~Label() override; diff --git a/Userland/Libraries/LibWeb/Layout/LabelableNode.h b/Userland/Libraries/LibWeb/Layout/LabelableNode.h index 6c579783c90..28f566b8dd8 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 aeb4163f8d7..a44cc343e7f 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 7ab85c4a077..755e6dd01ad 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 layout_node; + JS::Handle 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 4ac9ccb430a..29f70350396 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 marker) +void ListItemBox::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_marker); +} + +void ListItemBox::set_marker(JS::GCPtr marker) { m_marker = move(marker); } diff --git a/Userland/Libraries/LibWeb/Layout/ListItemBox.h b/Userland/Libraries/LibWeb/Layout/ListItemBox.h index b285e2b0df9..d3b79f3e3d2 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); virtual ~ListItemBox() override; @@ -20,10 +22,12 @@ public: DOM::Element const& dom_node() const { return static_cast(*BlockContainer::dom_node()); } ListItemMarkerBox const* marker() const { return m_marker; } - void set_marker(RefPtr); + void set_marker(JS::GCPtr); private: - RefPtr m_marker; + virtual void visit_edges(Cell::Visitor&) override; + + JS::GCPtr m_marker; }; } diff --git a/Userland/Libraries/LibWeb/Layout/ListItemMarkerBox.h b/Userland/Libraries/LibWeb/Layout/ListItemMarkerBox.h index 647f4a7f203..170a620d895 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); virtual ~ListItemMarkerBox() override; diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp index 4a0838af27c..778e3cf4a98 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.cpp +++ b/Userland/Libraries/LibWeb/Layout/Node.cpp @@ -15,24 +15,26 @@ #include #include #include -#include 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(*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::create_anonymous_wrapper() const +JS::NonnullGCPtr NodeWithStyle::create_anonymous_wrapper() const { - auto wrapper = adopt_ref(*new BlockContainer(const_cast(document()), nullptr, m_computed_values.clone_inherited_values())); + auto wrapper = heap().allocate_without_realm(const_cast(document()), nullptr, m_computed_values.clone_inherited_values()); static_cast(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 paintable) diff --git a/Userland/Libraries/LibWeb/Layout/Node.h b/Userland/Libraries/LibWeb/Layout/Node.h index e8ca0bfe1b2..b3a044d3f80 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 { +class Node + : public JS::Cell + , public TreeNode + , public Weakable { + 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 m_dom_node; + JS::NonnullGCPtr m_dom_node; RefPtr 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 const& background_layers() const { return computed_values().background_layers(); } const CSS::AbstractImageStyleValue* list_style_image() const { return m_list_style_image; } - NonnullRefPtr create_anonymous_wrapper() const; + JS::NonnullGCPtr create_anonymous_wrapper() const; protected: NodeWithStyle(DOM::Document&, DOM::Node*, NonnullRefPtr); @@ -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 0f26ae6142e..a55ed6860b3 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); virtual ~Progress() override; diff --git a/Userland/Libraries/LibWeb/Layout/RadioButton.h b/Userland/Libraries/LibWeb/Layout/RadioButton.h index 9be341f00ad..bf30e2dde31 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); virtual ~RadioButton() override; diff --git a/Userland/Libraries/LibWeb/Layout/ReplacedBox.h b/Userland/Libraries/LibWeb/Layout/ReplacedBox.h index 28032d5aa88..f2bfa4a3cdc 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); virtual ~ReplacedBox() override; diff --git a/Userland/Libraries/LibWeb/Layout/SVGBox.h b/Userland/Libraries/LibWeb/Layout/SVGBox.h index 30caf476d3f..69bd8212792 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); virtual ~SVGBox() override = default; diff --git a/Userland/Libraries/LibWeb/Layout/SVGGeometryBox.h b/Userland/Libraries/LibWeb/Layout/SVGGeometryBox.h index 0da419179b1..d5a009c891f 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); virtual ~SVGGeometryBox() override = default; diff --git a/Userland/Libraries/LibWeb/Layout/SVGGraphicsBox.h b/Userland/Libraries/LibWeb/Layout/SVGGraphicsBox.h index efa43332390..1411ef93dda 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); virtual ~SVGGraphicsBox() override = default; diff --git a/Userland/Libraries/LibWeb/Layout/SVGSVGBox.h b/Userland/Libraries/LibWeb/Layout/SVGSVGBox.h index 55d4967c416..ee681c23c19 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); virtual ~SVGSVGBox() override = default; diff --git a/Userland/Libraries/LibWeb/Layout/TableBox.h b/Userland/Libraries/LibWeb/Layout/TableBox.h index 8fd3b9aba88..fbe3371d0c0 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); TableBox(DOM::Document&, DOM::Element*, CSS::ComputedValues); diff --git a/Userland/Libraries/LibWeb/Layout/TableCellBox.h b/Userland/Libraries/LibWeb/Layout/TableCellBox.h index 3662c62fa08..b63d8c5b1e0 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); TableCellBox(DOM::Document&, DOM::Element*, CSS::ComputedValues); diff --git a/Userland/Libraries/LibWeb/Layout/TableRowBox.h b/Userland/Libraries/LibWeb/Layout/TableRowBox.h index e7f6b1f7832..26c7f6de7d4 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); TableRowBox(DOM::Document&, DOM::Element*, CSS::ComputedValues); diff --git a/Userland/Libraries/LibWeb/Layout/TableRowGroupBox.h b/Userland/Libraries/LibWeb/Layout/TableRowGroupBox.h index 46ac7f49979..923c662f47c 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); virtual ~TableRowGroupBox() override; diff --git a/Userland/Libraries/LibWeb/Layout/TextNode.h b/Userland/Libraries/LibWeb/Layout/TextNode.h index 128f80b893a..e13ca542723 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 ac86d9ddc69..e4c7ceb04b1 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 children; - while (RefPtr child = layout_parent.first_child()) { + Vector> children; + while (JS::GCPtr 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(document.realm(), document, pseudo_element_content.data); - auto text_node = adopt_ref(*new TextNode(document, *text)); + auto text_node = document.heap().allocate_without_realm(document, *text); text_node->set_generated(true); push_parent(verify_cast(*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; + JS::GCPtr layout_node; RefPtr style; CSS::Display display; @@ -211,12 +211,12 @@ void TreeBuilder::create_layout_tree(DOM::Node& dom_node, TreeBuilder::Context& } else if (is(dom_node)) { style = style_computer.create_document_style(); display = style->display(); - layout_node = adopt_ref(*new Layout::InitialContainingBlock(static_cast(dom_node), *style)); + layout_node = document.heap().allocate_without_realm(static_cast(dom_node), *style); } else if (is(dom_node)) { - layout_node = adopt_ref(*new Layout::TextNode(document, static_cast(dom_node))); + layout_node = document.heap().allocate_without_realm(document, static_cast(dom_node)); display = CSS::Display(CSS::Display::Outside::Inline, CSS::Display::Inside::Flow); } else if (is(dom_node)) { - layout_node = adopt_ref(*new Layout::BlockContainer(document, &static_cast(dom_node), CSS::ComputedValues {})); + layout_node = document.heap().allocate_without_realm(document, &static_cast(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_node); int child_index = layout_node->parent()->index_of_child(*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(document, layout_node->computed_values().list_style_type(), child_index + 1, *marker_style); static_cast(*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(dom_node)) { @@ -287,7 +287,7 @@ void TreeBuilder::create_layout_tree(DOM::Node& dom_node, TreeBuilder::Context& } } -RefPtr TreeBuilder::build(DOM::Node& dom_node) +JS::GCPtr 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 to_remove; + Vector> to_remove; // Children of a table-column. for_each_in_tree_with_internal_display(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 static void for_each_sequence_of_consecutive_children_matching(NodeWithStyle& parent, Matcher matcher, Callback callback) { - NonnullRefPtrVector sequence; + Vector> 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 -static void wrap_in_anonymous(NonnullRefPtrVector& sequence, Node* nearest_sibling) +static void wrap_in_anonymous(Vector>& 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(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(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 f3b844b2407..0c0c238ad41 100644 --- a/Userland/Libraries/LibWeb/Layout/TreeBuilder.h +++ b/Userland/Libraries/LibWeb/Layout/TreeBuilder.h @@ -17,7 +17,7 @@ class TreeBuilder { public: TreeBuilder(); - RefPtr build(DOM::Node&); + JS::GCPtr 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 m_layout_root; + JS::GCPtr m_layout_root; Vector m_ancestor_stack; }; diff --git a/Userland/Libraries/LibWeb/Page/EventHandler.cpp b/Userland/Libraries/LibWeb/Page/EventHandler.cpp index f60d7c624b6..a5ed478ced4 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_root = *document->layout_node(); + JS::NonnullGCPtr 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 34d56620a0c..c9326e047eb 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 34642e5eec0..c7127dff916 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGClipPathElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGClipPathElement.cpp @@ -19,7 +19,7 @@ SVGClipPathElement::~SVGClipPathElement() { } -RefPtr SVGClipPathElement::create_layout_node(NonnullRefPtr) +JS::GCPtr SVGClipPathElement::create_layout_node(NonnullRefPtr) { return nullptr; } diff --git a/Userland/Libraries/LibWeb/SVG/SVGClipPathElement.h b/Userland/Libraries/LibWeb/SVG/SVGClipPathElement.h index 8a76da5aaee..36712c18b44 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 create_layout_node(NonnullRefPtr) override; + virtual JS::GCPtr create_layout_node(NonnullRefPtr) override; private: SVGClipPathElement(DOM::Document&, DOM::QualifiedName); diff --git a/Userland/Libraries/LibWeb/SVG/SVGDefsElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGDefsElement.cpp index 4d4a8dfaa67..86e7d87ff0b 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGDefsElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGDefsElement.cpp @@ -19,7 +19,7 @@ SVGDefsElement::~SVGDefsElement() { } -RefPtr SVGDefsElement::create_layout_node(NonnullRefPtr) +JS::GCPtr SVGDefsElement::create_layout_node(NonnullRefPtr) { return nullptr; } diff --git a/Userland/Libraries/LibWeb/SVG/SVGDefsElement.h b/Userland/Libraries/LibWeb/SVG/SVGDefsElement.h index 68e521b5e9e..ddb2eeb437d 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 create_layout_node(NonnullRefPtr) override; + virtual JS::GCPtr create_layout_node(NonnullRefPtr) override; private: SVGDefsElement(DOM::Document&, DOM::QualifiedName); diff --git a/Userland/Libraries/LibWeb/SVG/SVGGElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGGElement.cpp index 20601ea4a8c..25fdd0beeec 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 SVGGElement::create_layout_node(NonnullRefPtr style) +JS::GCPtr SVGGElement::create_layout_node(NonnullRefPtr style) { - return adopt_ref(*new Layout::SVGGraphicsBox(document(), *this, move(style))); + return heap().allocate_without_realm(document(), *this, move(style)); } } diff --git a/Userland/Libraries/LibWeb/SVG/SVGGElement.h b/Userland/Libraries/LibWeb/SVG/SVGGElement.h index a2609680ca4..825983c2dca 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 create_layout_node(NonnullRefPtr) override; + virtual JS::GCPtr create_layout_node(NonnullRefPtr) override; private: SVGGElement(DOM::Document&, DOM::QualifiedName); diff --git a/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.cpp index 2c56eadce25..974f9667971 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 SVGGeometryElement::create_layout_node(NonnullRefPtr style) +JS::GCPtr SVGGeometryElement::create_layout_node(NonnullRefPtr style) { - return adopt_ref(*new Layout::SVGGeometryBox(document(), *this, move(style))); + return heap().allocate_without_realm(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 70d48b7669e..bf01c92a932 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 create_layout_node(NonnullRefPtr) override; + virtual JS::GCPtr create_layout_node(NonnullRefPtr) override; virtual Gfx::Path& get_path() = 0; diff --git a/Userland/Libraries/LibWeb/SVG/SVGSVGElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGSVGElement.cpp index 640b4d7edcc..24a34d343d6 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 SVGSVGElement::create_layout_node(NonnullRefPtr style) +JS::GCPtr SVGSVGElement::create_layout_node(NonnullRefPtr style) { - return adopt_ref(*new Layout::SVGSVGBox(document(), *this, move(style))); + return heap().allocate_without_realm(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 c3518e09b33..92835066e76 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 create_layout_node(NonnullRefPtr) override; + virtual JS::GCPtr create_layout_node(NonnullRefPtr) 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 1972c4fd050..74d7a94d409 100644 --- a/Userland/Libraries/LibWeb/TreeNode.h +++ b/Userland/Libraries/LibWeb/TreeNode.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2018-2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ @@ -7,54 +7,27 @@ #pragma once #include -#include #include -#include +#include #include namespace Web { template -class TreeNode : public Weakable { +class TreeNode { public: - void ref() - { - VERIFY(!m_in_removed_last_ref); - if constexpr (!IsBaseOf) { - // 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) { - m_in_removed_last_ref = true; - static_cast(this)->removed_last_ref(); - } else { - delete static_cast(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(this)->child_at_index(index); } @@ -90,7 +63,7 @@ public: return index; } - Optional index_of_child(const T& search_child) + Optional index_of_child(T const& search_child) { VERIFY(search_child.parent() == this); size_t index = 0; @@ -106,7 +79,7 @@ public: } template - Optional index_of_child(const T& search_child) + Optional 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 node); - void prepend_child(NonnullRefPtr node); - void insert_before(NonnullRefPtr node, RefPtr child); - void remove_child(NonnullRefPtr node); + void append_child(JS::NonnullGCPtr node); + void prepend_child(JS::NonnullGCPtr node); + void insert_before(JS::NonnullGCPtr node, JS::GCPtr child); + void remove_child(JS::NonnullGCPtr 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 IterationDecision for_each_in_inclusive_subtree(Callback callback) const { - if (callback(static_cast(*this)) == IterationDecision::Break) + if (callback(static_cast(*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 IterationDecision for_each_in_inclusive_subtree_of_type(Callback callback) { - if (is(static_cast(*this))) { + if (is(static_cast(*this))) { if (callback(static_cast(*this)) == IterationDecision::Break) return IterationDecision::Break; } @@ -268,8 +241,8 @@ public: template IterationDecision for_each_in_inclusive_subtree_of_type(Callback callback) const { - if (is(static_cast(*this))) { - if (callback(static_cast(*this)) == IterationDecision::Break) + if (is(static_cast(*this))) { + if (callback(static_cast(*this)) == IterationDecision::Break) return IterationDecision::Break; } for (auto* child = first_child(); child; child = child->next_sibling()) { @@ -348,7 +321,7 @@ public: } template - const U* next_sibling_of_type() const + U const* next_sibling_of_type() const { return const_cast(this)->template next_sibling_of_type(); } @@ -364,7 +337,7 @@ public: } template - const U* previous_sibling_of_type() const + U const* previous_sibling_of_type() const { return const_cast(this)->template previous_sibling_of_type(); } @@ -380,13 +353,13 @@ public: } template - const U* first_child_of_type() const + U const* first_child_of_type() const { return const_cast(this)->template first_child_of_type(); } template - const U* last_child_of_type() const + U const* last_child_of_type() const { return const_cast(this)->template last_child_of_type(); } @@ -418,7 +391,7 @@ public: } template - const U* first_ancestor_of_type() const + U const* first_ancestor_of_type() const { return const_cast(this)->template first_ancestor_of_type(); } @@ -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 -inline void TreeNode::remove_child(NonnullRefPtr node) +inline void TreeNode::remove_child(JS::NonnullGCPtr node) { VERIFY(node->m_parent == this); @@ -488,12 +457,10 @@ inline void TreeNode::remove_child(NonnullRefPtr node) node->m_next_sibling = nullptr; node->m_previous_sibling = nullptr; node->m_parent = nullptr; - - node->unref(); } template -inline void TreeNode::append_child(NonnullRefPtr node) +inline void TreeNode::append_child(JS::NonnullGCPtr node) { VERIFY(!node->m_parent); @@ -507,11 +474,10 @@ inline void TreeNode::append_child(NonnullRefPtr node) m_last_child = node.ptr(); if (!m_first_child) m_first_child = m_last_child; - [[maybe_unused]] auto& rc = node.leak_ref(); } template -inline void TreeNode::insert_before(NonnullRefPtr node, RefPtr child) +inline void TreeNode::insert_before(JS::NonnullGCPtr node, JS::GCPtr child) { if (!child) return append_child(move(node)); @@ -531,11 +497,10 @@ inline void TreeNode::insert_before(NonnullRefPtr node, RefPtr child) child->m_previous_sibling = node; node->m_parent = static_cast(this); - [[maybe_unused]] auto& rc = node.leak_ref(); } template -inline void TreeNode::prepend_child(NonnullRefPtr node) +inline void TreeNode::prepend_child(JS::NonnullGCPtr node) { VERIFY(!node->m_parent); @@ -550,7 +515,6 @@ inline void TreeNode::prepend_child(NonnullRefPtr node) if (!m_last_child) m_last_child = m_first_child; node->inserted_into(static_cast(*this)); - [[maybe_unused]] auto& rc = node.leak_ref(); static_cast(this)->children_changed(); } diff --git a/Userland/Services/WebContent/ConnectionFromClient.cpp b/Userland/Services/WebContent/ConnectionFromClient.cpp index c2dec08eaf5..73846aade67 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.cpp +++ b/Userland/Services/WebContent/ConnectionFromClient.cpp @@ -354,7 +354,7 @@ Messages::WebContentServer::InspectDomNodeResponse ConnectionFromClient::inspect if (pseudo_element.has_value()) { auto pseudo_element_node = element.get_pseudo_element_node(pseudo_element.value()); - if (pseudo_element_node.is_null()) + if (!pseudo_element_node) return { false, "", "", "", "" }; // FIXME: Pseudo-elements only exist as Layout::Nodes, which don't have style information