diff --git a/Userland/Libraries/LibWeb/DOM/Element.cpp b/Userland/Libraries/LibWeb/DOM/Element.cpp index 1688b5765f9..5816582d54d 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.cpp +++ b/Userland/Libraries/LibWeb/DOM/Element.cpp @@ -101,8 +101,10 @@ void Element::visit_edges(Cell::Visitor& visitor) visitor.visit(m_class_list); visitor.visit(m_shadow_root); visitor.visit(m_custom_element_definition); - if (m_pseudo_element_nodes) { - visitor.visit(m_pseudo_element_nodes->span()); + if (m_pseudo_element_data) { + for (auto& pseudo_element : *m_pseudo_element_data) { + visitor.visit(pseudo_element.layout_node); + } } if (m_registered_intersection_observers) { for (auto& registered_intersection_observers : *m_registered_intersection_observers) @@ -1087,34 +1089,36 @@ void Element::children_changed() void Element::set_pseudo_element_node(Badge, CSS::Selector::PseudoElement::Type pseudo_element, JS::GCPtr pseudo_element_node) { - if (!m_pseudo_element_nodes) { - if (!pseudo_element_node) - return; - m_pseudo_element_nodes = make(); - } + auto existing_pseudo_element = get_pseudo_element(pseudo_element); + if (!existing_pseudo_element.has_value() && !pseudo_element_node) + return; - (*m_pseudo_element_nodes)[to_underlying(pseudo_element)] = pseudo_element_node; + ensure_pseudo_element(pseudo_element).layout_node = move(pseudo_element_node); } JS::GCPtr Element::get_pseudo_element_node(CSS::Selector::PseudoElement::Type pseudo_element) const { - if (!m_pseudo_element_nodes) - return nullptr; - return (*m_pseudo_element_nodes)[to_underlying(pseudo_element)]; + if (auto element_data = get_pseudo_element(pseudo_element); element_data.has_value()) + return element_data->layout_node; + return nullptr; } void Element::clear_pseudo_element_nodes(Badge) { - m_pseudo_element_nodes = nullptr; + if (m_pseudo_element_data) { + for (auto& pseudo_element : *m_pseudo_element_data) { + pseudo_element.layout_node = nullptr; + } + } } void Element::serialize_pseudo_elements_as_json(JsonArraySerializer& children_array) const { - if (!m_pseudo_element_nodes) + if (!m_pseudo_element_data) 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) + for (size_t i = 0; i < m_pseudo_element_data->size(); ++i) { + auto& pseudo_element = (*m_pseudo_element_data)[i].layout_node; + if (!pseudo_element) continue; auto object = MUST(children_array.add_object()); MUST(object.add("name"sv, MUST(String::formatted("::{}", CSS::Selector::PseudoElement::name(static_cast(i)))))); @@ -2219,11 +2223,18 @@ void Element::set_computed_css_values(RefPtr style) computed_css_values_changed(); } -auto Element::pseudo_element_custom_properties() const -> PseudoElementCustomProperties& +Optional Element::get_pseudo_element(CSS::Selector::PseudoElement::Type type) const { - if (!m_pseudo_element_custom_properties) - m_pseudo_element_custom_properties = make(); - return *m_pseudo_element_custom_properties; + if (!m_pseudo_element_data) + return {}; + return m_pseudo_element_data->at(to_underlying(type)); +} + +Element::PseudoElement& Element::ensure_pseudo_element(CSS::Selector::PseudoElement::Type type) const +{ + if (!m_pseudo_element_data) + m_pseudo_element_data = make(); + return m_pseudo_element_data->at(to_underlying(type)); } void Element::set_custom_properties(Optional pseudo_element, HashMap custom_properties) @@ -2232,14 +2243,14 @@ void Element::set_custom_properties(Optional m_custom_properties = move(custom_properties); return; } - pseudo_element_custom_properties()[to_underlying(pseudo_element.value())] = move(custom_properties); + ensure_pseudo_element(pseudo_element.value()).custom_properties = move(custom_properties); } HashMap const& Element::custom_properties(Optional pseudo_element) const { if (!pseudo_element.has_value()) return m_custom_properties; - return pseudo_element_custom_properties()[to_underlying(pseudo_element.value())]; + return ensure_pseudo_element(pseudo_element.value()).custom_properties; } // https://drafts.csswg.org/cssom-view/#dom-element-scroll diff --git a/Userland/Libraries/LibWeb/DOM/Element.h b/Userland/Libraries/LibWeb/DOM/Element.h index c490fce8c31..baa279c0875 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.h +++ b/Userland/Libraries/LibWeb/DOM/Element.h @@ -449,9 +449,16 @@ private: RefPtr m_computed_css_values; HashMap m_custom_properties; - using PseudoElementCustomProperties = Array, to_underlying(CSS::Selector::PseudoElement::Type::KnownPseudoElementCount)>; - mutable OwnPtr m_pseudo_element_custom_properties; - PseudoElementCustomProperties& pseudo_element_custom_properties() const; + struct PseudoElement { + JS::GCPtr layout_node; + HashMap custom_properties; + }; + // TODO: CSS::Selector::PseudoElement::Type includes a lot of pseudo-elements that exist in shadow trees, + // and so we don't want to include data for them here. + using PseudoElementData = Array; + mutable OwnPtr m_pseudo_element_data; + Optional get_pseudo_element(CSS::Selector::PseudoElement::Type) const; + PseudoElement& ensure_pseudo_element(CSS::Selector::PseudoElement::Type) const; Optional m_use_pseudo_element; @@ -461,9 +468,6 @@ private: Optional m_id; Optional m_name; - using PseudoElementLayoutNodes = Array, to_underlying(CSS::Selector::PseudoElement::Type::KnownPseudoElementCount)>; - 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: // NOTE: See the structs at the top of this header.