From 15d2857a01b5bda90ace3d02cf9e1bc8ce279d38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20K=C3=B6nig?= Date: Tue, 15 Oct 2024 23:07:58 +0200 Subject: [PATCH] LibWeb: Don't crash on encountering display: list-item on pseudo element On any `display: list-item` Node a CSS pseudo element (`::marker`) needs to be created. This commit allows the ::maker pseudo element to be nested within other pseudo elements (e. g. ::before or ::after). This fixes this WPT test: http://wpt.live/css/CSS2/generated-content/after-content-display-003.xht --- .../css-pseudo-element-display-list-item.txt | 26 +++++++++++++++++++ .../css-pseudo-element-display-list-item.html | 9 +++++++ .../Libraries/LibWeb/Layout/TreeBuilder.cpp | 16 ++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 Tests/LibWeb/Layout/expected/css-pseudo-element-display-list-item.txt create mode 100644 Tests/LibWeb/Layout/input/css-pseudo-element-display-list-item.html diff --git a/Tests/LibWeb/Layout/expected/css-pseudo-element-display-list-item.txt b/Tests/LibWeb/Layout/expected/css-pseudo-element-display-list-item.txt new file mode 100644 index 00000000000..ee765692070 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/css-pseudo-element-display-list-item.txt @@ -0,0 +1,26 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x600 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x34 children: not-inline + BlockContainer
at (8,8) content-size 784x34 children: not-inline + BlockContainer <(anonymous)> at (8,8) content-size 784x17 children: inline + frag 0 from TextNode start: 0, length: 11, rect: [8,8 83.265625x17] baseline: 13.296875 + "Filler text" + TextNode <#text> + ListItemBox <(anonymous)> at (24,25) content-size 768x17 children: inline + frag 0 from TextNode start: 0, length: 11, rect: [24,25 88.703125x17] baseline: 13.296875 + "Filler Text" + ListItemMarkerBox <(anonymous)> at (0,25) content-size 12x17 children: not-inline + TextNode <#text> + BlockContainer <(anonymous)> at (8,42) content-size 784x0 children: inline + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x600] + PaintableWithLines (BlockContainer) [8,8 784x34] + PaintableWithLines (BlockContainer
) [8,8 784x34] + PaintableWithLines (BlockContainer(anonymous)) [8,8 784x17] + TextPaintable (TextNode<#text>) + PaintableWithLines (ListItemBox(anonymous)) [24,25 768x17] + MarkerPaintable (ListItemMarkerBox(anonymous)) [0,25 12x17] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer(anonymous)) [8,42 784x0] diff --git a/Tests/LibWeb/Layout/input/css-pseudo-element-display-list-item.html b/Tests/LibWeb/Layout/input/css-pseudo-element-display-list-item.html new file mode 100644 index 00000000000..09d9793b3bd --- /dev/null +++ b/Tests/LibWeb/Layout/input/css-pseudo-element-display-list-item.html @@ -0,0 +1,9 @@ + + +
Filler text
diff --git a/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp b/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp index 2ca9a1b4d47..bee86fbef8e 100644 --- a/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp +++ b/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp @@ -211,6 +211,22 @@ void TreeBuilder::create_pseudo_element_if_needed(DOM::Element& element, CSS::Se if (!pseudo_element_node) return; + auto& style_computer = document.style_computer(); + + // FIXME: This code actually computes style for element::marker, and shouldn't for element::pseudo::marker + if (is(*pseudo_element_node)) { + auto marker_style = style_computer.compute_style(element, CSS::Selector::PseudoElement::Type::Marker); + auto list_item_marker = document.heap().allocate_without_realm( + document, + pseudo_element_node->computed_values().list_style_type(), + pseudo_element_node->computed_values().list_style_position(), + 0, + *marker_style); + static_cast(*pseudo_element_node).set_marker(list_item_marker); + element.set_pseudo_element_node({}, CSS::Selector::PseudoElement::Type::Marker, list_item_marker); + pseudo_element_node->append_child(*list_item_marker); + } + auto generated_for = Node::GeneratedFor::NotGenerated; if (pseudo_element == CSS::Selector::PseudoElement::Type::Before) { generated_for = Node::GeneratedFor::PseudoBefore;