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