From 74c803c87bc052d7aa7e1c3212e913f63a89b54a Mon Sep 17 00:00:00 2001 From: Tim Ledbetter Date: Sun, 27 Apr 2025 12:53:58 +0100 Subject: [PATCH] LibWeb: Ensure `|=` value selector handles multiple segments correctly Previously, the `|=` would not compare strings containing `-` characters correctly because it would only compare the element attribute up to the first `-` character. --- Libraries/LibWeb/CSS/SelectorEngine.cpp | 21 ++++++++-- .../attribute-value-selector-009-ref.html | 24 +++++++++++ .../attribute-value-selector-010-ref.html | 24 +++++++++++ .../selector/attribute-value-selector-009.xht | 41 ++++++++++++++++++ .../attribute-value-selector-010.html | 42 +++++++++++++++++++ 5 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 Tests/LibWeb/Ref/expected/wpt-import/css/CSS2/selector/attribute-value-selector-009-ref.html create mode 100644 Tests/LibWeb/Ref/expected/wpt-import/css/CSS2/selector/attribute-value-selector-010-ref.html create mode 100644 Tests/LibWeb/Ref/input/wpt-import/css/CSS2/selector/attribute-value-selector-009.xht create mode 100644 Tests/LibWeb/Ref/input/wpt-import/css/CSS2/selector/attribute-value-selector-010.html diff --git a/Libraries/LibWeb/CSS/SelectorEngine.cpp b/Libraries/LibWeb/CSS/SelectorEngine.cpp index bda666c9f86..b11887ba98a 100644 --- a/Libraries/LibWeb/CSS/SelectorEngine.cpp +++ b/Libraries/LibWeb/CSS/SelectorEngine.cpp @@ -291,6 +291,10 @@ static inline bool matches_attribute(CSS::Selector::SimpleSelector::Attribute co return !attribute.value.is_empty() && attr->value().contains(attribute.value, case_sensitivity); case CSS::Selector::SimpleSelector::Attribute::MatchType::StartsWithSegment: { + // https://www.w3.org/TR/CSS2/selector.html#attribute-selectors + // [att|=val] + // Represents an element with the att attribute, its value either being exactly "val" or beginning with "val" immediately followed by "-" (U+002D). + auto const& element_attr_value = attr->value(); if (element_attr_value.is_empty()) { // If the attribute value on element is empty, the selector is true @@ -300,10 +304,19 @@ static inline bool matches_attribute(CSS::Selector::SimpleSelector::Attribute co if (attribute.value.is_empty()) { return false; } - auto segments = element_attr_value.bytes_as_string_view().split_view('-'); - return case_insensitive_match - ? Infra::is_ascii_case_insensitive_match(segments.first(), attribute.value) - : segments.first() == attribute.value; + + auto element_attribute_length = element_attr_value.bytes_as_string_view().length(); + auto attribute_length = attribute.value.bytes_as_string_view().length(); + if (element_attribute_length < attribute_length) + return false; + + if (attribute_length == element_attribute_length) { + return case_insensitive_match + ? Infra::is_ascii_case_insensitive_match(element_attr_value, attribute.value) + : element_attr_value == attribute.value; + } + + return element_attr_value.starts_with_bytes(attribute.value, case_insensitive_match ? CaseSensitivity::CaseInsensitive : CaseSensitivity::CaseSensitive) && element_attr_value.bytes_as_string_view()[attribute_length] == '-'; } case CSS::Selector::SimpleSelector::Attribute::MatchType::StartsWithString: return !attribute.value.is_empty() diff --git a/Tests/LibWeb/Ref/expected/wpt-import/css/CSS2/selector/attribute-value-selector-009-ref.html b/Tests/LibWeb/Ref/expected/wpt-import/css/CSS2/selector/attribute-value-selector-009-ref.html new file mode 100644 index 00000000000..78f497708d4 --- /dev/null +++ b/Tests/LibWeb/Ref/expected/wpt-import/css/CSS2/selector/attribute-value-selector-009-ref.html @@ -0,0 +1,24 @@ + + +CSS Reference + + +
This line should be green
+
This line should be green
+
This line should be green
+
This line should be green
+

This line should be green and this should be green too

+ +
This line should NOT be green
+
This line should NOT be green
+
This line should NOT be green
+
This line should NOT be green
+
This line should NOT be green
+
This line should NOT be green

This line should NOT be green

+

This line should NOT be green and this should not be green either

+ diff --git a/Tests/LibWeb/Ref/expected/wpt-import/css/CSS2/selector/attribute-value-selector-010-ref.html b/Tests/LibWeb/Ref/expected/wpt-import/css/CSS2/selector/attribute-value-selector-010-ref.html new file mode 100644 index 00000000000..1e2975c57f0 --- /dev/null +++ b/Tests/LibWeb/Ref/expected/wpt-import/css/CSS2/selector/attribute-value-selector-010-ref.html @@ -0,0 +1,24 @@ + + +CSS Reference + + +
This line should be green
+
This line should be green
+
This line should be green
+
This line should be green
+
This line should be green
+

This line should be green and this should be green too

+ +
This line should NOT be green
+
This line should NOT be green
+
This line should NOT be green
+
This line should NOT be green
+
This line should NOT be green

This line should NOT be green

+

This line should NOT be green and this should not be green either

+ diff --git a/Tests/LibWeb/Ref/input/wpt-import/css/CSS2/selector/attribute-value-selector-009.xht b/Tests/LibWeb/Ref/input/wpt-import/css/CSS2/selector/attribute-value-selector-009.xht new file mode 100644 index 00000000000..d6c32ce4ad6 --- /dev/null +++ b/Tests/LibWeb/Ref/input/wpt-import/css/CSS2/selector/attribute-value-selector-009.xht @@ -0,0 +1,41 @@ + + + + CSS Test: lang attribute selector - att |= val + + + + + + + + + + +
This line should be green
+
This line should be green
+ +
This line should be green
+
This line should be green
+ +

This line should be green and this should be green too

+ +
This line should NOT be green
+
This line should NOT be green
+
This line should NOT be green
+ +
This line should NOT be green
+
This line should NOT be green
+ +
This line should NOT be green

This line should NOT be green

+

This line should NOT be green and this should not be green either

+ + + diff --git a/Tests/LibWeb/Ref/input/wpt-import/css/CSS2/selector/attribute-value-selector-010.html b/Tests/LibWeb/Ref/input/wpt-import/css/CSS2/selector/attribute-value-selector-010.html new file mode 100644 index 00000000000..cb9f9cebb6f --- /dev/null +++ b/Tests/LibWeb/Ref/input/wpt-import/css/CSS2/selector/attribute-value-selector-010.html @@ -0,0 +1,42 @@ + + + + CSS Test: lang attribute selector - att |= val + + + + + + + + + + +
This line should be green
+
This line should be green
+
This line should be green
+ +
This line should be green
+
This line should be green
+ +

This line should be green and this should be green too

+ +
This line should NOT be green
+
This line should NOT be green
+ +
This line should NOT be green
+
This line should NOT be green
+ +
This line should NOT be green

This line should NOT be green

+

This line should NOT be green and this should not be green either

+ +