From 48dbec8a9e0015cdddc7248355ac21df72296ac2 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 19 Nov 2023 20:30:13 +0100 Subject: [PATCH] LibWeb: Allocate storage for pseudo element layout nodes on demand This saves us 64 bytes for every element that doesn't have pseudo elements associated with it. Which is most of them. :^) --- Userland/Libraries/LibWeb/DOM/Element.cpp | 26 +++++++++++++++++------ Userland/Libraries/LibWeb/DOM/Element.h | 3 ++- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/Userland/Libraries/LibWeb/DOM/Element.cpp b/Userland/Libraries/LibWeb/DOM/Element.cpp index a9be123ef1..27bdb08643 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.cpp +++ b/Userland/Libraries/LibWeb/DOM/Element.cpp @@ -125,8 +125,10 @@ void Element::visit_edges(Cell::Visitor& visitor) visitor.visit(m_class_list); visitor.visit(m_shadow_root); visitor.visit(m_custom_element_definition); - for (auto& pseudo_element_layout_node : m_pseudo_element_nodes) - visitor.visit(pseudo_element_layout_node); + if (m_pseudo_element_nodes) { + for (auto& pseudo_element_layout_node : *m_pseudo_element_nodes) + visitor.visit(pseudo_element_layout_node); + } for (auto& registered_intersection_observers : m_registered_intersection_observers) visitor.visit(registered_intersection_observers.observer); } @@ -987,23 +989,33 @@ void Element::children_changed() void Element::set_pseudo_element_node(Badge, CSS::Selector::PseudoElement pseudo_element, JS::GCPtr pseudo_element_node) { - m_pseudo_element_nodes[to_underlying(pseudo_element)] = pseudo_element_node; + if (!m_pseudo_element_nodes) { + if (!pseudo_element_node) + return; + m_pseudo_element_nodes = make(); + } + + (*m_pseudo_element_nodes)[to_underlying(pseudo_element)] = pseudo_element_node; } JS::GCPtr Element::get_pseudo_element_node(CSS::Selector::PseudoElement pseudo_element) const { - return m_pseudo_element_nodes[to_underlying(pseudo_element)]; + if (!m_pseudo_element_nodes) + return nullptr; + return (*m_pseudo_element_nodes)[to_underlying(pseudo_element)]; } void Element::clear_pseudo_element_nodes(Badge) { - m_pseudo_element_nodes.fill({}); + m_pseudo_element_nodes = nullptr; } void Element::serialize_pseudo_elements_as_json(JsonArraySerializer& children_array) const { - for (size_t i = 0; i < m_pseudo_element_nodes.size(); ++i) { - auto& pseudo_element_node = m_pseudo_element_nodes[i]; + if (!m_pseudo_element_nodes) + return; + for (size_t i = 0; i < m_pseudo_element_nodes->size(); ++i) { + auto& pseudo_element_node = (*m_pseudo_element_nodes)[i]; if (!pseudo_element_node) continue; auto object = MUST(children_array.add_object()); diff --git a/Userland/Libraries/LibWeb/DOM/Element.h b/Userland/Libraries/LibWeb/DOM/Element.h index 1375a66246..f087ed9f8f 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.h +++ b/Userland/Libraries/LibWeb/DOM/Element.h @@ -412,7 +412,8 @@ private: Optional m_id; - Array, to_underlying(CSS::Selector::PseudoElement::PseudoElementCount)> m_pseudo_element_nodes; + using PseudoElementLayoutNodes = Array, to_underlying(CSS::Selector::PseudoElement::PseudoElementCount)>; + OwnPtr m_pseudo_element_nodes; // https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element-reaction-queue // All elements have an associated custom element reaction queue, initially empty. Each item in the custom element reaction queue is of one of two types: