layout: Store most anonymous pseudo-elements in box slots (#37941)

Previously, anonymous boxes, such for anonymous table parts were not
associated with their non-pseudo ancestor DOM nodes. This presents a
problem when it comes time to clear layout data during incremental
layouts. This change reworks the way that pseudo-elements in general are
stored in their non-pseudo ancestor DOM nodes, allowing for any number
to be placed there.

This trades a bit of performance for space, as just adding a vector to
the node would add something like 24 bytes of storage to every node.
This change should have a neutral runtime memory usage.

Testing: This shouldn't change observable behavior and is thus covered
by
existing WPT tests. It will allow tests to pass in a subsequent PR.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
Martin Robinson 2025-07-08 17:22:09 +02:00 committed by GitHub
parent 4054f9a5a0
commit 51367c22a6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 106 additions and 95 deletions

View file

@ -231,9 +231,7 @@ fn traverse_element<'dom>(
context: &LayoutContext,
handler: &mut impl TraversalHandler<'dom>,
) {
// Clear any existing pseudo-element box slot, because markers are not handled like
// `::before`` and `::after`. They are processed during box tree creation.
element.unset_pseudo_element_box(PseudoElement::Marker);
element.unset_all_pseudo_boxes();
let replaced = ReplacedContents::for_element(element, context);
let style = element.style(&context.style_context);
@ -286,9 +284,6 @@ fn traverse_eager_pseudo_element<'dom>(
) {
assert!(pseudo_element_type.is_eager());
// First clear any old contents from the node.
node_info.node.unset_pseudo_element_box(pseudo_element_type);
// If this node doesn't have this eager pseudo-element, exit early. This depends on
// the style applied to the element.
let Some(pseudo_element_info) = node_info.pseudo(context, pseudo_element_type) else {
@ -353,8 +348,8 @@ fn traverse_pseudo_element_contents<'dom>(
anonymous_info,
display_inline,
Contents::Replaced(contents),
// We dont keep pointers to boxes generated by contents of pseudo-elements
BoxSlot::dummy(),
info.node
.pseudo_element_box_slot(PseudoElement::ServoAnonymousBox),
)
},
}