mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-09 01:29:17 +00:00
LibWeb: Add support for trees of pseudo-elements
This is needed for CSS view transitions.
This commit is contained in:
parent
a2ecafb968
commit
31301ef08b
Notes:
github-actions[bot]
2025-05-13 11:39:50 +00:00
Author: https://github.com/Psychpsyo
Commit: 31301ef08b
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4690
Reviewed-by: https://github.com/AtkinsSJ ✅
5 changed files with 88 additions and 25 deletions
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue