From 7de5032e739ac7bfd6f76611c5f1a2bb15c15a1e Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Fri, 16 May 2025 15:12:11 +0100 Subject: [PATCH] LibWeb/CSS: Serialize the initial combinator of relative selectors Selector::serialize() is used for both normal and relative selectors. For the latter, we need to serialize their initial combinator, and for the former, we always set the initial combinator as None anyway, so this would be a no-op there. Gets us 3 WPT passes. --- Libraries/LibWeb/CSS/Selector.cpp | 20 +++++++++++++++++++ .../css/selectors/parsing/parse-has.txt | 9 ++++----- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/Libraries/LibWeb/CSS/Selector.cpp b/Libraries/LibWeb/CSS/Selector.cpp index 952761d301d..3934418e38b 100644 --- a/Libraries/LibWeb/CSS/Selector.cpp +++ b/Libraries/LibWeb/CSS/Selector.cpp @@ -496,6 +496,26 @@ String Selector::serialize() const { StringBuilder s; + // AD-HOC: If this is a relative selector, we need to serialize the starting combinator. + if (!compound_selectors().is_empty()) { + switch (compound_selectors().first().combinator) { + case Combinator::ImmediateChild: + s.append("> "sv); + break; + case Combinator::NextSibling: + s.append("+ "sv); + break; + case Combinator::SubsequentSibling: + s.append("~ "sv); + break; + case Combinator::Column: + s.append("|| "sv); + break; + default: + break; + } + } + // To serialize a selector let s be the empty string, run the steps below for each part of the chain of the selector, and finally return s: for (size_t i = 0; i < compound_selectors().size(); ++i) { auto const& compound_selector = compound_selectors()[i]; diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/selectors/parsing/parse-has.txt b/Tests/LibWeb/Text/expected/wpt-import/css/selectors/parsing/parse-has.txt index abf8e4775a5..62fc63073e7 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/selectors/parsing/parse-has.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/selectors/parsing/parse-has.txt @@ -2,8 +2,7 @@ Harness status: OK Found 29 tests -26 Pass -3 Fail +29 Pass Pass ":has(a)" should be a valid selector Pass ":has(#a)" should be a valid selector Pass ":has(.a)" should be a valid selector @@ -13,9 +12,9 @@ Pass ":has([a|=\"b\"])" should be a valid selector Pass ":has(:hover)" should be a valid selector Pass "*:has(.a)" should be a valid selector Pass ".a:has(.b)" should be a valid selector -Fail ".a:has(> .b)" should be a valid selector -Fail ".a:has(~ .b)" should be a valid selector -Fail ".a:has(+ .b)" should be a valid selector +Pass ".a:has(> .b)" should be a valid selector +Pass ".a:has(~ .b)" should be a valid selector +Pass ".a:has(+ .b)" should be a valid selector Pass ".a:has(.b) .c" should be a valid selector Pass ".a .b:has(.c)" should be a valid selector Pass ".a .b:has(.c .d)" should be a valid selector