mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
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:
parent
af000d6c91
commit
7a8e75266f
1 changed files with 31 additions and 8 deletions
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue