diff --git a/Libraries/LibWeb/CSS/CSSStyleProperties.cpp b/Libraries/LibWeb/CSS/CSSStyleProperties.cpp index 6a18d47624..9665446ee4 100644 --- a/Libraries/LibWeb/CSS/CSSStyleProperties.cpp +++ b/Libraries/LibWeb/CSS/CSSStyleProperties.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -603,6 +604,11 @@ Optional CSSStyleProperties::get_direct_property(PropertyNameAndI layout_node = abstract_element.layout_node(); } + if (auto pseudo_element = abstract_element.pseudo_element(); layout_node && pseudo_element.has_value()) { + if (auto pseudo_style = abstract_element.element().computed_properties(*pseudo_element); pseudo_style && pseudo_style->display().is_contents()) + layout_node = nullptr; + } + // FIXME: Somehow get custom properties if there's no layout node. if (property_name_and_id.is_custom_property()) { if (auto maybe_value = abstract_element.get_custom_property(property_name_and_id.name())) { @@ -642,6 +648,37 @@ Optional CSSStyleProperties::get_direct_property(PropertyNameAndI // ancestor-dependent selectors still match for no `layout_node` // queries (for example `.outer .inner .target`). auto style = abstract_element.document().style_computer().compute_style_with_seeded_ancestors(abstract_element); + if (first_is_one_of(property_id, + PropertyID::BackgroundColor, + PropertyID::BorderBottomColor, + PropertyID::BorderLeftColor, + PropertyID::BorderRightColor, + PropertyID::BorderTopColor, + PropertyID::CaretColor, + PropertyID::Color, + PropertyID::OutlineColor, + PropertyID::TextDecorationColor)) { + auto color_scheme = style->color_scheme(abstract_element.document().page().preferred_color_scheme(), abstract_element.document().supported_color_schemes()); + ColorResolutionContext color_resolution_context { + .color_scheme = color_scheme, + .current_color = CSS::InitialValues::color(), + .calculation_resolution_context = {}, + }; + color_resolution_context.current_color = style->color(PropertyID::Color, color_resolution_context); + auto const& value = style->property(property_id); + Optional color; + if (property_id == PropertyID::CaretColor && value.is_keyword() && value.to_keyword() == Keyword::Auto) + color = style->color(PropertyID::Color, color_resolution_context); + else if (value.has_color()) + color = value.to_color(color_resolution_context).value(); + + if (color.has_value()) { + return StyleProperty { + .property_id = property_id, + .value = ColorStyleValue::create_from_color(*color, ColorSyntax::Modern), + }; + } + } return StyleProperty { .property_id = property_id, .value = style->property(property_id), diff --git a/Libraries/LibWeb/CSS/Interpolation.cpp b/Libraries/LibWeb/CSS/Interpolation.cpp index f21dec1acc..40d8b3cb74 100644 --- a/Libraries/LibWeb/CSS/Interpolation.cpp +++ b/Libraries/LibWeb/CSS/Interpolation.cpp @@ -1426,9 +1426,8 @@ RefPtr interpolate_box_shadow(DOM::Element& element, Calculati // NB: Called during style interpolation. ColorResolutionContext color_resolution_context {}; - if (auto node = element.unsafe_layout_node()) { - color_resolution_context = ColorResolutionContext::for_layout_node_with_style(*element.unsafe_layout_node()); - } + if (auto* node = element.unsafe_layout_node()) + color_resolution_context = ColorResolutionContext::for_layout_node_with_style(*node); for (size_t i = 0; i < from_shadows.size(); i++) { auto const& from_shadow = from_shadows[i]->as_shadow(); @@ -1740,9 +1739,8 @@ static RefPtr interpolate_value_impl(DOM::Element& element, Ca case StyleValue::Type::Color: { // NB: Called during style interpolation. ColorResolutionContext color_resolution_context {}; - if (auto node = element.unsafe_layout_node()) { - color_resolution_context = ColorResolutionContext::for_layout_node_with_style(*element.unsafe_layout_node()); - } + if (auto* node = element.unsafe_layout_node()) + color_resolution_context = ColorResolutionContext::for_layout_node_with_style(*node); if (auto interpolated = interpolate_color(from, to, delta, {}, color_resolution_context)) return interpolated; diff --git a/Libraries/LibWeb/DOM/AbstractElement.cpp b/Libraries/LibWeb/DOM/AbstractElement.cpp index 7e0fced1e2..8d4f07ca03 100644 --- a/Libraries/LibWeb/DOM/AbstractElement.cpp +++ b/Libraries/LibWeb/DOM/AbstractElement.cpp @@ -73,14 +73,14 @@ AbstractElement::TreeCountingFunctionResolutionContext AbstractElement::tree_cou }; } -GC::Ptr AbstractElement::layout_node() +Layout::NodeWithStyle* AbstractElement::layout_node() { if (m_pseudo_element.has_value()) return m_element->pseudo_element_layout_node(*m_pseudo_element); return m_element->layout_node(); } -GC::Ptr AbstractElement::unsafe_layout_node() +Layout::NodeWithStyle* AbstractElement::unsafe_layout_node() { if (m_pseudo_element.has_value()) return m_element->pseudo_element_unsafe_layout_node(*m_pseudo_element); @@ -110,7 +110,7 @@ Optional AbstractElement::element_to_inherit_style_from() const Optional AbstractElement::walk_layout_tree(WalkMethod walk_method) { // NB: Called during style recalculation. - GC::Ptr node = unsafe_layout_node(); + Layout::Node* node = unsafe_layout_node(); if (!node) return OptionalNone {}; diff --git a/Libraries/LibWeb/DOM/AbstractElement.h b/Libraries/LibWeb/DOM/AbstractElement.h index 74902ed962..eb3d0a862a 100644 --- a/Libraries/LibWeb/DOM/AbstractElement.h +++ b/Libraries/LibWeb/DOM/AbstractElement.h @@ -26,11 +26,11 @@ public: Element const& element() const { return m_element; } Optional pseudo_element() const { return m_pseudo_element; } - GC::Ptr layout_node(); - GC::Ptr layout_node() const { return const_cast(this)->layout_node(); } + Layout::NodeWithStyle* layout_node(); + Layout::NodeWithStyle const* layout_node() const { return const_cast(this)->layout_node(); } - GC::Ptr unsafe_layout_node(); - GC::Ptr unsafe_layout_node() const { return const_cast(this)->unsafe_layout_node(); } + Layout::NodeWithStyle* unsafe_layout_node(); + Layout::NodeWithStyle const* unsafe_layout_node() const { return const_cast(this)->unsafe_layout_node(); } struct TreeCountingFunctionResolutionContext { size_t sibling_count; diff --git a/Libraries/LibWeb/DOM/Document.cpp b/Libraries/LibWeb/DOM/Document.cpp index 86d3cb1a10..48b9bf7607 100644 --- a/Libraries/LibWeb/DOM/Document.cpp +++ b/Libraries/LibWeb/DOM/Document.cpp @@ -672,7 +672,6 @@ void Document::visit_edges(Cell::Visitor& visitor) visitor.visit(m_pending_css_import_rules); visitor.visit(m_page); visitor.visit(m_window); - visitor.visit(m_layout_root); visitor.visit(m_style_sheets); visitor.visit(m_hovered_node); visitor.visit(m_inspected_node); @@ -725,7 +724,6 @@ void Document::visit_edges(Cell::Visitor& visitor) for (auto& resize_observer : m_resize_observers) visitor.visit(resize_observer); - visitor.visit(m_svg_roots_needing_relayout); visitor.visit(m_query_containers_needing_container_query_evaluation_after_layout); visitor.visit(m_shared_resource_requests); @@ -1353,6 +1351,7 @@ void Document::tear_down_layout_tree() { if (m_layout_root) m_layout_root->prepare_subtree_for_detach_from_layout_tree(); + m_hit_test_display_list = nullptr; m_layout_root = nullptr; m_paintable = nullptr; m_needs_full_layout_tree_update = true; @@ -1634,7 +1633,7 @@ void Document::invalidate_layout_tree(InvalidateLayoutTreeReason reason) void Document::mark_svg_root_as_needing_relayout(Layout::SVGSVGBox& svg_root) { - m_svg_roots_needing_relayout.set(svg_root); + m_svg_roots_needing_relayout.set(svg_root.make_weak_ptr()); } void Document::set_needs_container_query_evaluation_after_layout(Element const& query_container) @@ -1799,8 +1798,10 @@ void Document::update_layout(UpdateLayoutReason reason) // Partial SVG relayout if (!needs_layout_tree_rebuild && !svg_roots_to_relayout.is_empty() && !m_layout_root->needs_layout_update()) { - for (auto const& svg_root : svg_roots_to_relayout) - relayout_svg_root(*svg_root); + for (auto const& svg_root : svg_roots_to_relayout) { + if (svg_root) + relayout_svg_root(*svg_root); + } invalidate_stacking_context_tree(); set_needs_to_record_display_list(); @@ -2761,7 +2762,7 @@ void Document::clear_grid_highlighted_node(GC::Ptr node) node->set_needs_repaint(); } -GC::Ptr Document::highlighted_layout_node() +Layout::Node* Document::highlighted_layout_node() { if (!m_highlighted_node) return nullptr; @@ -7919,16 +7920,18 @@ Vector> Document::find_matching_text(String const& query, CaseSe match_start_position = &text_block.positions[i + 1]; auto start_position = match_index.value() - match_start_position->start_offset + match_start_position->dom_offset_within_node; - auto& start_dom_node = match_start_position->dom_node; + auto start_dom_node = match_start_position->dom_node.ptr(); + VERIFY(start_dom_node); auto* match_end_position = match_start_position; for (; i < text_block.positions.size() - 1 && (match_index.value() + utf16_query.length_in_code_units() > text_block.positions[i + 1].start_offset); ++i) match_end_position = &text_block.positions[i + 1]; - auto& end_dom_node = match_end_position->dom_node; + auto end_dom_node = match_end_position->dom_node.ptr(); + VERIFY(end_dom_node); auto end_position = match_index.value() + utf16_query.length_in_code_units() - match_end_position->start_offset + match_end_position->dom_offset_within_node; - matches.append(Range::create(start_dom_node, start_position, end_dom_node, end_position)); + matches.append(Range::create(*start_dom_node, start_position, *end_dom_node, end_position)); match_start_position = match_end_position; offset = match_index.value() + utf16_query.length_in_code_units() + 1; if (offset >= text_view.length_in_code_units()) diff --git a/Libraries/LibWeb/DOM/Document.h b/Libraries/LibWeb/DOM/Document.h index 028cadc37a..f40a8cf339 100644 --- a/Libraries/LibWeb/DOM/Document.h +++ b/Libraries/LibWeb/DOM/Document.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -316,8 +317,8 @@ public: void set_highlighted_node(GC::Ptr, Optional); GC::Ptr highlighted_node() const { return m_highlighted_node; } - GC::Ptr highlighted_layout_node(); - GC::Ptr highlighted_layout_node() const { return const_cast(this)->highlighted_layout_node(); } + Layout::Node* highlighted_layout_node(); + Layout::Node const* highlighted_layout_node() const { return const_cast(this)->highlighted_layout_node(); } void set_flexbox_highlighted_node(GC::Ptr, Painting::FlexboxInspectorOverlayOptions); void clear_flexbox_highlighted_node(GC::Ptr); void set_grid_highlighted_node(GC::Ptr, Painting::GridInspectorOverlayOptions); @@ -1221,7 +1222,7 @@ private: GC::Ptr m_window; - GC::Ptr m_layout_root; + RefPtr m_layout_root; GC::Ptr m_hovered_node; GC::Ptr m_inspected_node; @@ -1360,7 +1361,7 @@ private: bool m_is_running_update_layout { false }; - HashTable> m_svg_roots_needing_relayout; + HashTable> m_svg_roots_needing_relayout; bool m_needs_animated_style_update { false }; diff --git a/Libraries/LibWeb/DOM/Element.cpp b/Libraries/LibWeb/DOM/Element.cpp index 58ce735ae6..baeeaa9b13 100644 --- a/Libraries/LibWeb/DOM/Element.cpp +++ b/Libraries/LibWeb/DOM/Element.cpp @@ -806,7 +806,7 @@ Optional>> Element::get_the_attribute_assoc return elements; } -GC::Ptr Element::create_layout_node(CSS::ComputedProperties const& style) +RefPtr Element::create_layout_node(CSS::ComputedProperties const& style) { if (local_name() == "noscript" && document().is_scripting_enabled()) return nullptr; @@ -815,23 +815,26 @@ GC::Ptr Element::create_layout_node(CSS::ComputedProperties const& return create_layout_node_for_display_type(document(), display, style, this); } -GC::Ptr Element::create_layout_node_for_display_type(DOM::Document& document, CSS::Display const& display, CSS::ComputedProperties const& style, Element* element) +RefPtr Element::create_layout_node_for_display_type(DOM::Document& document, CSS::Display const& display, CSS::ComputedProperties const& style, Element* element) { if (display.is_none()) return {}; + if (display.is_contents()) + return {}; + if (display.is_table_inside() || display.is_table_row_group() || display.is_table_header_group() || display.is_table_footer_group() || display.is_table_row()) - return document.heap().allocate(document, element, style); + return make_ref_counted(document, element, style); if (display.is_list_item()) - return document.heap().allocate(document, element, style); + return make_ref_counted(document, element, style); if (display.is_table_cell()) - return document.heap().allocate(document, element, style); + return make_ref_counted(document, element, 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 document.heap().allocate(document, element, style); + return make_ref_counted(document, element, style); } if (display.is_math_inside()) { @@ -839,35 +842,35 @@ GC::Ptr Element::create_layout_node_for_display_type(DOM: // MathML elements with a computed display value equal to block math or inline math control box generation // and layout according to their tag name, as described in the relevant sections. // FIXME: Figure out what kind of node we should make for them. For now, we'll stick with a generic Box. - return document.heap().allocate(document, element, style); + return make_ref_counted(document, element, style); } if (display.is_inline_outside()) { if (display.is_flow_root_inside()) - return document.heap().allocate(document, element, style); + return make_ref_counted(document, element, style); if (display.is_flow_inside()) - return document.heap().allocate(document, element, style); + return make_ref_counted(document, element, style); if (display.is_flex_inside()) - return document.heap().allocate(document, element, style); + return make_ref_counted(document, element, style); if (display.is_grid_inside()) - return document.heap().allocate(document, element, style); + return make_ref_counted(document, element, style); dbgln_if(LIBWEB_CSS_DEBUG, "FIXME: Support display: {}", display.to_string()); - return document.heap().allocate(document, element, style); + return make_ref_counted(document, element, style); } if (display.is_flex_inside() || display.is_grid_inside()) - return document.heap().allocate(document, element, style); + return make_ref_counted(document, element, style); - if (display.is_flow_inside() || display.is_flow_root_inside() || display.is_contents()) - return document.heap().allocate(document, element, style); + if (display.is_flow_inside() || display.is_flow_root_inside()) + return make_ref_counted(document, element, style); dbgln("FIXME: CSS display '{}' not implemented yet.", display.to_string()); // FIXME: We don't actually support `display: block ruby`, this is just a hack to prevent a crash if (display.is_ruby_inside()) - return document.heap().allocate(document, element, style); + return make_ref_counted(document, element, style); - return document.heap().allocate(document, element, style); + return make_ref_counted(document, element, style); } void Element::apply_presentational_hints(Vector& properties) const @@ -1844,7 +1847,7 @@ void Element::children_changed(ChildrenChangedMetadata const& metadata) } } -void Element::set_synthetic_pseudo_element_node(Badge, CSS::PseudoElement pseudo_element, GC::Ptr pseudo_element_node) +void Element::set_synthetic_pseudo_element_node(Badge, CSS::PseudoElement pseudo_element, Layout::NodeWithStyle* pseudo_element_node) { auto existing_pseudo_element = get_synthetic_pseudo_element(pseudo_element); if (!existing_pseudo_element.has_value() && !pseudo_element_node) @@ -1857,14 +1860,14 @@ void Element::set_synthetic_pseudo_element_node(Badge, CSS: ensure_synthetic_pseudo_element(pseudo_element).set_layout_node(move(pseudo_element_node)); } -GC::Ptr Element::pseudo_element_layout_node(CSS::PseudoElement pseudo_element) const +Layout::NodeWithStyle* Element::pseudo_element_layout_node(CSS::PseudoElement pseudo_element) const { if (auto element_data = get_pseudo_element(pseudo_element); element_data.has_value()) return element_data->layout_node(); return nullptr; } -GC::Ptr Element::pseudo_element_unsafe_layout_node(CSS::PseudoElement pseudo_element) const +Layout::NodeWithStyle* Element::pseudo_element_unsafe_layout_node(CSS::PseudoElement pseudo_element) const { if (auto element_data = get_pseudo_element(pseudo_element); element_data.has_value()) return element_data->unsafe_layout_node(); @@ -2041,6 +2044,8 @@ void Element::clear_synthetic_pseudo_element_layout_nodes() return TraversalDecision::Continue; }); layout_node->prepare_subtree_for_detach_from_layout_tree(); + if (layout_node->parent()) + layout_node->remove(); } pseudo_element.set_layout_node(nullptr); }); @@ -3607,22 +3612,22 @@ void Element::for_each_attribute(Function }); } -GC::Ptr Element::layout_node() +Layout::NodeWithStyle* Element::layout_node() { return static_cast(Node::layout_node()); } -GC::Ptr Element::layout_node() const +Layout::NodeWithStyle const* Element::layout_node() const { return static_cast(Node::layout_node()); } -GC::Ptr Element::unsafe_layout_node() +Layout::NodeWithStyle* Element::unsafe_layout_node() { return static_cast(Node::unsafe_layout_node()); } -GC::Ptr Element::unsafe_layout_node() const +Layout::NodeWithStyle const* Element::unsafe_layout_node() const { return static_cast(Node::unsafe_layout_node()); } diff --git a/Libraries/LibWeb/DOM/Element.h b/Libraries/LibWeb/DOM/Element.h index fbf7b5e7bd..aa20d32772 100644 --- a/Libraries/LibWeb/DOM/Element.h +++ b/Libraries/LibWeb/DOM/Element.h @@ -202,11 +202,11 @@ public: Optional associated_shadow_host_pseudo_element() const { return m_associated_shadow_host_pseudo_element; } void set_associated_shadow_host_pseudo_element(CSS::PseudoElement pseudo_element); - GC::Ptr layout_node(); - GC::Ptr layout_node() const; + Layout::NodeWithStyle* layout_node(); + Layout::NodeWithStyle const* layout_node() const; - GC::Ptr unsafe_layout_node(); - GC::Ptr unsafe_layout_node() const; + Layout::NodeWithStyle* unsafe_layout_node(); + Layout::NodeWithStyle const* unsafe_layout_node() const; RefPtr computed_properties(Optional = {}); RefPtr computed_properties(Optional = {}) const; @@ -361,7 +361,7 @@ public: [[nodiscard]] Vector client_rects_assuming_layout_clean() const; [[nodiscard]] CSSPixelRect bounding_client_rect_assuming_layout_clean() const; - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&); + virtual RefPtr create_layout_node(CSS::ComputedProperties const&); virtual void adjust_computed_style(CSS::ComputedProperties&) { } virtual void did_receive_focus() { } @@ -369,7 +369,7 @@ public: bool should_indicate_focus() const; virtual bool is_focusable() const override; - static GC::Ptr create_layout_node_for_display_type(DOM::Document&, CSS::Display const&, CSS::ComputedProperties const&, Element*); + static RefPtr create_layout_node_for_display_type(DOM::Document&, CSS::Display const&, CSS::ComputedProperties const&, Element*); void clear_removed_attributes_for_style_invalidation() { m_removed_attributes_for_style_invalidation.clear(); } bool has_removed_attribute_for_style_invalidation(FlyString const& attribute_name) const @@ -382,10 +382,10 @@ public: m_removed_attributes_for_style_invalidation.append(attribute_name); } - void set_synthetic_pseudo_element_node(Badge, CSS::PseudoElement, GC::Ptr); + void set_synthetic_pseudo_element_node(Badge, CSS::PseudoElement, Layout::NodeWithStyle*); - GC::Ptr pseudo_element_layout_node(CSS::PseudoElement) const; - GC::Ptr pseudo_element_unsafe_layout_node(CSS::PseudoElement) const; + Layout::NodeWithStyle* pseudo_element_layout_node(CSS::PseudoElement) const; + Layout::NodeWithStyle* pseudo_element_unsafe_layout_node(CSS::PseudoElement) const; bool has_synthetic_pseudo_elements() const; template T> diff --git a/Libraries/LibWeb/DOM/Node.cpp b/Libraries/LibWeb/DOM/Node.cpp index bc1af2db1e..e5ac7f714a 100644 --- a/Libraries/LibWeb/DOM/Node.cpp +++ b/Libraries/LibWeb/DOM/Node.cpp @@ -137,7 +137,6 @@ void Node::visit_edges(Cell::Visitor& visitor) visitor.visit(m_document); visitor.visit(m_child_nodes); - visitor.visit(m_layout_node); if (m_registered_observer_list) { visitor.visit(*m_registered_observer_list); } @@ -750,7 +749,7 @@ void Node::insert_before(GC::Ref node, GC::Ptr child, bool suppress_ if (is_connected()) { // NB: Called during DOM insertion, layout is not up to date. - if (unsafe_layout_node() && unsafe_layout_node()->display().is_contents() && parent_element()) { + if (auto* element = as_if(*this); element && element->computed_properties() && element->computed_properties()->display().is_contents() && parent_element()) { parent_element()->set_needs_layout_tree_update(true, SetNeedsLayoutTreeUpdateReason::NodeInsertBeforeWithDisplayContents); } set_needs_layout_tree_update(true, SetNeedsLayoutTreeUpdateReason::NodeInsertBefore); @@ -1673,7 +1672,7 @@ GC::Ptr Node::editing_host() return {}; } -void Node::set_layout_node(Badge, GC::Ref layout_node) +void Node::set_layout_node(Badge, Layout::Node& layout_node) { m_layout_node = layout_node; } @@ -1758,7 +1757,7 @@ void Node::set_needs_layout_tree_update(bool value, SetNeedsLayoutTreeUpdateReas // If the layout node has an anonymous parent, rebuild from the nearest non-anonymous ancestor. // FIXME: This is not optimal, and we should figure out how to rebuild a smaller part of the tree. if (layout_node->parent() && layout_node->parent()->is_anonymous()) { - GC::Ptr ancestor = layout_node->parent(); + auto* ancestor = layout_node->parent(); while (ancestor && ancestor->is_anonymous()) ancestor = ancestor->parent(); if (ancestor) diff --git a/Libraries/LibWeb/DOM/Node.h b/Libraries/LibWeb/DOM/Node.h index fda4135ee4..d5a542c57e 100644 --- a/Libraries/LibWeb/DOM/Node.h +++ b/Libraries/LibWeb/DOM/Node.h @@ -328,8 +328,8 @@ public: Layout::Node const* layout_node() const; Layout::Node* layout_node(); - Layout::Node const* unsafe_layout_node() const { return m_layout_node; } - Layout::Node* unsafe_layout_node() { return m_layout_node; } + Layout::Node const* unsafe_layout_node() const { return m_layout_node.ptr(); } + Layout::Node* unsafe_layout_node() { return m_layout_node.ptr(); } RefPtr paintable_box() const; RefPtr paintable_box(); @@ -348,7 +348,7 @@ public: void set_needs_layout_update(SetNeedsLayoutReason); void clear_layout_node_and_paintable(Badge); - void set_layout_node(Badge, GC::Ref); + void set_layout_node(Badge, Layout::Node&); void detach_layout_node(Badge); virtual bool is_child_allowed(Node const&) const { return true; } @@ -507,7 +507,7 @@ protected: virtual size_t external_memory_size() const override; GC::Ptr m_document; - GC::Ptr m_layout_node; + WeakPtr m_layout_node; WeakPtr m_paintable; NodeType m_type { NodeType::INVALID }; bool m_needs_layout_tree_update { false }; diff --git a/Libraries/LibWeb/DOM/PseudoElement.cpp b/Libraries/LibWeb/DOM/PseudoElement.cpp index 6601b16518..034f8e9c35 100644 --- a/Libraries/LibWeb/DOM/PseudoElement.cpp +++ b/Libraries/LibWeb/DOM/PseudoElement.cpp @@ -20,11 +20,15 @@ void SyntheticPseudoElement::visit_edges(JS::Cell::Visitor& visitor) { Base::visit_edges(visitor); - visitor.visit(m_layout_node); if (m_counters_set) m_counters_set->visit_edges(visitor); } +void SyntheticPseudoElement::set_layout_node(Layout::NodeWithStyle* value) +{ + m_layout_node = value; +} + Optional SyntheticPseudoElement::counters_set() const { if (!m_counters_set) @@ -50,12 +54,12 @@ void SyntheticPseudoElementTreeNode::visit_edges(JS::Cell::Visitor& visitor) TreeNode::visit_edges(visitor); } -GC::Ptr ElementReferencePseudoElement::layout_node() const +Layout::NodeWithStyle* ElementReferencePseudoElement::layout_node() const { return m_referenced_element->layout_node(); } -GC::Ptr ElementReferencePseudoElement::unsafe_layout_node() const +Layout::NodeWithStyle* ElementReferencePseudoElement::unsafe_layout_node() const { return m_referenced_element->unsafe_layout_node(); } diff --git a/Libraries/LibWeb/DOM/PseudoElement.h b/Libraries/LibWeb/DOM/PseudoElement.h index 74bfff066d..cead1b390f 100644 --- a/Libraries/LibWeb/DOM/PseudoElement.h +++ b/Libraries/LibWeb/DOM/PseudoElement.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include #include @@ -23,8 +24,8 @@ class WEB_API PseudoElement : public JS::Cell { GC_DECLARE_ALLOCATOR(PseudoElement); public: - virtual GC::Ptr layout_node() const = 0; - virtual GC::Ptr unsafe_layout_node() const = 0; + virtual Layout::NodeWithStyle* layout_node() const = 0; + virtual Layout::NodeWithStyle* unsafe_layout_node() const = 0; virtual RefPtr computed_properties() const = 0; @@ -36,9 +37,9 @@ class WEB_API SyntheticPseudoElement : public PseudoElement { GC_CELL(SyntheticPseudoElement, PseudoElement); GC_DECLARE_ALLOCATOR(SyntheticPseudoElement); - GC::Ptr layout_node() const override { return m_layout_node; } - GC::Ptr unsafe_layout_node() const override { return m_layout_node; } - void set_layout_node(GC::Ptr value) { m_layout_node = value; } + Layout::NodeWithStyle* layout_node() const override { return m_layout_node.ptr(); } + Layout::NodeWithStyle* unsafe_layout_node() const override { return m_layout_node.ptr(); } + void set_layout_node(Layout::NodeWithStyle*); RefPtr computed_properties() const override { return m_computed_properties; } void set_computed_properties(RefPtr value) { m_computed_properties = value; } @@ -57,7 +58,7 @@ class WEB_API SyntheticPseudoElement : public PseudoElement { virtual void visit_edges(JS::Cell::Visitor&) override; private: - GC::Ptr m_layout_node; + WeakPtr m_layout_node; RefPtr m_computed_properties; RefPtr m_custom_property_data; OwnPtr m_counters_set; @@ -84,8 +85,8 @@ class WEB_API ElementReferencePseudoElement : public PseudoElement { { } - GC::Ptr layout_node() const override; - GC::Ptr unsafe_layout_node() const override; + Layout::NodeWithStyle* layout_node() const override; + Layout::NodeWithStyle* unsafe_layout_node() const override; RefPtr computed_properties() const override; diff --git a/Libraries/LibWeb/HTML/HTMLAudioElement.cpp b/Libraries/LibWeb/HTML/HTMLAudioElement.cpp index 46f512433d..ae34d9a3cd 100644 --- a/Libraries/LibWeb/HTML/HTMLAudioElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLAudioElement.cpp @@ -37,9 +37,9 @@ void HTMLAudioElement::adjust_computed_style(CSS::ComputedProperties& style) style.set_property(CSS::PropertyID::Display, CSS::DisplayStyleValue::create(CSS::Display::from_short(CSS::Display::Short::None))); } -GC::Ptr HTMLAudioElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr HTMLAudioElement::create_layout_node(CSS::ComputedProperties const& style) { - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); } Layout::AudioBox* HTMLAudioElement::layout_node() diff --git a/Libraries/LibWeb/HTML/HTMLAudioElement.h b/Libraries/LibWeb/HTML/HTMLAudioElement.h index 068491852b..24eacd25e3 100644 --- a/Libraries/LibWeb/HTML/HTMLAudioElement.h +++ b/Libraries/LibWeb/HTML/HTMLAudioElement.h @@ -29,7 +29,7 @@ private: virtual void initialize(JS::Realm&) override; - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; }; } diff --git a/Libraries/LibWeb/HTML/HTMLBRElement.cpp b/Libraries/LibWeb/HTML/HTMLBRElement.cpp index fcf2790885..561f86950b 100644 --- a/Libraries/LibWeb/HTML/HTMLBRElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLBRElement.cpp @@ -29,9 +29,9 @@ void HTMLBRElement::initialize(JS::Realm& realm) Base::initialize(realm); } -GC::Ptr HTMLBRElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr HTMLBRElement::create_layout_node(CSS::ComputedProperties const& style) { - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); } bool HTMLBRElement::is_presentational_hint(FlyString const& name) const diff --git a/Libraries/LibWeb/HTML/HTMLBRElement.h b/Libraries/LibWeb/HTML/HTMLBRElement.h index 320a4e8e74..6c15a40c21 100644 --- a/Libraries/LibWeb/HTML/HTMLBRElement.h +++ b/Libraries/LibWeb/HTML/HTMLBRElement.h @@ -17,7 +17,7 @@ class HTMLBRElement final : public HTMLElement { public: virtual ~HTMLBRElement() override; - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(Vector&) const override; virtual void adjust_computed_style(CSS::ComputedProperties&) override; diff --git a/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp b/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp index 7a2cd44351..46f010046a 100644 --- a/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp @@ -239,9 +239,9 @@ void HTMLCanvasElement::attribute_changed(FlyString const& local_name, Optional< } } -GC::Ptr HTMLCanvasElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr HTMLCanvasElement::create_layout_node(CSS::ComputedProperties const& style) { - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); } void HTMLCanvasElement::adjust_computed_style(CSS::ComputedProperties& style) diff --git a/Libraries/LibWeb/HTML/HTMLCanvasElement.h b/Libraries/LibWeb/HTML/HTMLCanvasElement.h index f218ae8825..f01abd52af 100644 --- a/Libraries/LibWeb/HTML/HTMLCanvasElement.h +++ b/Libraries/LibWeb/HTML/HTMLCanvasElement.h @@ -68,7 +68,7 @@ private: virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(Vector&) const override; - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; virtual void adjust_computed_style(CSS::ComputedProperties&) override; template diff --git a/Libraries/LibWeb/HTML/HTMLFieldSetElement.cpp b/Libraries/LibWeb/HTML/HTMLFieldSetElement.cpp index 5baae27bf9..bdda6107cf 100644 --- a/Libraries/LibWeb/HTML/HTMLFieldSetElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLFieldSetElement.cpp @@ -92,9 +92,9 @@ Layout::FieldSetBox* HTMLFieldSetElement::layout_node() return static_cast(Node::layout_node()); } -GC::Ptr HTMLFieldSetElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr HTMLFieldSetElement::create_layout_node(CSS::ComputedProperties const& style) { - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); } } diff --git a/Libraries/LibWeb/HTML/HTMLFieldSetElement.h b/Libraries/LibWeb/HTML/HTMLFieldSetElement.h index dbb6e0949a..e3bbbc67a3 100644 --- a/Libraries/LibWeb/HTML/HTMLFieldSetElement.h +++ b/Libraries/LibWeb/HTML/HTMLFieldSetElement.h @@ -42,7 +42,7 @@ public: virtual Optional default_role() const override { return ARIA::Role::group; } - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; Layout::FieldSetBox* layout_node(); Layout::FieldSetBox const* layout_node() const; diff --git a/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp b/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp index 2071998000..75005c89f5 100644 --- a/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp @@ -40,9 +40,9 @@ void HTMLIFrameElement::initialize(JS::Realm& realm) Base::initialize(realm); } -GC::Ptr HTMLIFrameElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr HTMLIFrameElement::create_layout_node(CSS::ComputedProperties const& style) { - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); } void HTMLIFrameElement::adjust_computed_style(CSS::ComputedProperties& style) diff --git a/Libraries/LibWeb/HTML/HTMLIFrameElement.h b/Libraries/LibWeb/HTML/HTMLIFrameElement.h index 6eb40f80f0..734548537d 100644 --- a/Libraries/LibWeb/HTML/HTMLIFrameElement.h +++ b/Libraries/LibWeb/HTML/HTMLIFrameElement.h @@ -23,7 +23,7 @@ class HTMLIFrameElement final public: virtual ~HTMLIFrameElement() override; - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; virtual void adjust_computed_style(CSS::ComputedProperties&) override; // ^EventTarget diff --git a/Libraries/LibWeb/HTML/HTMLImageElement.cpp b/Libraries/LibWeb/HTML/HTMLImageElement.cpp index ff681e59e3..cd4e380b5a 100644 --- a/Libraries/LibWeb/HTML/HTMLImageElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLImageElement.cpp @@ -133,7 +133,7 @@ static void reset_intrinsic_size_caches_after_image_data_change(Layout::ImageBox static void set_needs_layout_update_or_repaint_after_image_data_change(HTMLImageElement& image_element, DOM::SetNeedsLayoutReason reason) { auto layout_node = image_element.unsafe_layout_node(); - auto* image_box = as_if(layout_node.ptr()); + auto* image_box = as_if(layout_node); if (!image_box || image_element_dimensions_may_depend_on_intrinsic_size(*image_box)) { image_element.set_needs_layout_update(reason); return; @@ -207,7 +207,6 @@ void HTMLImageElement::adopted_from(DOM::Document& old_document) void HTMLImageElement::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); - image_provider_visit_edges(visitor); visitor.visit(m_current_request); visitor.visit(m_pending_request); visitor.visit(m_document_observer); @@ -296,9 +295,9 @@ void HTMLImageElement::form_associated_element_attribute_changed(FlyString const } } -GC::Ptr HTMLImageElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr HTMLImageElement::create_layout_node(CSS::ComputedProperties const& style) { - return heap().allocate(document(), *this, style, *this); + return make_ref_counted(document(), *this, style, *this); } void HTMLImageElement::adjust_computed_style(CSS::ComputedProperties& style) diff --git a/Libraries/LibWeb/HTML/HTMLImageElement.h b/Libraries/LibWeb/HTML/HTMLImageElement.h index 33beef8a6a..8164533a07 100644 --- a/Libraries/LibWeb/HTML/HTMLImageElement.h +++ b/Libraries/LibWeb/HTML/HTMLImageElement.h @@ -136,7 +136,7 @@ private: // https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element:dimension-attributes virtual bool supports_dimension_attributes() const override { return true; } - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; virtual void adjust_computed_style(CSS::ComputedProperties&) override; virtual void did_set_viewport_rect(CSSPixelRect const&) override; diff --git a/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Libraries/LibWeb/HTML/HTMLInputElement.cpp index 979c3b9c4b..7a638def5f 100644 --- a/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -107,7 +107,6 @@ void HTMLInputElement::initialize(JS::Realm& realm) void HTMLInputElement::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); - image_provider_visit_edges(visitor); visitor.visit(m_inner_text_element); visitor.visit(m_text_node); visitor.visit(m_placeholder_element); @@ -132,7 +131,7 @@ void HTMLInputElement::set_being_activated(bool activated) set_needs_repaint(); } -GC::Ptr HTMLInputElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr HTMLInputElement::create_layout_node(CSS::ComputedProperties const& style) { if (type_state() == TypeAttributeState::Hidden) return nullptr; @@ -140,7 +139,7 @@ GC::Ptr HTMLInputElement::create_layout_node(CSS::ComputedProperti // NOTE: Image inputs are `appearance: none` per the default UA style, // but we still need to create an ImageBox for them, or no image will get loaded. if (type_state() == TypeAttributeState::ImageButton) { - return heap().allocate(document(), *this, style, *this); + return make_ref_counted(document(), *this, style, *this); } // https://drafts.csswg.org/css-ui/#appearance-switching @@ -156,18 +155,18 @@ GC::Ptr HTMLInputElement::create_layout_node(CSS::ComputedProperti case TypeAttributeState::SubmitButton: case TypeAttributeState::Button: case TypeAttributeState::ResetButton: - return heap().allocate(document(), this, style); + return make_ref_counted(document(), this, style); case TypeAttributeState::Checkbox: - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); case TypeAttributeState::RadioButton: - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); case TypeAttributeState::Range: - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); case TypeAttributeState::Color: case TypeAttributeState::FileUpload: return Element::create_layout_node_for_display_type(document(), style.display(), style, this); default: - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); } } diff --git a/Libraries/LibWeb/HTML/HTMLInputElement.h b/Libraries/LibWeb/HTML/HTMLInputElement.h index b9bef873d5..9a31823a19 100644 --- a/Libraries/LibWeb/HTML/HTMLInputElement.h +++ b/Libraries/LibWeb/HTML/HTMLInputElement.h @@ -64,7 +64,7 @@ class WEB_API HTMLInputElement final public: virtual ~HTMLInputElement() override; - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; virtual void adjust_computed_style(CSS::ComputedProperties&) override; virtual void set_being_activated(bool) override; diff --git a/Libraries/LibWeb/HTML/HTMLLegendElement.cpp b/Libraries/LibWeb/HTML/HTMLLegendElement.cpp index f3c35fa092..9a4cf012c0 100644 --- a/Libraries/LibWeb/HTML/HTMLLegendElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLLegendElement.cpp @@ -40,9 +40,9 @@ HTMLFormElement* HTMLLegendElement::form() return nullptr; } -GC::Ptr HTMLLegendElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr HTMLLegendElement::create_layout_node(CSS::ComputedProperties const& style) { - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); } Layout::LegendBox* HTMLLegendElement::layout_node() diff --git a/Libraries/LibWeb/HTML/HTMLLegendElement.h b/Libraries/LibWeb/HTML/HTMLLegendElement.h index 0b3ff6baf8..b1f0ee8ae6 100644 --- a/Libraries/LibWeb/HTML/HTMLLegendElement.h +++ b/Libraries/LibWeb/HTML/HTMLLegendElement.h @@ -20,7 +20,7 @@ public: HTMLFormElement* form(); - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; Layout::LegendBox* layout_node(); Layout::LegendBox const* layout_node() const; diff --git a/Libraries/LibWeb/HTML/HTMLObjectElement.cpp b/Libraries/LibWeb/HTML/HTMLObjectElement.cpp index e71f7171f4..7e7a76f8e5 100644 --- a/Libraries/LibWeb/HTML/HTMLObjectElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLObjectElement.cpp @@ -80,7 +80,6 @@ void HTMLObjectElement::initialize(JS::Realm& realm) void HTMLObjectElement::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); - image_provider_visit_edges(visitor); visitor.visit(m_resource_request); visitor.visit(m_document_observer); } @@ -194,16 +193,16 @@ void HTMLObjectElement::set_data(String const& data) set_attribute_value(HTML::AttributeNames::data, data); } -GC::Ptr HTMLObjectElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr HTMLObjectElement::create_layout_node(CSS::ComputedProperties const& style) { switch (m_representation) { case Representation::Children: return NavigableContainer::create_layout_node(style); case Representation::ContentNavigable: - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); case Representation::Image: if (image_data()) - return heap().allocate(document(), *this, style, *this); + return make_ref_counted(document(), *this, style, *this); break; default: break; diff --git a/Libraries/LibWeb/HTML/HTMLObjectElement.h b/Libraries/LibWeb/HTML/HTMLObjectElement.h index eb64c5968b..5ee5fc0437 100644 --- a/Libraries/LibWeb/HTML/HTMLObjectElement.h +++ b/Libraries/LibWeb/HTML/HTMLObjectElement.h @@ -62,7 +62,7 @@ private: virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(Vector&) const override; - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; virtual void adjust_computed_style(CSS::ComputedProperties&) override; bool has_ancestor_media_element_or_object_element_not_showing_fallback_content() const; diff --git a/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp b/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp index 823db1e451..437cb9ba54 100644 --- a/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp @@ -482,9 +482,9 @@ Optional HTMLTextAreaElement::placeholder_value() const return get_attribute_value(HTML::AttributeNames::placeholder); } -GC::Ptr HTMLTextAreaElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr HTMLTextAreaElement::create_layout_node(CSS::ComputedProperties const& style) { - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); } } diff --git a/Libraries/LibWeb/HTML/HTMLTextAreaElement.h b/Libraries/LibWeb/HTML/HTMLTextAreaElement.h index 8c3b5bddd5..7f3b21431a 100644 --- a/Libraries/LibWeb/HTML/HTMLTextAreaElement.h +++ b/Libraries/LibWeb/HTML/HTMLTextAreaElement.h @@ -154,7 +154,7 @@ private: virtual void initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; void set_raw_value(Utf16String); diff --git a/Libraries/LibWeb/HTML/HTMLVideoElement.cpp b/Libraries/LibWeb/HTML/HTMLVideoElement.cpp index e53832e201..6b577b2733 100644 --- a/Libraries/LibWeb/HTML/HTMLVideoElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLVideoElement.cpp @@ -68,9 +68,9 @@ void HTMLVideoElement::attribute_changed(FlyString const& name, Optional } } -GC::Ptr HTMLVideoElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr HTMLVideoElement::create_layout_node(CSS::ComputedProperties const& style) { - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); } Layout::VideoBox* HTMLVideoElement::layout_node() diff --git a/Libraries/LibWeb/HTML/HTMLVideoElement.h b/Libraries/LibWeb/HTML/HTMLVideoElement.h index db69cb9c13..41bc2f9995 100644 --- a/Libraries/LibWeb/HTML/HTMLVideoElement.h +++ b/Libraries/LibWeb/HTML/HTMLVideoElement.h @@ -74,7 +74,7 @@ private: // https://html.spec.whatwg.org/multipage/media.html#the-video-element:dimension-attributes virtual bool supports_dimension_attributes() const override { return true; } - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; WebIDL::ExceptionOr determine_element_poster_frame(Optional const& poster); diff --git a/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.cpp b/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.cpp index 52cc3ef64e..de073c0c49 100644 --- a/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.cpp +++ b/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.cpp @@ -312,7 +312,7 @@ CSSPixelRect IntersectionObserver::root_intersection_rectangle() const document = &intersection_root.get>()->document(); } if (m_document && document->origin().is_same_origin(m_document->origin())) { - if (auto layout_node = intersection_root.visit([&](auto& node) -> GC::Ptr { return node->layout_node(); })) { + if (auto layout_node = intersection_root.visit([&](auto& node) -> Layout::Node* { return node->layout_node(); })) { rect.inflate( m_root_margin[0].to_px(*layout_node, rect.height()), m_root_margin[1].to_px(*layout_node, rect.width()), diff --git a/Libraries/LibWeb/Layout/AudioBox.cpp b/Libraries/LibWeb/Layout/AudioBox.cpp index 6fa69e2e24..c8c09beb70 100644 --- a/Libraries/LibWeb/Layout/AudioBox.cpp +++ b/Libraries/LibWeb/Layout/AudioBox.cpp @@ -10,8 +10,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(AudioBox); - AudioBox::AudioBox(DOM::Document& document, DOM::Element& element, CSS::ComputedProperties const& style) : ReplacedBox(document, element, style) { diff --git a/Libraries/LibWeb/Layout/AudioBox.h b/Libraries/LibWeb/Layout/AudioBox.h index 0fde21a8f7..e2dc5dd5fa 100644 --- a/Libraries/LibWeb/Layout/AudioBox.h +++ b/Libraries/LibWeb/Layout/AudioBox.h @@ -17,6 +17,8 @@ class AudioBox final : public ReplacedBox { GC_DECLARE_ALLOCATOR(AudioBox); public: + AudioBox(DOM::Document&, DOM::Element&, CSS::ComputedProperties const&); + HTML::HTMLAudioElement& dom_node(); HTML::HTMLAudioElement const& dom_node() const; @@ -28,7 +30,6 @@ private: // Treat the audio element as if it was not a replaced element, sizing based on its content. // Thus, it can fit to the shadow DOM controls, instead of having a hardcoded height. virtual bool has_auto_content_box_size() const override { return false; } - AudioBox(DOM::Document&, DOM::Element&, CSS::ComputedProperties const&); }; } diff --git a/Libraries/LibWeb/Layout/BlockContainer.cpp b/Libraries/LibWeb/Layout/BlockContainer.cpp index 777baca131..2b9d99d8ac 100644 --- a/Libraries/LibWeb/Layout/BlockContainer.cpp +++ b/Libraries/LibWeb/Layout/BlockContainer.cpp @@ -9,8 +9,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(BlockContainer); - BlockContainer::BlockContainer(DOM::Document& document, DOM::Node* node, CSS::ComputedProperties const& style) : Box(document, node, style) { diff --git a/Libraries/LibWeb/Layout/BlockContainer.h b/Libraries/LibWeb/Layout/BlockContainer.h index 4738404323..a4a20840c2 100644 --- a/Libraries/LibWeb/Layout/BlockContainer.h +++ b/Libraries/LibWeb/Layout/BlockContainer.h @@ -13,8 +13,7 @@ namespace Web::Layout { // https://www.w3.org/TR/css-display/#block-container class BlockContainer : public Box { - GC_CELL(BlockContainer, Box); - GC_DECLARE_ALLOCATOR(BlockContainer); + LAYOUT_NODE(BlockContainer, Box); public: BlockContainer(DOM::Document&, DOM::Node*, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Libraries/LibWeb/Layout/BlockFormattingContext.cpp index b879618b3e..4188a86b56 100644 --- a/Libraries/LibWeb/Layout/BlockFormattingContext.cpp +++ b/Libraries/LibWeb/Layout/BlockFormattingContext.cpp @@ -773,7 +773,8 @@ void BlockFormattingContext::layout_block_level_box(Box const& box, BlockContain auto static_position_x = CSSPixels(0); auto static_position_y = m_y_offset_of_current_block_container.value(); if (box.display_before_box_type_transformation().is_inline_outside()) { - auto const* sibling = as_if(box.previous_sibling()); + auto sibling_ref = box.previous_sibling(); + auto const* sibling = as_if(sibling_ref.ptr()); if (sibling && sibling->is_anonymous() && sibling->children_are_inline()) { auto const& sibling_state = m_state.get(*sibling); if (auto const& inline_end_static_position_rect = sibling_state.inline_end_static_position_rect(); inline_end_static_position_rect.has_value()) { @@ -1576,7 +1577,7 @@ BlockFormattingContext::SpaceUsedAndContainingMarginForFloats BlockFormattingCon + floating_box.used_values.content_width() + floating_box.used_values.margin_box_right(); space_and_containing_margin.left_total_containing_margin = offset_from_containing_block_chain_margins_between_here_and_root; - space_and_containing_margin.matching_left_float_box = floating_box.box; + space_and_containing_margin.matching_left_float_box = &floating_box.box; break; } } @@ -1593,7 +1594,7 @@ BlockFormattingContext::SpaceUsedAndContainingMarginForFloats BlockFormattingCon space_and_containing_margin.right_used_space = floating_box.offset_from_edge + floating_box.used_values.margin_box_left(); space_and_containing_margin.right_total_containing_margin = offset_from_containing_block_chain_margins_between_here_and_root; - space_and_containing_margin.matching_right_float_box = floating_box.box; + space_and_containing_margin.matching_right_float_box = &floating_box.box; break; } } @@ -1648,7 +1649,7 @@ CSSPixels BlockFormattingContext::greatest_child_width(Box const& box) const CSSPixels extra_width_from_left_floats = 0; for (auto& left_float : m_left_floats.all_boxes) { // NOTE: Floats directly affect the automatic size of their containing block, but only indirectly anything above in the tree. - if (left_float->box->containing_block() != &box) + if (left_float->box.containing_block() != &box) continue; if (line_top < left_float->bottom_margin_edge && line_bottom > left_float->top_margin_edge) { extra_width_from_left_floats = max(extra_width_from_left_floats, left_float->offset_from_edge + left_float->used_values.content_width() + left_float->used_values.margin_box_right()); @@ -1657,7 +1658,7 @@ CSSPixels BlockFormattingContext::greatest_child_width(Box const& box) const CSSPixels extra_width_from_right_floats = 0; for (auto& right_float : m_right_floats.all_boxes) { // NOTE: Floats directly affect the automatic size of their containing block, but only indirectly anything above in the tree. - if (right_float->box->containing_block() != &box) + if (right_float->box.containing_block() != &box) continue; if (line_top < right_float->bottom_margin_edge && line_bottom > right_float->top_margin_edge) { extra_width_from_right_floats = max(extra_width_from_right_floats, right_float->offset_from_edge + right_float->used_values.margin_box_left()); diff --git a/Libraries/LibWeb/Layout/BlockFormattingContext.h b/Libraries/LibWeb/Layout/BlockFormattingContext.h index 8f75fec46d..10fcc21eed 100644 --- a/Libraries/LibWeb/Layout/BlockFormattingContext.h +++ b/Libraries/LibWeb/Layout/BlockFormattingContext.h @@ -77,7 +77,7 @@ public: void reset_margin_state() { m_margin_state.reset(); } struct FloatingBox { - GC::Ref box; + Box const& box; LayoutState::UsedValues& used_values; diff --git a/Libraries/LibWeb/Layout/Box.cpp b/Libraries/LibWeb/Layout/Box.cpp index af52e78ebf..88f4b56ed6 100644 --- a/Libraries/LibWeb/Layout/Box.cpp +++ b/Libraries/LibWeb/Layout/Box.cpp @@ -15,8 +15,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(Box); - Box::Box(DOM::Document& document, DOM::Node* node, CSS::ComputedProperties const& style) : NodeWithStyleAndBoxModelMetrics(document, node, style) { @@ -42,12 +40,6 @@ CSS::SizeWithAspectRatio Box::auto_content_box_size() const return compute_auto_content_box_size(); } -void Box::visit_edges(Cell::Visitor& visitor) -{ - Base::visit_edges(visitor); - visitor.visit(m_contained_abspos_children); -} - RefPtr Box::create_paintable() const { return Painting::PaintableBox::create(*this); diff --git a/Libraries/LibWeb/Layout/Box.h b/Libraries/LibWeb/Layout/Box.h index 98add8ea49..92f36fca8b 100644 --- a/Libraries/LibWeb/Layout/Box.h +++ b/Libraries/LibWeb/Layout/Box.h @@ -55,11 +55,9 @@ public: virtual RefPtr create_paintable() const override; - void add_contained_abspos_child(GC::Ref child) { m_contained_abspos_children.append(child); } + void add_contained_abspos_child(Node& child) { m_contained_abspos_children.append(child.make_weak_ptr()); } void clear_contained_abspos_children() { m_contained_abspos_children.clear(); } - Vector> const& contained_abspos_children() const { return m_contained_abspos_children; } - - virtual void visit_edges(Cell::Visitor&) override; + Vector> const& contained_abspos_children() const { return m_contained_abspos_children; } IntrinsicSizes& cached_intrinsic_sizes() const { @@ -69,15 +67,16 @@ public: } void reset_cached_intrinsic_sizes() const { m_cached_intrinsic_sizes.clear(); } -protected: Box(DOM::Document&, DOM::Node*, CSS::ComputedProperties const&); Box(DOM::Document&, DOM::Node*, NonnullOwnPtr); + +protected: virtual CSS::SizeWithAspectRatio compute_auto_content_box_size() const { return natural_size(); } private: virtual bool is_box() const final { return true; } - Vector> m_contained_abspos_children; + Vector> m_contained_abspos_children; OwnPtr mutable m_cached_intrinsic_sizes; }; diff --git a/Libraries/LibWeb/Layout/BreakNode.cpp b/Libraries/LibWeb/Layout/BreakNode.cpp index 360d6de6f7..0b3ceb2c96 100644 --- a/Libraries/LibWeb/Layout/BreakNode.cpp +++ b/Libraries/LibWeb/Layout/BreakNode.cpp @@ -10,8 +10,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(BreakNode); - BreakNode::BreakNode(DOM::Document& document, HTML::HTMLBRElement& element, CSS::ComputedProperties const& style) : Layout::NodeWithStyleAndBoxModelMetrics(document, &element, style) { diff --git a/Libraries/LibWeb/Layout/BreakNode.h b/Libraries/LibWeb/Layout/BreakNode.h index be1069e9dd..bd3ce3ee20 100644 --- a/Libraries/LibWeb/Layout/BreakNode.h +++ b/Libraries/LibWeb/Layout/BreakNode.h @@ -12,8 +12,7 @@ namespace Web::Layout { class BreakNode final : public NodeWithStyleAndBoxModelMetrics { - GC_CELL(BreakNode, NodeWithStyleAndBoxModelMetrics); - GC_DECLARE_ALLOCATOR(BreakNode); + LAYOUT_NODE(BreakNode, NodeWithStyleAndBoxModelMetrics); public: BreakNode(DOM::Document&, HTML::HTMLBRElement&, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/CanvasBox.cpp b/Libraries/LibWeb/Layout/CanvasBox.cpp index 0c66a1f5c2..4df5f2fac6 100644 --- a/Libraries/LibWeb/Layout/CanvasBox.cpp +++ b/Libraries/LibWeb/Layout/CanvasBox.cpp @@ -9,8 +9,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(CanvasBox); - CanvasBox::CanvasBox(DOM::Document& document, HTML::HTMLCanvasElement& element, CSS::ComputedProperties const& style) : ReplacedBox(document, element, style) { diff --git a/Libraries/LibWeb/Layout/CanvasBox.h b/Libraries/LibWeb/Layout/CanvasBox.h index f999d6aeab..f340daa6ba 100644 --- a/Libraries/LibWeb/Layout/CanvasBox.h +++ b/Libraries/LibWeb/Layout/CanvasBox.h @@ -12,8 +12,7 @@ namespace Web::Layout { class CanvasBox final : public ReplacedBox { - GC_CELL(CanvasBox, ReplacedBox); - GC_DECLARE_ALLOCATOR(CanvasBox); + LAYOUT_NODE(CanvasBox, ReplacedBox); public: CanvasBox(DOM::Document&, HTML::HTMLCanvasElement&, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/CheckBox.cpp b/Libraries/LibWeb/Layout/CheckBox.cpp index 952e439ace..02c968abb3 100644 --- a/Libraries/LibWeb/Layout/CheckBox.cpp +++ b/Libraries/LibWeb/Layout/CheckBox.cpp @@ -11,8 +11,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(CheckBox); - CheckBox::CheckBox(DOM::Document& document, HTML::HTMLInputElement& element, CSS::ComputedProperties const& style) : ReplacedBox(document, element, style) { diff --git a/Libraries/LibWeb/Layout/CheckBox.h b/Libraries/LibWeb/Layout/CheckBox.h index 35da4946e5..3daf3ca77a 100644 --- a/Libraries/LibWeb/Layout/CheckBox.h +++ b/Libraries/LibWeb/Layout/CheckBox.h @@ -12,8 +12,7 @@ namespace Web::Layout { class CheckBox final : public ReplacedBox { - GC_CELL(CheckBox, ReplacedBox); - GC_DECLARE_ALLOCATOR(CheckBox); + LAYOUT_NODE(CheckBox, ReplacedBox); public: CheckBox(DOM::Document&, HTML::HTMLInputElement&, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/FieldSetBox.cpp b/Libraries/LibWeb/Layout/FieldSetBox.cpp index 1be831c738..0baff53579 100644 --- a/Libraries/LibWeb/Layout/FieldSetBox.cpp +++ b/Libraries/LibWeb/Layout/FieldSetBox.cpp @@ -10,8 +10,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(FieldSetBox); - FieldSetBox::FieldSetBox(DOM::Document& document, DOM::Element& element, CSS::ComputedProperties const& style) : BlockContainer(document, &element, style) { diff --git a/Libraries/LibWeb/Layout/FieldSetBox.h b/Libraries/LibWeb/Layout/FieldSetBox.h index 1157a9f07b..25a19ff452 100644 --- a/Libraries/LibWeb/Layout/FieldSetBox.h +++ b/Libraries/LibWeb/Layout/FieldSetBox.h @@ -14,8 +14,7 @@ namespace Web::Layout { class FieldSetBox final : public BlockContainer { - GC_CELL(FieldSetBox, BlockContainer); - GC_DECLARE_ALLOCATOR(FieldSetBox); + LAYOUT_NODE(FieldSetBox, BlockContainer); public: FieldSetBox(DOM::Document&, DOM::Element&, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/FlexFormattingContext.cpp b/Libraries/LibWeb/Layout/FlexFormattingContext.cpp index 8958f4f112..fe144e0572 100644 --- a/Libraries/LibWeb/Layout/FlexFormattingContext.cpp +++ b/Libraries/LibWeb/Layout/FlexFormattingContext.cpp @@ -145,9 +145,9 @@ void FlexFormattingContext::run(AvailableSpace const& available_space) // different formula with intrinsic sizes), and items with aspect-ratio (transferred_size_suggestion // complicates the calculation). auto can_skip_automatic_minimum_size_for_item = [&](FlexItem const& item) -> bool { - if (item.box->is_scroll_container()) + if (item.box.is_scroll_container()) return false; - if (item.box->is_replaced_box() || item.box->has_preferred_aspect_ratio()) + if (item.box.is_replaced_box() || item.box.has_preferred_aspect_ratio()) return false; if (!item.used_flex_basis_is_definite) return false; @@ -308,51 +308,51 @@ void FlexFormattingContext::populate_specified_margins(FlexItem& item, CSS::Flex { auto width_of_containing_block = m_flex_container_state.content_width(); - item.used_values.padding_left = item.box->computed_values().padding().left().to_px_or_zero(item.box, width_of_containing_block); - item.used_values.padding_right = item.box->computed_values().padding().right().to_px_or_zero(item.box, width_of_containing_block); - item.used_values.padding_top = item.box->computed_values().padding().top().to_px_or_zero(item.box, width_of_containing_block); - item.used_values.padding_bottom = item.box->computed_values().padding().bottom().to_px_or_zero(item.box, width_of_containing_block); + item.used_values.padding_left = item.box.computed_values().padding().left().to_px_or_zero(item.box, width_of_containing_block); + item.used_values.padding_right = item.box.computed_values().padding().right().to_px_or_zero(item.box, width_of_containing_block); + item.used_values.padding_top = item.box.computed_values().padding().top().to_px_or_zero(item.box, width_of_containing_block); + item.used_values.padding_bottom = item.box.computed_values().padding().bottom().to_px_or_zero(item.box, width_of_containing_block); if (main_axis_is_horizontal()) { - item.borders.main_before = item.box->computed_values().border_left().width; - item.borders.main_after = item.box->computed_values().border_right().width; - item.borders.cross_before = item.box->computed_values().border_top().width; - item.borders.cross_after = item.box->computed_values().border_bottom().width; + item.borders.main_before = item.box.computed_values().border_left().width; + item.borders.main_after = item.box.computed_values().border_right().width; + item.borders.cross_before = item.box.computed_values().border_top().width; + item.borders.cross_after = item.box.computed_values().border_bottom().width; - item.padding.main_before = item.box->computed_values().padding().left().to_px_or_zero(item.box, width_of_containing_block); - item.padding.main_after = item.box->computed_values().padding().right().to_px_or_zero(item.box, width_of_containing_block); - item.padding.cross_before = item.box->computed_values().padding().top().to_px_or_zero(item.box, width_of_containing_block); - item.padding.cross_after = item.box->computed_values().padding().bottom().to_px_or_zero(item.box, width_of_containing_block); + item.padding.main_before = item.box.computed_values().padding().left().to_px_or_zero(item.box, width_of_containing_block); + item.padding.main_after = item.box.computed_values().padding().right().to_px_or_zero(item.box, width_of_containing_block); + item.padding.cross_before = item.box.computed_values().padding().top().to_px_or_zero(item.box, width_of_containing_block); + item.padding.cross_after = item.box.computed_values().padding().bottom().to_px_or_zero(item.box, width_of_containing_block); - item.margins.main_before = item.box->computed_values().margin().left().to_px_or_zero(item.box, width_of_containing_block); - item.margins.main_after = item.box->computed_values().margin().right().to_px_or_zero(item.box, width_of_containing_block); - item.margins.cross_before = item.box->computed_values().margin().top().to_px_or_zero(item.box, width_of_containing_block); - item.margins.cross_after = item.box->computed_values().margin().bottom().to_px_or_zero(item.box, width_of_containing_block); + item.margins.main_before = item.box.computed_values().margin().left().to_px_or_zero(item.box, width_of_containing_block); + item.margins.main_after = item.box.computed_values().margin().right().to_px_or_zero(item.box, width_of_containing_block); + item.margins.cross_before = item.box.computed_values().margin().top().to_px_or_zero(item.box, width_of_containing_block); + item.margins.cross_after = item.box.computed_values().margin().bottom().to_px_or_zero(item.box, width_of_containing_block); - item.margins.main_before_is_auto = item.box->computed_values().margin().left().is_auto(); - item.margins.main_after_is_auto = item.box->computed_values().margin().right().is_auto(); - item.margins.cross_before_is_auto = item.box->computed_values().margin().top().is_auto(); - item.margins.cross_after_is_auto = item.box->computed_values().margin().bottom().is_auto(); + item.margins.main_before_is_auto = item.box.computed_values().margin().left().is_auto(); + item.margins.main_after_is_auto = item.box.computed_values().margin().right().is_auto(); + item.margins.cross_before_is_auto = item.box.computed_values().margin().top().is_auto(); + item.margins.cross_after_is_auto = item.box.computed_values().margin().bottom().is_auto(); } else { - item.borders.main_before = item.box->computed_values().border_top().width; - item.borders.main_after = item.box->computed_values().border_bottom().width; - item.borders.cross_before = item.box->computed_values().border_left().width; - item.borders.cross_after = item.box->computed_values().border_right().width; + item.borders.main_before = item.box.computed_values().border_top().width; + item.borders.main_after = item.box.computed_values().border_bottom().width; + item.borders.cross_before = item.box.computed_values().border_left().width; + item.borders.cross_after = item.box.computed_values().border_right().width; item.padding.main_before = item.used_values.padding_top; item.padding.main_after = item.used_values.padding_bottom; item.padding.cross_before = item.used_values.padding_left; item.padding.cross_after = item.used_values.padding_right; - item.margins.main_before = item.box->computed_values().margin().top().to_px_or_zero(item.box, width_of_containing_block); - item.margins.main_after = item.box->computed_values().margin().bottom().to_px_or_zero(item.box, width_of_containing_block); - item.margins.cross_before = item.box->computed_values().margin().left().to_px_or_zero(item.box, width_of_containing_block); - item.margins.cross_after = item.box->computed_values().margin().right().to_px_or_zero(item.box, width_of_containing_block); + item.margins.main_before = item.box.computed_values().margin().top().to_px_or_zero(item.box, width_of_containing_block); + item.margins.main_after = item.box.computed_values().margin().bottom().to_px_or_zero(item.box, width_of_containing_block); + item.margins.cross_before = item.box.computed_values().margin().left().to_px_or_zero(item.box, width_of_containing_block); + item.margins.cross_after = item.box.computed_values().margin().right().to_px_or_zero(item.box, width_of_containing_block); - item.margins.main_before_is_auto = item.box->computed_values().margin().top().is_auto(); - item.margins.main_after_is_auto = item.box->computed_values().margin().bottom().is_auto(); - item.margins.cross_before_is_auto = item.box->computed_values().margin().left().is_auto(); - item.margins.cross_after_is_auto = item.box->computed_values().margin().right().is_auto(); + item.margins.main_before_is_auto = item.box.computed_values().margin().top().is_auto(); + item.margins.main_after_is_auto = item.box.computed_values().margin().bottom().is_auto(); + item.margins.cross_before_is_auto = item.box.computed_values().margin().left().is_auto(); + item.margins.cross_after_is_auto = item.box.computed_values().margin().right().is_auto(); } } @@ -589,7 +589,7 @@ void FlexFormattingContext::determine_available_space_for_items(AvailableSpace c // https://drafts.csswg.org/css-flexbox-1/#propdef-flex-basis CSS::FlexBasis FlexFormattingContext::used_flex_basis_for_item(FlexItem const& item) const { - auto flex_basis = item.box->computed_values().flex_basis(); + auto flex_basis = item.box.computed_values().flex_basis(); if (flex_basis.has() && flex_basis.get().is_auto()) { // https://drafts.csswg.org/css-flexbox-1/#valdef-flex-basis-auto @@ -709,7 +709,7 @@ void FlexFormattingContext::determine_flex_base_size(FlexItem& item) // AD-HOC: If we're sizing the flex container under a min-content constraint in the main axis, // non-replaced flex items resolve percentages in the main axis to 0. // https://drafts.csswg.org/css-sizing-3/#cyclic-percentage-contribution - if (item.box->is_replaced_box() + if (item.box.is_replaced_box() && m_available_space_for_items->main.is_min_content() && computed_main_size(item.box).contains_percentage()) { return CSSPixels(0); @@ -719,7 +719,7 @@ void FlexFormattingContext::determine_flex_base_size(FlexItem& item) // - an intrinsic aspect ratio, // - a used flex basis of content, and // - a definite cross size, - if (item.box->has_preferred_aspect_ratio() + if (item.box.has_preferred_aspect_ratio() && item.used_flex_basis->has() && has_definite_cross_size(item)) { // flex_base_size is calculated from definite cross size and intrinsic aspect ratio @@ -730,7 +730,7 @@ void FlexFormattingContext::determine_flex_base_size(FlexItem& item) return adjust_main_size_through_aspect_ratio_for_cross_size_min_max_constraints( item.box, - calculate_main_size_from_cross_size_and_aspect_ratio(inner_cross_size(item), item.box->preferred_aspect_ratio().value()), + calculate_main_size_from_cross_size_and_aspect_ratio(inner_cross_size(item), item.box.preferred_aspect_ratio().value()), computed_cross_min_size(item.box), computed_cross_max_size(item.box)); } @@ -800,7 +800,7 @@ void FlexFormattingContext::determine_flex_base_size(FlexItem& item) // - using stretch-fit main size if the flex basis is indefinite, there is no // intrinsic size and no cross size to resolve the ratio against. // - in response to cross size min/max constraints. - auto auto_size = item.box->auto_content_box_size(); + auto auto_size = item.box.auto_content_box_size(); if (auto_size.has_aspect_ratio()) { if (!item.used_flex_basis_is_definite && !auto_size.has_width() && !auto_size.has_height() && !has_definite_cross_size(item) && has_definite_main_size(m_flex_container_state)) { item.flex_base_size = inner_main_size(m_flex_container_state); @@ -817,7 +817,7 @@ CSSPixels FlexFormattingContext::automatic_minimum_size(FlexItem const& item) co // To provide a more reasonable default minimum size for flex items, // the used value of a main axis automatic minimum size on a flex item that is not a scroll container is its content-based minimum size; // for scroll containers the automatic minimum size is zero, as usual. - if (!item.box->is_scroll_container()) + if (!item.box.is_scroll_container()) return content_based_minimum_size(item); return 0; } @@ -839,7 +839,7 @@ CSSPixels FlexFormattingContext::content_size_suggestion(FlexItem const& item) c { auto suggestion = calculate_min_content_main_size(item); - if (item.box->has_preferred_aspect_ratio()) { + if (item.box.has_preferred_aspect_ratio()) { suggestion = adjust_main_size_through_aspect_ratio_for_cross_size_min_max_constraints(item.box, suggestion, computed_cross_min_size(item.box), computed_cross_max_size(item.box)); } @@ -852,8 +852,8 @@ Optional FlexFormattingContext::transferred_size_suggestion(FlexItem // If the item has a preferred aspect ratio and its preferred cross size is definite, // then the transferred size suggestion is that size // (clamped by its minimum and maximum cross sizes if they are definite), converted through the aspect ratio. - if (item.box->has_preferred_aspect_ratio() && has_definite_cross_size(item)) { - auto aspect_ratio = item.box->preferred_aspect_ratio().value(); + if (item.box.has_preferred_aspect_ratio() && has_definite_cross_size(item)) { + auto aspect_ratio = item.box.preferred_aspect_ratio().value(); return adjust_main_size_through_aspect_ratio_for_cross_size_min_max_constraints( item.box, calculate_main_size_from_cross_size_and_aspect_ratio(inner_cross_size(item), aspect_ratio), @@ -871,7 +871,7 @@ CSSPixels FlexFormattingContext::content_based_minimum_size(FlexItem const& item auto unclamped_size = [&] { // The content-based minimum size of a flex item differs depending on whether the flex item is replaced or not: // -> For replaced elements - if (item.box->is_replaced_box()) { + if (item.box.is_replaced_box()) { // Use the smaller of the content size suggestion and the transferred size suggestion (if one exists), // capped by the specified size suggestion (if one exists). auto size = content_size_suggestion(item); @@ -1005,9 +1005,9 @@ void FlexFormattingContext::resolve_flexible_lengths_for_line(FlexLine& line) for (FlexItem& item : line.items) { if (used_flex_factor == FlexFactor::FlexGrowFactor) { - item.flex_factor = item.box->computed_values().flex_grow(); + item.flex_factor = item.box.computed_values().flex_grow(); } else if (used_flex_factor == FlexFactor::FlexShrinkFactor) { - item.flex_factor = item.box->computed_values().flex_shrink(); + item.flex_factor = item.box.computed_values().flex_shrink(); } // Freeze, setting its target main size to its hypothetical main size… // - any item that has a flex factor of zero @@ -1239,7 +1239,7 @@ void FlexFormattingContext::save_flex_layout_data() const cross_start = cross_start.has_value() ? min(cross_start.value(), item_cross_start) : item_cross_start; FlexLayoutItem layout_item; - if (auto* dom_node = item.box->dom_node()) + if (auto* dom_node = item.box.dom_node()) layout_item.node_id = dom_node->unique_id(); layout_item.main_axis_direction = main_axis_direction; layout_item.cross_axis_direction = cross_axis_direction; @@ -1254,12 +1254,12 @@ void FlexFormattingContext::save_flex_layout_data() const ? FlexLayoutClampState::ClampedToMin : item.is_max_violation ? FlexLayoutClampState::ClampedToMax : FlexLayoutClampState::Unclamped; - layout_item.flex_basis = serialize_flex_basis(item.box->computed_values().flex_basis()); + layout_item.flex_basis = serialize_flex_basis(item.box.computed_values().flex_basis()); layout_item.main_size_property = MUST(String::formatted("{}", computed_main_size(item.box))); layout_item.main_min_size_property = MUST(String::formatted("{}", computed_main_min_size(item.box))); layout_item.main_max_size_property = MUST(String::formatted("{}", computed_main_max_size(item.box))); - layout_item.flex_grow = item.box->computed_values().flex_grow(); - layout_item.flex_shrink = item.box->computed_values().flex_shrink(); + layout_item.flex_grow = item.box.computed_values().flex_grow(); + layout_item.flex_shrink = item.box.computed_values().flex_shrink(); layout_line.items.append(move(layout_item)); } @@ -1287,10 +1287,10 @@ void FlexFormattingContext::determine_hypothetical_cross_size_of_item(FlexItem& return; } - if (item.box->has_preferred_aspect_ratio()) { - auto auto_size = item.box->auto_content_box_size(); + if (item.box.has_preferred_aspect_ratio()) { + auto auto_size = item.box.auto_content_box_size(); if (item.used_flex_basis_is_definite || (auto_size.has_width() && auto_size.has_height())) { - item.hypothetical_cross_size = css_clamp(calculate_cross_size_from_main_size_and_aspect_ratio(item.main_size.value(), item.box->preferred_aspect_ratio().value()), clamp_min, clamp_max); + item.hypothetical_cross_size = css_clamp(calculate_cross_size_from_main_size_and_aspect_ratio(item.main_size.value(), item.box.preferred_aspect_ratio().value()), clamp_min, clamp_max); return; } item.hypothetical_cross_size = css_clamp(inner_cross_size(m_flex_container_state), clamp_min, clamp_max); @@ -1604,7 +1604,7 @@ void FlexFormattingContext::dump_items() const dbgln("{} flex-line #{}:", flex_container().debug_description(), i); for (size_t j = 0; j < m_flex_lines[i].items.size(); ++j) { auto& item = m_flex_lines[i].items[j]; - dbgln("{} flex-item #{}: {} (main:{}, cross:{})", flex_container().debug_description(), j, item.box->debug_description(), item.main_size.value_or(-1), item.cross_size.value_or(-1)); + dbgln("{} flex-item #{}: {} (main:{}, cross:{})", flex_container().debug_description(), j, item.box.debug_description(), item.main_size.value_or(-1), item.cross_size.value_or(-1)); } } } @@ -1880,15 +1880,15 @@ void FlexFormattingContext::copy_dimensions_from_flex_items_to_boxes() for (auto& item : m_flex_items) { auto const& box = item.box; - item.used_values.margin_left = box->computed_values().margin().left().to_px_or_zero(box, m_flex_container_state.content_width()); - item.used_values.margin_right = box->computed_values().margin().right().to_px_or_zero(box, m_flex_container_state.content_width()); - item.used_values.margin_top = box->computed_values().margin().top().to_px_or_zero(box, m_flex_container_state.content_width()); - item.used_values.margin_bottom = box->computed_values().margin().bottom().to_px_or_zero(box, m_flex_container_state.content_width()); + item.used_values.margin_left = box.computed_values().margin().left().to_px_or_zero(box, m_flex_container_state.content_width()); + item.used_values.margin_right = box.computed_values().margin().right().to_px_or_zero(box, m_flex_container_state.content_width()); + item.used_values.margin_top = box.computed_values().margin().top().to_px_or_zero(box, m_flex_container_state.content_width()); + item.used_values.margin_bottom = box.computed_values().margin().bottom().to_px_or_zero(box, m_flex_container_state.content_width()); - item.used_values.border_left = box->computed_values().border_left().width; - item.used_values.border_right = box->computed_values().border_right().width; - item.used_values.border_top = box->computed_values().border_top().width; - item.used_values.border_bottom = box->computed_values().border_bottom().width; + item.used_values.border_left = box.computed_values().border_left().width; + item.used_values.border_right = box.computed_values().border_right().width; + item.used_values.border_top = box.computed_values().border_top().width; + item.used_values.border_bottom = box.computed_values().border_bottom().width; set_main_size(item, item.main_size.value()); set_cross_size(item, item.cross_size.value()); @@ -1946,10 +1946,10 @@ CSSPixels FlexFormattingContext::calculate_intrinsic_main_size_of_flex_container CSSPixels result = contribution - outer_flex_base_size; if (result > 0) { - if (item.box->computed_values().flex_grow() >= 1) { - result.scale_by(1 / item.box->computed_values().flex_grow()); + if (item.box.computed_values().flex_grow() >= 1) { + result.scale_by(1 / item.box.computed_values().flex_grow()); } else { - result.scale_by(item.box->computed_values().flex_grow()); + result.scale_by(item.box.computed_values().flex_grow()); } } else if (result < 0) { if (item.scaled_flex_shrink_factor == 0) @@ -1978,8 +1978,8 @@ CSSPixels FlexFormattingContext::calculate_intrinsic_main_size_of_flex_container float sum_of_flex_shrink_factors = 0; for (auto& item : flex_line.items) { greatest_desired_flex_fraction = max(greatest_desired_flex_fraction, item.desired_flex_fraction); - sum_of_flex_grow_factors += item.box->computed_values().flex_grow(); - sum_of_flex_shrink_factors += item.box->computed_values().flex_shrink(); + sum_of_flex_grow_factors += item.box.computed_values().flex_grow(); + sum_of_flex_shrink_factors += item.box.computed_values().flex_shrink(); } float chosen_flex_fraction = greatest_desired_flex_fraction; @@ -2005,7 +2005,7 @@ CSSPixels FlexFormattingContext::calculate_intrinsic_main_size_of_flex_container for (auto& item : flex_line.items) { double product = 0; if (item.desired_flex_fraction > 0) - product = flex_line.chosen_flex_fraction * static_cast(item.box->computed_values().flex_grow()); + product = flex_line.chosen_flex_fraction * static_cast(item.box.computed_values().flex_grow()); else if (item.desired_flex_fraction < 0) product = flex_line.chosen_flex_fraction * item.scaled_flex_shrink_factor; auto result = item.flex_base_size + CSSPixels::nearest_value_for(product); @@ -2184,7 +2184,7 @@ CSSPixels FlexFormattingContext::calculate_cross_min_content_contribution(FlexIt return cross_axis_is_horizontal() ? get_pixel_width(item, computed_cross_size(item.box)) : get_pixel_height(item, computed_cross_size(item.box)); }(); - if (cross_size_auto && item.box->has_preferred_aspect_ratio()) + if (cross_size_auto && item.box.has_preferred_aspect_ratio()) size = adjust_cross_size_through_aspect_ratio_for_main_size_min_max_constraints(item.box, size, computed_main_min_size(item.box), computed_main_max_size(item.box)); auto const& computed_min_size = this->computed_cross_min_size(item.box); @@ -2207,7 +2207,7 @@ CSSPixels FlexFormattingContext::calculate_cross_max_content_contribution(FlexIt return cross_axis_is_horizontal() ? get_pixel_width(item, computed_cross_size(item.box)) : get_pixel_height(item, computed_cross_size(item.box)); }(); - if (cross_size_auto && item.box->has_preferred_aspect_ratio()) + if (cross_size_auto && item.box.has_preferred_aspect_ratio()) size = adjust_cross_size_through_aspect_ratio_for_main_size_min_max_constraints(item.box, size, computed_main_min_size(item.box), computed_main_max_size(item.box)); auto const& computed_min_size = this->computed_cross_min_size(item.box); @@ -2223,7 +2223,7 @@ CSSPixels FlexFormattingContext::calculate_cross_max_content_contribution(FlexIt CSSPixels FlexFormattingContext::calculate_width_to_use_when_determining_intrinsic_height_of_item(FlexItem const& item) const { - auto const& box = *item.box; + auto const& box = item.box; auto computed_width = box.computed_values().width(); auto const& computed_min_width = box.computed_values().min_width(); auto const& computed_max_width = box.computed_values().max_width(); diff --git a/Libraries/LibWeb/Layout/FlexFormattingContext.h b/Libraries/LibWeb/Layout/FlexFormattingContext.h index efcfb64af8..e4f99a5f8e 100644 --- a/Libraries/LibWeb/Layout/FlexFormattingContext.h +++ b/Libraries/LibWeb/Layout/FlexFormattingContext.h @@ -55,7 +55,7 @@ private: }; struct FlexItem { - GC::Ref box; + Box& box; LayoutState::UsedValues& used_values; Optional used_flex_basis {}; bool used_flex_basis_is_definite { false }; diff --git a/Libraries/LibWeb/Layout/FormattingContext.cpp b/Libraries/LibWeb/Layout/FormattingContext.cpp index 1fed0ea26e..bb5ad0b3be 100644 --- a/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/Libraries/LibWeb/Layout/FormattingContext.cpp @@ -1468,12 +1468,12 @@ static Optional compute_inline_containing_block_rect(InlineNode co } } - for (auto const* child = node.first_child(); child; child = child->next_sibling()) { + for (auto child = node.first_child(); child; child = child->next_sibling()) { if (child->is_absolutely_positioned() || child->is_floating()) continue; auto const* child_used_values = state.try_get(*child); auto child_offset = child_used_values ? offset + child_used_values->offset : offset; - auto const* box_child = as_if(child); + auto const* box_child = as_if(child.ptr()); if (box_child && !box_child->is_anonymous()) { auto const* dom = box_child->dom_node(); if (!dom || !inline_dom_node->is_inclusive_ancestor_of(*dom)) @@ -1752,6 +1752,8 @@ void FormattingContext::layout_absolutely_positioned_children() if (m_layout_mode != LayoutMode::Normal) return; for (auto& child : context_box().contained_abspos_children()) { + if (!child) + continue; auto& box = as(*child); layout_absolutely_positioned_element(box); } @@ -1879,7 +1881,7 @@ void FormattingContext::layout_absolutely_positioned_element(Box& box) auto static_position = m_state.get(box).static_position(); auto const* static_position_cb = box.static_position_containing_block(); auto actual_containing_block = box.containing_block(); - if (static_position_cb && static_position_cb != actual_containing_block.ptr()) { + if (static_position_cb && static_position_cb != actual_containing_block) { auto offset = m_state.get(*static_position_cb).cumulative_offset() - m_state.get(*actual_containing_block).cumulative_offset(); static_position += offset; } @@ -2535,7 +2537,7 @@ Box const* FormattingContext::box_child_to_derive_baseline_from(Box const& box) if (!box.has_children() || box.children_are_inline()) return nullptr; // Find the last in-flow child that has a baseline (either directly via line boxes, or via its descendants). - for (auto const* child = box.last_child(); child; child = child->previous_sibling()) { + for (auto child = box.last_child(); child; child = child->previous_sibling()) { auto const* child_box = as_if(*child); if (!child_box) continue; diff --git a/Libraries/LibWeb/Layout/FormattingContext.h b/Libraries/LibWeb/Layout/FormattingContext.h index be929c52c4..b7e9410c23 100644 --- a/Libraries/LibWeb/Layout/FormattingContext.h +++ b/Libraries/LibWeb/Layout/FormattingContext.h @@ -194,8 +194,8 @@ protected: // Each block in the containing chain adds its own margin and we store the total here. CSSPixels left_total_containing_margin; CSSPixels right_total_containing_margin; - GC::Ptr matching_left_float_box; - GC::Ptr matching_right_float_box; + Box const* matching_left_float_box { nullptr }; + Box const* matching_right_float_box { nullptr }; }; struct ShrinkToFitResult { @@ -239,7 +239,7 @@ protected: LayoutMode m_layout_mode; FormattingContext* m_parent { nullptr }; - GC::Ref m_context_box; + Box const& m_context_box; LayoutState& m_state; }; @@ -253,7 +253,7 @@ public: for (int i = 0; i < s_depth; ++i) indent_builder.append("| "sv); auto intrinsic_marker = fc.m_layout_mode == LayoutMode::IntrinsicSizing ? " [intrinsic]"sv : ""sv; - dbgln("{}|- {} <{}> run({}){}", indent_builder.string_view(), FormattingContext::type_name(fc.m_type), fc.m_context_box->debug_description(), available_space, intrinsic_marker); + dbgln("{}|- {} <{}> run({}){}", indent_builder.string_view(), FormattingContext::type_name(fc.m_type), fc.m_context_box.debug_description(), available_space, intrinsic_marker); ++s_depth; } diff --git a/Libraries/LibWeb/Layout/GridFormattingContext.cpp b/Libraries/LibWeb/Layout/GridFormattingContext.cpp index bcd2facd71..718cd18e6a 100644 --- a/Libraries/LibWeb/Layout/GridFormattingContext.cpp +++ b/Libraries/LibWeb/Layout/GridFormattingContext.cpp @@ -300,7 +300,7 @@ GridFormattingContext const* GridFormattingContext::parent_grid_formatting_conte GridItem const* GridFormattingContext::grid_item_for_box(Box const& box) const { for (auto const& item : m_grid_items) { - if (item.box.ptr() == &box) + if (&item.box == &box) return &item; } return nullptr; @@ -316,7 +316,7 @@ GridItem const* GridFormattingContext::parent_grid_item() const bool GridFormattingContext::grid_item_is_subgridded_in_axis(GridItem const& item, GridDimension dimension) const { - if (!item.box->display().is_grid_inside()) + if (!item.box.display().is_grid_inside()) return false; auto const& grid_template = dimension == GridDimension::Column @@ -1942,7 +1942,7 @@ void GridFormattingContext::place_grid_items() // flex items), which are then assigned to predefined areas in the grid. They can be explicitly // placed using coordinates through the grid-placement properties or implicitly placed into // empty areas using auto-placement. - HashMap>> order_item_bucket; + HashMap> order_item_bucket; grid_container().for_each_child_of_type([&](Box& child_box) { if (can_skip_is_anonymous_text_run(child_box)) return IterationDecision::Continue; @@ -1973,7 +1973,7 @@ void GridFormattingContext::place_grid_items() auto& boxes_to_place = order_item_bucket.get(key).value(); for (size_t i = 0; i < boxes_to_place.size(); i++) { auto const& child_box = boxes_to_place[i]; - auto const& computed_values = child_box->computed_values(); + auto const& computed_values = child_box.computed_values(); if (is_auto_positioned_track(computed_values.grid_row_start(), computed_values.grid_row_end()) || is_auto_positioned_track(computed_values.grid_column_start(), computed_values.grid_column_end())) continue; @@ -1988,7 +1988,7 @@ void GridFormattingContext::place_grid_items() auto& boxes_to_place = order_item_bucket.get(key).value(); for (size_t i = 0; i < boxes_to_place.size(); i++) { auto const& child_box = boxes_to_place[i]; - auto const& computed_values = child_box->computed_values(); + auto const& computed_values = child_box.computed_values(); if (is_auto_positioned_track(computed_values.grid_row_start(), computed_values.grid_row_end())) continue; place_item_with_row_position(child_box); @@ -2037,7 +2037,7 @@ void GridFormattingContext::place_grid_items() auto& boxes_to_place = order_item_bucket.get(key).value(); for (size_t i = 0; i < boxes_to_place.size(); i++) { auto const& child_box = boxes_to_place[i]; - auto const& computed_values = child_box->computed_values(); + auto const& computed_values = child_box.computed_values(); if (!is_auto_positioned_track(computed_values.grid_column_start(), computed_values.grid_column_end())) { // 4.1.1 / 4.2.1: Item with definite column position. @@ -2222,7 +2222,7 @@ void GridFormattingContext::resolve_grid_item_sizes(GridDimension dimension) result.margin_start = absorbed_margin_space; } else if (end_is_auto) { result.margin_end = absorbed_margin_space; - } else if (css_size.is_auto() && !item.box->is_replaced_box()) { + } else if (css_size.is_auto() && !item.box.is_replaced_box()) { result.size += free_space_left_for_margins; } @@ -2274,15 +2274,15 @@ void GridFormattingContext::resolve_grid_item_sizes(GridDimension dimension) }; ItemAlignment used_alignment; - auto hint = item.box->auto_content_box_size(); + auto hint = item.box.auto_content_box_size(); bool has_replaced_size_hint_in_this_axis = false; if (dimension == GridDimension::Column) { - has_replaced_size_hint_in_this_axis = hint.has_width() || (hint.has_height() && item.box->has_preferred_aspect_ratio()); + has_replaced_size_hint_in_this_axis = hint.has_width() || (hint.has_height() && item.box.has_preferred_aspect_ratio()); } else { - has_replaced_size_hint_in_this_axis = hint.has_height() || (hint.has_width() && item.box->has_preferred_aspect_ratio()); + has_replaced_size_hint_in_this_axis = hint.has_height() || (hint.has_width() && item.box.has_preferred_aspect_ratio()); } - if (item.box->is_replaced_box() && has_replaced_size_hint_in_this_axis) { + if (item.box.is_replaced_box() && has_replaced_size_hint_in_this_axis) { auto tentative_size = tentative_size_for_replaced_element(preferred_size); used_alignment = try_compute_size(tentative_size, item.preferred_size(dimension)); } else { @@ -2303,7 +2303,7 @@ void GridFormattingContext::resolve_grid_item_sizes(GridDimension dimension) .margin_end = item.used_margin_end(dimension), .size = stretched_size }; - } else if (dimension == GridDimension::Column && is(*item.box)) { + } else if (dimension == GridDimension::Column && is(item.box)) { // CSS Grid lays out each grid item into its grid-area containing block before alignment. For // display:table, the anonymous table wrapper is the grid item, while table layout computes the inner // table's border-box width, so resolve the wrapper width with the same grid-area basis used later. @@ -2317,11 +2317,11 @@ void GridFormattingContext::resolve_grid_item_sizes(GridDimension dimension) CSSPixels fit_content_size; if (dimension == GridDimension::Column) { fit_content_size = calculate_fit_content_width(item.box, available_space); - } else if (preferred_size.is_auto() && item.box->has_preferred_aspect_ratio() && *item.box->preferred_aspect_ratio() != 0 && item.used_values.has_definite_width()) { + } else if (preferred_size.is_auto() && item.box.has_preferred_aspect_ratio() && *item.box.preferred_aspect_ratio() != 0 && item.used_values.has_definite_width()) { // NB: When the item has a preferred aspect ratio and a definite width, resolve the // height through the aspect ratio instead of using fit-content sizing, which would // incorrectly use the available width (grid area width) instead of the item's width. - fit_content_size = item.used_values.content_width() / *item.box->preferred_aspect_ratio(); + fit_content_size = item.used_values.content_width() / *item.box.preferred_aspect_ratio(); } else { fit_content_size = calculate_fit_content_height(item.box, available_space); } @@ -2578,7 +2578,7 @@ CSSPixels GridFormattingContext::grid_container_size_for_track_alignment(GridDim void GridFormattingContext::resolve_items_box_metrics(GridDimension dimension) { for (auto& item : m_grid_items) { - auto& computed_values = item.box->computed_values(); + auto& computed_values = item.box.computed_values(); CSSPixels containing_block_width = containing_block_size_for_item(item, GridDimension::Column); if (dimension == GridDimension::Column) { @@ -2688,7 +2688,7 @@ CSSPixelRect GridFormattingContext::get_grid_area_rect(GridItem const& grid_item }; auto place_into_track_formed_by_last_line_and_grid_container_padding_edge = [&](GridDimension dimension) { - VERIFY(grid_item.box->is_absolutely_positioned()); + VERIFY(grid_item.box.is_absolutely_positioned()); auto const& tracks_and_gaps = dimension == GridDimension::Column ? m_grid_columns_and_gaps : m_grid_rows_and_gaps; CSSPixels offset = 0; for (auto const& row_track : tracks_and_gaps) { @@ -2784,7 +2784,7 @@ void GridFormattingContext::run(AvailableSpace const& available_space) collapse_auto_fit_tracks_if_needed(GridDimension::Row); for (auto& item : m_grid_items) { - auto& computed_values = item.box->computed_values(); + auto& computed_values = item.box.computed_values(); // NOTE: As the containing blocks of grid items are created by implicit grid areas that are not present in the // layout tree, the initial value of has_definite_width/height computed by LayoutState::UsedValues::set_node @@ -2844,7 +2844,7 @@ void GridFormattingContext::run(AvailableSpace const& available_space) for (auto& grid_item : m_grid_items) { auto const grid_area_rect = get_grid_area_rect(grid_item); - if (is(*grid_item.box)) { + if (is(grid_item.box)) { // Track spacing can expand the final grid area after the earlier width pass. Recompute the wrapper width // against that final area and store it so the real table layout resolves percentages against the grid area. resolve_table_wrapper_grid_item_width(grid_item, grid_area_rect.width()); @@ -3417,7 +3417,7 @@ bool GridFormattingContext::should_treat_preferred_size_as_auto_for_intrinsic_co // When a non-replaced grid item's percentage preferred size contributes to // sizing tracks in the same axis, the percentage is cyclic and behaves as // the property's initial value for intrinsic contribution calculations. - return !item.box->is_replaced_box() && item.preferred_size(dimension).contains_percentage(); + return !item.box.is_replaced_box() && item.preferred_size(dimension).contains_percentage(); } CSSPixels GridFormattingContext::calculate_min_content_size(GridItem const& item, GridDimension dimension) const @@ -3448,7 +3448,7 @@ CSSPixels GridFormattingContext::containing_block_size_for_item(GridItem const& Box const& GridFormattingContext::table_box_inside_table_wrapper(GridItem const& item) const { Optional table_box; - item.box->for_each_in_subtree_of_type([&](Box const& child_box) { + item.box.for_each_in_subtree_of_type([&](Box const& child_box) { if (child_box.display().is_table_inside()) { table_box = child_box; return TraversalDecision::Break; @@ -3461,7 +3461,7 @@ Box const& GridFormattingContext::table_box_inside_table_wrapper(GridItem const& void GridFormattingContext::resolve_table_wrapper_grid_item_width(GridItem& item, CSSPixels containing_block_width) { - VERIFY(is(*item.box)); + VERIFY(is(item.box)); auto table_wrapper_containing_block_width = non_cyclic_containing_block_width_for_table_wrapper(item, containing_block_width); auto available_space = AvailableSpace { @@ -3487,7 +3487,7 @@ void GridFormattingContext::resolve_table_wrapper_grid_item_width(GridItem& item if (!item.minimum_size(GridDimension::Column).is_auto()) table_wrapper_width = max(table_wrapper_width, calculate_inner_width(item.box, available_space.width, item.minimum_size(GridDimension::Column))); - auto const& computed_values = item.box->computed_values(); + auto const& computed_values = item.box.computed_values(); item.used_values.margin_left = computed_values.margin().left().to_px_or_zero(grid_container(), table_wrapper_containing_block_width); item.used_values.margin_right = computed_values.margin().right().to_px_or_zero(grid_container(), table_wrapper_containing_block_width); @@ -3585,7 +3585,7 @@ CSSPixels GridFormattingContext::calculate_min_content_contribution(GridItem con // width contribution is 0 because its content can overflow and scroll horizontally. // This does NOT apply to the row dimension — scroll containers must still contribute // their content height, otherwise grids with height:min-content collapse rows to 0. - if (dimension == GridDimension::Column && item.box->is_scroll_container()) { + if (dimension == GridDimension::Column && item.box.is_scroll_container()) { min_content_size = 0; } else { min_content_size = calculate_min_content_size(item, dimension); @@ -3738,7 +3738,7 @@ Optional GridFormattingContext::specified_size_suggestion(GridItem co // https://www.w3.org/TR/css-grid-1/#specified-size-suggestion // If the item’s preferred size in the relevant axis is definite, then the specified size suggestion is that size. // It is otherwise undefined. - if (!item.box->is_replaced_box() && item.preferred_size(dimension).contains_percentage()) + if (!item.box.is_replaced_box() && item.preferred_size(dimension).contains_percentage()) return {}; auto has_definite_preferred_size = dimension == GridDimension::Column ? item.used_values.has_definite_width() : item.used_values.has_definite_height(); @@ -3757,7 +3757,7 @@ Optional GridFormattingContext::transferred_size_suggestion(GridItem // If the item has a preferred aspect ratio and its preferred size in the opposite axis is definite, then the transferred // size suggestion is that size (clamped by the opposite-axis minimum and maximum sizes if they are definite), converted // through the aspect ratio. It is otherwise undefined. - if (!item.box->preferred_aspect_ratio().has_value()) { + if (!item.box.preferred_aspect_ratio().has_value()) { return {}; } @@ -3765,7 +3765,7 @@ Optional GridFormattingContext::transferred_size_suggestion(GridItem if (preferred_size_in_opposite_axis.is_length()) { auto opposite_axis_size = preferred_size_in_opposite_axis.length().to_px(item.box); // FIXME: Clamp by opposite-axis minimum and maximum sizes if they are definite - return opposite_axis_size * item.box->preferred_aspect_ratio().value(); + return opposite_axis_size * item.box.preferred_aspect_ratio().value(); } return {}; @@ -3823,7 +3823,7 @@ CSSPixels GridFormattingContext::content_based_minimum_size(GridItem const& item // against zero (and considered definite). // FIXME: "compressible replaced element" includes more elements than is_replaced_box(). auto const& preferred_size = item.preferred_size(dimension); - if (item.box->is_replaced_box() && (preferred_size.is_percentage() || maximum_size.is_percentage())) { + if (item.box.is_replaced_box() && (preferred_size.is_percentage() || maximum_size.is_percentage())) { // NOTE: Implements "for this purpose, any indefinite percentages in these sizes are resolved // against zero (and considered definite)." part. result = 0; @@ -3854,7 +3854,7 @@ CSSPixels GridFormattingContext::automatic_minimum_size(GridItem const& item, Gr if (track.min_track_sizing_function.is_auto(available_size)) spans_auto_tracks = true; } - if (spans_auto_tracks && !item.box->is_scroll_container() && (item_track_span == 1 || !spans_flexible_tracks)) { + if (spans_auto_tracks && !item.box.is_scroll_container() && (item_track_span == 1 || !spans_flexible_tracks)) { return content_based_minimum_size(item, dimension); } diff --git a/Libraries/LibWeb/Layout/GridFormattingContext.h b/Libraries/LibWeb/Layout/GridFormattingContext.h index e70fe88778..da233f0ae6 100644 --- a/Libraries/LibWeb/Layout/GridFormattingContext.h +++ b/Libraries/LibWeb/Layout/GridFormattingContext.h @@ -26,7 +26,7 @@ struct GridPosition { }; struct GridItem { - GC::Ref box; + Box const& box; LayoutState::UsedValues& used_values; // Position and span are empty if the item is auto-placed which could only be the case for abspos items @@ -62,7 +62,7 @@ struct GridItem { CSS::ComputedValues const& computed_values() const { - return box->computed_values(); + return box.computed_values(); } CSS::Size const& minimum_size(GridDimension dimension) const diff --git a/Libraries/LibWeb/Layout/ImageBox.cpp b/Libraries/LibWeb/Layout/ImageBox.cpp index 528555458a..be654741e6 100644 --- a/Libraries/LibWeb/Layout/ImageBox.cpp +++ b/Libraries/LibWeb/Layout/ImageBox.cpp @@ -6,6 +6,8 @@ #include #include +#include +#include #include #include #include @@ -13,29 +15,52 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(ImageBox); +static ImageProvider const& image_provider_for_element(DOM::Element const& element) +{ + if (auto const* image = as_if(element)) + return *image; + if (auto const* input = as_if(element)) + return *input; + if (auto const* object = as_if(element)) + return *object; + + VERIFY_NOT_REACHED(); +} ImageBox::ImageBox(DOM::Document& document, GC::Ptr element, CSS::ComputedProperties const& style, ImageProvider const& image_provider) : ReplacedBox(document, element, style) - , m_image_provider(image_provider) { + VERIFY(element); + VERIFY(&image_provider == &image_provider_for_element(*element)); +} + +ImageBox::ImageBox(DOM::Document& document, CSS::ComputedProperties const& style, NonnullOwnPtr image_provider) + : ReplacedBox(document, nullptr, style) + , m_owned_image_provider(move(image_provider)) +{ +} + +ImageProvider const& ImageBox::image_provider() const +{ + if (m_owned_image_provider) + return *m_owned_image_provider; + + auto element = dom_node(); + VERIFY(element); + + return image_provider_for_element(*element); } ImageBox::~ImageBox() = default; -void ImageBox::visit_edges(JS::Cell::Visitor& visitor) -{ - Base::visit_edges(visitor); - m_image_provider.image_provider_visit_edges(visitor); -} - CSS::SizeWithAspectRatio ImageBox::natural_size() const { - if (m_image_provider.is_image_available()) { + auto const& image_provider = this->image_provider(); + if (image_provider.is_image_available()) { return { - .width = m_image_provider.intrinsic_width(), - .height = m_image_provider.intrinsic_height(), - .aspect_ratio = m_image_provider.intrinsic_aspect_ratio() + .width = image_provider.intrinsic_width(), + .height = image_provider.intrinsic_height(), + .aspect_ratio = image_provider.intrinsic_aspect_ratio() }; } @@ -66,7 +91,7 @@ void ImageBox::dom_node_did_update_alt_text(Badge) bool ImageBox::renders_as_alt_text() const { - return !m_image_provider.is_image_available(); + return !image_provider().is_image_available(); } RefPtr ImageBox::create_paintable() const diff --git a/Libraries/LibWeb/Layout/ImageBox.h b/Libraries/LibWeb/Layout/ImageBox.h index 710e1b1f42..5c877de051 100644 --- a/Libraries/LibWeb/Layout/ImageBox.h +++ b/Libraries/LibWeb/Layout/ImageBox.h @@ -6,33 +6,36 @@ #pragma once +#include #include #include namespace Web::Layout { class ImageBox final : public ReplacedBox { - GC_CELL(ImageBox, ReplacedBox); - GC_DECLARE_ALLOCATOR(ImageBox); + LAYOUT_NODE(ImageBox, ReplacedBox); public: ImageBox(DOM::Document&, GC::Ptr, CSS::ComputedProperties const&, ImageProvider const&); + ImageBox(DOM::Document&, CSS::ComputedProperties const&, NonnullOwnPtr); virtual ~ImageBox() override; bool renders_as_alt_text() const; virtual RefPtr create_paintable() const override; - auto const& image_provider() const { return m_image_provider; } - auto& image_provider() { return m_image_provider; } + ImageProvider const& image_provider() const; + ImageProvider& image_provider() + { + return const_cast(const_cast(*this).image_provider()); + } void dom_node_did_update_alt_text(Badge); private: - virtual void visit_edges(Visitor&) override; virtual CSS::SizeWithAspectRatio natural_size() const override; - ImageProvider const& m_image_provider; + OwnPtr m_owned_image_provider; mutable Optional m_cached_alt_text_width; }; diff --git a/Libraries/LibWeb/Layout/ImageProvider.h b/Libraries/LibWeb/Layout/ImageProvider.h index 74e01bed71..31ae2c952a 100644 --- a/Libraries/LibWeb/Layout/ImageProvider.h +++ b/Libraries/LibWeb/Layout/ImageProvider.h @@ -39,11 +39,6 @@ public: virtual void set_visible_in_viewport(bool) = 0; virtual void layout_node_was_detached() const { } - virtual void image_provider_visit_edges(GC::Cell::Visitor& visitor) const - { - visitor.visit(to_html_element()); - } - protected: virtual GC::Ptr to_html_element() const = 0; static void did_update_alt_text(ImageBox&); diff --git a/Libraries/LibWeb/Layout/InlineFormattingContext.cpp b/Libraries/LibWeb/Layout/InlineFormattingContext.cpp index 9eaca74f98..a2b6fb5dba 100644 --- a/Libraries/LibWeb/Layout/InlineFormattingContext.cpp +++ b/Libraries/LibWeb/Layout/InlineFormattingContext.cpp @@ -252,9 +252,9 @@ void InlineFormattingContext::apply_text_overflow_ellipsis(Vector& line // NB: When inline children are wrapped in anonymous blocks (e.g. due to floats), we look past the anonymous // wrapper to the actual element that has text-overflow and overflow set. - GC::Ref block = containing_block(); + Box const* block = &containing_block(); if (block->is_anonymous()) - block = *block->non_anonymous_containing_block(); + block = block->non_anonymous_containing_block(); // FIXME: Support the , fade, and fade() values, as well as the two-value syntax. auto const& block_values = block->computed_values(); @@ -345,8 +345,8 @@ void InlineFormattingContext::generate_line_boxes() auto& line_boxes = m_containing_block_used_values.line_boxes; line_boxes.clear_with_capacity(); - auto direction = m_context_box->computed_values().direction(); - auto writing_mode = m_context_box->computed_values().writing_mode(); + auto direction = m_context_box.computed_values().direction(); + auto writing_mode = m_context_box.computed_values().writing_mode(); InlineLevelIterator iterator(*this, m_state, containing_block(), m_containing_block_used_values, m_layout_mode); LineBuilder line_builder(*this, m_state, m_containing_block_used_values, direction, writing_mode); @@ -570,10 +570,10 @@ StaticPositionRect InlineFormattingContext::calculate_static_position_rect(Box c // We're calculating the position for an absolutely positioned box in an IFC. // Walk backwards through previous siblings to find the most recent one with a line box fragment. LineBoxFragment const* last_fragment = nullptr; - for (auto const* sibling = box.previous_sibling(); sibling && !last_fragment; sibling = sibling->previous_sibling()) { + for (auto sibling = box.previous_sibling(); sibling && !last_fragment; sibling = sibling->previous_sibling()) { for (auto const& line_box : m_containing_block_used_values.line_boxes) { for (auto const& fragment : line_box.fragments()) { - if (&fragment.layout_node() == sibling) + if (&fragment.layout_node() == sibling.ptr()) last_fragment = &fragment; } } diff --git a/Libraries/LibWeb/Layout/InlineLevelIterator.cpp b/Libraries/LibWeb/Layout/InlineLevelIterator.cpp index d9c42bd6bc..6634d79c50 100644 --- a/Libraries/LibWeb/Layout/InlineLevelIterator.cpp +++ b/Libraries/LibWeb/Layout/InlineLevelIterator.cpp @@ -79,7 +79,7 @@ void InlineLevelIterator::enter_node_with_box_model_metrics(Layout::NodeWithStyl // Now's our chance to resolve the inset properties for this node. m_inline_formatting_context.compute_inset(node, m_inline_formatting_context.content_box_rect(m_containing_block_used_values).size()); - m_box_model_node_stack.append(node); + m_box_model_node_stack.append(&node); } void InlineLevelIterator::exit_node_with_box_model_metrics() @@ -87,7 +87,7 @@ void InlineLevelIterator::exit_node_with_box_model_metrics() if (!m_extra_trailing_metrics.has_value()) m_extra_trailing_metrics = ExtraBoxMetrics {}; - auto& node = m_box_model_node_stack.last(); + auto& node = *m_box_model_node_stack.last(); auto& used_values = m_layout_state.get_mutable(node); m_extra_trailing_metrics->margin += used_values.margin_right; @@ -136,7 +136,7 @@ void InlineLevelIterator::compute_next() if (m_next_node == nullptr) return; do { - m_next_node = next_inline_node_in_pre_order(*m_next_node, m_containing_block); + m_next_node = next_inline_node_in_pre_order(*m_next_node, &m_containing_block); if (m_next_node && m_next_node->is_svg_mask_box()) { // NOTE: It is possible to encounter SVGMaskBox nodes while doing layout of formatting context established by with a mask. // We should skip and let SVGFormattingContext take care of them. @@ -206,7 +206,7 @@ Gfx::GlyphRun::TextType InlineLevelIterator::resolve_text_direction_from_context auto last_known_direction = m_text_node_context->last_known_direction; if (last_known_direction.has_value() && next_known_direction.has_value() && *last_known_direction != *next_known_direction) { - switch (m_containing_block->computed_values().direction()) { + switch (m_containing_block.computed_values().direction()) { case CSS::Direction::Ltr: return Gfx::GlyphRun::TextType::Ltr; case CSS::Direction::Rtl: diff --git a/Libraries/LibWeb/Layout/InlineLevelIterator.h b/Libraries/LibWeb/Layout/InlineLevelIterator.h index fa2dbf86cd..f48e53aa4d 100644 --- a/Libraries/LibWeb/Layout/InlineLevelIterator.h +++ b/Libraries/LibWeb/Layout/InlineLevelIterator.h @@ -30,7 +30,7 @@ public: FloatingElement, }; Type type {}; - GC::Ptr node {}; + Layout::Node const* node { nullptr }; RefPtr glyph_run {}; size_t offset_in_node { 0 }; size_t length_in_node { 0 }; @@ -73,10 +73,10 @@ private: Layout::InlineFormattingContext& m_inline_formatting_context; Layout::LayoutState& m_layout_state; - GC::Ref m_containing_block; + BlockContainer const& m_containing_block; LayoutState::UsedValues const& m_containing_block_used_values; - GC::Ptr m_current_node; - GC::Ptr m_next_node; + Layout::Node const* m_current_node { nullptr }; + Layout::Node const* m_next_node { nullptr }; LayoutMode const m_layout_mode; struct TextNodeContext { @@ -99,7 +99,7 @@ private: Optional m_extra_leading_metrics; Optional m_extra_trailing_metrics; - Vector> m_box_model_node_stack; + Vector m_box_model_node_stack; // Pre-generated items for O(1) iteration and lookahead. Vector m_items; diff --git a/Libraries/LibWeb/Layout/InlineNode.cpp b/Libraries/LibWeb/Layout/InlineNode.cpp index 00e5a3f755..be10dd4784 100644 --- a/Libraries/LibWeb/Layout/InlineNode.cpp +++ b/Libraries/LibWeb/Layout/InlineNode.cpp @@ -14,8 +14,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(InlineNode); - InlineNode::InlineNode(DOM::Document& document, DOM::Element* element, CSS::ComputedProperties const& style) : Layout::NodeWithStyleAndBoxModelMetrics(document, element, style) { diff --git a/Libraries/LibWeb/Layout/InlineNode.h b/Libraries/LibWeb/Layout/InlineNode.h index de8173b47d..715b8a5b02 100644 --- a/Libraries/LibWeb/Layout/InlineNode.h +++ b/Libraries/LibWeb/Layout/InlineNode.h @@ -11,8 +11,7 @@ namespace Web::Layout { class InlineNode final : public NodeWithStyleAndBoxModelMetrics { - GC_CELL(InlineNode, NodeWithStyleAndBoxModelMetrics); - GC_DECLARE_ALLOCATOR(InlineNode); + LAYOUT_NODE(InlineNode, NodeWithStyleAndBoxModelMetrics); public: InlineNode(DOM::Document&, DOM::Element*, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/LayoutState.cpp b/Libraries/LibWeb/Layout/LayoutState.cpp index 1d3b5d25e5..99295db88c 100644 --- a/Libraries/LibWeb/Layout/LayoutState.cpp +++ b/Libraries/LibWeb/Layout/LayoutState.cpp @@ -425,7 +425,7 @@ static void build_paint_tree(Node& node, RefPtr parent_pain if (node.dom_node()) node.dom_node()->set_paintable(paintable); } - for (auto* child = node.first_child(); child; child = child->next_sibling()) { + for (auto child = node.first_child(); child; child = child->next_sibling()) { build_paint_tree(*child, node.first_paintable()); } } @@ -744,8 +744,8 @@ void LayoutState::commit(Box& root) auto const* box = as_if(used_values.node()); if (!box || !box->paintable_box()) return; - if (auto containing_block = box->containing_block()) - contained_boxes_map.ensure(containing_block.ptr()).append(box); + if (auto const* containing_block = box->containing_block()) + contained_boxes_map.ensure(containing_block).append(box); }); // Measure overflow in scroll containers. diff --git a/Libraries/LibWeb/Layout/LayoutState.h b/Libraries/LibWeb/Layout/LayoutState.h index 3eea491eda..091f74afc1 100644 --- a/Libraries/LibWeb/Layout/LayoutState.h +++ b/Libraries/LibWeb/Layout/LayoutState.h @@ -229,9 +229,9 @@ struct LayoutState { } void add_floating_descendant(Box const& box) { ensure_rare_data().floating_descendants.set(&box); } - HashTable> const& floating_descendants() const + HashTable const& floating_descendants() const { - static auto const& empty = *new HashTable>; + static auto const& empty = *new HashTable; return m_rare ? m_rare->floating_descendants : empty; } @@ -349,7 +349,7 @@ struct LayoutState { flex_layout_data = make(*other.flex_layout_data); } - HashTable> floating_descendants; + HashTable floating_descendants; Optional table_cell_coordinates; Optional computed_svg_path; OwnPtr grid_layout_data; @@ -370,7 +370,7 @@ struct LayoutState { return *m_rare; } - GC::Ptr m_node { nullptr }; + Layout::NodeWithStyle const* m_node { nullptr }; UsedValues const* m_containing_block_used_values { nullptr }; Optional m_cumulative_offset; @@ -410,7 +410,7 @@ private: void resolve_relative_positions(); PagedStore m_used_values_store; - GC::Ptr m_subtree_root; + Layout::NodeWithStyle const* m_subtree_root { nullptr }; bool m_should_collect_devtools_layout_data { false }; }; diff --git a/Libraries/LibWeb/Layout/LegendBox.cpp b/Libraries/LibWeb/Layout/LegendBox.cpp index 36572be881..950d5de495 100644 --- a/Libraries/LibWeb/Layout/LegendBox.cpp +++ b/Libraries/LibWeb/Layout/LegendBox.cpp @@ -8,8 +8,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(LegendBox); - LegendBox::LegendBox(DOM::Document& document, DOM::Element& element, CSS::ComputedProperties const& style) : BlockContainer(document, &element, style) { diff --git a/Libraries/LibWeb/Layout/LegendBox.h b/Libraries/LibWeb/Layout/LegendBox.h index 21f4275e08..61db9a9f0c 100644 --- a/Libraries/LibWeb/Layout/LegendBox.h +++ b/Libraries/LibWeb/Layout/LegendBox.h @@ -12,8 +12,7 @@ namespace Web::Layout { class LegendBox final : public BlockContainer { - GC_CELL(LegendBox, BlockContainer); - GC_DECLARE_ALLOCATOR(LegendBox); + LAYOUT_NODE(LegendBox, BlockContainer); public: LegendBox(DOM::Document&, DOM::Element&, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/LineBoxFragment.h b/Libraries/LibWeb/Layout/LineBoxFragment.h index f95ecd9417..3b472c3d97 100644 --- a/Libraries/LibWeb/Layout/LineBoxFragment.h +++ b/Libraries/LibWeb/Layout/LineBoxFragment.h @@ -6,6 +6,8 @@ #pragma once +#include +#include #include #include #include @@ -20,7 +22,11 @@ class LineBoxFragment { public: LineBoxFragment(Node const& layout_node, size_t start, size_t length, CSSPixels inline_offset, CSSPixels block_offset, CSSPixels inline_length, CSSPixels block_length, CSSPixels border_box_top, CSS::Direction, CSS::WritingMode, RefPtr); - Node const& layout_node() const { return m_layout_node; } + Node const& layout_node() const + { + VERIFY(m_layout_node); + return *m_layout_node; + } size_t start() const { return m_start; } size_t length_in_code_units() const { return m_length_in_code_units; } @@ -65,7 +71,7 @@ private: void append_glyph_run_ltr(RefPtr const&, CSSPixels run_width); void append_glyph_run_rtl(RefPtr const&, CSSPixels run_width); - GC::Ref m_layout_node; + WeakPtr m_layout_node; size_t m_start { 0 }; size_t m_length_in_code_units { 0 }; CSSPixels m_inline_offset; diff --git a/Libraries/LibWeb/Layout/ListItemBox.cpp b/Libraries/LibWeb/Layout/ListItemBox.cpp index 632e9283eb..ebc86c91c2 100644 --- a/Libraries/LibWeb/Layout/ListItemBox.cpp +++ b/Libraries/LibWeb/Layout/ListItemBox.cpp @@ -10,8 +10,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(ListItemBox); - ListItemBox::ListItemBox(DOM::Document& document, DOM::Element* element, CSS::ComputedProperties const& style) : Layout::BlockContainer(document, element, style) { @@ -19,15 +17,9 @@ ListItemBox::ListItemBox(DOM::Document& document, DOM::Element* element, CSS::Co ListItemBox::~ListItemBox() = default; -void ListItemBox::visit_edges(Cell::Visitor& visitor) +void ListItemBox::set_marker(ListItemMarkerBox* marker) { - Base::visit_edges(visitor); - visitor.visit(m_marker); -} - -void ListItemBox::set_marker(GC::Ptr marker) -{ - m_marker = move(marker); + m_marker = marker; } } diff --git a/Libraries/LibWeb/Layout/ListItemBox.h b/Libraries/LibWeb/Layout/ListItemBox.h index edd9380fc0..6ba2f0134c 100644 --- a/Libraries/LibWeb/Layout/ListItemBox.h +++ b/Libraries/LibWeb/Layout/ListItemBox.h @@ -12,8 +12,7 @@ namespace Web::Layout { class ListItemBox final : public BlockContainer { - GC_CELL(ListItemBox, BlockContainer); - GC_DECLARE_ALLOCATOR(ListItemBox); + LAYOUT_NODE(ListItemBox, BlockContainer); public: ListItemBox(DOM::Document&, DOM::Element*, CSS::ComputedProperties const&); @@ -23,14 +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(GC::Ptr); + void set_marker(ListItemMarkerBox*); private: virtual bool is_list_item_box() const override { return true; } - virtual void visit_edges(Cell::Visitor&) override; - - GC::Ptr m_marker; + WeakPtr m_marker; }; template<> diff --git a/Libraries/LibWeb/Layout/ListItemMarkerBox.cpp b/Libraries/LibWeb/Layout/ListItemMarkerBox.cpp index c524488986..0bc2702526 100644 --- a/Libraries/LibWeb/Layout/ListItemMarkerBox.cpp +++ b/Libraries/LibWeb/Layout/ListItemMarkerBox.cpp @@ -12,8 +12,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(ListItemMarkerBox); - ListItemMarkerBox::ListItemMarkerBox(DOM::Document& document, CSS::ListStyleType style_type, CSS::ListStylePosition style_position, GC::Ref list_item_element, CSS::ComputedProperties const& style) : Box(document, nullptr, style) , m_list_style_type(style_type) @@ -41,6 +39,8 @@ bool ListItemMarkerBox::counter_style_is_rendered_with_custom_image(RefPtr ListItemMarkerBox::text() const { + VERIFY(m_list_item_element); + // https://drafts.csswg.org/css-lists-3/#text-markers auto index = m_list_item_element->ordinal_value(); @@ -61,7 +61,7 @@ Optional ListItemMarkerBox::text() const return {}; // NB: Fallback to decimal if the counter style does not exist is handled within generate_a_counter_representation() - auto counter_representation = CSS::generate_a_counter_representation(counter_style, DOM::AbstractElement { m_list_item_element }.style_scope(), index); + auto counter_representation = CSS::generate_a_counter_representation(counter_style, DOM::AbstractElement { *m_list_item_element }.style_scope(), index); if (!counter_style) return MUST(String::formatted("{}. ", counter_representation)); @@ -109,10 +109,4 @@ CSSPixels ListItemMarkerBox::relative_size() const VERIFY_NOT_REACHED(); } -void ListItemMarkerBox::visit_edges(Cell::Visitor& visitor) -{ - Base::visit_edges(visitor); - visitor.visit(m_list_item_element); -} - } diff --git a/Libraries/LibWeb/Layout/ListItemMarkerBox.h b/Libraries/LibWeb/Layout/ListItemMarkerBox.h index 05f2e2935d..cb2ab3df1c 100644 --- a/Libraries/LibWeb/Layout/ListItemMarkerBox.h +++ b/Libraries/LibWeb/Layout/ListItemMarkerBox.h @@ -13,8 +13,7 @@ namespace Web::Layout { class ListItemMarkerBox final : public Box { - GC_CELL(ListItemMarkerBox, Box); - GC_DECLARE_ALLOCATOR(ListItemMarkerBox); + LAYOUT_NODE(ListItemMarkerBox, Box); public: static bool counter_style_is_rendered_with_custom_image(RefPtr const& counter_style); @@ -32,14 +31,12 @@ public: CSSPixels relative_size() const; private: - virtual void visit_edges(Cell::Visitor&) override; - virtual bool is_list_item_marker_box() const final { return true; } virtual bool can_have_children() const override { return false; } CSS::ListStyleType m_list_style_type; CSS::ListStylePosition m_list_style_position { CSS::ListStylePosition::Outside }; - GC::Ref m_list_item_element; + GC::Weak m_list_item_element; }; template<> diff --git a/Libraries/LibWeb/Layout/NavigableContainerViewport.cpp b/Libraries/LibWeb/Layout/NavigableContainerViewport.cpp index e82c349456..15e5b0388e 100644 --- a/Libraries/LibWeb/Layout/NavigableContainerViewport.cpp +++ b/Libraries/LibWeb/Layout/NavigableContainerViewport.cpp @@ -15,8 +15,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(NavigableContainerViewport); - NavigableContainerViewport::NavigableContainerViewport(DOM::Document& document, HTML::NavigableContainer& element, CSS::ComputedProperties const& style) : ReplacedBox(document, element, style) { diff --git a/Libraries/LibWeb/Layout/NavigableContainerViewport.h b/Libraries/LibWeb/Layout/NavigableContainerViewport.h index adcea78200..c47db79a60 100644 --- a/Libraries/LibWeb/Layout/NavigableContainerViewport.h +++ b/Libraries/LibWeb/Layout/NavigableContainerViewport.h @@ -12,8 +12,7 @@ namespace Web::Layout { class NavigableContainerViewport final : public ReplacedBox { - GC_CELL(NavigableContainerViewport, ReplacedBox); - GC_DECLARE_ALLOCATOR(NavigableContainerViewport); + LAYOUT_NODE(NavigableContainerViewport, ReplacedBox); public: NavigableContainerViewport(DOM::Document&, HTML::NavigableContainer&, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/Node.cpp b/Libraries/LibWeb/Layout/Node.cpp index a0b258b1d9..2e177618de 100644 --- a/Libraries/LibWeb/Layout/Node.cpp +++ b/Libraries/LibWeb/Layout/Node.cpp @@ -55,7 +55,11 @@ Node::Node(DOM::Document& document, DOM::Node* node, AttachToDOMNode attach_to_d node->set_layout_node({}, *this); } -Node::~Node() = default; +Node::~Node() +{ + for (auto& paintable : m_paintable) + paintable->detach_from_layout_node({}); +} static void invalidate_paint_caches(Node& node) { @@ -82,16 +86,6 @@ void Node::prepare_subtree_for_detach_from_layout_tree() }); } -void Node::visit_edges(Cell::Visitor& visitor) -{ - Base::visit_edges(visitor); - visitor.visit(m_dom_node); - visitor.visit(m_containing_block); - visitor.visit(m_inline_containing_block_if_applicable); - visitor.visit(m_pseudo_element_generator); - TreeNode::visit_edges(visitor); -} - // https://www.w3.org/TR/css-display-3/#out-of-flow bool Node::is_out_of_flow(FormattingContext const& formatting_context) const { @@ -269,14 +263,14 @@ bool Node::establishes_a_fixed_positioning_containing_block() const return false; } -static GC::Ptr nearest_ancestor_capable_of_forming_a_containing_block(Node& node) +static Box* nearest_ancestor_capable_of_forming_a_containing_block(Node& node) { for (auto* ancestor = node.parent(); ancestor; ancestor = ancestor->parent()) { if (ancestor->is_block_container() || ancestor->display().is_flex_inside() || ancestor->display().is_grid_inside() || ancestor->is_replaced_box_with_children()) { - return as(ancestor); + return static_cast(ancestor); } } return nullptr; @@ -357,7 +351,7 @@ void Node::recompute_containing_block(Badge) || computed_values.filter().has_filters() || will_change.has_property(CSS::PropertyID::Filter) || computed_values.backdrop_filter().has_filters() || will_change.has_property(CSS::PropertyID::BackdropFilter); if (inline_establishes_cb) { - m_inline_containing_block_if_applicable = const_cast(static_cast(layout_node.ptr())); + m_inline_containing_block_if_applicable = &as(*layout_node); break; } } @@ -655,14 +649,8 @@ void NodeWithStyle::ImageObserver::image_style_value_did_update(CSS::ImageStyleV } } -void NodeWithStyle::ImageObserver::visit_edges(JS::Cell::Visitor& visitor) const +NodeWithStyle::~NodeWithStyle() { - (void)visitor; -} - -void NodeWithStyle::finalize() -{ - Base::finalize(); clear_image_observers(); } @@ -697,11 +685,6 @@ void NodeWithStyle::rebuild_image_observers() m_image_observers = move(new_observers); } -void NodeWithStyle::visit_edges(Visitor& visitor) -{ - Base::visit_edges(visitor); -} - void NodeWithStyle::apply_style(CSS::ComputedProperties const& computed_style) { auto& computed_values = mutable_computed_values(); @@ -1219,9 +1202,9 @@ bool Node::is_atomic_inline() const return display.is_inline_outside() && !display.is_flow_inside(); } -GC::Ref NodeWithStyle::create_anonymous_wrapper() const +NonnullRefPtr NodeWithStyle::create_anonymous_wrapper() const { - auto wrapper = heap().allocate(const_cast(document()), nullptr, computed_values().clone_inherited_values()); + auto wrapper = adopt_ref(*new BlockContainer(const_cast(document()), nullptr, computed_values().clone_inherited_values())); wrapper->mutable_computed_values().set_display(CSS::Display(CSS::DisplayOutside::Block, CSS::DisplayInside::Flow)); propagate_non_inherit_values(*wrapper); // CSS 2.2 9.2.1.1 creates anonymous block boxes, but 9.4.1 states inline-block creates a BFC. @@ -1354,6 +1337,7 @@ DOM::Node const* Node::dom_node() const { if (m_anonymous) return nullptr; + VERIFY(m_dom_node); return m_dom_node.ptr(); } @@ -1361,28 +1345,39 @@ DOM::Node* Node::dom_node() { if (m_anonymous) return nullptr; + VERIFY(m_dom_node); return m_dom_node.ptr(); } DOM::Element const* Node::pseudo_element_generator() const { VERIFY(m_generated_for.has_value()); + VERIFY(m_pseudo_element_generator); return m_pseudo_element_generator.ptr(); } DOM::Element* Node::pseudo_element_generator() { VERIFY(m_generated_for.has_value()); + VERIFY(m_pseudo_element_generator); return m_pseudo_element_generator.ptr(); } +void Node::set_generated_for(CSS::PseudoElement type, DOM::Element& element) +{ + m_generated_for = type; + m_pseudo_element_generator = element; +} + DOM::Document& Node::document() { + VERIFY(m_dom_node); return m_dom_node->document(); } DOM::Document const& Node::document() const { + VERIFY(m_dom_node); return m_dom_node->document(); } @@ -1614,12 +1609,6 @@ void NodeWithStyleAndBoxModelMetrics::propagate_style_along_continuation(CSS::Co continuation->apply_style(computed_style); } -void NodeWithStyleAndBoxModelMetrics::visit_edges(Cell::Visitor& visitor) -{ - Base::visit_edges(visitor); - visitor.visit(m_continuation_of_node); -} - void Node::set_needs_layout_update(DOM::SetNeedsLayoutReason reason) { if (m_needs_layout_update) diff --git a/Libraries/LibWeb/Layout/Node.h b/Libraries/LibWeb/Layout/Node.h index c1c9d33f0f..d987b13728 100644 --- a/Libraries/LibWeb/Layout/Node.h +++ b/Libraries/LibWeb/Layout/Node.h @@ -10,19 +10,30 @@ #include #include #include +#include #include +#include +#include +#include #include -#include #include #include #include #include #include #include -#include +#include namespace Web::Layout { +#define LAYOUT_NODE(class_, base_class) \ +public: \ + using Base = base_class; \ + virtual StringView class_name() const override \ + { \ + return #class_##sv; \ + } + class InlineNode; enum class LayoutMode { @@ -37,12 +48,15 @@ enum class LayoutMode { }; class WEB_API Node - : public JS::Cell - , public TreeNode { - GC_CELL(Node, JS::Cell); + : public RefCounted + , public Weakable + , public RefCountedTreeNode { public: + using Base = RefCountedTreeNode; + virtual ~Node(); + virtual StringView class_name() const { return "Node"sv; } bool is_anonymous() const; DOM::Node const* dom_node() const; @@ -60,11 +74,7 @@ public: bool is_generated_for_before_pseudo_element() const { return m_generated_for == CSS::PseudoElement::Before; } bool is_generated_for_after_pseudo_element() const { return m_generated_for == CSS::PseudoElement::After; } bool is_generated_for_backdrop_pseudo_element() const { return m_generated_for == CSS::PseudoElement::Backdrop; } - void set_generated_for(CSS::PseudoElement type, DOM::Element& element) - { - m_generated_for = type; - m_pseudo_element_generator = &element; - } + void set_generated_for(CSS::PseudoElement type, DOM::Element&); using PaintableList = DoublyLinkedList>; @@ -176,15 +186,15 @@ public: return true; } - [[nodiscard]] GC::Ptr containing_block() const { return m_containing_block; } - [[nodiscard]] GC::Ptr containing_block() { return m_containing_block; } + [[nodiscard]] Box const* containing_block() const { return m_containing_block; } + [[nodiscard]] Box* containing_block() { return m_containing_block; } // Returns the inline node that actually establishes the containing block for this absolutely // positioned element, if applicable. This is needed because m_containing_block can only hold // a Box*, but CSS allows inline elements (like a with position:relative) to establish // containing blocks for their absolutely positioned descendants. // See the large FIXME comment in FormattingContext.cpp for full context. - [[nodiscard]] GC::Ptr inline_containing_block_if_applicable() const { return m_inline_containing_block_if_applicable; } + [[nodiscard]] InlineNode const* inline_containing_block_if_applicable() const { return m_inline_containing_block_if_applicable; } void recompute_containing_block(Badge); @@ -260,24 +270,22 @@ public: protected: Node(DOM::Document&, DOM::Node*, AttachToDOMNode = AttachToDOMNode::Yes); - virtual void visit_edges(Cell::Visitor&) override; - private: friend class NodeWithStyle; - GC::Ref m_dom_node; + GC::Weak m_dom_node; PaintableList m_paintable; - GC::Ptr m_containing_block; + Box* m_containing_block { nullptr }; // For absolutely positioned elements, if there's an inline element (like a with // position:relative) that should be the containing block but can't be stored in m_containing_block // (because it's not a Box), we store it here. This happens when a block element is inside an // inline element - the layout tree restructures so the block becomes a sibling of the inline, // but the CSS containing block relationship is based on the DOM structure. - GC::Ptr m_inline_containing_block_if_applicable; + InlineNode const* m_inline_containing_block_if_applicable { nullptr }; - GC::Ptr m_pseudo_element_generator; + GC::Weak m_pseudo_element_generator; bool m_anonymous { false }; bool m_has_style { false }; @@ -297,12 +305,10 @@ private: }; class WEB_API NodeWithStyle : public Node { - GC_CELL(NodeWithStyle, Node); + LAYOUT_NODE(NodeWithStyle, Node); public: - virtual ~NodeWithStyle() override = default; - - static constexpr bool OVERRIDES_FINALIZE = true; + virtual ~NodeWithStyle() override; class ImageObserver final : public CSS::ImageStyleValue::Client { public: @@ -310,10 +316,9 @@ public: virtual ~ImageObserver() override; virtual void image_style_value_did_update(CSS::ImageStyleValue&) override; - void visit_edges(JS::Cell::Visitor&) const; private: - GC::Weak m_owner; + WeakPtr m_owner; NonnullRefPtr m_image; }; @@ -328,15 +333,13 @@ public: CSS::AbstractImageStyleValue const* list_style_image() const { return m_list_style_image; } CSS::StyleScope const& style_scope() const; - GC::Ref create_anonymous_wrapper() const; + NonnullRefPtr create_anonymous_wrapper() const; void transfer_table_box_computed_values_to_wrapper_computed_values(CSS::ComputedValues& wrapper_computed_values); bool is_body() const { return m_is_body; } bool is_scroll_container() const; - virtual void visit_edges(Cell::Visitor& visitor) override; - void set_computed_values(NonnullOwnPtr); u32 layout_index() const { return m_layout_index; } @@ -348,7 +351,6 @@ protected: private: virtual bool is_node_with_style() const final { return true; } - virtual void finalize() override; void reset_table_box_computed_values_used_by_wrapper_to_init_values(); void propagate_non_inherit_values(NodeWithStyle& target_node) const; @@ -366,18 +368,16 @@ template<> inline bool Node::fast_is() const { return is_node_with_style(); } class NodeWithStyleAndBoxModelMetrics : public NodeWithStyle { - GC_CELL(NodeWithStyleAndBoxModelMetrics, NodeWithStyle); + LAYOUT_NODE(NodeWithStyleAndBoxModelMetrics, NodeWithStyle); public: - GC::Ptr continuation_of_node() const { return m_continuation_of_node; } - void set_continuation_of_node(Badge, GC::Ptr node) { m_continuation_of_node = node; } + NodeWithStyleAndBoxModelMetrics* continuation_of_node() const { return m_continuation_of_node.ptr(); } + void set_continuation_of_node(Badge, NodeWithStyleAndBoxModelMetrics* node) { m_continuation_of_node = node; } bool should_create_inline_continuation() const; void propagate_style_along_continuation(CSS::ComputedProperties const&) const; - virtual void visit_edges(Cell::Visitor& visitor) override; - protected: NodeWithStyleAndBoxModelMetrics(DOM::Document&, DOM::Node*, CSS::ComputedProperties const&); @@ -389,7 +389,7 @@ protected: private: virtual bool is_node_with_style_and_box_model_metrics() const final { return true; } - GC::Ptr m_continuation_of_node; + WeakPtr m_continuation_of_node; }; template<> @@ -430,12 +430,12 @@ inline CSS::ImmutableComputedValues const& Node::computed_values() const inline NodeWithStyle const* Node::parent() const { - return static_cast(TreeNode::parent()); + return static_cast(Base::parent().ptr()); } inline NodeWithStyle* Node::parent() { - return static_cast(TreeNode::parent()); + return static_cast(Base::parent().ptr()); } inline Gfx::Font const& NodeWithStyle::first_available_font() const diff --git a/Libraries/LibWeb/Layout/RadioButton.cpp b/Libraries/LibWeb/Layout/RadioButton.cpp index d248de9827..192d3acaf1 100644 --- a/Libraries/LibWeb/Layout/RadioButton.cpp +++ b/Libraries/LibWeb/Layout/RadioButton.cpp @@ -12,8 +12,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(RadioButton); - RadioButton::RadioButton(DOM::Document& document, HTML::HTMLInputElement& element, CSS::ComputedProperties const& style) : ReplacedBox(document, element, style) { diff --git a/Libraries/LibWeb/Layout/RadioButton.h b/Libraries/LibWeb/Layout/RadioButton.h index 2b4bb60c45..3463c2aae6 100644 --- a/Libraries/LibWeb/Layout/RadioButton.h +++ b/Libraries/LibWeb/Layout/RadioButton.h @@ -12,8 +12,7 @@ namespace Web::Layout { class RadioButton final : public ReplacedBox { - GC_CELL(RadioButton, ReplacedBox); - GC_DECLARE_ALLOCATOR(RadioButton); + LAYOUT_NODE(RadioButton, ReplacedBox); public: RadioButton(DOM::Document&, HTML::HTMLInputElement&, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/RangeInputBox.cpp b/Libraries/LibWeb/Layout/RangeInputBox.cpp index 277ca98857..6400c79ea0 100644 --- a/Libraries/LibWeb/Layout/RangeInputBox.cpp +++ b/Libraries/LibWeb/Layout/RangeInputBox.cpp @@ -8,8 +8,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(RangeInputBox); - RangeInputBox::RangeInputBox(DOM::Document& document, GC::Ptr element, CSS::ComputedProperties const& style) : BlockContainer(document, element, style) { diff --git a/Libraries/LibWeb/Layout/RangeInputBox.h b/Libraries/LibWeb/Layout/RangeInputBox.h index 99e1a2edc0..a6e54fe6ab 100644 --- a/Libraries/LibWeb/Layout/RangeInputBox.h +++ b/Libraries/LibWeb/Layout/RangeInputBox.h @@ -12,8 +12,7 @@ namespace Web::Layout { class RangeInputBox final : public BlockContainer { - GC_CELL(RangeInputBox, BlockContainer); - GC_DECLARE_ALLOCATOR(RangeInputBox); + LAYOUT_NODE(RangeInputBox, BlockContainer); public: RangeInputBox(DOM::Document&, GC::Ptr, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/ReplacedBox.h b/Libraries/LibWeb/Layout/ReplacedBox.h index 0838ccff42..6d947fe24f 100644 --- a/Libraries/LibWeb/Layout/ReplacedBox.h +++ b/Libraries/LibWeb/Layout/ReplacedBox.h @@ -12,7 +12,7 @@ namespace Web::Layout { class ReplacedBox : public Box { - GC_CELL(ReplacedBox, Box); + LAYOUT_NODE(ReplacedBox, Box); public: ReplacedBox(DOM::Document&, GC::Ptr, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/SVGBox.cpp b/Libraries/LibWeb/Layout/SVGBox.cpp index 892e5f175e..44c5d0fc18 100644 --- a/Libraries/LibWeb/Layout/SVGBox.cpp +++ b/Libraries/LibWeb/Layout/SVGBox.cpp @@ -8,8 +8,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(SVGBox); - SVGBox::SVGBox(DOM::Document& document, SVG::SVGElement& element, CSS::ComputedProperties const& style) : Box(document, &element, style) { diff --git a/Libraries/LibWeb/Layout/SVGBox.h b/Libraries/LibWeb/Layout/SVGBox.h index 2687d54dfa..22b25c0de5 100644 --- a/Libraries/LibWeb/Layout/SVGBox.h +++ b/Libraries/LibWeb/Layout/SVGBox.h @@ -13,8 +13,7 @@ namespace Web::Layout { class SVGBox : public Box { - GC_CELL(SVGBox, Box); - GC_DECLARE_ALLOCATOR(SVGBox); + LAYOUT_NODE(SVGBox, Box); public: SVGBox(DOM::Document&, SVG::SVGElement&, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/SVGClipBox.cpp b/Libraries/LibWeb/Layout/SVGClipBox.cpp index c29950a51c..8dd8f3d27c 100644 --- a/Libraries/LibWeb/Layout/SVGClipBox.cpp +++ b/Libraries/LibWeb/Layout/SVGClipBox.cpp @@ -10,8 +10,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(SVGClipBox); - SVGClipBox::SVGClipBox(DOM::Document& document, SVG::SVGClipPathElement& element, CSS::ComputedProperties const& style) : SVGBox(document, element, style) { diff --git a/Libraries/LibWeb/Layout/SVGClipBox.h b/Libraries/LibWeb/Layout/SVGClipBox.h index 0d812f94ff..be14e0d7c2 100644 --- a/Libraries/LibWeb/Layout/SVGClipBox.h +++ b/Libraries/LibWeb/Layout/SVGClipBox.h @@ -13,8 +13,7 @@ namespace Web::Layout { class SVGClipBox final : public SVGBox { - GC_CELL(SVGClipBox, SVGBox); - GC_DECLARE_ALLOCATOR(SVGClipBox); + LAYOUT_NODE(SVGClipBox, SVGBox); public: SVGClipBox(DOM::Document&, SVG::SVGClipPathElement&, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/SVGForeignObjectBox.cpp b/Libraries/LibWeb/Layout/SVGForeignObjectBox.cpp index 080b61304b..c78e9d9eed 100644 --- a/Libraries/LibWeb/Layout/SVGForeignObjectBox.cpp +++ b/Libraries/LibWeb/Layout/SVGForeignObjectBox.cpp @@ -10,8 +10,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(SVGForeignObjectBox); - SVGForeignObjectBox::SVGForeignObjectBox(DOM::Document& document, SVG::SVGForeignObjectElement& element, CSS::ComputedProperties const& style) : BlockContainer(document, &element, style) { diff --git a/Libraries/LibWeb/Layout/SVGForeignObjectBox.h b/Libraries/LibWeb/Layout/SVGForeignObjectBox.h index dc07a81a59..e1deb68cf3 100644 --- a/Libraries/LibWeb/Layout/SVGForeignObjectBox.h +++ b/Libraries/LibWeb/Layout/SVGForeignObjectBox.h @@ -14,8 +14,7 @@ namespace Web::Layout { class SVGForeignObjectBox final : public BlockContainer { - GC_CELL(SVGForeignObjectBox, BlockContainer); - GC_DECLARE_ALLOCATOR(SVGForeignObjectBox); + LAYOUT_NODE(SVGForeignObjectBox, BlockContainer); public: SVGForeignObjectBox(DOM::Document&, SVG::SVGForeignObjectElement&, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/SVGGeometryBox.cpp b/Libraries/LibWeb/Layout/SVGGeometryBox.cpp index 6ac0782a20..81b4bdc8a4 100644 --- a/Libraries/LibWeb/Layout/SVGGeometryBox.cpp +++ b/Libraries/LibWeb/Layout/SVGGeometryBox.cpp @@ -12,8 +12,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(SVGGeometryBox); - SVGGeometryBox::SVGGeometryBox(DOM::Document& document, SVG::SVGGeometryElement& element, CSS::ComputedProperties const& style) : SVGGraphicsBox(document, element, style) { diff --git a/Libraries/LibWeb/Layout/SVGGeometryBox.h b/Libraries/LibWeb/Layout/SVGGeometryBox.h index 8f0daf8db9..5535b7cbb2 100644 --- a/Libraries/LibWeb/Layout/SVGGeometryBox.h +++ b/Libraries/LibWeb/Layout/SVGGeometryBox.h @@ -13,8 +13,7 @@ namespace Web::Layout { class SVGGeometryBox final : public SVGGraphicsBox { - GC_CELL(SVGGeometryBox, SVGGraphicsBox); - GC_DECLARE_ALLOCATOR(SVGGeometryBox); + LAYOUT_NODE(SVGGeometryBox, SVGGraphicsBox); public: SVGGeometryBox(DOM::Document&, SVG::SVGGeometryElement&, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/SVGGraphicsBox.cpp b/Libraries/LibWeb/Layout/SVGGraphicsBox.cpp index fcfe791a3b..5c69b9b36d 100644 --- a/Libraries/LibWeb/Layout/SVGGraphicsBox.cpp +++ b/Libraries/LibWeb/Layout/SVGGraphicsBox.cpp @@ -10,8 +10,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(SVGGraphicsBox); - SVGGraphicsBox::SVGGraphicsBox(DOM::Document& document, SVG::SVGGraphicsElement& element, CSS::ComputedProperties const& style) : SVGBox(document, element, style) { diff --git a/Libraries/LibWeb/Layout/SVGGraphicsBox.h b/Libraries/LibWeb/Layout/SVGGraphicsBox.h index d2aee036da..a48c62199c 100644 --- a/Libraries/LibWeb/Layout/SVGGraphicsBox.h +++ b/Libraries/LibWeb/Layout/SVGGraphicsBox.h @@ -14,8 +14,7 @@ namespace Web::Layout { class WEB_API SVGGraphicsBox : public SVGBox { - GC_CELL(SVGGraphicsBox, SVGBox); - GC_DECLARE_ALLOCATOR(SVGGraphicsBox); + LAYOUT_NODE(SVGGraphicsBox, SVGBox); public: SVGGraphicsBox(DOM::Document&, SVG::SVGGraphicsElement&, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/SVGImageBox.cpp b/Libraries/LibWeb/Layout/SVGImageBox.cpp index d85a3e2152..434d7436c7 100644 --- a/Libraries/LibWeb/Layout/SVGImageBox.cpp +++ b/Libraries/LibWeb/Layout/SVGImageBox.cpp @@ -11,8 +11,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(SVGImageBox); - SVGImageBox::SVGImageBox(DOM::Document& document, SVG::SVGGraphicsElement& element, CSS::ComputedProperties const& style) : SVGGraphicsBox(document, element, style) { diff --git a/Libraries/LibWeb/Layout/SVGImageBox.h b/Libraries/LibWeb/Layout/SVGImageBox.h index efbb21111d..e892b4cb2a 100644 --- a/Libraries/LibWeb/Layout/SVGImageBox.h +++ b/Libraries/LibWeb/Layout/SVGImageBox.h @@ -13,8 +13,7 @@ namespace Web::Layout { class SVGImageBox : public SVGGraphicsBox { - GC_CELL(SVGImageBox, SVGGraphicsBox); - GC_DECLARE_ALLOCATOR(SVGImageBox); + LAYOUT_NODE(SVGImageBox, SVGGraphicsBox); public: SVGImageBox(DOM::Document&, SVG::SVGGraphicsElement&, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/SVGMaskBox.cpp b/Libraries/LibWeb/Layout/SVGMaskBox.cpp index 91c4a064da..12409c3abe 100644 --- a/Libraries/LibWeb/Layout/SVGMaskBox.cpp +++ b/Libraries/LibWeb/Layout/SVGMaskBox.cpp @@ -10,8 +10,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(SVGMaskBox); - SVGMaskBox::SVGMaskBox(DOM::Document& document, SVG::SVGMaskElement& element, CSS::ComputedProperties const& style) : SVGGraphicsBox(document, element, style) { diff --git a/Libraries/LibWeb/Layout/SVGMaskBox.h b/Libraries/LibWeb/Layout/SVGMaskBox.h index a9690fd694..224c7b101f 100644 --- a/Libraries/LibWeb/Layout/SVGMaskBox.h +++ b/Libraries/LibWeb/Layout/SVGMaskBox.h @@ -13,8 +13,7 @@ namespace Web::Layout { class SVGMaskBox : public SVGGraphicsBox { - GC_CELL(SVGMaskBox, SVGGraphicsBox); - GC_DECLARE_ALLOCATOR(SVGMaskBox); + LAYOUT_NODE(SVGMaskBox, SVGGraphicsBox); public: SVGMaskBox(DOM::Document&, SVG::SVGMaskElement&, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/SVGPatternBox.cpp b/Libraries/LibWeb/Layout/SVGPatternBox.cpp index 0da0d3e11d..1cc4cfdc21 100644 --- a/Libraries/LibWeb/Layout/SVGPatternBox.cpp +++ b/Libraries/LibWeb/Layout/SVGPatternBox.cpp @@ -9,8 +9,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(SVGPatternBox); - SVGPatternBox::SVGPatternBox(DOM::Document& document, SVG::SVGPatternElement& element, CSS::ComputedProperties const& style) : SVGBox(document, element, style) { diff --git a/Libraries/LibWeb/Layout/SVGPatternBox.h b/Libraries/LibWeb/Layout/SVGPatternBox.h index 17b8743a65..ef37cf4b64 100644 --- a/Libraries/LibWeb/Layout/SVGPatternBox.h +++ b/Libraries/LibWeb/Layout/SVGPatternBox.h @@ -12,8 +12,7 @@ namespace Web::Layout { class SVGPatternBox final : public SVGBox { - GC_CELL(SVGPatternBox, SVGBox); - GC_DECLARE_ALLOCATOR(SVGPatternBox); + LAYOUT_NODE(SVGPatternBox, SVGBox); public: SVGPatternBox(DOM::Document&, SVG::SVGPatternElement&, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/SVGSVGBox.cpp b/Libraries/LibWeb/Layout/SVGSVGBox.cpp index 27531b9f32..e5dcff3b2b 100644 --- a/Libraries/LibWeb/Layout/SVGSVGBox.cpp +++ b/Libraries/LibWeb/Layout/SVGSVGBox.cpp @@ -13,8 +13,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(SVGSVGBox); - SVGSVGBox::SVGSVGBox(DOM::Document& document, SVG::SVGSVGElement& element, CSS::ComputedProperties const& style) : ReplacedBox(document, element, style) { diff --git a/Libraries/LibWeb/Layout/SVGSVGBox.h b/Libraries/LibWeb/Layout/SVGSVGBox.h index 82d9875527..51edb25d40 100644 --- a/Libraries/LibWeb/Layout/SVGSVGBox.h +++ b/Libraries/LibWeb/Layout/SVGSVGBox.h @@ -12,8 +12,7 @@ namespace Web::Layout { class SVGSVGBox final : public ReplacedBox { - GC_CELL(SVGSVGBox, ReplacedBox); - GC_DECLARE_ALLOCATOR(SVGSVGBox); + LAYOUT_NODE(SVGSVGBox, ReplacedBox); public: SVGSVGBox(DOM::Document&, SVG::SVGSVGElement&, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/SVGTextBox.cpp b/Libraries/LibWeb/Layout/SVGTextBox.cpp index 3f5b562d50..bbbed42292 100644 --- a/Libraries/LibWeb/Layout/SVGTextBox.cpp +++ b/Libraries/LibWeb/Layout/SVGTextBox.cpp @@ -10,8 +10,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(SVGTextBox); - SVGTextBox::SVGTextBox(DOM::Document& document, SVG::SVGTextPositioningElement& element, CSS::ComputedProperties const& style) : SVGGraphicsBox(document, element, style) { diff --git a/Libraries/LibWeb/Layout/SVGTextBox.h b/Libraries/LibWeb/Layout/SVGTextBox.h index f723801236..15077bf94a 100644 --- a/Libraries/LibWeb/Layout/SVGTextBox.h +++ b/Libraries/LibWeb/Layout/SVGTextBox.h @@ -13,8 +13,7 @@ namespace Web::Layout { class SVGTextBox final : public SVGGraphicsBox { - GC_CELL(SVGTextBox, SVGGraphicsBox); - GC_DECLARE_ALLOCATOR(SVGTextBox); + LAYOUT_NODE(SVGTextBox, SVGGraphicsBox); public: SVGTextBox(DOM::Document&, SVG::SVGTextPositioningElement&, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/SVGTextPathBox.cpp b/Libraries/LibWeb/Layout/SVGTextPathBox.cpp index b3cc39db80..f8250960b5 100644 --- a/Libraries/LibWeb/Layout/SVGTextPathBox.cpp +++ b/Libraries/LibWeb/Layout/SVGTextPathBox.cpp @@ -9,8 +9,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(SVGTextPathBox); - SVGTextPathBox::SVGTextPathBox(DOM::Document& document, SVG::SVGTextPathElement& element, CSS::ComputedProperties const& style) : SVGGraphicsBox(document, element, style) { diff --git a/Libraries/LibWeb/Layout/SVGTextPathBox.h b/Libraries/LibWeb/Layout/SVGTextPathBox.h index 9df4f445d3..5e046cea65 100644 --- a/Libraries/LibWeb/Layout/SVGTextPathBox.h +++ b/Libraries/LibWeb/Layout/SVGTextPathBox.h @@ -12,8 +12,7 @@ namespace Web::Layout { class SVGTextPathBox final : public SVGGraphicsBox { - GC_CELL(SVGTextPathBox, SVGGraphicsBox); - GC_DECLARE_ALLOCATOR(SVGTextPathBox); + LAYOUT_NODE(SVGTextPathBox, SVGGraphicsBox); public: SVGTextPathBox(DOM::Document&, SVG::SVGTextPathElement&, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/TableFormattingContext.cpp b/Libraries/LibWeb/Layout/TableFormattingContext.cpp index f1e0853ac0..677f01df5b 100644 --- a/Libraries/LibWeb/Layout/TableFormattingContext.cpp +++ b/Libraries/LibWeb/Layout/TableFormattingContext.cpp @@ -60,7 +60,7 @@ static inline bool is_table_column(Box const& box) CSSPixels TableFormattingContext::run_caption_layout(CSS::CaptionSide phase, AvailableSpace const& caption_available_space) { CSSPixels caption_height = 0; - for (auto* child = table_box().first_child(); child; child = child->next_sibling()) { + for (auto child = table_box().first_child(); child; child = child->next_sibling()) { if (!child->display().is_table_caption() || child->computed_values().caption_side() != phase) { continue; } @@ -123,14 +123,14 @@ void TableFormattingContext::compute_constrainedness() }); for (auto& row : m_rows) { - auto const& computed_values = row.box->computed_values(); + auto const& computed_values = row.box.computed_values(); if (computed_values.height().is_length()) { row.is_constrained = true; } } for (auto& cell : m_cells) { - auto const& computed_values = cell.box->computed_values(); + auto const& computed_values = cell.box.computed_values(); if (computed_values.width().is_length()) { m_columns[cell.column_index].is_constrained = true; } @@ -150,7 +150,7 @@ void TableFormattingContext::compute_cell_measures(RowMeasurement row_measuremen compute_constrainedness(); for (auto& cell : m_cells) { - auto const& computed_values = cell.box->computed_values(); + auto const& computed_values = cell.box.computed_values(); CSSPixels padding_top = computed_values.padding().top().to_px_or_zero(cell.box, containing_block_height); CSSPixels padding_bottom = computed_values.padding().bottom().to_px_or_zero(cell.box, containing_block_height); CSSPixels padding_left = computed_values.padding().left().to_px_or_zero(cell.box, containing_block_width); @@ -246,7 +246,7 @@ void TableFormattingContext::compute_outer_content_sizes() }); for (auto& row : m_rows) { - auto const& computed_values = row.box->computed_values(); + auto const& computed_values = row.box.computed_values(); auto min_height = computed_values.min_height().to_px(row.box, containing_block_height); auto max_height = computed_values.max_height().is_length() ? computed_values.max_height().to_px(row.box, containing_block_height) : CSSPixels::max(); auto height = computed_values.height().to_px(row.box, containing_block_height); @@ -263,7 +263,7 @@ void TableFormattingContext::initialize_table_measurescomputed_values(); + auto const& computed_values = cell.box.computed_values(); if (cell.row_span == 1) { auto specified_height = computed_values.height().to_px(cell.box, containing_block_height); // https://www.w3.org/TR/css-tables-3/#row-layout makes specified cell height part of the initialization formula for row table measures: @@ -486,7 +486,7 @@ CSSPixels TableFormattingContext::compute_capmin() // https://drafts.csswg.org/css-tables-3/#computing-the-table-width CSSPixels capmin = 0; auto width_of_table_wrapper_containing_block = table_wrapper_containing_block_width(); - for (auto* child = table_box().first_child(); child; child = child->next_sibling()) { + for (auto child = table_box().first_child(); child; child = child->next_sibling()) { if (!child->display().is_table_caption()) { continue; } @@ -604,7 +604,7 @@ void TableFormattingContext::compute_table_width() // A percentage value for a column width is relative to the table width. If the table has 'width: auto', // a percentage represents a constraint on the column's width, which a UA should try to satisfy. for (auto& cell : m_cells) { - auto const& cell_width = cell.box->computed_values().width(); + auto const& cell_width = cell.box.computed_values().width(); if (cell_width.is_percentage()) { CSSPixels adjusted_used_width = undistributable_space; if (cell_width.percentage().value() != 0) @@ -953,7 +953,7 @@ bool TableFormattingContext::can_skip_row_intrinsic_measurement() const if (row.is_collapsed) return false; - auto const& computed_values = row.box->computed_values(); + auto const& computed_values = row.box.computed_values(); if (!computed_values.height().is_auto() || !computed_values.min_height().is_auto() || !computed_values.max_height().is_none()) { @@ -965,7 +965,7 @@ bool TableFormattingContext::can_skip_row_intrinsic_measurement() const if (cell.row_span != 1) return false; - auto const& computed_values = cell.box->computed_values(); + auto const& computed_values = cell.box.computed_values(); if (!computed_values.height().is_auto() || !computed_values.min_height().is_auto() || !computed_values.max_height().is_none()) { @@ -984,9 +984,9 @@ void TableFormattingContext::compute_table_height() row.base_height = 0; continue; } - auto row_computed_height = row.box->computed_values().height(); + auto row_computed_height = row.box.computed_values().height(); if (row_computed_height.is_length()) { - auto height_of_containing_block = m_state.get(*row.box->containing_block()).content_height(); + auto height_of_containing_block = m_state.get(*row.box.containing_block()).content_height(); auto row_used_height = row_computed_height.to_px(row.box, height_of_containing_block); row.base_height = max(row.base_height, row_used_height); } @@ -1004,20 +1004,20 @@ void TableFormattingContext::compute_table_height() auto width_of_containing_block = cell_state.containing_block_used_values()->content_width(); auto height_of_containing_block = cell_state.containing_block_used_values()->content_height(); - cell_state.padding_top = cell.box->computed_values().padding().top().to_px_or_zero(cell.box, width_of_containing_block); - cell_state.padding_bottom = cell.box->computed_values().padding().bottom().to_px_or_zero(cell.box, width_of_containing_block); - cell_state.padding_left = cell.box->computed_values().padding().left().to_px_or_zero(cell.box, width_of_containing_block); - cell_state.padding_right = cell.box->computed_values().padding().right().to_px_or_zero(cell.box, width_of_containing_block); + cell_state.padding_top = cell.box.computed_values().padding().top().to_px_or_zero(cell.box, width_of_containing_block); + cell_state.padding_bottom = cell.box.computed_values().padding().bottom().to_px_or_zero(cell.box, width_of_containing_block); + cell_state.padding_left = cell.box.computed_values().padding().left().to_px_or_zero(cell.box, width_of_containing_block); + cell_state.padding_right = cell.box.computed_values().padding().right().to_px_or_zero(cell.box, width_of_containing_block); if (table_box().computed_values().border_collapse() == CSS::BorderCollapse::Separate) { - cell_state.border_top = cell.box->computed_values().border_top().width; - cell_state.border_bottom = cell.box->computed_values().border_bottom().width; - cell_state.border_left = cell.box->computed_values().border_left().width; - cell_state.border_right = cell.box->computed_values().border_right().width; + cell_state.border_top = cell.box.computed_values().border_top().width; + cell_state.border_bottom = cell.box.computed_values().border_bottom().width; + cell_state.border_left = cell.box.computed_values().border_left().width; + cell_state.border_right = cell.box.computed_values().border_right().width; } if (!row.is_collapsed) { - auto cell_computed_height = cell.box->computed_values().height(); + auto cell_computed_height = cell.box.computed_values().height(); if (cell_computed_height.is_length()) { auto cell_used_height = cell_computed_height.to_px(cell.box, height_of_containing_block); cell_state.set_content_height(cell_used_height - cell_state.border_box_top() - cell_state.border_box_bottom()); @@ -1094,7 +1094,7 @@ void TableFormattingContext::compute_table_height() row.reference_height = 0; continue; } - auto row_computed_height = row.box->computed_values().height(); + auto row_computed_height = row.box.computed_values().height(); if (row_computed_height.is_percentage()) { auto row_used_height = row_computed_height.to_px(row.box, m_table_height); row.reference_height = max(row.reference_height, row_used_height); @@ -1113,7 +1113,7 @@ void TableFormattingContext::compute_table_height() for (size_t i = 0; i < cell.column_span; ++i) span_width += m_columns[cell.column_index + i].used_width; - auto cell_computed_height = cell.box->computed_values().height(); + auto cell_computed_height = cell.box.computed_values().height(); if (cell_computed_height.is_percentage()) { auto cell_used_height = cell_computed_height.to_px(cell.box, m_table_height); cell_state.set_content_height(cell_used_height - cell_state.border_box_top() - cell_state.border_box_bottom()); @@ -1153,7 +1153,7 @@ void TableFormattingContext::distribute_height_to_rows() Vector rows_with_auto_height; for (auto& row : m_rows) { - if (row.box->computed_values().height().is_auto() && !row.is_collapsed) { + if (row.box.computed_values().height().is_auto() && !row.is_collapsed) { rows_with_auto_height.append(row); } } @@ -1269,9 +1269,9 @@ void TableFormattingContext::position_cell_boxes() // wrapped in an anonymous table-cell box per CSS Tables 3), the cell should be aligned to the top. This allows // the flex/grid container to fill the cell and handle alignment of its children via its own properties. auto cell_is_anonymous_wrapper_for_flex_or_grid = [](auto const& cell) { - if (!cell.box->is_anonymous()) + if (!cell.box.is_anonymous()) return false; - auto const* child = cell.box->first_child(); + auto child = cell.box.first_child(); if (!child || child->next_sibling()) return false; auto const& display = child->computed_values().display(); @@ -1282,7 +1282,7 @@ void TableFormattingContext::position_cell_boxes() auto& cell_state = m_state.get_mutable(cell.box); auto& row_state = m_state.get(m_rows[cell.row_index].box); auto const row_content_height = compute_row_content_height(cell); - auto const& vertical_align = cell.box->computed_values().vertical_align(); + auto const& vertical_align = cell.box.computed_values().vertical_align(); // The following image shows various alignment lines of a row: // https://www.w3.org/TR/css-tables-3/images/cell-align-explainer.png // https://drafts.csswg.org/css2/#height-layout @@ -1476,7 +1476,7 @@ void TableFormattingContext::border_conflict_resolution() } Painting::PaintableBox::BordersDataWithElementKind override_borders_data; ConflictingEdge winning_edge_left { - .element = cell.box, + .element = &cell.box, .element_kind = Painting::PaintableBox::ConflictingElementKind::Cell, .side = ConflictingSide::Left, .row = cell.row_index, @@ -1488,7 +1488,7 @@ void TableFormattingContext::border_conflict_resolution() override_borders_data.left = border_data_with_element_kind_from_conflicting_edge(winning_edge_left); cell_state.border_left = override_borders_data.left.border_data.width; ConflictingEdge winning_edge_right { - .element = cell.box, + .element = &cell.box, .element_kind = Painting::PaintableBox::ConflictingElementKind::Cell, .side = ConflictingSide::Right, .row = cell.row_index, @@ -1500,7 +1500,7 @@ void TableFormattingContext::border_conflict_resolution() override_borders_data.right = border_data_with_element_kind_from_conflicting_edge(winning_edge_right); cell_state.border_right = override_borders_data.right.border_data.width; ConflictingEdge winning_edge_top { - .element = cell.box, + .element = &cell.box, .element_kind = Painting::PaintableBox::ConflictingElementKind::Cell, .side = ConflictingSide::Top, .row = cell.row_index, @@ -1512,7 +1512,7 @@ void TableFormattingContext::border_conflict_resolution() override_borders_data.top = border_data_with_element_kind_from_conflicting_edge(winning_edge_top); cell_state.border_top = override_borders_data.top.border_data.width; ConflictingEdge winning_edge_bottom { - .element = cell.box, + .element = &cell.box, .element_kind = Painting::PaintableBox::ConflictingElementKind::Cell, .side = ConflictingSide::Bottom, .row = cell.row_index, @@ -1572,11 +1572,11 @@ void TableFormattingContext::BorderConflictFinder::collect_conflicting_col_eleme { m_col_elements_by_index.resize(m_context->m_columns.size()); size_t column_index = 0; - for (auto* child = m_context->table_box().first_child(); child; child = child->next_sibling()) { + for (auto child = m_context->table_box().first_child(); child; child = child->next_sibling()) { if (!child->display().is_table_column_group()) { continue; } - for (auto* child_of_column_group = child->first_child(); child_of_column_group; child_of_column_group = child_of_column_group->next_sibling()) { + for (auto child_of_column_group = child->first_child(); child_of_column_group; child_of_column_group = child_of_column_group->next_sibling()) { VERIFY(child_of_column_group->display().is_table_column()); auto const& col_node = static_cast(*child_of_column_group->dom_node()); unsigned span = col_node.get_attribute_value(HTML::AttributeNames::span).to_number().value_or(1); @@ -1616,7 +1616,7 @@ void TableFormattingContext::BorderConflictFinder::collect_cell_conflicting_edge auto left_cell_column_index = cell.column_index - cell.column_span; auto maybe_cell_to_left = m_context->m_cells_by_coordinate[cell.row_index][left_cell_column_index]; if (maybe_cell_to_left.has_value()) { - result.append({ maybe_cell_to_left->box, Painting::PaintableBox::ConflictingElementKind::Cell, ConflictingSide::Right, cell.row_index, left_cell_column_index }); + result.append({ &maybe_cell_to_left->box, Painting::PaintableBox::ConflictingElementKind::Cell, ConflictingSide::Right, cell.row_index, left_cell_column_index }); } } // Left edge of the cell to the right. @@ -1624,7 +1624,7 @@ void TableFormattingContext::BorderConflictFinder::collect_cell_conflicting_edge auto right_cell_column_index = cell.column_index + cell.column_span; auto maybe_cell_to_right = m_context->m_cells_by_coordinate[cell.row_index][right_cell_column_index]; if (maybe_cell_to_right.has_value()) { - result.append({ maybe_cell_to_right->box, Painting::PaintableBox::ConflictingElementKind::Cell, ConflictingSide::Left, cell.row_index, right_cell_column_index }); + result.append({ &maybe_cell_to_right->box, Painting::PaintableBox::ConflictingElementKind::Cell, ConflictingSide::Left, cell.row_index, right_cell_column_index }); } } // Bottom edge of the cell above. @@ -1632,7 +1632,7 @@ void TableFormattingContext::BorderConflictFinder::collect_cell_conflicting_edge auto above_cell_row_index = cell.row_index - cell.row_span; auto maybe_cell_above = m_context->m_cells_by_coordinate[above_cell_row_index][cell.column_index]; if (maybe_cell_above.has_value()) { - result.append({ maybe_cell_above->box, Painting::PaintableBox::ConflictingElementKind::Cell, ConflictingSide::Bottom, above_cell_row_index, cell.column_index }); + result.append({ &maybe_cell_above->box, Painting::PaintableBox::ConflictingElementKind::Cell, ConflictingSide::Bottom, above_cell_row_index, cell.column_index }); } } // Top edge of the cell below. @@ -1640,7 +1640,7 @@ void TableFormattingContext::BorderConflictFinder::collect_cell_conflicting_edge auto below_cell_row_index = cell.row_index + cell.row_span; auto maybe_cell_below = m_context->m_cells_by_coordinate[below_cell_row_index][cell.column_index]; if (maybe_cell_below.has_value()) { - result.append({ maybe_cell_below->box, Painting::PaintableBox::ConflictingElementKind::Cell, ConflictingSide::Top, below_cell_row_index, cell.column_index }); + result.append({ &maybe_cell_below->box, Painting::PaintableBox::ConflictingElementKind::Cell, ConflictingSide::Top, below_cell_row_index, cell.column_index }); } } } @@ -1649,21 +1649,21 @@ void TableFormattingContext::BorderConflictFinder::collect_row_conflicting_edges { // Top edge of the row. if (edge == ConflictingSide::Top) { - result.append({ m_context->m_rows[cell.row_index].box, Painting::PaintableBox::ConflictingElementKind::Row, ConflictingSide::Top, cell.row_index, {} }); + result.append({ &m_context->m_rows[cell.row_index].box, Painting::PaintableBox::ConflictingElementKind::Row, ConflictingSide::Top, cell.row_index, {} }); } // Bottom edge of the row. if (edge == ConflictingSide::Bottom) { - result.append({ m_context->m_rows[cell.row_index].box, Painting::PaintableBox::ConflictingElementKind::Row, ConflictingSide::Bottom, cell.row_index, {} }); + result.append({ &m_context->m_rows[cell.row_index].box, Painting::PaintableBox::ConflictingElementKind::Row, ConflictingSide::Bottom, cell.row_index, {} }); } // Bottom edge of the row above. if (cell.row_index >= cell.row_span && edge == ConflictingSide::Top) { auto above_row_index = cell.row_index - cell.row_span; - result.append({ m_context->m_rows[above_row_index].box, Painting::PaintableBox::ConflictingElementKind::Row, ConflictingSide::Bottom, above_row_index, {} }); + result.append({ &m_context->m_rows[above_row_index].box, Painting::PaintableBox::ConflictingElementKind::Row, ConflictingSide::Bottom, above_row_index, {} }); } // Top edge of the row below. if (cell.row_index + cell.row_span < m_context->m_rows.size() && edge == ConflictingSide::Bottom) { auto below_row_index = cell.row_index + cell.row_span; - result.append({ m_context->m_rows[below_row_index].box, Painting::PaintableBox::ConflictingElementKind::Row, ConflictingSide::Top, below_row_index, {} }); + result.append({ &m_context->m_rows[below_row_index].box, Painting::PaintableBox::ConflictingElementKind::Row, ConflictingSide::Top, below_row_index, {} }); } } @@ -1732,7 +1732,7 @@ void TableFormattingContext::BorderConflictFinder::collect_table_box_conflicting } // Left edge from row group or table. Top and bottom edges of the row group are handled in collect_row_group_conflicting_edges. if (cell.column_index == 0 && edge == ConflictingSide::Left) { - result.append({ m_context->m_rows[cell.row_index].box, Painting::PaintableBox::ConflictingElementKind::Row, ConflictingSide::Left, cell.row_index, {} }); + result.append({ &m_context->m_rows[cell.row_index].box, Painting::PaintableBox::ConflictingElementKind::Row, ConflictingSide::Left, cell.row_index, {} }); if (m_row_group_elements_by_index[cell.row_index].has_value()) { result.append({ m_row_group_elements_by_index[cell.row_index]->row_group, Painting::PaintableBox::ConflictingElementKind::RowGroup, ConflictingSide::Left, cell.row_index, {} }); } @@ -1740,7 +1740,7 @@ void TableFormattingContext::BorderConflictFinder::collect_table_box_conflicting } // Right edge from row group or table. Top and bottom edges of the row group are handled in collect_row_group_conflicting_edges. if (cell.column_index + cell.column_span == m_context->m_columns.size() && edge == ConflictingSide::Right) { - result.append({ m_context->m_rows[cell.row_index].box, Painting::PaintableBox::ConflictingElementKind::Row, ConflictingSide::Right, cell.row_index, {} }); + result.append({ &m_context->m_rows[cell.row_index].box, Painting::PaintableBox::ConflictingElementKind::Row, ConflictingSide::Right, cell.row_index, {} }); if (m_row_group_elements_by_index[cell.row_index].has_value()) { result.append({ m_row_group_elements_by_index[cell.row_index]->row_group, Painting::PaintableBox::ConflictingElementKind::RowGroup, ConflictingSide::Right, cell.row_index, {} }); } @@ -1932,7 +1932,7 @@ template<> double TableFormattingContext::cell_percentage_contribution(TableFormattingContext::Cell const& cell) { // Definition of percentage contribution: https://www.w3.org/TR/css-tables-3/#percentage-contribution - auto const& computed_values = cell.box->computed_values(); + auto const& computed_values = cell.box.computed_values(); auto max_height_percentage = computed_values.max_height().is_percentage() ? computed_values.max_height().percentage().value() : static_cast(INFINITY); auto height_percentage = computed_values.height().is_percentage() ? computed_values.height().percentage().value() : 0; return min(height_percentage, max_height_percentage); @@ -1942,7 +1942,7 @@ template<> double TableFormattingContext::cell_percentage_contribution(TableFormattingContext::Cell const& cell) { // Definition of percentage contribution: https://www.w3.org/TR/css-tables-3/#percentage-contribution - auto const& computed_values = cell.box->computed_values(); + auto const& computed_values = cell.box.computed_values(); auto max_width_percentage = computed_values.max_width().is_percentage() ? computed_values.max_width().percentage().value() : static_cast(INFINITY); auto width_percentage = computed_values.width().is_percentage() ? computed_values.width().percentage().value() : 0; return min(width_percentage, max_width_percentage); @@ -1951,20 +1951,20 @@ double TableFormattingContext::cell_percentage_contribution bool TableFormattingContext::cell_has_intrinsic_percentage(TableFormattingContext::Cell const& cell) { - return cell.box->computed_values().height().is_percentage(); + return cell.box.computed_values().height().is_percentage(); } template<> bool TableFormattingContext::cell_has_intrinsic_percentage(TableFormattingContext::Cell const& cell) { - return cell.box->computed_values().width().is_percentage(); + return cell.box.computed_values().width().is_percentage(); } template<> void TableFormattingContext::initialize_intrinsic_percentages_from_rows_or_columns() { for (auto& row : m_rows) { - auto const& computed_values = row.box->computed_values(); + auto const& computed_values = row.box.computed_values(); // Definition of percentage contribution: https://www.w3.org/TR/css-tables-3/#percentage-contribution auto max_height_percentage = computed_values.max_height().is_percentage() ? computed_values.max_height().percentage().value() : static_cast(INFINITY); auto height_percentage = computed_values.height().is_percentage() ? computed_values.height().percentage().value() : 0; diff --git a/Libraries/LibWeb/Layout/TableFormattingContext.h b/Libraries/LibWeb/Layout/TableFormattingContext.h index d4ac916f5a..6cfcf1c501 100644 --- a/Libraries/LibWeb/Layout/TableFormattingContext.h +++ b/Libraries/LibWeb/Layout/TableFormattingContext.h @@ -150,7 +150,7 @@ private: }; struct ConflictingEdge { - GC::Ptr element; + Node const* element { nullptr }; Painting::PaintableBox::ConflictingElementKind element_kind; ConflictingSide side; Optional row; @@ -177,20 +177,20 @@ private: void collect_column_group_conflicting_edges(Vector&, Cell const&, ConflictingSide) const; void collect_table_box_conflicting_edges(Vector&, Cell const&, ConflictingSide) const; - GC::Ptr get_col_element(size_t index) const + Node const* get_col_element(size_t index) const { if (index >= m_col_elements_by_index.size()) - return {}; + return nullptr; return m_col_elements_by_index[index]; } struct RowGroupInfo { - GC::Ptr row_group; + Node const* row_group { nullptr }; size_t start_index; size_t row_count; }; - Vector> m_col_elements_by_index; + Vector m_col_elements_by_index; Vector> m_row_group_elements_by_index; TableFormattingContext const* m_context; }; diff --git a/Libraries/LibWeb/Layout/TableGrid.cpp b/Libraries/LibWeb/Layout/TableGrid.cpp index 2c2b4e9c75..7cdfced16b 100644 --- a/Libraries/LibWeb/Layout/TableGrid.cpp +++ b/Libraries/LibWeb/Layout/TableGrid.cpp @@ -37,7 +37,7 @@ TableGrid TableGrid::calculate_row_column_grid(Box const& box, Vector& cel // NB: The remaining steps already accomplish the same thing in this case. // 5. Let current cell be the first td or th element child in the tr element being processed. - for (auto* child = row.first_child(); child; child = child->next_sibling()) { + for (auto child = row.first_child(); child; child = child->next_sibling()) { // NB: This actually applies to children with `display: table-cell`, not just td/th elements. if (!child->display().is_table_cell()) continue; diff --git a/Libraries/LibWeb/Layout/TableGrid.h b/Libraries/LibWeb/Layout/TableGrid.h index 8b9a71fb6f..e691485728 100644 --- a/Libraries/LibWeb/Layout/TableGrid.h +++ b/Libraries/LibWeb/Layout/TableGrid.h @@ -20,7 +20,7 @@ public: }; struct Row { - GC::Ref box; + Box const& box; CSSPixels base_height { 0 }; CSSPixels reference_height { 0 }; CSSPixels final_height { 0 }; @@ -35,7 +35,7 @@ public: }; struct Cell { - GC::Ref box; + Box const& box; size_t column_index; size_t row_index; size_t column_span; diff --git a/Libraries/LibWeb/Layout/TableWrapper.cpp b/Libraries/LibWeb/Layout/TableWrapper.cpp index 16e3298ff2..f878558b52 100644 --- a/Libraries/LibWeb/Layout/TableWrapper.cpp +++ b/Libraries/LibWeb/Layout/TableWrapper.cpp @@ -8,8 +8,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(TableWrapper); - TableWrapper::TableWrapper(DOM::Document& document, DOM::Node* node, CSS::ComputedProperties const& style) : BlockContainer(document, node, style) { diff --git a/Libraries/LibWeb/Layout/TableWrapper.h b/Libraries/LibWeb/Layout/TableWrapper.h index c6168b8fe6..ae9694aff0 100644 --- a/Libraries/LibWeb/Layout/TableWrapper.h +++ b/Libraries/LibWeb/Layout/TableWrapper.h @@ -11,8 +11,7 @@ namespace Web::Layout { class TableWrapper : public BlockContainer { - GC_CELL(TableWrapper, BlockContainer); - GC_DECLARE_ALLOCATOR(TableWrapper); + LAYOUT_NODE(TableWrapper, BlockContainer); public: TableWrapper(DOM::Document&, DOM::Node*, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/TextAreaBox.cpp b/Libraries/LibWeb/Layout/TextAreaBox.cpp index 99b4429a54..416dc8f71a 100644 --- a/Libraries/LibWeb/Layout/TextAreaBox.cpp +++ b/Libraries/LibWeb/Layout/TextAreaBox.cpp @@ -8,8 +8,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(TextAreaBox); - TextAreaBox::TextAreaBox(DOM::Document& document, GC::Ptr element, CSS::ComputedProperties const& style) : BlockContainer(document, element, style) { diff --git a/Libraries/LibWeb/Layout/TextAreaBox.h b/Libraries/LibWeb/Layout/TextAreaBox.h index 1163974aee..52c6f50c10 100644 --- a/Libraries/LibWeb/Layout/TextAreaBox.h +++ b/Libraries/LibWeb/Layout/TextAreaBox.h @@ -12,8 +12,7 @@ namespace Web::Layout { class TextAreaBox : public BlockContainer { - GC_CELL(TextAreaBox, BlockContainer); - GC_DECLARE_ALLOCATOR(TextAreaBox); + LAYOUT_NODE(TextAreaBox, BlockContainer); public: TextAreaBox(DOM::Document&, GC::Ptr, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/TextInputBox.cpp b/Libraries/LibWeb/Layout/TextInputBox.cpp index c48764d3f9..ae0efe28bd 100644 --- a/Libraries/LibWeb/Layout/TextInputBox.cpp +++ b/Libraries/LibWeb/Layout/TextInputBox.cpp @@ -8,8 +8,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(TextInputBox); - TextInputBox::TextInputBox(DOM::Document& document, GC::Ptr element, CSS::ComputedProperties const& style) : BlockContainer(document, element, style) { diff --git a/Libraries/LibWeb/Layout/TextInputBox.h b/Libraries/LibWeb/Layout/TextInputBox.h index a3d0df86e0..1d9d9f7470 100644 --- a/Libraries/LibWeb/Layout/TextInputBox.h +++ b/Libraries/LibWeb/Layout/TextInputBox.h @@ -12,8 +12,7 @@ namespace Web::Layout { class TextInputBox : public BlockContainer { - GC_CELL(TextInputBox, BlockContainer); - GC_DECLARE_ALLOCATOR(TextInputBox); + LAYOUT_NODE(TextInputBox, BlockContainer); public: TextInputBox(DOM::Document&, GC::Ptr, CSS::ComputedProperties const&); diff --git a/Libraries/LibWeb/Layout/TextNode.cpp b/Libraries/LibWeb/Layout/TextNode.cpp index 182ecf065a..c3e2736e19 100644 --- a/Libraries/LibWeb/Layout/TextNode.cpp +++ b/Libraries/LibWeb/Layout/TextNode.cpp @@ -19,8 +19,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(TextNode); - TextNode::TextNode(DOM::Document& document, DOM::Text& text) : Node(document, &text) { @@ -48,8 +46,6 @@ bool TextNode::is_password_input() const return dom_node().is_password_input(); } -GC_DEFINE_ALLOCATOR(GeneratedTextNode); - GeneratedTextNode::GeneratedTextNode(DOM::Document& document, Utf16String text) : TextNode(document) , m_text(move(text)) @@ -67,8 +63,6 @@ DOM::Element const* GeneratedTextNode::parent_element_for_text_transform() const return nullptr; } -GC_DEFINE_ALLOCATOR(TextSliceNode); - TextSliceNode::TextSliceNode(DOM::Document& document, DOM::Text& text, AttachToDOMNode attach_to_dom_node, size_t dom_start_offset, size_t dom_length) : TextNode(document, text, attach_to_dom_node) , m_dom_start_offset(dom_start_offset) @@ -78,12 +72,6 @@ TextSliceNode::TextSliceNode(DOM::Document& document, DOM::Text& text, AttachToD TextSliceNode::~TextSliceNode() = default; -void TextSliceNode::visit_edges(Cell::Visitor& visitor) -{ - Base::visit_edges(visitor); - visitor.visit(m_first_letter_slice); -} - // https://w3c.github.io/mathml-core/#new-text-transform-values static Utf16String apply_math_auto_text_transform(Utf16String const& string) { diff --git a/Libraries/LibWeb/Layout/TextNode.h b/Libraries/LibWeb/Layout/TextNode.h index 6fd171f848..5aa9e07746 100644 --- a/Libraries/LibWeb/Layout/TextNode.h +++ b/Libraries/LibWeb/Layout/TextNode.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -22,8 +23,7 @@ class GeneratedTextNode; class TextSliceNode; class TextNode : public Node { - GC_CELL(TextNode, Node); - GC_DECLARE_ALLOCATOR(TextNode); + LAYOUT_NODE(TextNode, Node); public: TextNode(DOM::Document&, DOM::Text&); @@ -155,8 +155,7 @@ private: }; class GeneratedTextNode final : public TextNode { - GC_CELL(GeneratedTextNode, TextNode); - GC_DECLARE_ALLOCATOR(GeneratedTextNode); + LAYOUT_NODE(GeneratedTextNode, TextNode); public: GeneratedTextNode(DOM::Document&, Utf16String); @@ -173,8 +172,7 @@ private: }; class TextSliceNode final : public TextNode { - GC_CELL(TextSliceNode, TextNode); - GC_DECLARE_ALLOCATOR(TextSliceNode); + LAYOUT_NODE(TextSliceNode, TextNode); public: TextSliceNode(DOM::Document&, DOM::Text&, AttachToDOMNode, size_t dom_start_offset, size_t dom_length); @@ -185,18 +183,17 @@ public: // Only meaningful on a remainder slice. Returns the first-letter slice that renders the leading // sub-range of the same DOM::Text, or nullptr if first-letter is not active for this DOM::Text. - TextSliceNode const* first_letter_slice() const { return m_first_letter_slice; } - TextSliceNode* first_letter_slice() { return m_first_letter_slice; } + TextSliceNode const* first_letter_slice() const { return m_first_letter_slice.ptr(); } + TextSliceNode* first_letter_slice() { return m_first_letter_slice.ptr(); } void set_first_letter_slice(TextSliceNode& slice) { m_first_letter_slice = slice; } private: virtual bool is_text_slice_node() const override { return true; } - virtual void visit_edges(Cell::Visitor&) override; size_t m_dom_start_offset { 0 }; size_t m_dom_length_in_code_units { 0 }; - GC::Ptr m_first_letter_slice; + WeakPtr m_first_letter_slice; }; template<> diff --git a/Libraries/LibWeb/Layout/TextOffsetMapping.cpp b/Libraries/LibWeb/Layout/TextOffsetMapping.cpp index 6566790291..0f292e0781 100644 --- a/Libraries/LibWeb/Layout/TextOffsetMapping.cpp +++ b/Libraries/LibWeb/Layout/TextOffsetMapping.cpp @@ -13,7 +13,7 @@ namespace Web::Layout { TextOffsetMapping::TextOffsetMapping(DOM::Text const& text) { m_primary = as_if(text.unsafe_layout_node()); - if (auto* primary_slice = as_if(m_primary.ptr())) + if (auto* primary_slice = as_if(m_primary)) m_first_letter_slice = primary_slice->first_letter_slice(); } diff --git a/Libraries/LibWeb/Layout/TextOffsetMapping.h b/Libraries/LibWeb/Layout/TextOffsetMapping.h index 89ae4b8071..940a5b3797 100644 --- a/Libraries/LibWeb/Layout/TextOffsetMapping.h +++ b/Libraries/LibWeb/Layout/TextOffsetMapping.h @@ -68,8 +68,8 @@ public: private: // TextOffsetMapping is a short-lived stack object, and the layout nodes are kept alive by the document's layout // tree for the duration of its use, so there's no need to visit these. - GC::RawPtr m_primary; - GC::RawPtr m_first_letter_slice; + TextNode const* m_primary { nullptr }; + TextSliceNode const* m_first_letter_slice { nullptr }; }; } diff --git a/Libraries/LibWeb/Layout/TreeBuilder.cpp b/Libraries/LibWeb/Layout/TreeBuilder.cpp index 22573d2469..0fa2b351cc 100644 --- a/Libraries/LibWeb/Layout/TreeBuilder.cpp +++ b/Libraries/LibWeb/Layout/TreeBuilder.cpp @@ -144,8 +144,8 @@ static Layout::Node& insertion_parent_for_block_node(Layout::NodeWithStyle& layo auto wrapper = new_parent->create_anonymous_wrapper(); wrapper->set_children_are_inline(true); - for (GC::Ptr child = new_parent->first_child(); child;) { - GC::Ptr next_child = child->next_sibling(); + for (auto child = new_parent->first_child(); child;) { + auto next_child = child->next_sibling(); new_parent->remove_child(*child); wrapper->append_child(*child); child = next_child; @@ -160,14 +160,11 @@ static Layout::Node& insertion_parent_for_block_node(Layout::NodeWithStyle& layo void TreeBuilder::insert_node_into_inline_or_block_ancestor(Layout::Node& node, CSS::Display display, AppendOrPrepend mode) { - if (node.display().is_contents()) - return; - // Find the nearest ancestor that can host the node. auto& nearest_insertion_ancestor = [&]() -> NodeWithStyle& { for (auto& ancestor : m_ancestor_stack.in_reverse()) { if (ancestor->is_svg_foreign_object_box()) - return ancestor; + return *ancestor; auto const& ancestor_display = ancestor->display(); @@ -175,8 +172,7 @@ void TreeBuilder::insert_node_into_inline_or_block_ancestor(Layout::Node& node, if (node.is_out_of_flow() && ancestor_display.is_inline_outside() && ancestor_display.is_flow_inside()) continue; - if (!ancestor_display.is_contents()) - return ancestor; + return *ancestor; } VERIFY_NOT_REACHED(); }(); @@ -199,20 +195,11 @@ void TreeBuilder::insert_node_into_inline_or_block_ancestor(Layout::Node& node, } class GeneratedContentImageProvider final - : public GC::Cell - , public ImageProvider + : public ImageProvider , public CSS::ImageStyleValue::Client { - GC_CELL(GeneratedContentImageProvider, GC::Cell); - GC_DECLARE_ALLOCATOR(GeneratedContentImageProvider); - public: - static constexpr bool OVERRIDES_FINALIZE = true; - - virtual ~GeneratedContentImageProvider() override = default; - - virtual void finalize() override + virtual ~GeneratedContentImageProvider() override { - Base::finalize(); unregister_image_style_value_client(); } @@ -262,12 +249,12 @@ public: virtual GC::Ptr to_html_element() const override { return nullptr; } - static GC::Ref create(GC::Heap& heap, DOM::Document& document, NonnullRefPtr image) + static NonnullOwnPtr create(DOM::Document& document, NonnullRefPtr image) { - return heap.allocate(document, move(image)); + return adopt_own(*new GeneratedContentImageProvider(document, move(image))); } - void set_layout_node(GC::Ref layout_node) + void set_layout_node(Layout::Node& layout_node) { m_layout_node = layout_node; } @@ -293,18 +280,6 @@ private: { } - virtual void visit_edges(Visitor& visitor) override - { - Base::visit_edges(visitor); - visitor.visit(m_layout_node); - } - - virtual void image_provider_visit_edges(Visitor& visitor) const override - { - ImageProvider::image_provider_visit_edges(visitor); - visitor.visit(*this); - } - virtual void image_style_value_did_update(CSS::ImageStyleValue&) override { if (!m_layout_node) @@ -320,15 +295,13 @@ private: m_registered_as_image_style_value_client = false; } - mutable GC::Ptr m_layout_node; + mutable WeakPtr m_layout_node; NonnullRefPtr m_image; mutable bool m_registered_as_image_style_value_client { true }; }; -GC_DEFINE_ALLOCATOR(GeneratedContentImageProvider); - struct FirstLetterTarget { - GC::Ref text_node; + TextNode* text_node { nullptr }; size_t letter_start { 0 }; size_t letter_end { 0 }; }; @@ -421,7 +394,7 @@ static Optional find_first_letter_in_text(TextNode& text_node // The letter (L|N|S) must follow the preceding group. If the preceding punctuation consumed the entire text // node, accept it as the first-letter. if (cursor >= code_units) - return FirstLetterTarget { text_node, match_start, cursor }; + return FirstLetterTarget { &text_node, match_start, cursor }; if (!is_first_letter_character(view.code_point_at(cursor))) continue; @@ -435,7 +408,7 @@ static Optional find_first_letter_in_text(TextNode& text_node letter_end = advance_cluster(letter_end); } - return FirstLetterTarget { text_node, match_start, letter_end }; + return FirstLetterTarget { &text_node, match_start, letter_end }; } return {}; } @@ -469,7 +442,7 @@ static Optional find_first_letter_in_block(BlockContainer& bl // We have no inline content of our own but ::first-letter can still apply to text in an in-flow block descendant, // so walk into each in-flow block child in document order until one yields a letter. - for (auto* child = block.first_child(); child; child = child->next_sibling()) { + for (auto child = block.first_child(); child; child = child->next_sibling()) { if (is_marker_content(*child)) continue; if (child->is_out_of_flow()) @@ -505,24 +478,23 @@ void TreeBuilder::create_first_letter_wrapper_if_needed(DOM::Element& element, B auto const letter_end = target->letter_end; auto& document = element.document(); - auto& heap = document.heap(); - GC::Ptr remainder_slice; - GC::Ptr first_letter_slice; + RefPtr remainder_slice; + RefPtr first_letter_slice; if (auto* dom_text = text_node.dom_text()) { auto& mutable_dom_text = const_cast(*dom_text); - auto dom_remainder_slice = heap.allocate(document, mutable_dom_text, Node::AttachToDOMNode::Yes, letter_end, full_length - letter_end); - auto dom_first_letter_slice = heap.allocate(document, mutable_dom_text, Node::AttachToDOMNode::No, 0, letter_end); + auto dom_remainder_slice = make_ref_counted(document, mutable_dom_text, Node::AttachToDOMNode::Yes, letter_end, full_length - letter_end); + auto dom_first_letter_slice = make_ref_counted(document, mutable_dom_text, Node::AttachToDOMNode::No, 0, letter_end); dom_remainder_slice->set_first_letter_slice(*dom_first_letter_slice); - remainder_slice = dom_remainder_slice; - first_letter_slice = dom_first_letter_slice; + remainder_slice = move(dom_remainder_slice); + first_letter_slice = move(dom_first_letter_slice); } else { auto text = text_node.text(); - remainder_slice = heap.allocate(document, Utf16String::from_utf16(text.utf16_view().substring_view(letter_end, full_length - letter_end))); - first_letter_slice = heap.allocate(document, Utf16String::from_utf16(text.utf16_view().substring_view(0, letter_end))); + remainder_slice = make_ref_counted(document, Utf16String::from_utf16(text.utf16_view().substring_view(letter_end, full_length - letter_end))); + first_letter_slice = make_ref_counted(document, Utf16String::from_utf16(text.utf16_view().substring_view(0, letter_end))); } - auto first_letter_wrapper = heap.allocate(document, nullptr, *first_letter_style); + auto first_letter_wrapper = make_ref_counted(document, nullptr, *first_letter_style); first_letter_wrapper->set_generated_for(CSS::PseudoElement::FirstLetter, element); first_letter_wrapper->set_children_are_inline(true); first_letter_wrapper->append_child(*first_letter_slice); @@ -535,7 +507,7 @@ void TreeBuilder::create_first_letter_wrapper_if_needed(DOM::Element& element, B parent->remove_child(text_node); } -GC::Ptr TreeBuilder::create_pseudo_element_if_needed(DOM::Element& element, CSS::PseudoElement pseudo_element, Optional insertion_mode) +RefPtr TreeBuilder::create_pseudo_element_if_needed(DOM::Element& element, CSS::PseudoElement pseudo_element, Optional insertion_mode) { auto& document = element.document(); @@ -582,7 +554,7 @@ GC::Ptr TreeBuilder::create_pseudo_element_if_needed(DOM::Element return {}; } - auto list_item_marker = document.heap().allocate( + auto list_item_marker = make_ref_counted( document, list_style_type, list_box->computed_values().list_style_position(), @@ -595,16 +567,22 @@ GC::Ptr TreeBuilder::create_pseudo_element_if_needed(DOM::Element return list_item_marker; } - auto pseudo_element_node = DOM::Element::create_layout_node_for_display_type(document, pseudo_element_display, *pseudo_element_style, nullptr); - if (!pseudo_element_node) - return {}; + RefPtr pseudo_element_node; + if (pseudo_element_display.is_contents()) { + pseudo_element_node = make_ref_counted(document, nullptr, *pseudo_element_style); + pseudo_element_node->mutable_computed_values().set_display(CSS::Display(CSS::DisplayOutside::Inline, CSS::DisplayInside::Flow)); + } else { + pseudo_element_node = DOM::Element::create_layout_node_for_display_type(document, pseudo_element_display, *pseudo_element_style, nullptr); + if (!pseudo_element_node) + return {}; + } // FIXME: This code actually computes style for element::marker, and shouldn't for element::pseudo::marker if (is(*pseudo_element_node)) { auto& style_computer = document.style_computer(); auto marker_style = style_computer.compute_style({ element, CSS::PseudoElement::Marker }); - auto list_item_marker = document.heap().allocate( + auto list_item_marker = make_ref_counted( document, pseudo_element_node->computed_values().list_style_type(), pseudo_element_node->computed_values().list_style_position(), @@ -622,7 +600,7 @@ GC::Ptr TreeBuilder::create_pseudo_element_if_needed(DOM::Element element.set_synthetic_pseudo_element_node({}, pseudo_element, pseudo_element_node); if (insertion_mode.has_value()) - insert_node_into_inline_or_block_ancestor(*pseudo_element_node, pseudo_element_display, insertion_mode.value()); + insert_node_into_inline_or_block_ancestor(*pseudo_element_node, pseudo_element_node->display(), insertion_mode.value()); pseudo_element_node->mutable_computed_values().set_content(pseudo_element_content); CSS::resolve_counters(element_reference); @@ -635,15 +613,16 @@ GC::Ptr TreeBuilder::create_pseudo_element_if_needed(DOM::Element if (new_content.type == CSS::ContentData::Type::List) { push_parent(*pseudo_element_node); for (auto& item : new_content.data) { - GC::Ptr layout_node; + RefPtr layout_node; if (auto const* string = item.get_pointer()) { - layout_node = document.heap().allocate(document, Utf16String::from_utf8(*string)); + layout_node = make_ref_counted(document, Utf16String::from_utf8(*string)); } else { auto& image = *item.get>(); image.load_any_resources(document); - auto image_provider = GeneratedContentImageProvider::create(element.heap(), document, image); - layout_node = document.heap().allocate(document, nullptr, *pseudo_element_style, image_provider); - image_provider->set_layout_node(*layout_node); + auto image_provider = GeneratedContentImageProvider::create(document, image); + auto& image_provider_ref = *image_provider; + layout_node = make_ref_counted(document, *pseudo_element_style, move(image_provider)); + image_provider_ref.set_layout_node(*layout_node); } layout_node->set_generated_for(pseudo_element, element); insert_node_into_inline_or_block_ancestor(*layout_node, layout_node->display(), AppendOrPrepend::Append); @@ -711,7 +690,7 @@ void TreeBuilder::restructure_block_node_in_inline_parent(NodeWithStyleAndBoxMod nearest_block_ancestor.set_children_are_inline(false); // Find the topmost inline ancestor. - GC::Ptr topmost_inline_ancestor; + RefPtr topmost_inline_ancestor; for (auto* ancestor = &parent; ancestor; ancestor = ancestor->parent()) { if (ancestor == &nearest_block_ancestor) break; @@ -722,8 +701,8 @@ void TreeBuilder::restructure_block_node_in_inline_parent(NodeWithStyleAndBoxMod // We need to host the topmost inline ancestor and its previous siblings in an anonymous "before" wrapper. If an // inline wrapper does not already exist, we create a new one and add it to the nearest block ancestor. - GC::Ptr before_wrapper; - if (auto* last_child = nearest_block_ancestor.last_child(); last_child->is_anonymous() && last_child->children_are_inline()) { + RefPtr before_wrapper; + if (auto last_child = nearest_block_ancestor.last_child(); last_child->is_anonymous() && last_child->children_are_inline()) { before_wrapper = last_child; } else { before_wrapper = nearest_block_ancestor.create_anonymous_wrapper(); @@ -732,9 +711,9 @@ void TreeBuilder::restructure_block_node_in_inline_parent(NodeWithStyleAndBoxMod nearest_block_ancestor.append_child(*before_wrapper); } if (topmost_inline_ancestor->parent() != before_wrapper.ptr()) { - GC::Ptr inline_to_move = topmost_inline_ancestor; + RefPtr inline_to_move = topmost_inline_ancestor; while (inline_to_move) { - auto* next = inline_to_move->previous_sibling(); + auto next = inline_to_move->previous_sibling(); inline_to_move->remove(); before_wrapper->insert_before(*inline_to_move, before_wrapper->first_child()); inline_to_move = next; @@ -745,10 +724,10 @@ void TreeBuilder::restructure_block_node_in_inline_parent(NodeWithStyleAndBoxMod // the existing middle wrapper. Otherwiser, we create a new middle wrapper to contain the block node and add it to // the nearest block ancestor. bool needs_new_continuation = true; - GC::Ptr middle_wrapper; + RefPtr middle_wrapper; if (topmost_inline_ancestor->continuation_of_node()) { needs_new_continuation = false; - for (GC::Ptr ancestor = node; ancestor != topmost_inline_ancestor; ancestor = ancestor->parent()) { + for (RefPtr ancestor = node; ancestor != topmost_inline_ancestor; ancestor = ancestor->parent()) { if (ancestor->previous_sibling()) { needs_new_continuation = true; break; @@ -772,21 +751,22 @@ void TreeBuilder::restructure_block_node_in_inline_parent(NodeWithStyleAndBoxMod // any inclusive ancestor of node in the after wrapper. if (needs_new_continuation) { auto after_wrapper = nearest_block_ancestor.create_anonymous_wrapper(); - GC::Ptr current_parent = after_wrapper; - for (GC::Ptr inline_node = topmost_inline_ancestor; + RefPtr current_parent = after_wrapper; + for (RefPtr inline_node = topmost_inline_ancestor; inline_node && is(inline_node->dom_node()); inline_node = inline_node->last_child()) { auto& element = static_cast(*inline_node->dom_node()); auto style = element.computed_properties(); - auto& new_inline_node = static_cast(*element.create_layout_node(*style)); + auto new_layout_node = element.create_layout_node(*style); + auto& new_inline_node = static_cast(*new_layout_node); if (inline_node == topmost_inline_ancestor) { // The topmost inline ancestor points to the middle wrapper, which in turns points to the original node. - new_inline_node.set_continuation_of_node({}, middle_wrapper); + new_inline_node.set_continuation_of_node({}, middle_wrapper.ptr()); topmost_inline_ancestor = new_inline_node; } else { // We need all other inline nodes to point to their original node so we can walk the continuation chain // in LayoutState and create the right paintables. - new_inline_node.set_continuation_of_node({}, static_cast(*inline_node)); + new_inline_node.set_continuation_of_node({}, &static_cast(*inline_node)); } current_parent->append_child(new_inline_node); @@ -794,8 +774,8 @@ void TreeBuilder::restructure_block_node_in_inline_parent(NodeWithStyleAndBoxMod // Replace the node in the ancestor stack with the new node. auto& node_with_style = static_cast(*inline_node); - if (auto stack_index = m_ancestor_stack.find_first_index(node_with_style); stack_index.has_value()) - m_ancestor_stack[stack_index.release_value()] = new_inline_node; + if (auto stack_index = m_ancestor_stack.find_first_index(&node_with_style); stack_index.has_value()) + m_ancestor_stack[stack_index.release_value()] = &new_inline_node; // Stop recreating nodes when we've reached node's parent. if (inline_node == &parent) @@ -848,13 +828,32 @@ static bool layout_node_is_attached_to_dom_subtree(Node const& layout_node, DOM: return false; } +static DOM::Element* display_contents_style_parent_for_text_node(DOM::Text& text_node) +{ + auto* parent = text_node.flat_tree_parent(); + auto* parent_element = as_if(parent); + if (!parent_element || !parent_element->computed_properties()) + return nullptr; + if (!parent_element->computed_properties()->display().is_contents()) + return nullptr; + return parent_element; +} + +static bool display_contents_text_needs_style_wrapper(DOM::Text& text_node, DOM::Element const& style_parent) +{ + if (!text_node.data().is_ascii_whitespace()) + return true; + + return !first_is_one_of(style_parent.computed_properties()->white_space_collapse(), CSS::WhiteSpaceCollapse::Collapse); +} + TraversalDecision TreeBuilder::clear_stale_layout_and_paint_node(DOM::Node& node, DOM::Node const* content_visibility_hidden_root) { node.set_needs_layout_tree_update(false, DOM::SetNeedsLayoutTreeUpdateReason::None); node.set_child_needs_layout_tree_update(false); // NB: Called during layout tree construction. - auto layout_node = node.unsafe_layout_node(); + RefPtr layout_node = node.unsafe_layout_node(); // SVGPatternBox, SVGMaskBox, and SVGClipBox are created on behalf of a referencing // element and attached to that element's layout subtree. Skip them so they survive // cleanup of their DOM ancestor, unless their layout attachment is inside the @@ -898,14 +897,16 @@ void TreeBuilder::update_layout_tree(DOM::Node& dom_node, TreeBuilder::Context& }; // NB: Called during layout tree construction. - GC::Ptr old_layout_node = dom_node.unsafe_layout_node(); - GC::Ptr layout_node; + RefPtr old_layout_node = dom_node.unsafe_layout_node(); + RefPtr layout_node; Optional> has_svg_root_change; + auto& document = dom_node.document(); + bool should_clear_stale_layout_subtree_if_no_layout_node = true; ScopeGuard remove_stale_layout_node_guard = [&] { // If we didn't create a layout node for this DOM node, // go through the shadow-including subtree and remove any old layout & paint nodes since they are now all stale. - if (!layout_node) { + if (should_clear_stale_layout_subtree_if_no_layout_node && !layout_node) { dom_node.for_each_shadow_including_inclusive_descendant([&](auto& node) { return clear_stale_layout_and_paint_node(node); }); @@ -918,7 +919,6 @@ void TreeBuilder::update_layout_tree(DOM::Node& dom_node, TreeBuilder::Context& return; } - auto& document = dom_node.document(); auto& style_computer = document.style_computer(); RefPtr style; CSS::Display display; @@ -928,6 +928,11 @@ void TreeBuilder::update_layout_tree(DOM::Node& dom_node, TreeBuilder::Context& auto& element = static_cast(dom_node); style = element.computed_properties(); display = style->display(); + if (display.is_contents()) { + should_clear_stale_layout_subtree_if_no_layout_node = false; + update_layout_tree_for_display_contents(element, context, must_create_subtree, should_create_layout_node); + return; + } } // NB: Called during layout tree construction. layout_node = dom_node.unsafe_layout_node(); @@ -953,18 +958,23 @@ void TreeBuilder::update_layout_tree(DOM::Node& dom_node, TreeBuilder::Context& display = style->display(); if (display.is_none()) return; + if (display.is_contents()) { + should_clear_stale_layout_subtree_if_no_layout_node = false; + update_layout_tree_for_display_contents(element, context, must_create_subtree, should_create_layout_node); + return; + } // TODO: Implement changing element contents with the `content` property. if (context.layout_svg_mask_or_clip_path) { if (is(dom_node)) - layout_node = document.heap().allocate(document, static_cast(dom_node), *style); + layout_node = make_ref_counted(document, static_cast(dom_node), *style); else if (is(dom_node)) - layout_node = document.heap().allocate(document, static_cast(dom_node), *style); + layout_node = make_ref_counted(document, static_cast(dom_node), *style); else VERIFY_NOT_REACHED(); // Only layout direct uses of SVG masks/clipPaths. context.layout_svg_mask_or_clip_path = false; } else if (context.layout_svg_pattern) { - layout_node = document.heap().allocate(document, as(dom_node), *style); + layout_node = make_ref_counted(document, as(dom_node), *style); context.layout_svg_pattern = false; } else { layout_node = element.create_layout_node(*style); @@ -972,10 +982,18 @@ void TreeBuilder::update_layout_tree(DOM::Node& dom_node, TreeBuilder::Context& } else if (is(dom_node)) { style = style_computer.create_document_style(); display = style->display(); - layout_node = document.heap().allocate(static_cast(dom_node), *style); + layout_node = make_ref_counted(static_cast(dom_node), *style); } else if (is(dom_node)) { - layout_node = document.heap().allocate(document, static_cast(dom_node)); + auto& text_node = static_cast(dom_node); + layout_node = make_ref_counted(document, text_node); display = CSS::Display(CSS::DisplayOutside::Inline, CSS::DisplayInside::Flow); + if (auto* style_parent = display_contents_style_parent_for_text_node(text_node); style_parent && display_contents_text_needs_style_wrapper(text_node, *style_parent)) { + auto wrapper = make_ref_counted(document, nullptr, *style_parent->computed_properties()); + wrapper->mutable_computed_values().set_display(display); + wrapper->set_children_are_inline(true); + wrapper->append_child(*layout_node); + layout_node = move(wrapper); + } } } @@ -999,7 +1017,7 @@ void TreeBuilder::update_layout_tree(DOM::Node& dom_node, TreeBuilder::Context& old_layout_node->parent()->insert_before(*backdrop_node, old_layout_node); } } else { - create_pseudo_element_if_needed(element, CSS::PseudoElement::Backdrop, AppendOrPrepend::Append); + (void)create_pseudo_element_if_needed(element, CSS::PseudoElement::Backdrop, AppendOrPrepend::Append); } } } @@ -1144,7 +1162,71 @@ void TreeBuilder::update_layout_tree(DOM::Node& dom_node, TreeBuilder::Context& dom_node.set_child_needs_layout_tree_update(false); } -void TreeBuilder::wrap_in_button_layout_tree_if_needed(DOM::Node& dom_node, GC::Ref layout_node) +void TreeBuilder::update_layout_tree_for_display_contents(DOM::Element& element, TreeBuilder::Context& context, MustCreateSubtree must_create_subtree, bool should_create_layout_node) +{ + element.clear_synthetic_pseudo_element_layout_nodes(Badge {}); + + if (should_create_layout_node) { + element.for_each_shadow_including_inclusive_descendant([&](auto& node) { + return clear_stale_layout_and_paint_node(node); + }); + + DOM::AbstractElement element_reference { element }; + CSS::resolve_counters(element_reference); + } + + auto element_has_content_visibility_hidden = element.computed_properties()->content_visibility() == CSS::ContentVisibility::Hidden; + if (!element_has_content_visibility_hidden) + (void)create_pseudo_element_if_needed(element, CSS::PseudoElement::Before, AppendOrPrepend::Append); + + auto should_layout_dom_children = [&]() { + if (auto const* slot_element = as_if(element)) + return slot_element->assigned_nodes_internal().is_empty() && element.has_children(); + return element.has_children(); + }(); + + auto shadow_root = element.shadow_root(); + if (!element_has_content_visibility_hidden && (should_create_layout_node || element.child_needs_layout_tree_update())) { + if (shadow_root) { + for (auto* node = shadow_root->first_child(); node; node = node->next_sibling()) + update_layout_tree(*node, context, should_create_layout_node ? MustCreateSubtree::Yes : MustCreateSubtree::No); + shadow_root->set_child_needs_layout_tree_update(false); + shadow_root->set_needs_layout_tree_update(false, DOM::SetNeedsLayoutTreeUpdateReason::None); + } else if (should_layout_dom_children) { + for (auto* node = element.first_child(); node; node = node->next_sibling()) + update_layout_tree(*node, context, should_create_layout_node ? MustCreateSubtree::Yes : MustCreateSubtree::No); + } + } + + if (is(element)) { + auto& slot_element = static_cast(element); + + if (!element_has_content_visibility_hidden) { + MustCreateSubtree must_create_subtree_for_slottable = must_create_subtree; + if (slot_element.needs_layout_tree_update()) + must_create_subtree_for_slottable = MustCreateSubtree::Yes; + + for (auto const& slottable : slot_element.assigned_nodes_internal()) + slottable.visit([&](auto& node) { update_layout_tree(node, context, must_create_subtree_for_slottable); }); + } else { + for (auto const& slottable : slot_element.assigned_nodes_internal()) { + slottable.visit([&](DOM::Node& slottable_root) { + slottable_root.for_each_shadow_including_inclusive_descendant([&](auto& node) { + return clear_stale_layout_and_paint_node(node, &slottable_root); + }); + }); + } + } + } + + if (!element_has_content_visibility_hidden) + (void)create_pseudo_element_if_needed(element, CSS::PseudoElement::After, AppendOrPrepend::Append); + + element.set_needs_layout_tree_update(false, DOM::SetNeedsLayoutTreeUpdateReason::None); + element.set_child_needs_layout_tree_update(false); +} + +void TreeBuilder::wrap_in_button_layout_tree_if_needed(DOM::Node& dom_node, Layout::Node& layout_node) { auto const* html_element = as_if(dom_node); if (!html_element || !html_element->uses_button_layout()) @@ -1154,9 +1236,9 @@ void TreeBuilder::wrap_in_button_layout_tree_if_needed(DOM::Node& dom_node, GC:: // If the element is an input element, or if it is a button element and its computed value for 'display' is not // 'inline-grid', 'grid', 'inline-flex', or 'flex', then the element's box has a child anonymous button content box // with the following behaviors: - auto display = layout_node->display(); + auto display = layout_node.display(); if (!display.is_grid_inside() && !display.is_flex_inside()) { - auto& parent = as(*layout_node); + auto& parent = as(layout_node); // If the box does not overflow in the vertical axis, then it is centered vertically. // FIXME: Only apply alignment when box overflows @@ -1175,7 +1257,7 @@ void TreeBuilder::wrap_in_button_layout_tree_if_needed(DOM::Node& dom_node, GC:: content_computed_values.set_min_height(CSS::Size::make_px(CSSPixels(0))); content_box_wrapper->set_children_are_inline(parent.children_are_inline()); - Vector> sequence; + Vector> sequence; for (auto child = parent.first_child(); child; child = child->next_sibling()) sequence.append(*child); @@ -1191,19 +1273,19 @@ void TreeBuilder::wrap_in_button_layout_tree_if_needed(DOM::Node& dom_node, GC:: } } -void TreeBuilder::update_layout_tree_before_children(DOM::Node& dom_node, GC::Ref layout_node, TreeBuilder::Context&, bool element_has_content_visibility_hidden) +void TreeBuilder::update_layout_tree_before_children(DOM::Node& dom_node, Layout::Node& layout_node, TreeBuilder::Context&, bool element_has_content_visibility_hidden) { // Add node for the ::before pseudo-element. - if (is(dom_node) && layout_node->can_have_children() && !element_has_content_visibility_hidden) { + if (is(dom_node) && layout_node.can_have_children() && !element_has_content_visibility_hidden) { auto& element = static_cast(dom_node); - push_parent(as(*layout_node)); - create_pseudo_element_if_needed(element, CSS::PseudoElement::Before, AppendOrPrepend::Prepend); + push_parent(as(layout_node)); + (void)create_pseudo_element_if_needed(element, CSS::PseudoElement::Before, AppendOrPrepend::Prepend); pop_parent(); } } -void TreeBuilder::update_layout_tree_after_children(DOM::Node& dom_node, GC::Ref layout_node, TreeBuilder::Context& context, bool element_has_content_visibility_hidden) +void TreeBuilder::update_layout_tree_after_children(DOM::Node& dom_node, Layout::Node& layout_node, TreeBuilder::Context& context, bool element_has_content_visibility_hidden) { if (is(dom_node)) { auto& graphics_element = static_cast(dom_node); @@ -1213,10 +1295,10 @@ void TreeBuilder::update_layout_tree_after_children(DOM::Node& dom_node, GC::Ref // duplication is necessary. auto layout_mask_or_clip_path = [&](GC::Ptr mask_or_clip_path) { TemporaryChange layout_mask(context.layout_svg_mask_or_clip_path, true); - push_parent(as(*layout_node)); + push_parent(as(layout_node)); // Check for reference cycle - for (GC::Ref ancestor : m_ancestor_stack) { + for (auto* ancestor : m_ancestor_stack) { if (ancestor->dom_node() == mask_or_clip_path) { // FIXME: Somehow either remove ancestor from the layout tree or mark it as invalid. pop_parent(); @@ -1241,8 +1323,8 @@ void TreeBuilder::update_layout_tree_after_children(DOM::Node& dom_node, GC::Ref if (seen_content_elements.set(content_element.ptr()) != AK::HashSetResult::InsertedNewEntry) return; TemporaryChange layout_flag(context.layout_svg_pattern, true); - push_parent(as(*layout_node)); - for (GC::Ref ancestor : m_ancestor_stack) { + push_parent(as(layout_node)); + for (auto* ancestor : m_ancestor_stack) { if (ancestor->dom_node() == content_element.ptr()) { pop_parent(); return; @@ -1258,9 +1340,9 @@ void TreeBuilder::update_layout_tree_after_children(DOM::Node& dom_node, GC::Ref } // Add nodes for the ::after pseudo-element. - if (is(dom_node) && layout_node->can_have_children() && !element_has_content_visibility_hidden) { + if (is(dom_node) && layout_node.can_have_children() && !element_has_content_visibility_hidden) { auto& element = static_cast(dom_node); - push_parent(as(*layout_node)); + push_parent(as(layout_node)); // https://drafts.csswg.org/css-lists-3/#marker-pseudo // The marker box is generated by the ::marker pseudo-element of a list item as the list item’s first child, @@ -1268,13 +1350,13 @@ void TreeBuilder::update_layout_tree_after_children(DOM::Node& dom_node, GC::Ref // in § 3.2 Generating Marker Contents. // NOTE: This happens in update_layout_tree_after_children (and not in ..._before_...), since potential // block container wrapper children are created after update_layout_tree_before_children. - if (layout_node->is_list_item_box()) - create_pseudo_element_if_needed(element, CSS::PseudoElement::Marker, AppendOrPrepend::Prepend); + if (layout_node.is_list_item_box()) + (void)create_pseudo_element_if_needed(element, CSS::PseudoElement::Marker, AppendOrPrepend::Prepend); - create_pseudo_element_if_needed(element, CSS::PseudoElement::After, AppendOrPrepend::Append); + (void)create_pseudo_element_if_needed(element, CSS::PseudoElement::After, AppendOrPrepend::Append); pop_parent(); - if (auto* block_container = as_if(*layout_node)) + if (auto* block_container = as_if(layout_node)) create_first_letter_wrapper_if_needed(element, *block_container); } @@ -1282,7 +1364,7 @@ void TreeBuilder::update_layout_tree_after_children(DOM::Node& dom_node, GC::Ref // The anonymous fieldset content box is expected to appear after the rendered legend and is expected to contain the // content (including the '::before' and '::after' pseudo-elements) of the fieldset element except for the rendered // legend, if there is one. - if (auto* fieldset_box = as_if(*layout_node)) { + if (auto* fieldset_box = as_if(layout_node)) { if (auto legend = fieldset_box->rendered_legend()) { auto wrapper = fieldset_box->create_anonymous_wrapper(); auto& wrapper_mutable_values = wrapper->mutable_computed_values(); @@ -1303,7 +1385,7 @@ void TreeBuilder::update_layout_tree_after_children(DOM::Node& dom_node, GC::Ref wrapper_mutable_values.set_overflow_y(fieldset_box->computed_values().overflow_y()); fieldset_mutable_values.set_overflow_y(CSS::InitialValues::overflow()); - for (GC::Ptr child = fieldset_box->first_child(); child;) { + for (auto child = fieldset_box->first_child(); child;) { auto next = child->next_sibling(); if (child != legend) { fieldset_box->remove_child(*child); @@ -1316,7 +1398,7 @@ void TreeBuilder::update_layout_tree_after_children(DOM::Node& dom_node, GC::Ref } } -GC::Ptr TreeBuilder::build(DOM::Node& dom_node) +RefPtr TreeBuilder::build(DOM::Node& dom_node) { VERIFY(dom_node.is_document()); @@ -1370,7 +1452,7 @@ void TreeBuilder::remove_irrelevant_boxes(NodeWithStyle& root) { // The following boxes are discarded as if they were display:none: - Vector> to_remove; + Vector> to_remove; // 1. Children of a table-column. for_each_in_tree_with_internal_display(root, [&](Box& table_column) { @@ -1461,7 +1543,7 @@ static bool is_table_row_group_column_group_or_caption(Node const& node) template static void for_each_sequence_of_consecutive_children_matching(NodeWithStyle& parent, Matcher matcher, Callback callback) { - Vector> sequence; + Vector> sequence; auto sequence_is_all_ignorable_whitespace = [&]() -> bool { for (auto& node : sequence) { @@ -1487,13 +1569,13 @@ static void for_each_sequence_of_consecutive_children_matching(NodeWithStyle& pa } template -static void wrap_in_anonymous(Vector>& sequence, Node* nearest_sibling, CSS::Display display) +static void wrap_in_anonymous(Vector>& sequence, Node* nearest_sibling, CSS::Display display) { VERIFY(!sequence.is_empty()); auto& parent = *sequence.first()->parent(); auto computed_values = parent.computed_values().clone_inherited_values(); static_cast(*computed_values).set_display(display); - auto wrapper = parent.heap().template allocate(parent.document(), nullptr, move(computed_values)); + auto wrapper = make_ref_counted(parent.document(), nullptr, move(computed_values)); for (auto& child : sequence) { parent.remove_child(*child); wrapper->append_child(*child); @@ -1548,9 +1630,9 @@ void TreeBuilder::generate_missing_child_wrappers(NodeWithStyle& root) // https://drafts.csswg.org/css-tables-3/#fixup-algorithm // 3. Generate missing parents: -Vector> TreeBuilder::generate_missing_parents(NodeWithStyle& root) +Vector> TreeBuilder::generate_missing_parents(NodeWithStyle& root) { - Vector> table_roots_to_wrap; + Vector> table_roots_to_wrap; root.for_each_in_inclusive_subtree_of_type([&](auto& parent) { // 1. An anonymous table-row box must be generated around each sequence of consecutive table-cell boxes whose // parent is not a table-row. @@ -1605,7 +1687,7 @@ Vector> TreeBuilder::generate_missing_parents(NodeWithStyle& root) }); for (auto& table_box : table_roots_to_wrap) { - auto* nearest_sibling = table_box->next_sibling(); + auto nearest_sibling = table_box->next_sibling(); auto& parent = *table_box->parent(); auto wrapper_computed_values = table_box->computed_values().clone_inherited_values(); @@ -1617,7 +1699,7 @@ Vector> TreeBuilder::generate_missing_parents(NodeWithStyle& root) continue; } - auto wrapper = parent.heap().allocate(parent.document(), nullptr, move(wrapper_computed_values)); + auto wrapper = make_ref_counted(parent.document(), nullptr, move(wrapper_computed_values)); parent.remove_child(*table_box); wrapper->append_child(*table_box); @@ -1644,13 +1726,13 @@ static void fixup_row(Box& row_box, TableGrid const& table_grid, size_t row_inde mutable_computed_values.set_display(Web::CSS::Display { CSS::DisplayInternal::TableCell }); // Ensure that the cell (with zero content height) will have the same height as the row by setting vertical-align to middle. mutable_computed_values.set_vertical_align(CSS::VerticalAlign::Middle); - auto cell_box = row_box.heap().template allocate(row_box.document(), nullptr, move(computed_values)); + auto cell_box = make_ref_counted(row_box.document(), nullptr, move(computed_values)); row_box.append_child(cell_box); } } // https://drafts.csswg.org/css-tables-3/#missing-cells-fixup -void TreeBuilder::missing_cells_fixup(Vector> const& table_root_boxes) +void TreeBuilder::missing_cells_fixup(Vector> const& table_root_boxes) { // Once the amount of columns in a table is known, any table-row box must be modified such that it owns enough // cells to fill all the columns of the table, when taking spans into account. New table-cell anonymous boxes must diff --git a/Libraries/LibWeb/Layout/TreeBuilder.h b/Libraries/LibWeb/Layout/TreeBuilder.h index 0f5127f9b1..2e188675d2 100644 --- a/Libraries/LibWeb/Layout/TreeBuilder.h +++ b/Libraries/LibWeb/Layout/TreeBuilder.h @@ -6,7 +6,8 @@ #pragma once -#include +#include +#include #include namespace Web::Layout { @@ -15,7 +16,7 @@ class TreeBuilder { public: TreeBuilder(); - GC::Ptr build(DOM::Node&); + RefPtr build(DOM::Node&); private: struct Context { @@ -27,17 +28,18 @@ private: i32 calculate_list_item_index(DOM::Node&); - void update_layout_tree_before_children(DOM::Node&, GC::Ref, Context&, bool element_has_content_visibility_hidden); - void update_layout_tree_after_children(DOM::Node&, GC::Ref, Context&, bool element_has_content_visibility_hidden); - void wrap_in_button_layout_tree_if_needed(DOM::Node&, GC::Ref); + void update_layout_tree_before_children(DOM::Node&, Layout::Node&, Context&, bool element_has_content_visibility_hidden); + void update_layout_tree_after_children(DOM::Node&, Layout::Node&, Context&, bool element_has_content_visibility_hidden); + void wrap_in_button_layout_tree_if_needed(DOM::Node&, Layout::Node&); enum class MustCreateSubtree { No, Yes, }; void update_layout_tree(DOM::Node&, Context&, MustCreateSubtree); + void update_layout_tree_for_display_contents(DOM::Element&, Context&, MustCreateSubtree, bool should_create_layout_node); TraversalDecision clear_stale_layout_and_paint_node(DOM::Node&, DOM::Node const* content_visibility_hidden_root = nullptr); - void push_parent(Layout::NodeWithStyle& node) { m_ancestor_stack.append(node); } + void push_parent(Layout::NodeWithStyle& node) { m_ancestor_stack.append(&node); } void pop_parent() { m_ancestor_stack.take_last(); } template @@ -49,20 +51,20 @@ private: void fixup_tables(NodeWithStyle& root); void remove_irrelevant_boxes(NodeWithStyle& root); void generate_missing_child_wrappers(NodeWithStyle& root); - Vector> generate_missing_parents(NodeWithStyle& root); - void missing_cells_fixup(Vector> const&); + Vector> generate_missing_parents(NodeWithStyle& root); + void missing_cells_fixup(Vector> const&); enum class AppendOrPrepend { Append, Prepend, }; void insert_node_into_inline_or_block_ancestor(Layout::Node&, CSS::Display, AppendOrPrepend); - GC::Ptr create_pseudo_element_if_needed(DOM::Element&, CSS::PseudoElement, Optional); + RefPtr create_pseudo_element_if_needed(DOM::Element&, CSS::PseudoElement, Optional); static void create_first_letter_wrapper_if_needed(DOM::Element&, Layout::BlockContainer&); void restructure_block_node_in_inline_parent(NodeWithStyleAndBoxModelMetrics&); - GC::Ptr m_layout_root; - Vector> m_ancestor_stack; + RefPtr m_layout_root; + Vector m_ancestor_stack; u32 m_quote_nesting_level { 0 }; }; diff --git a/Libraries/LibWeb/Layout/VideoBox.cpp b/Libraries/LibWeb/Layout/VideoBox.cpp index 8caba3bf7e..e4f05b9602 100644 --- a/Libraries/LibWeb/Layout/VideoBox.cpp +++ b/Libraries/LibWeb/Layout/VideoBox.cpp @@ -11,8 +11,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(VideoBox); - VideoBox::VideoBox(DOM::Document& document, DOM::Element& element, CSS::ComputedProperties const& style) : ReplacedBox(document, element, style) { diff --git a/Libraries/LibWeb/Layout/VideoBox.h b/Libraries/LibWeb/Layout/VideoBox.h index bebe521e07..cfc21de731 100644 --- a/Libraries/LibWeb/Layout/VideoBox.h +++ b/Libraries/LibWeb/Layout/VideoBox.h @@ -16,6 +16,8 @@ class VideoBox final : public ReplacedBox { GC_DECLARE_ALLOCATOR(VideoBox); public: + VideoBox(DOM::Document&, DOM::Element&, CSS::ComputedProperties const&); + HTML::HTMLVideoElement& dom_node(); HTML::HTMLVideoElement const& dom_node() const; @@ -24,7 +26,6 @@ public: virtual RefPtr create_paintable() const override; private: - VideoBox(DOM::Document&, DOM::Element&, CSS::ComputedProperties const&); virtual CSS::SizeWithAspectRatio natural_size() const override; }; diff --git a/Libraries/LibWeb/Layout/Viewport.cpp b/Libraries/LibWeb/Layout/Viewport.cpp index a0a3b24ca2..cbb6f4f0ea 100644 --- a/Libraries/LibWeb/Layout/Viewport.cpp +++ b/Libraries/LibWeb/Layout/Viewport.cpp @@ -16,8 +16,6 @@ namespace Web::Layout { -GC_DEFINE_ALLOCATOR(Viewport); - Viewport::Viewport(DOM::Document& document, CSS::ComputedProperties const& style) : BlockContainer(document, &document, style) { @@ -35,18 +33,6 @@ RefPtr Viewport::create_paintable() const return Painting::ViewportPaintable::create(*this); } -void Viewport::visit_edges(Visitor& visitor) -{ - Base::visit_edges(visitor); - if (!m_text_blocks.has_value()) - return; - - for (auto& text_block : *m_text_blocks) { - for (auto& text_position : text_block.positions) - visitor.visit(text_position.dom_node); - } -} - Vector const& Viewport::text_blocks() { if (!m_text_blocks.has_value()) diff --git a/Libraries/LibWeb/Layout/Viewport.h b/Libraries/LibWeb/Layout/Viewport.h index d29bb9902a..9b8360ba40 100644 --- a/Libraries/LibWeb/Layout/Viewport.h +++ b/Libraries/LibWeb/Layout/Viewport.h @@ -12,15 +12,14 @@ namespace Web::Layout { class Viewport final : public BlockContainer { - GC_CELL(Viewport, BlockContainer); - GC_DECLARE_ALLOCATOR(Viewport); + LAYOUT_NODE(Viewport, BlockContainer); public: explicit Viewport(DOM::Document&, CSS::ComputedProperties const&); virtual ~Viewport() override; struct TextPosition { - GC::Ref dom_node; + GC::Weak dom_node; size_t start_offset { 0 }; size_t dom_offset_within_node { 0 }; }; @@ -33,8 +32,6 @@ public: DOM::Document const& dom_node() const; - virtual void visit_edges(Visitor&) override; - private: virtual RefPtr create_paintable() const override; diff --git a/Libraries/LibWeb/Page/EventHandler.cpp b/Libraries/LibWeb/Page/EventHandler.cpp index 1a15f294bd..c069999f42 100644 --- a/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Libraries/LibWeb/Page/EventHandler.cpp @@ -120,14 +120,15 @@ static Optional dispatch_event_to_nested_navigable(Painting::Painta return {}; } -static bool parent_element_for_event_dispatch(Painting::Paintable& paintable, GC::Ptr& node, GC::Ptr& layout_node) +static bool parent_element_for_event_dispatch(Painting::Paintable& paintable, GC::Ptr& node, Layout::Node*& layout_node) { layout_node = &paintable.layout_node(); if (layout_node->is_generated_for_backdrop_pseudo_element() || layout_node->is_generated_for_after_pseudo_element() || layout_node->is_generated_for_before_pseudo_element()) { node = layout_node->pseudo_element_generator(); - layout_node = node->layout_node(); + if (auto* generator_layout_node = node->layout_node()) + layout_node = generator_layout_node; } auto* current_ancestor_node = node.ptr(); @@ -214,7 +215,7 @@ EventResult EventHandler::handle_mousedown(CSSPixelPoint visual_viewport_positio // https://www.w3.org/TR/uievents/#topmost-event-target // The topmost event target MUST be the element highest in the rendering order which is capable of being an // event target. - GC::Ptr layout_node; + Layout::Node* layout_node = nullptr; if (!parent_element_for_event_dispatch(*paintable, node, layout_node)) return EventResult::Dropped; @@ -365,7 +366,7 @@ EventResult EventHandler::handle_mousemove(CSSPixelPoint visual_viewport_positio // https://www.w3.org/TR/uievents/#topmost-event-target // The topmost event target MUST be the element highest in the rendering order which is capable of being an // event target. - GC::Ptr layout_node; + Layout::Node* layout_node = nullptr; bool found_parent_element = parent_element_for_event_dispatch(*paintable, node, layout_node); if (found_parent_element) { @@ -492,7 +493,7 @@ EventResult EventHandler::handle_mouseup(CSSPixelPoint visual_viewport_position, // https://www.w3.org/TR/uievents/#topmost-event-target // The topmost event target MUST be the element highest in the rendering order which is capable of being an // event target. - GC::Ptr layout_node; + Layout::Node* layout_node = nullptr; if (!parent_element_for_event_dispatch(*paintable, node, layout_node)) return EventResult::Dropped; @@ -695,7 +696,7 @@ EventResult EventHandler::dispatch_wheel_event(Painting::Paintable& paintable, C return EventResult::Dropped; // NB: Search for the first parent of the hit target that's an element. - GC::Ptr layout_node; + Layout::Node* layout_node = nullptr; if (!parent_element_for_event_dispatch(paintable, node, layout_node)) return EventResult::Dropped; @@ -824,7 +825,7 @@ void EventHandler::update_hover_after_scroll(CSSPixelPoint visual_viewport_posit return; } - GC::Ptr layout_node; + Layout::Node* layout_node = nullptr; if (!parent_element_for_event_dispatch(*paintable, node, layout_node)) return; diff --git a/Libraries/LibWeb/Painting/Paintable.h b/Libraries/LibWeb/Painting/Paintable.h index 82c46635de..11590a112f 100644 --- a/Libraries/LibWeb/Painting/Paintable.h +++ b/Libraries/LibWeb/Painting/Paintable.h @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -151,8 +150,14 @@ protected: Optional> mutable m_containing_block; private: + void detach_from_layout_node(Badge) + { + m_containing_block.clear(); + m_layout_node.clear(); + } + GC::Weak m_dom_node; - GC::Weak m_layout_node; + WeakPtr m_layout_node; SelectionState m_selection_state { SelectionState::None }; diff --git a/Libraries/LibWeb/Painting/PaintableFragment.cpp b/Libraries/LibWeb/Painting/PaintableFragment.cpp index 923262cfb4..c58e624d24 100644 --- a/Libraries/LibWeb/Painting/PaintableFragment.cpp +++ b/Libraries/LibWeb/Painting/PaintableFragment.cpp @@ -49,7 +49,7 @@ PaintableFragment::PaintableFragment(Layout::LineBoxFragment const& fragment, Li , m_writing_mode(fragment.writing_mode()) , m_has_trailing_whitespace(fragment.has_trailing_whitespace()) { - if (auto const* text_node = as_if(*m_layout_node)) + if (auto const* text_node = as_if(layout_node())) m_dom_start_offset_in_node = text_node->dom_start_offset() + m_start_offset; else m_dom_start_offset_in_node = m_start_offset; diff --git a/Libraries/LibWeb/Painting/PaintableFragment.h b/Libraries/LibWeb/Painting/PaintableFragment.h index b54231ff15..1f439f629a 100644 --- a/Libraries/LibWeb/Painting/PaintableFragment.h +++ b/Libraries/LibWeb/Painting/PaintableFragment.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include #include @@ -26,8 +27,12 @@ class WEB_API PaintableFragment { public: PaintableFragment(Layout::LineBoxFragment const&, LineBoxData); - Layout::Node const& layout_node() const { return m_layout_node; } - Paintable const& paintable() const { return *m_layout_node->first_paintable(); } + Layout::Node const& layout_node() const + { + VERIFY(m_layout_node); + return *m_layout_node; + } + Paintable const& paintable() const { return *layout_node().first_paintable(); } size_t start_offset() const { return m_start_offset; } size_t length_in_code_units() const { return m_length_in_code_units; } @@ -92,7 +97,7 @@ public: private: Optional compute_selection_offsets(Paintable::SelectionState, size_t start_offset_in_code_units, size_t end_offset_in_code_units) const; - GC::Ref m_layout_node; + WeakPtr m_layout_node; CSSPixelPoint m_offset; CSSPixelSize m_size; LineBoxData m_line_box_data; diff --git a/Libraries/LibWeb/RefCountedTreeNode.h b/Libraries/LibWeb/RefCountedTreeNode.h index c7ce3c6dab..5559dbb341 100644 --- a/Libraries/LibWeb/RefCountedTreeNode.h +++ b/Libraries/LibWeb/RefCountedTreeNode.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -105,6 +106,70 @@ public: return const_cast(*this).previous_sibling(); } + size_t index() const + { + size_t index = 0; + for (auto node = previous_sibling(); node; node = node->previous_sibling()) + ++index; + return index; + } + + T& root() + { + auto root = RefPtr { static_cast(*this) }; + while (auto parent = root->parent()) + root = parent; + return *root; + } + T const& root() const { return const_cast(this)->root(); } + + bool is_ancestor_of(RefCountedTreeNode const& other) const + { + for (auto ancestor = other.parent(); ancestor; ancestor = ancestor->parent()) { + if (ancestor.ptr() == static_cast(this)) + return true; + } + return false; + } + + bool is_inclusive_ancestor_of(RefCountedTreeNode const& other) const + { + return &other == this || is_ancestor_of(other); + } + + bool contains(T const* other) const + { + return other && other->is_inclusive_descendant_of(*this); + } + + bool is_descendant_of(RefCountedTreeNode const& other) const + { + return other.is_ancestor_of(*this); + } + + bool is_inclusive_descendant_of(RefCountedTreeNode const& other) const + { + return other.is_inclusive_ancestor_of(*this); + } + + bool is_following(RefCountedTreeNode const& other) const + { + for (auto* node = previous_in_pre_order(); node; node = node->previous_in_pre_order()) { + if (node == &other) + return true; + } + return false; + } + + bool is_parent_of(RefCountedTreeNode const& other) const + { + for (auto child = first_child(); child; child = child->next_sibling()) { + if (child.ptr() == static_cast(&other)) + return true; + } + return false; + } + void append_child(NonnullRefPtr node) { VERIFY(!node->parent()); @@ -122,11 +187,54 @@ public: m_first_child = move(node); } + void prepend_child(NonnullRefPtr node) + { + VERIFY(!node->parent()); + VERIFY(!node->next_sibling()); + VERIFY(!node->previous_sibling()); + + if (m_first_child) + m_first_child->m_previous_sibling = node; + node->m_next_sibling = m_first_child; + node->m_parent = static_cast(*this); + m_first_child = move(node); + if (!m_last_child) + m_last_child = m_first_child; + } + + void insert_before(NonnullRefPtr node, T* child) + { + if (!child) + return append_child(move(node)); + + VERIFY(!node->parent()); + VERIFY(!node->next_sibling()); + VERIFY(!node->previous_sibling()); + VERIFY(static_cast*>(child)->parent().ptr() == static_cast(this)); + + auto previous_sibling = child->previous_sibling(); + node->m_previous_sibling = previous_sibling; + node->m_next_sibling = *child; + node->m_parent = static_cast(*this); + + if (previous_sibling) + previous_sibling->m_next_sibling = node; + else + m_first_child = node; + + child->m_previous_sibling = move(node); + } + + void insert_before(NonnullRefPtr node, T& child) + { + insert_before(move(node), &child); + } + void remove_child(T& node) { RefPtr self = static_cast(*this); RefPtr child_to_remove = node; - VERIFY(node.parent() == self); + VERIFY(static_cast&>(node).parent() == self); auto previous_sibling = node.previous_sibling(); auto next_sibling = node.next_sibling(); @@ -151,6 +259,37 @@ public: node.m_parent.clear(); } + void replace_child(NonnullRefPtr new_child, T& old_child) + { + VERIFY(&old_child != new_child.ptr()); + VERIFY(static_cast&>(old_child).parent().ptr() == static_cast(this)); + VERIFY(!new_child->parent()); + VERIFY(!new_child->next_sibling()); + VERIFY(!new_child->previous_sibling()); + + auto previous_sibling = old_child.previous_sibling(); + auto next_sibling = old_child.next_sibling(); + RefPtr old_child_ref = old_child; + + new_child->m_parent = static_cast(*this); + new_child->m_previous_sibling = previous_sibling; + new_child->m_next_sibling = next_sibling; + + if (previous_sibling) + previous_sibling->m_next_sibling = new_child; + else + m_first_child = new_child; + + if (next_sibling) + next_sibling->m_previous_sibling = new_child; + else + m_last_child = new_child; + + old_child_ref->m_next_sibling.clear(); + old_child_ref->m_previous_sibling.clear(); + old_child_ref->m_parent.clear(); + } + void remove() { auto parent = this->parent(); @@ -264,21 +403,170 @@ public: } template - RefPtr first_ancestor_of_type() const + U const* next_sibling_of_type() const + { + return const_cast(this)->template next_sibling_of_type(); + } + + template + U* next_sibling_of_type() + { + for (auto sibling = next_sibling(); sibling; sibling = sibling->next_sibling()) { + if (auto* sibling_of_type = as_if(*sibling)) + return sibling_of_type; + } + return nullptr; + } + + template + U const* previous_sibling_of_type() const + { + return const_cast(this)->template previous_sibling_of_type(); + } + + template + U* previous_sibling_of_type() + { + for (auto sibling = previous_sibling(); sibling; sibling = sibling->previous_sibling()) { + if (auto* sibling_of_type = as_if(*sibling)) + return sibling_of_type; + } + return nullptr; + } + + template + bool has_child_of_type() const + { + return first_child_of_type() != nullptr; + } + + template + U const* first_child_of_type() const + { + return const_cast(this)->template first_child_of_type(); + } + + template + U const* last_child_of_type() const + { + return const_cast(this)->template last_child_of_type(); + } + + template + U* first_child_of_type() + { + for (auto child = first_child(); child; child = child->next_sibling()) { + if (auto* child_of_type = as_if(*child)) + return child_of_type; + } + return nullptr; + } + + template + U* last_child_of_type() + { + for (auto child = last_child(); child; child = child->previous_sibling()) { + if (auto* child_of_type = as_if(*child)) + return child_of_type; + } + return nullptr; + } + + template + U const* first_ancestor_of_type() const { return const_cast(*this).template first_ancestor_of_type(); } template - RefPtr first_ancestor_of_type() + U* first_ancestor_of_type() { for (auto ancestor = parent(); ancestor; ancestor = ancestor->parent()) { if (auto* ancestor_of_type = as_if(*ancestor)) - return *ancestor_of_type; + return ancestor_of_type; } return nullptr; } + template + void for_each_ancestor(Callback callback) const + { + for (auto ancestor = parent(); ancestor; ancestor = ancestor->parent()) { + if (callback(*ancestor) == IterationDecision::Break) + return; + } + } + + T* next_in_pre_order() + { + if (auto child = first_child()) + return child.ptr(); + + auto* node = static_cast(this); + while (node) { + if (auto next = node->next_sibling()) + return next.ptr(); + auto parent = static_cast*>(node)->parent(); + node = parent.ptr(); + } + return nullptr; + } + + T* next_in_pre_order(T const* stay_within) + { + if (auto child = first_child()) + return child.ptr(); + + auto* node = static_cast(this); + while (node) { + if (node == stay_within) + return nullptr; + if (auto next = node->next_sibling()) + return next.ptr(); + auto parent = static_cast*>(node)->parent(); + node = parent.ptr(); + } + return nullptr; + } + + T const* next_in_pre_order() const + { + return const_cast(this)->next_in_pre_order(); + } + + T const* next_in_pre_order(T const* stay_within) const + { + return const_cast(this)->next_in_pre_order(stay_within); + } + + T* previous_in_pre_order() + { + if (auto previous = previous_sibling()) { + auto* node = previous.ptr(); + while (auto last_child = node->last_child()) + node = last_child.ptr(); + return node; + } + + return parent().ptr(); + } + + T const* previous_in_pre_order() const + { + return const_cast(this)->previous_in_pre_order(); + } + + bool is_before(RefCountedTreeNode const& other) const + { + if (this == &other) + return false; + for (auto* node = static_cast(this); node; node = node->next_in_pre_order()) { + if (node == &other) + return true; + } + return false; + } + ~RefCountedTreeNode() { if (auto parent = this->parent()) diff --git a/Libraries/LibWeb/SVG/SVGAElement.cpp b/Libraries/LibWeb/SVG/SVGAElement.cpp index cebcacccba..828b34485b 100644 --- a/Libraries/LibWeb/SVG/SVGAElement.cpp +++ b/Libraries/LibWeb/SVG/SVGAElement.cpp @@ -75,9 +75,9 @@ GC::Ref SVGAElement::rel_list() return *m_rel_list; } -GC::Ptr SVGAElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr SVGAElement::create_layout_node(CSS::ComputedProperties const& style) { - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); } // https://html.spec.whatwg.org/multipage/links.html#links-created-by-a-and-area-elements diff --git a/Libraries/LibWeb/SVG/SVGAElement.h b/Libraries/LibWeb/SVG/SVGAElement.h index 30a55b6bd5..58dde35a52 100644 --- a/Libraries/LibWeb/SVG/SVGAElement.h +++ b/Libraries/LibWeb/SVG/SVGAElement.h @@ -25,7 +25,7 @@ public: GC::Ref rel_list(); - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; private: SVGAElement(DOM::Document&, DOM::QualifiedName); diff --git a/Libraries/LibWeb/SVG/SVGClipPathElement.cpp b/Libraries/LibWeb/SVG/SVGClipPathElement.cpp index 508a57693d..6ac3b969df 100644 --- a/Libraries/LibWeb/SVG/SVGClipPathElement.cpp +++ b/Libraries/LibWeb/SVG/SVGClipPathElement.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -36,7 +37,7 @@ void SVGClipPathElement::attribute_changed(FlyString const& name, Optional SVGClipPathElement::create_layout_node(CSS::ComputedProperties const&) +RefPtr SVGClipPathElement::create_layout_node(CSS::ComputedProperties const&) { // Clip paths are handled as a special case in the TreeBuilder. return nullptr; diff --git a/Libraries/LibWeb/SVG/SVGClipPathElement.h b/Libraries/LibWeb/SVG/SVGClipPathElement.h index c637d06cd0..f719b16a1d 100644 --- a/Libraries/LibWeb/SVG/SVGClipPathElement.h +++ b/Libraries/LibWeb/SVG/SVGClipPathElement.h @@ -34,7 +34,7 @@ public: return m_clip_path_units.value_or(ClipPathUnits::UserSpaceOnUse); } - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; private: SVGClipPathElement(DOM::Document&, DOM::QualifiedName); diff --git a/Libraries/LibWeb/SVG/SVGDefsElement.cpp b/Libraries/LibWeb/SVG/SVGDefsElement.cpp index afceec0fb2..dcddf00b3c 100644 --- a/Libraries/LibWeb/SVG/SVGDefsElement.cpp +++ b/Libraries/LibWeb/SVG/SVGDefsElement.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include diff --git a/Libraries/LibWeb/SVG/SVGDefsElement.h b/Libraries/LibWeb/SVG/SVGDefsElement.h index 26ff58cbe1..b5816ae701 100644 --- a/Libraries/LibWeb/SVG/SVGDefsElement.h +++ b/Libraries/LibWeb/SVG/SVGDefsElement.h @@ -6,6 +6,7 @@ #pragma once +#include #include namespace Web::SVG { @@ -17,7 +18,7 @@ class SVGDefsElement final : public SVGGraphicsElement { public: virtual ~SVGDefsElement(); - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override { return nullptr; } diff --git a/Libraries/LibWeb/SVG/SVGDescElement.cpp b/Libraries/LibWeb/SVG/SVGDescElement.cpp index 847871b6bf..823933ca91 100644 --- a/Libraries/LibWeb/SVG/SVGDescElement.cpp +++ b/Libraries/LibWeb/SVG/SVGDescElement.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -25,7 +26,7 @@ void SVGDescElement::initialize(JS::Realm& realm) Base::initialize(realm); } -GC::Ptr SVGDescElement::create_layout_node(CSS::ComputedProperties const&) +RefPtr SVGDescElement::create_layout_node(CSS::ComputedProperties const&) { return nullptr; } diff --git a/Libraries/LibWeb/SVG/SVGDescElement.h b/Libraries/LibWeb/SVG/SVGDescElement.h index c4c5a94701..8358e05daf 100644 --- a/Libraries/LibWeb/SVG/SVGDescElement.h +++ b/Libraries/LibWeb/SVG/SVGDescElement.h @@ -19,7 +19,7 @@ private: virtual void initialize(JS::Realm&) override; - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; }; } diff --git a/Libraries/LibWeb/SVG/SVGFEFloodElement.cpp b/Libraries/LibWeb/SVG/SVGFEFloodElement.cpp index a375b8e3f8..f893bd6532 100644 --- a/Libraries/LibWeb/SVG/SVGFEFloodElement.cpp +++ b/Libraries/LibWeb/SVG/SVGFEFloodElement.cpp @@ -32,9 +32,9 @@ void SVGFEFloodElement::visit_edges(Cell::Visitor& visitor) SVGFilterPrimitiveStandardAttributes::visit_edges(visitor); } -GC::Ptr SVGFEFloodElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr SVGFEFloodElement::create_layout_node(CSS::ComputedProperties const& style) { - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); } // https://www.w3.org/TR/filter-effects-1/#FloodColorProperty diff --git a/Libraries/LibWeb/SVG/SVGFEFloodElement.h b/Libraries/LibWeb/SVG/SVGFEFloodElement.h index a45922b12d..7537a12886 100644 --- a/Libraries/LibWeb/SVG/SVGFEFloodElement.h +++ b/Libraries/LibWeb/SVG/SVGFEFloodElement.h @@ -21,7 +21,7 @@ class SVGFEFloodElement final public: virtual ~SVGFEFloodElement() override = default; - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; Gfx::Color flood_color(); float flood_opacity() const; diff --git a/Libraries/LibWeb/SVG/SVGForeignObjectElement.cpp b/Libraries/LibWeb/SVG/SVGForeignObjectElement.cpp index b629d8d26d..7eb449fdbb 100644 --- a/Libraries/LibWeb/SVG/SVGForeignObjectElement.cpp +++ b/Libraries/LibWeb/SVG/SVGForeignObjectElement.cpp @@ -47,9 +47,9 @@ void SVGForeignObjectElement::visit_edges(Cell::Visitor& visitor) visitor.visit(m_height); } -GC::Ptr SVGForeignObjectElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr SVGForeignObjectElement::create_layout_node(CSS::ComputedProperties const& style) { - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); } GC::Ref SVGForeignObjectElement::x() diff --git a/Libraries/LibWeb/SVG/SVGForeignObjectElement.h b/Libraries/LibWeb/SVG/SVGForeignObjectElement.h index 35ad4394ba..8d98248a02 100644 --- a/Libraries/LibWeb/SVG/SVGForeignObjectElement.h +++ b/Libraries/LibWeb/SVG/SVGForeignObjectElement.h @@ -18,7 +18,7 @@ class SVGForeignObjectElement final : public SVGGraphicsElement { public: virtual ~SVGForeignObjectElement() override; - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; GC::Ref x(); GC::Ref y(); diff --git a/Libraries/LibWeb/SVG/SVGGElement.cpp b/Libraries/LibWeb/SVG/SVGGElement.cpp index 157730921d..57229863a5 100644 --- a/Libraries/LibWeb/SVG/SVGGElement.cpp +++ b/Libraries/LibWeb/SVG/SVGGElement.cpp @@ -26,9 +26,9 @@ void SVGGElement::initialize(JS::Realm& realm) Base::initialize(realm); } -GC::Ptr SVGGElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr SVGGElement::create_layout_node(CSS::ComputedProperties const& style) { - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); } } diff --git a/Libraries/LibWeb/SVG/SVGGElement.h b/Libraries/LibWeb/SVG/SVGGElement.h index ff6c732c38..aff4e3c818 100644 --- a/Libraries/LibWeb/SVG/SVGGElement.h +++ b/Libraries/LibWeb/SVG/SVGGElement.h @@ -17,7 +17,7 @@ class SVGGElement final : public SVGGraphicsElement { public: virtual ~SVGGElement() override = default; - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; private: virtual bool is_svg_g_element() const final { return true; } diff --git a/Libraries/LibWeb/SVG/SVGGeometryElement.cpp b/Libraries/LibWeb/SVG/SVGGeometryElement.cpp index c41be12079..451036aac0 100644 --- a/Libraries/LibWeb/SVG/SVGGeometryElement.cpp +++ b/Libraries/LibWeb/SVG/SVGGeometryElement.cpp @@ -28,9 +28,9 @@ void SVGGeometryElement::visit_edges(Cell::Visitor& visitor) visitor.visit(m_path_length); } -GC::Ptr SVGGeometryElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr SVGGeometryElement::create_layout_node(CSS::ComputedProperties const& style) { - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); } float SVGGeometryElement::get_total_length() diff --git a/Libraries/LibWeb/SVG/SVGGeometryElement.h b/Libraries/LibWeb/SVG/SVGGeometryElement.h index 718f899bb8..510d08094c 100644 --- a/Libraries/LibWeb/SVG/SVGGeometryElement.h +++ b/Libraries/LibWeb/SVG/SVGGeometryElement.h @@ -16,7 +16,7 @@ class SVGGeometryElement : public SVGGraphicsElement { WEB_PLATFORM_OBJECT(SVGGeometryElement, SVGGraphicsElement); public: - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; virtual Gfx::Path get_path(CSSPixelSize viewport_size) = 0; diff --git a/Libraries/LibWeb/SVG/SVGImageElement.cpp b/Libraries/LibWeb/SVG/SVGImageElement.cpp index 2cc1234109..e2da6d1d02 100644 --- a/Libraries/LibWeb/SVG/SVGImageElement.cpp +++ b/Libraries/LibWeb/SVG/SVGImageElement.cpp @@ -41,7 +41,6 @@ void SVGImageElement::initialize(JS::Realm& realm) void SVGImageElement::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); - image_provider_visit_edges(visitor); SVGURIReferenceMixin::visit_edges(visitor); visitor.visit(m_x); visitor.visit(m_y); @@ -206,9 +205,9 @@ void SVGImageElement::fetch_the_document(URL::URL const& url) } } -GC::Ptr SVGImageElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr SVGImageElement::create_layout_node(CSS::ComputedProperties const& style) { - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); } bool SVGImageElement::is_image_available() const diff --git a/Libraries/LibWeb/SVG/SVGImageElement.h b/Libraries/LibWeb/SVG/SVGImageElement.h index 0fb8e0e13f..1669f76fc0 100644 --- a/Libraries/LibWeb/SVG/SVGImageElement.h +++ b/Libraries/LibWeb/SVG/SVGImageElement.h @@ -56,7 +56,7 @@ protected: void fetch_the_document(URL::URL const& url); private: - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; void animate(); GC::Ptr m_x; diff --git a/Libraries/LibWeb/SVG/SVGMaskElement.cpp b/Libraries/LibWeb/SVG/SVGMaskElement.cpp index 04e7f31e99..78008d411a 100644 --- a/Libraries/LibWeb/SVG/SVGMaskElement.cpp +++ b/Libraries/LibWeb/SVG/SVGMaskElement.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -27,7 +28,7 @@ void SVGMaskElement::initialize(JS::Realm& realm) Base::initialize(realm); } -GC::Ptr SVGMaskElement::create_layout_node(CSS::ComputedProperties const&) +RefPtr SVGMaskElement::create_layout_node(CSS::ComputedProperties const&) { // Masks are handled as a special case in the TreeBuilder. return nullptr; diff --git a/Libraries/LibWeb/SVG/SVGMaskElement.h b/Libraries/LibWeb/SVG/SVGMaskElement.h index b13de95455..30ad7c779c 100644 --- a/Libraries/LibWeb/SVG/SVGMaskElement.h +++ b/Libraries/LibWeb/SVG/SVGMaskElement.h @@ -32,7 +32,7 @@ public: virtual void attribute_changed(FlyString const& name, Optional const& old_value, Optional const& value, Optional const& namespace_) override; - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; CSSPixelRect resolve_masking_area(CSSPixelRect const& mask_target) const; diff --git a/Libraries/LibWeb/SVG/SVGMetadataElement.cpp b/Libraries/LibWeb/SVG/SVGMetadataElement.cpp index 9263497089..4cbe297f9c 100644 --- a/Libraries/LibWeb/SVG/SVGMetadataElement.cpp +++ b/Libraries/LibWeb/SVG/SVGMetadataElement.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -25,7 +26,7 @@ void SVGMetadataElement::initialize(JS::Realm& realm) Base::initialize(realm); } -GC::Ptr SVGMetadataElement::create_layout_node(CSS::ComputedProperties const&) +RefPtr SVGMetadataElement::create_layout_node(CSS::ComputedProperties const&) { return nullptr; } diff --git a/Libraries/LibWeb/SVG/SVGMetadataElement.h b/Libraries/LibWeb/SVG/SVGMetadataElement.h index 5c02672284..ca3af87da4 100644 --- a/Libraries/LibWeb/SVG/SVGMetadataElement.h +++ b/Libraries/LibWeb/SVG/SVGMetadataElement.h @@ -20,7 +20,7 @@ private: virtual void initialize(JS::Realm&) override; - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; }; } diff --git a/Libraries/LibWeb/SVG/SVGPatternElement.cpp b/Libraries/LibWeb/SVG/SVGPatternElement.cpp index ea71db1200..161dde2ca8 100644 --- a/Libraries/LibWeb/SVG/SVGPatternElement.cpp +++ b/Libraries/LibWeb/SVG/SVGPatternElement.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/Libraries/LibWeb/SVG/SVGPatternElement.h b/Libraries/LibWeb/SVG/SVGPatternElement.h index fe9b9fdaa0..515e521864 100644 --- a/Libraries/LibWeb/SVG/SVGPatternElement.h +++ b/Libraries/LibWeb/SVG/SVGPatternElement.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -46,7 +47,7 @@ public: Optional to_gfx_paint_style(SVGPaintContext const&, DisplayListRecordingContext&, Layout::Node const& target_layout_node) const; - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override { return nullptr; } + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override { return nullptr; } protected: SVGPatternElement(DOM::Document&, DOM::QualifiedName); diff --git a/Libraries/LibWeb/SVG/SVGSVGElement.cpp b/Libraries/LibWeb/SVG/SVGSVGElement.cpp index b4180d8b3d..0c16cb2ddb 100644 --- a/Libraries/LibWeb/SVG/SVGSVGElement.cpp +++ b/Libraries/LibWeb/SVG/SVGSVGElement.cpp @@ -46,9 +46,9 @@ void SVGSVGElement::visit_edges(Visitor& visitor) visitor.visit(m_active_view_element); } -GC::Ptr SVGSVGElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr SVGSVGElement::create_layout_node(CSS::ComputedProperties const& style) { - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); } RefPtr SVGSVGElement::width_style_value_from_attribute() const diff --git a/Libraries/LibWeb/SVG/SVGSVGElement.h b/Libraries/LibWeb/SVG/SVGSVGElement.h index 52e899102f..b1384bbea3 100644 --- a/Libraries/LibWeb/SVG/SVGSVGElement.h +++ b/Libraries/LibWeb/SVG/SVGSVGElement.h @@ -25,7 +25,7 @@ class SVGSVGElement final : public SVGGraphicsElement GC_DECLARE_ALLOCATOR(SVGSVGElement); public: - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; virtual bool requires_svg_container() const override { return false; } virtual bool is_svg_container() const override { return true; } diff --git a/Libraries/LibWeb/SVG/SVGSymbolElement.cpp b/Libraries/LibWeb/SVG/SVGSymbolElement.cpp index 32d0f2a831..c7826b7710 100644 --- a/Libraries/LibWeb/SVG/SVGSymbolElement.cpp +++ b/Libraries/LibWeb/SVG/SVGSymbolElement.cpp @@ -62,14 +62,14 @@ bool SVGSymbolElement::is_direct_child_of_use_shadow_tree() const return is(host); } -GC::Ptr SVGSymbolElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr SVGSymbolElement::create_layout_node(CSS::ComputedProperties const& style) { // https://svgwg.org/svg2-draft/render.html#TermNeverRenderedElement // [..] it also includes a ‘symbol’ element that is not the instance root of a use-element shadow tree. if (!is_direct_child_of_use_shadow_tree()) return {}; - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); } } diff --git a/Libraries/LibWeb/SVG/SVGSymbolElement.h b/Libraries/LibWeb/SVG/SVGSymbolElement.h index 6ea5963e4a..9d87e4daeb 100644 --- a/Libraries/LibWeb/SVG/SVGSymbolElement.h +++ b/Libraries/LibWeb/SVG/SVGSymbolElement.h @@ -29,7 +29,7 @@ private: virtual void initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; bool is_direct_child_of_use_shadow_tree() const; diff --git a/Libraries/LibWeb/SVG/SVGTSpanElement.cpp b/Libraries/LibWeb/SVG/SVGTSpanElement.cpp index 403460e2de..d6649874dc 100644 --- a/Libraries/LibWeb/SVG/SVGTSpanElement.cpp +++ b/Libraries/LibWeb/SVG/SVGTSpanElement.cpp @@ -24,11 +24,11 @@ void SVGTSpanElement::initialize(JS::Realm& realm) Base::initialize(realm); } -GC::Ptr SVGTSpanElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr SVGTSpanElement::create_layout_node(CSS::ComputedProperties const& style) { // Text must be within an SVG element. if (first_flat_tree_ancestor_of_type()) - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); return {}; } diff --git a/Libraries/LibWeb/SVG/SVGTSpanElement.h b/Libraries/LibWeb/SVG/SVGTSpanElement.h index 9232bd41ed..d530fdba0a 100644 --- a/Libraries/LibWeb/SVG/SVGTSpanElement.h +++ b/Libraries/LibWeb/SVG/SVGTSpanElement.h @@ -17,7 +17,7 @@ class SVGTSpanElement : public SVGTextPositioningElement { GC_DECLARE_ALLOCATOR(SVGTSpanElement); public: - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; protected: SVGTSpanElement(DOM::Document&, DOM::QualifiedName); diff --git a/Libraries/LibWeb/SVG/SVGTextElement.cpp b/Libraries/LibWeb/SVG/SVGTextElement.cpp index ad918f0125..ff3d72e9f1 100644 --- a/Libraries/LibWeb/SVG/SVGTextElement.cpp +++ b/Libraries/LibWeb/SVG/SVGTextElement.cpp @@ -23,9 +23,9 @@ void SVGTextElement::initialize(JS::Realm& realm) Base::initialize(realm); } -GC::Ptr SVGTextElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr SVGTextElement::create_layout_node(CSS::ComputedProperties const& style) { - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); } } diff --git a/Libraries/LibWeb/SVG/SVGTextElement.h b/Libraries/LibWeb/SVG/SVGTextElement.h index 26d59d3165..9e17e14c71 100644 --- a/Libraries/LibWeb/SVG/SVGTextElement.h +++ b/Libraries/LibWeb/SVG/SVGTextElement.h @@ -17,7 +17,7 @@ class SVGTextElement : public SVGTextPositioningElement { GC_DECLARE_ALLOCATOR(SVGTextElement); public: - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; protected: SVGTextElement(DOM::Document&, DOM::QualifiedName); diff --git a/Libraries/LibWeb/SVG/SVGTextPathElement.cpp b/Libraries/LibWeb/SVG/SVGTextPathElement.cpp index 6b62bccc27..b2a9e0b5d7 100644 --- a/Libraries/LibWeb/SVG/SVGTextPathElement.cpp +++ b/Libraries/LibWeb/SVG/SVGTextPathElement.cpp @@ -64,9 +64,9 @@ void SVGTextPathElement::visit_edges(Cell::Visitor& visitor) SVGURIReferenceMixin::visit_edges(visitor); } -GC::Ptr SVGTextPathElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr SVGTextPathElement::create_layout_node(CSS::ComputedProperties const& style) { - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); } }; diff --git a/Libraries/LibWeb/SVG/SVGTextPathElement.h b/Libraries/LibWeb/SVG/SVGTextPathElement.h index 8b9012ed59..95c2d541db 100644 --- a/Libraries/LibWeb/SVG/SVGTextPathElement.h +++ b/Libraries/LibWeb/SVG/SVGTextPathElement.h @@ -22,7 +22,7 @@ class SVGTextPathElement GC_DECLARE_ALLOCATOR(SVGTextPathElement); public: - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; GC::Ptr path_or_shape() const; diff --git a/Libraries/LibWeb/SVG/SVGTitleElement.cpp b/Libraries/LibWeb/SVG/SVGTitleElement.cpp index ea5898fcec..8dd17cbeed 100644 --- a/Libraries/LibWeb/SVG/SVGTitleElement.cpp +++ b/Libraries/LibWeb/SVG/SVGTitleElement.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -25,7 +26,7 @@ void SVGTitleElement::initialize(JS::Realm& realm) Base::initialize(realm); } -GC::Ptr SVGTitleElement::create_layout_node(CSS::ComputedProperties const&) +RefPtr SVGTitleElement::create_layout_node(CSS::ComputedProperties const&) { return nullptr; } diff --git a/Libraries/LibWeb/SVG/SVGTitleElement.h b/Libraries/LibWeb/SVG/SVGTitleElement.h index 5b7dd1210b..4fe94dc95f 100644 --- a/Libraries/LibWeb/SVG/SVGTitleElement.h +++ b/Libraries/LibWeb/SVG/SVGTitleElement.h @@ -19,7 +19,7 @@ private: virtual void initialize(JS::Realm&) override; - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; virtual void children_changed(ChildrenChangedMetadata const&) override; }; diff --git a/Libraries/LibWeb/SVG/SVGUseElement.cpp b/Libraries/LibWeb/SVG/SVGUseElement.cpp index 11979c4b0d..f5ead98817 100644 --- a/Libraries/LibWeb/SVG/SVGUseElement.cpp +++ b/Libraries/LibWeb/SVG/SVGUseElement.cpp @@ -315,9 +315,9 @@ GC::Ptr SVGUseElement::animated_instance_root() const return instance_root(); } -GC::Ptr SVGUseElement::create_layout_node(CSS::ComputedProperties const& style) +RefPtr SVGUseElement::create_layout_node(CSS::ComputedProperties const& style) { - return heap().allocate(document(), *this, style); + return make_ref_counted(document(), *this, style); } } diff --git a/Libraries/LibWeb/SVG/SVGUseElement.h b/Libraries/LibWeb/SVG/SVGUseElement.h index 04be7e57e4..300e0b021b 100644 --- a/Libraries/LibWeb/SVG/SVGUseElement.h +++ b/Libraries/LibWeb/SVG/SVGUseElement.h @@ -48,7 +48,7 @@ private: virtual bool is_svg_use_element() const override { return true; } - virtual GC::Ptr create_layout_node(CSS::ComputedProperties const&) override; + virtual RefPtr create_layout_node(CSS::ComputedProperties const&) override; void process_the_url(Optional const& href); diff --git a/Tests/LibWeb/Layout/expected/display-contents-blockification-of-flex-items.txt b/Tests/LibWeb/Layout/expected/display-contents-blockification-of-flex-items.txt index 6d19999aa8..485b88b8ba 100644 --- a/Tests/LibWeb/Layout/expected/display-contents-blockification-of-flex-items.txt +++ b/Tests/LibWeb/Layout/expected/display-contents-blockification-of-flex-items.txt @@ -10,11 +10,12 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] [BFC] children BlockContainer at [32.171875,8] flex-item [0+0+0 58.15625 0+0+0] [0+0+0 28 0+0+0] [BFC] children: not-inline Box at [37.171875,13] flex-container(row) [0+5+0 48.15625 0+5+0] [0+5+0 18 0+5+0] [FFC] children: not-inline BlockContainer <(anonymous)> at [37.171875,13] flex-item [0+0+0 48.15625 0+0+0] [0+0+0 18 0+0+0] [BFC] children: inline - frag 0 from TextNode start: 9, length: 5, rect: [37.171875,13 48.15625x18] baseline: 13.796875 - "Share" - TextNode <#text> (not painted) TextNode <#text> (not painted) TextNode <#text> (not painted) + InlineNode <(anonymous)> at [37.171875,13] [0+0+0 48.15625 0+0+0] [0+0+0 18 0+0+0] + frag 0 from TextNode start: 9, length: 5, rect: [37.171875,13 48.15625x18] baseline: 13.796875 + "Share" + TextNode <#text> (not painted) TextNode <#text> (not painted) BlockContainer <(anonymous)> (not painted) [BFC] children: inline TextNode <#text> (not painted) @@ -30,7 +31,8 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600] PaintableWithLines (BlockContainer) [32.171875,8 58.15625x28] PaintableBox (Box) [32.171875,8 58.15625x28] PaintableWithLines (BlockContainer(anonymous)) [37.171875,13 48.15625x18] - TextPaintable (TextNode<#text>) + PaintableWithLines (InlineNode(anonymous)) [37.171875,13 48.15625x18] + TextPaintable (TextNode<#text>) PaintableWithLines (BlockContainer(anonymous)) [8,36 784x0] SC for Viewport<#document> [0,0 800x600] [children: 1] (z-index: auto) diff --git a/Tests/LibWeb/Text/expected/display-contents-flattened-text-style-and-order.txt b/Tests/LibWeb/Text/expected/display-contents-flattened-text-style-and-order.txt new file mode 100644 index 0000000000..914524a249 --- /dev/null +++ b/Tests/LibWeb/Text/expected/display-contents-flattened-text-style-and-order.txt @@ -0,0 +1,4 @@ +direct text inherited contents font: true +dynamic insertion preserves flattened order: true +significant whitespace inherited contents style: true +dynamic child update avoids duplicate pseudo: true diff --git a/Tests/LibWeb/Text/expected/display-contents-pseudo-accessible-name.txt b/Tests/LibWeb/Text/expected/display-contents-pseudo-accessible-name.txt new file mode 100644 index 0000000000..f0ca96779d --- /dev/null +++ b/Tests/LibWeb/Text/expected/display-contents-pseudo-accessible-name.txt @@ -0,0 +1 @@ +before content after diff --git a/Tests/LibWeb/Text/input/display-contents-flattened-text-style-and-order.html b/Tests/LibWeb/Text/input/display-contents-flattened-text-style-and-order.html new file mode 100644 index 0000000000..1f60994a69 --- /dev/null +++ b/Tests/LibWeb/Text/input/display-contents-flattened-text-style-and-order.html @@ -0,0 +1,85 @@ + + + +
Styled textStyled text
+
AC
+
A B
+ +
+A + diff --git a/Tests/LibWeb/Text/input/display-contents-pseudo-accessible-name.html b/Tests/LibWeb/Text/input/display-contents-pseudo-accessible-name.html new file mode 100644 index 0000000000..5f5eb0107a --- /dev/null +++ b/Tests/LibWeb/Text/input/display-contents-pseudo-accessible-name.html @@ -0,0 +1,20 @@ + + + +
content
+