layout: Throw away nested marker elements instead of storing them in a BoxSlot (#36568)

`::before` and `::after` pseudo-elements can have their own `::marker`
pseudo-element. Since this case wasn't taken into account, they were
being stored in main element's `::marker` `BoxSlot`. This could cause
problems where two layout boxes would try to use the same `BoxSlot`. For
now, just don't store the nested version of the marker. Later, we'll
need to figure out how to store these layout objects without causing too
much memory usage.

Testing: This is covered by `/css/css-lists/nested-marker-styling.html`.
In
addition, we also made a test case that always causes this crash, but
since it
had to create 100000 `<div>`s it's probably not appropriate for a test
suite.
Fixes: #36551

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
Martin Robinson 2025-04-16 17:32:48 +02:00 committed by GitHub
parent af000d6c91
commit 7a8e75266f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -169,10 +169,11 @@ impl BlockContainer {
if let Some((marker_info, marker_contents)) = crate::lists::make_marker(context, info) { if let Some((marker_info, marker_contents)) = crate::lists::make_marker(context, info) {
match marker_info.style.clone_list_style_position() { match marker_info.style.clone_list_style_position() {
ListStylePosition::Inside => { ListStylePosition::Inside => {
builder.handle_list_item_marker_inside(&marker_info, marker_contents) builder.handle_list_item_marker_inside(&marker_info, info, marker_contents)
}, },
ListStylePosition::Outside => builder.handle_list_item_marker_outside( ListStylePosition::Outside => builder.handle_list_item_marker_outside(
&marker_info, &marker_info,
info,
marker_contents, marker_contents,
info.style.clone(), info.style.clone(),
), ),
@ -384,28 +385,50 @@ where
{ {
fn handle_list_item_marker_inside( fn handle_list_item_marker_inside(
&mut self, &mut self,
info: &NodeAndStyleInfo<Node>, marker_info: &NodeAndStyleInfo<Node>,
container_info: &NodeAndStyleInfo<Node>,
contents: Vec<crate::dom_traversal::PseudoElementContentItem>, contents: Vec<crate::dom_traversal::PseudoElementContentItem>,
) { ) {
// TODO: We do not currently support saving box slots for ::marker pseudo-elements
// that are part nested in ::before and ::after pseudo elements. For now, just
// forget about them once they are built.
let box_slot = match container_info.pseudo_element_type {
Some(_) => BoxSlot::dummy(),
None => marker_info
.node
.pseudo_element_box_slot(PseudoElement::Marker),
};
self.handle_inline_level_element( self.handle_inline_level_element(
info, marker_info,
DisplayInside::Flow { DisplayInside::Flow {
is_list_item: false, is_list_item: false,
}, },
NonReplacedContents::OfPseudoElement(contents).into(), NonReplacedContents::OfPseudoElement(contents).into(),
info.node.pseudo_element_box_slot(PseudoElement::Marker), box_slot,
); );
} }
fn handle_list_item_marker_outside( fn handle_list_item_marker_outside(
&mut self, &mut self,
info: &NodeAndStyleInfo<Node>, marker_info: &NodeAndStyleInfo<Node>,
container_info: &NodeAndStyleInfo<Node>,
contents: Vec<crate::dom_traversal::PseudoElementContentItem>, contents: Vec<crate::dom_traversal::PseudoElementContentItem>,
list_item_style: Arc<ComputedValues>, list_item_style: Arc<ComputedValues>,
) { ) {
// TODO: We do not currently support saving box slots for ::marker pseudo-elements
// that are part nested in ::before and ::after pseudo elements. For now, just
// forget about them once they are built.
let box_slot = match container_info.pseudo_element_type {
Some(_) => BoxSlot::dummy(),
None => marker_info
.node
.pseudo_element_box_slot(PseudoElement::Marker),
};
self.block_level_boxes.push(BlockLevelJob { self.block_level_boxes.push(BlockLevelJob {
info: info.clone(), info: marker_info.clone(),
box_slot: info.node.pseudo_element_box_slot(PseudoElement::Marker), box_slot,
kind: BlockLevelCreator::OutsideMarker { kind: BlockLevelCreator::OutsideMarker {
contents, contents,
list_item_style, list_item_style,
@ -452,7 +475,7 @@ where
// Ignore `list-style-position` here: // Ignore `list-style-position` here:
// “If the list item is an inline box: this value is equivalent to `inside`.” // “If the list item is an inline box: this value is equivalent to `inside`.”
// https://drafts.csswg.org/css-lists/#list-style-position-outside // https://drafts.csswg.org/css-lists/#list-style-position-outside
self.handle_list_item_marker_inside(&marker_info, marker_contents) self.handle_list_item_marker_inside(&marker_info, info, marker_contents)
} }
} }