LibWeb: Add support for trees of pseudo-elements

This is needed for CSS view transitions.
This commit is contained in:
Psychpsyo 2025-03-25 18:13:18 +01:00 committed by Sam Atkins
commit 31301ef08b
Notes: github-actions[bot] 2025-05-13 11:39:50 +00:00
5 changed files with 88 additions and 25 deletions

View file

@ -87,6 +87,9 @@
namespace Web::DOM {
GC_DEFINE_ALLOCATOR(Element::PseudoElement);
GC_DEFINE_ALLOCATOR(Element::PseudoElementTreeNode);
Element::Element(Document& document, DOM::QualifiedName qualified_name)
: ParentNode(document, NodeType::ELEMENT_NODE)
, m_qualified_name(move(qualified_name))
@ -117,9 +120,7 @@ void Element::visit_edges(Cell::Visitor& visitor)
visitor.visit(m_computed_properties);
if (m_pseudo_element_data) {
for (auto& pseudo_element : *m_pseudo_element_data) {
visitor.visit(pseudo_element.cascaded_properties);
visitor.visit(pseudo_element.computed_properties);
visitor.visit(pseudo_element.layout_node);
visitor.visit(pseudo_element.value);
}
}
if (m_registered_intersection_observers) {
@ -128,6 +129,15 @@ void Element::visit_edges(Cell::Visitor& visitor)
}
}
void Element::PseudoElement::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(cascaded_properties);
visitor.visit(computed_properties);
visitor.visit(layout_node);
}
// https://dom.spec.whatwg.org/#dom-element-getattribute
Optional<String> Element::get_attribute(FlyString const& name) const
{
@ -1337,9 +1347,9 @@ bool Element::affected_by_pseudo_class(CSS::PseudoClass pseudo_class) const
}
if (m_pseudo_element_data) {
for (auto& pseudo_element : *m_pseudo_element_data) {
if (!pseudo_element.computed_properties)
if (!pseudo_element.value->computed_properties)
continue;
if (pseudo_element.computed_properties->has_attempted_match_against_pseudo_class(pseudo_class))
if (pseudo_element.value->computed_properties->has_attempted_match_against_pseudo_class(pseudo_class))
return true;
}
}
@ -1506,7 +1516,7 @@ bool Element::has_pseudo_elements() const
{
if (m_pseudo_element_data) {
for (auto& pseudo_element : *m_pseudo_element_data) {
if (pseudo_element.layout_node)
if (pseudo_element.value->layout_node)
return true;
}
}
@ -1517,7 +1527,7 @@ void Element::clear_pseudo_element_nodes(Badge<Layout::TreeBuilder>)
{
if (m_pseudo_element_data) {
for (auto& pseudo_element : *m_pseudo_element_data) {
pseudo_element.layout_node = nullptr;
pseudo_element.value->layout_node = nullptr;
}
}
}
@ -1526,15 +1536,12 @@ void Element::serialize_pseudo_elements_as_json(JsonArraySerializer<StringBuilde
{
if (!m_pseudo_element_data)
return;
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;
for (auto& pseudo_element : m_pseudo_element_data->keys()) {
auto object = MUST(children_array.add_object());
MUST(object.add("name"sv, MUST(String::formatted("::{}", CSS::pseudo_element_name(static_cast<CSS::PseudoElement>(i))))));
MUST(object.add("name"sv, MUST(String::formatted("::{}", CSS::pseudo_element_name(pseudo_element)))));
MUST(object.add("type"sv, "pseudo-element"));
MUST(object.add("parent-id"sv, unique_id().value()));
MUST(object.add("pseudo-element"sv, i));
MUST(object.add("pseudo-element"sv, to_underlying(pseudo_element)));
MUST(object.finish());
}
}
@ -2857,9 +2864,8 @@ void Element::set_pseudo_element_computed_properties(CSS::PseudoElement pseudo_e
if (!m_pseudo_element_data && !style)
return;
if (!CSS::Selector::PseudoElementSelector::is_known_pseudo_element_type(pseudo_element)) {
if (!CSS::Selector::PseudoElementSelector::is_known_pseudo_element_type(pseudo_element))
return;
}
ensure_pseudo_element(pseudo_element).computed_properties = style;
}
@ -2881,7 +2887,11 @@ Optional<Element::PseudoElement&> Element::get_pseudo_element(CSS::PseudoElement
return {};
}
return m_pseudo_element_data->at(to_underlying(type));
auto pseudo_element = m_pseudo_element_data->get(type);
if (!pseudo_element.has_value())
return {};
return *(pseudo_element.value());
}
Element::PseudoElement& Element::ensure_pseudo_element(CSS::PseudoElement type) const
@ -2891,7 +2901,15 @@ Element::PseudoElement& Element::ensure_pseudo_element(CSS::PseudoElement type)
VERIFY(CSS::Selector::PseudoElementSelector::is_known_pseudo_element_type(type));
return m_pseudo_element_data->at(to_underlying(type));
if (!m_pseudo_element_data->get(type).has_value()) {
if (is_pseudo_element_root(type)) {
m_pseudo_element_data->set(type, heap().allocate<PseudoElementTreeNode>());
} else {
m_pseudo_element_data->set(type, heap().allocate<PseudoElement>());
}
}
return *(m_pseudo_element_data->get(type).value());
}
void Element::set_custom_properties(Optional<CSS::PseudoElement> pseudo_element, HashMap<FlyString, CSS::StyleProperty> custom_properties)