From 13d2111b74ada6a173ae6d9bb2d28a803e807b3d Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Sat, 18 Feb 2023 15:42:55 +0000 Subject: [PATCH] LibWeb: Port Selector to new Strings Also use `Infra::is_ascii_case_insensitive_match()` in some appropriate places, after checking the specs. --- .../Libraries/LibWeb/CSS/CSSStyleRule.cpp | 4 +- .../Libraries/LibWeb/CSS/Parser/Parser.cpp | 15 ++-- Userland/Libraries/LibWeb/CSS/Selector.cpp | 88 +++++++++---------- Userland/Libraries/LibWeb/CSS/Selector.h | 50 +++++------ .../Libraries/LibWeb/CSS/SelectorEngine.cpp | 47 +++++----- .../Libraries/LibWeb/CSS/StyleComputer.cpp | 6 +- 6 files changed, 105 insertions(+), 105 deletions(-) diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSStyleRule.cpp index d0ee5919864..a36e637a79c 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSStyleRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSStyleRule.cpp @@ -51,7 +51,7 @@ DeprecatedString CSSStyleRule::serialized() const // 1. Let s initially be the result of performing serialize a group of selectors on the rule’s associated selectors, // followed by the string " {", i.e., a single SPACE (U+0020), followed by LEFT CURLY BRACKET (U+007B). - builder.append(serialize_a_group_of_selectors(selectors())); + builder.append(serialize_a_group_of_selectors(selectors()).release_value_but_fixme_should_propagate_errors()); builder.append(" {"sv); // 2. Let decls be the result of performing serialize a CSS declaration block on the rule’s associated declarations, or null if there are no such declarations. @@ -92,7 +92,7 @@ DeprecatedString CSSStyleRule::serialized() const DeprecatedString CSSStyleRule::selector_text() const { // The selectorText attribute, on getting, must return the result of serializing the associated group of selectors. - return serialize_a_group_of_selectors(selectors()); + return serialize_a_group_of_selectors(selectors()).release_value_but_fixme_should_propagate_errors().to_deprecated_string(); } // https://www.w3.org/TR/cssom/#dom-cssstylerule-selectortext diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index cffd2e6b974..76b4580efcc 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -280,7 +280,7 @@ Parser::ParseErrorOr Parser::parse_attribute_simple_se // they are converted to lowercase, so we do that here too. If we want to be // correct with XML later, we'll need to keep the original case and then do // a case-insensitive compare later. - .name = attribute_part.token().ident().to_lowercase_string(), + .name = FlyString::from_utf8(attribute_part.token().ident().to_lowercase_string()).release_value_but_fixme_should_propagate_errors(), .case_type = Selector::SimpleSelector::Attribute::CaseType::DefaultMatch, } }; @@ -340,7 +340,8 @@ Parser::ParseErrorOr Parser::parse_attribute_simple_se dbgln_if(CSS_PARSER_DEBUG, "Expected a string or ident for the value to match attribute against, got: '{}'", value_part.to_debug_string()); return ParseError::SyntaxError; } - simple_selector.attribute().value = value_part.token().is(Token::Type::Ident) ? value_part.token().ident() : value_part.token().string(); + auto value_string_view = value_part.token().is(Token::Type::Ident) ? value_part.token().ident() : value_part.token().string(); + simple_selector.attribute().value = String::from_utf8(value_string_view).release_value_but_fixme_should_propagate_errors(); attribute_tokens.skip_whitespace(); // Handle case-sensitivity suffixes. https://www.w3.org/TR/selectors-4/#attribute-case @@ -563,8 +564,8 @@ Parser::ParseErrorOr Parser::parse_pseudo_simple_selec return ParseError::SyntaxError; } // FIXME: Support multiple, comma-separated, language ranges. - Vector languages; - languages.append(pseudo_function.values().first().token().to_string().release_value_but_fixme_should_propagate_errors().to_deprecated_string()); + Vector languages; + languages.append(pseudo_function.values().first().token().to_string().release_value_but_fixme_should_propagate_errors()); return Selector::SimpleSelector { .type = Selector::SimpleSelector::Type::PseudoClass, .value = Selector::SimpleSelector::PseudoClass { @@ -618,7 +619,7 @@ Parser::ParseErrorOr> Parser::parse_simple_se } return Selector::SimpleSelector { .type = Selector::SimpleSelector::Type::Class, - .value = Selector::SimpleSelector::Name { class_name_value.token().ident() } + .value = Selector::SimpleSelector::Name { FlyString::from_utf8(class_name_value.token().ident()).release_value_but_fixme_should_propagate_errors() } }; } case '>': @@ -642,13 +643,13 @@ Parser::ParseErrorOr> Parser::parse_simple_se } return Selector::SimpleSelector { .type = Selector::SimpleSelector::Type::Id, - .value = Selector::SimpleSelector::Name { first_value.token().hash_value() } + .value = Selector::SimpleSelector::Name { FlyString::from_utf8(first_value.token().hash_value()).release_value_but_fixme_should_propagate_errors() } }; } if (first_value.is(Token::Type::Ident)) { return Selector::SimpleSelector { .type = Selector::SimpleSelector::Type::TagName, - .value = Selector::SimpleSelector::Name { first_value.token().ident() } + .value = Selector::SimpleSelector::Name { FlyString::from_utf8(first_value.token().ident()).release_value_but_fixme_should_propagate_errors() } }; } if (first_value.is_block() && first_value.block().is_square()) diff --git a/Userland/Libraries/LibWeb/CSS/Selector.cpp b/Userland/Libraries/LibWeb/CSS/Selector.cpp index 788525196ac..a43e1b4ccfa 100644 --- a/Userland/Libraries/LibWeb/CSS/Selector.cpp +++ b/Userland/Libraries/LibWeb/CSS/Selector.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2018-2020, Andreas Kling - * Copyright (c) 2021-2022, Sam Atkins + * Copyright (c) 2021-2023, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -119,7 +119,7 @@ u32 Selector::specificity() const } // https://www.w3.org/TR/cssom/#serialize-a-simple-selector -DeprecatedString Selector::SimpleSelector::serialize() const +ErrorOr Selector::SimpleSelector::serialize() const { StringBuilder s; switch (type) { @@ -129,50 +129,50 @@ DeprecatedString Selector::SimpleSelector::serialize() const // FIXME: 2. If the namespace prefix maps to a namespace that is the null namespace (not in a namespace) append "|" (U+007C) to s. // 3. If this is a type selector append the serialization of the element name as an identifier to s. if (type == Selector::SimpleSelector::Type::TagName) { - serialize_an_identifier(s, name()).release_value_but_fixme_should_propagate_errors(); + TRY(serialize_an_identifier(s, name())); } // 4. If this is a universal selector append "*" (U+002A) to s. if (type == Selector::SimpleSelector::Type::Universal) - s.append('*'); + TRY(s.try_append('*')); break; case Selector::SimpleSelector::Type::Attribute: { auto& attribute = this->attribute(); // 1. Append "[" (U+005B) to s. - s.append('['); + TRY(s.try_append('[')); // FIXME: 2. If the namespace prefix maps to a namespace that is not the null namespace (not in a namespace) append the serialization of the namespace prefix as an identifier, followed by a "|" (U+007C) to s. // 3. Append the serialization of the attribute name as an identifier to s. - serialize_an_identifier(s, attribute.name).release_value_but_fixme_should_propagate_errors(); + TRY(serialize_an_identifier(s, attribute.name)); // 4. If there is an attribute value specified, append "=", "~=", "|=", "^=", "$=", or "*=" as appropriate (depending on the type of attribute selector), // followed by the serialization of the attribute value as a string, to s. - if (!attribute.value.is_null()) { + if (!attribute.value.is_empty()) { switch (attribute.match_type) { case Selector::SimpleSelector::Attribute::MatchType::ExactValueMatch: - s.append("="sv); + TRY(s.try_append("="sv)); break; case Selector::SimpleSelector::Attribute::MatchType::ContainsWord: - s.append("~="sv); + TRY(s.try_append("~="sv)); break; case Selector::SimpleSelector::Attribute::MatchType::ContainsString: - s.append("*="sv); + TRY(s.try_append("*="sv)); break; case Selector::SimpleSelector::Attribute::MatchType::StartsWithSegment: - s.append("|="sv); + TRY(s.try_append("|="sv)); break; case Selector::SimpleSelector::Attribute::MatchType::StartsWithString: - s.append("^="sv); + TRY(s.try_append("^="sv)); break; case Selector::SimpleSelector::Attribute::MatchType::EndsWithString: - s.append("$="sv); + TRY(s.try_append("$="sv)); break; default: break; } - serialize_a_string(s, attribute.value).release_value_but_fixme_should_propagate_errors(); + TRY(serialize_a_string(s, attribute.value)); } // 5. If the attribute selector has the case-insensitivity flag present, append " i" (U+0020 U+0069) to s. @@ -180,30 +180,30 @@ DeprecatedString Selector::SimpleSelector::serialize() const // (the line just above is an addition to CSS OM to match Selectors Level 4 last draft) switch (attribute.case_type) { case Selector::SimpleSelector::Attribute::CaseType::CaseInsensitiveMatch: - s.append(" i"sv); + TRY(s.try_append(" i"sv)); break; case Selector::SimpleSelector::Attribute::CaseType::CaseSensitiveMatch: - s.append(" s"sv); + TRY(s.try_append(" s"sv)); break; default: break; } // 6. Append "]" (U+005D) to s. - s.append(']'); + TRY(s.try_append(']')); break; } case Selector::SimpleSelector::Type::Class: // Append a "." (U+002E), followed by the serialization of the class name as an identifier to s. - s.append('.'); - serialize_an_identifier(s, name()).release_value_but_fixme_should_propagate_errors(); + TRY(s.try_append('.')); + TRY(serialize_an_identifier(s, name())); break; case Selector::SimpleSelector::Type::Id: // Append a "#" (U+0023), followed by the serialization of the ID as an identifier to s. - s.append('#'); - serialize_an_identifier(s, name()).release_value_but_fixme_should_propagate_errors(); + TRY(s.try_append('#')); + TRY(serialize_an_identifier(s, name())); break; case Selector::SimpleSelector::Type::PseudoClass: { @@ -228,8 +228,8 @@ DeprecatedString Selector::SimpleSelector::serialize() const case Selector::SimpleSelector::PseudoClass::Type::Checked: case Selector::SimpleSelector::PseudoClass::Type::Active: // If the pseudo-class does not accept arguments append ":" (U+003A), followed by the name of the pseudo-class, to s. - s.append(':'); - s.append(pseudo_class_name(pseudo_class.type)); + TRY(s.try_append(':')); + TRY(s.try_append(pseudo_class_name(pseudo_class.type))); break; case Selector::SimpleSelector::PseudoClass::Type::NthChild: case Selector::SimpleSelector::PseudoClass::Type::NthLastChild: @@ -241,26 +241,26 @@ DeprecatedString Selector::SimpleSelector::serialize() const case Selector::SimpleSelector::PseudoClass::Type::Lang: // Otherwise, append ":" (U+003A), followed by the name of the pseudo-class, followed by "(" (U+0028), // followed by the value of the pseudo-class argument(s) determined as per below, followed by ")" (U+0029), to s. - s.append(':'); - s.append(pseudo_class_name(pseudo_class.type)); - s.append('('); + TRY(s.try_append(':')); + TRY(s.try_append(pseudo_class_name(pseudo_class.type))); + TRY(s.try_append('(')); if (pseudo_class.type == Selector::SimpleSelector::PseudoClass::Type::NthChild || pseudo_class.type == Selector::SimpleSelector::PseudoClass::Type::NthLastChild || pseudo_class.type == Selector::SimpleSelector::PseudoClass::Type::NthOfType || pseudo_class.type == Selector::SimpleSelector::PseudoClass::Type::NthLastOfType) { // The result of serializing the value using the rules to serialize an value. - s.append(pseudo_class.nth_child_pattern.serialize()); + TRY(s.try_append(TRY(pseudo_class.nth_child_pattern.serialize()))); } else if (pseudo_class.type == Selector::SimpleSelector::PseudoClass::Type::Not || pseudo_class.type == Selector::SimpleSelector::PseudoClass::Type::Is || pseudo_class.type == Selector::SimpleSelector::PseudoClass::Type::Where) { // The result of serializing the value using the rules for serializing a group of selectors. // NOTE: `:is()` and `:where()` aren't in the spec for this yet, but it should be! - s.append(serialize_a_group_of_selectors(pseudo_class.argument_selector_list)); + TRY(s.try_append(TRY(serialize_a_group_of_selectors(pseudo_class.argument_selector_list)))); } else if (pseudo_class.type == Selector::SimpleSelector::PseudoClass::Type::Lang) { // The serialization of a comma-separated list of each argument’s serialization as a string, preserving relative order. s.join(", "sv, pseudo_class.languages); } - s.append(')'); + TRY(s.try_append(')')); break; default: dbgln("FIXME: Unknown pseudo class type for serialization: {}", to_underlying(pseudo_class.type)); @@ -275,11 +275,11 @@ DeprecatedString Selector::SimpleSelector::serialize() const dbgln("FIXME: Unsupported simple selector serialization for type {}", to_underlying(type)); break; } - return s.to_deprecated_string(); + return s.to_string(); } // https://www.w3.org/TR/cssom/#serialize-a-selector -DeprecatedString Selector::serialize() const +ErrorOr Selector::serialize() const { StringBuilder s; @@ -289,14 +289,14 @@ DeprecatedString Selector::serialize() const // 1. If there is only one simple selector in the compound selectors which is a universal selector, append the result of serializing the universal selector to s. if (compound_selector.simple_selectors.size() == 1 && compound_selector.simple_selectors.first().type == Selector::SimpleSelector::Type::Universal) { - s.append(compound_selector.simple_selectors.first().serialize()); + TRY(s.try_append(TRY(compound_selector.simple_selectors.first().serialize()))); } // 2. Otherwise, for each simple selector in the compound selectors... // FIXME: ...that is not a universal selector of which the namespace prefix maps to a namespace that is not the default namespace... // ...serialize the simple selector and append the result to s. else { for (auto& simple_selector : compound_selector.simple_selectors) { - s.append(simple_selector.serialize()); + TRY(s.try_append(TRY(simple_selector.serialize()))); } } @@ -304,21 +304,21 @@ DeprecatedString Selector::serialize() const // followed by the combinator ">", "+", "~", ">>", "||", as appropriate, followed by another // single SPACE (U+0020) if the combinator was not whitespace, to s. if (i != compound_selectors().size() - 1) { - s.append(' '); + TRY(s.try_append(' ')); // Note: The combinator that appears between parts `i` and `i+1` appears with the `i+1` selector, // so we have to check that one. switch (compound_selectors()[i + 1].combinator) { case Selector::Combinator::ImmediateChild: - s.append("> "sv); + TRY(s.try_append("> "sv)); break; case Selector::Combinator::NextSibling: - s.append("+ "sv); + TRY(s.try_append("+ "sv)); break; case Selector::Combinator::SubsequentSibling: - s.append("~ "sv); + TRY(s.try_append("~ "sv)); break; case Selector::Combinator::Column: - s.append("|| "sv); + TRY(s.try_append("|| "sv)); break; default: break; @@ -327,22 +327,20 @@ DeprecatedString Selector::serialize() const // 4. If this is the last part of the chain of the selector and there is a pseudo-element, // append "::" followed by the name of the pseudo-element, to s. if (compound_selector.simple_selectors.last().type == Selector::SimpleSelector::Type::PseudoElement) { - s.append("::"sv); - s.append(pseudo_element_name(compound_selector.simple_selectors.last().pseudo_element())); + TRY(s.try_append("::"sv)); + TRY(s.try_append(pseudo_element_name(compound_selector.simple_selectors.last().pseudo_element()))); } } } - return s.to_deprecated_string(); + return s.to_string(); } // https://www.w3.org/TR/cssom/#serialize-a-group-of-selectors -DeprecatedString serialize_a_group_of_selectors(NonnullRefPtrVector const& selectors) +ErrorOr serialize_a_group_of_selectors(NonnullRefPtrVector const& selectors) { // To serialize a group of selectors serialize each selector in the group of selectors and then serialize a comma-separated list of these serializations. - StringBuilder builder; - builder.join(", "sv, selectors); - return builder.to_deprecated_string(); + return String::join(", "sv, selectors); } Optional pseudo_element_from_string(StringView name) diff --git a/Userland/Libraries/LibWeb/CSS/Selector.h b/Userland/Libraries/LibWeb/CSS/Selector.h index 837cdb11b85..fb9e0976d2b 100644 --- a/Userland/Libraries/LibWeb/CSS/Selector.h +++ b/Userland/Libraries/LibWeb/CSS/Selector.h @@ -7,10 +7,10 @@ #pragma once -#include -#include +#include #include #include +#include #include namespace Web::CSS { @@ -50,11 +50,11 @@ public: int offset = { 0 }; // "B" // https://www.w3.org/TR/css-syntax-3/#serializing-anb - DeprecatedString serialize() const + ErrorOr serialize() const { // 1. If A is zero, return the serialization of B. if (step_size == 0) { - return DeprecatedString::formatted("{}", offset); + return String::formatted("{}", offset); } // 2. Otherwise, let result initially be an empty string. @@ -63,24 +63,24 @@ public: // 3. // - A is 1: Append "n" to result. if (step_size == 1) - result.append('n'); + TRY(result.try_append('n')); // - A is -1: Append "-n" to result. else if (step_size == -1) - result.append("-n"sv); + TRY(result.try_append("-n"sv)); // - A is non-zero: Serialize A and append it to result, then append "n" to result. else if (step_size != 0) - result.appendff("{}n", step_size); + TRY(result.try_appendff("{}n", step_size)); // 4. // - B is greater than zero: Append "+" to result, then append the serialization of B to result. if (offset > 0) - result.appendff("+{}", offset); + TRY(result.try_appendff("+{}", offset)); // - B is less than zero: Append the serialization of B to result. if (offset < 0) - result.appendff("{}", offset); + TRY(result.try_appendff("{}", offset)); // 5. Return result. - return result.to_deprecated_string(); + return result.to_string(); } }; @@ -121,7 +121,7 @@ public: SelectorList argument_selector_list {}; // Used for :lang(en-gb,dk) - Vector languages {}; + Vector languages {}; }; struct Attribute { @@ -140,20 +140,20 @@ public: CaseInsensitiveMatch, }; MatchType match_type; - DeprecatedFlyString name {}; - DeprecatedString value {}; + FlyString name {}; + String value {}; CaseType case_type; }; struct Name { - Name(DeprecatedFlyString n) + Name(FlyString n) : name(move(n)) - , lowercase_name(name.to_lowercase()) + , lowercase_name(name.to_string().to_lowercase().release_value_but_fixme_should_propagate_errors()) { } - DeprecatedFlyString name; - DeprecatedFlyString lowercase_name; + FlyString name; + FlyString lowercase_name; }; Type type; @@ -166,12 +166,12 @@ public: PseudoElement const& pseudo_element() const { return value.get(); } PseudoElement& pseudo_element() { return value.get(); } - DeprecatedFlyString const& name() const { return value.get().name; } - DeprecatedFlyString& name() { return value.get().name; } - DeprecatedFlyString const& lowercase_name() const { return value.get().lowercase_name; } - DeprecatedFlyString& lowercase_name() { return value.get().lowercase_name; } + FlyString const& name() const { return value.get().name; } + FlyString& name() { return value.get().name; } + FlyString const& lowercase_name() const { return value.get().lowercase_name; } + FlyString& lowercase_name() { return value.get().lowercase_name; } - DeprecatedString serialize() const; + ErrorOr serialize() const; }; enum class Combinator { @@ -200,7 +200,7 @@ public: Vector const& compound_selectors() const { return m_compound_selectors; } Optional pseudo_element() const { return m_pseudo_element; } u32 specificity() const; - DeprecatedString serialize() const; + ErrorOr serialize() const; private: explicit Selector(Vector&&); @@ -294,7 +294,7 @@ constexpr StringView pseudo_class_name(Selector::SimpleSelector::PseudoClass::Ty VERIFY_NOT_REACHED(); } -DeprecatedString serialize_a_group_of_selectors(NonnullRefPtrVector const& selectors); +ErrorOr serialize_a_group_of_selectors(NonnullRefPtrVector const& selectors); } @@ -304,7 +304,7 @@ template<> struct Formatter : Formatter { ErrorOr format(FormatBuilder& builder, Web::CSS::Selector const& selector) { - return Formatter::format(builder, selector.serialize()); + return Formatter::format(builder, TRY(selector.serialize())); } }; diff --git a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp index 116bdfa00db..eb14395241a 100644 --- a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp +++ b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2018-2022, Andreas Kling - * Copyright (c) 2021, Sam Atkins + * Copyright (c) 2021-2023, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -21,21 +21,22 @@ #include #include #include +#include namespace Web::SelectorEngine { // https://drafts.csswg.org/selectors-4/#the-lang-pseudo -static inline bool matches_lang_pseudo_class(DOM::Element const& element, Vector const& languages) +static inline bool matches_lang_pseudo_class(DOM::Element const& element, Vector const& languages) { - DeprecatedFlyString element_language; + FlyString element_language; for (auto const* e = &element; e; e = e->parent_element()) { auto lang = e->attribute(HTML::AttributeNames::lang); if (!lang.is_null()) { - element_language = lang; + element_language = FlyString::from_utf8(lang).release_value_but_fixme_should_propagate_errors(); break; } } - if (element_language.is_null()) + if (element_language.is_empty()) return false; // FIXME: This is ad-hoc. Implement a proper language range matching algorithm as recommended by BCP47. @@ -44,10 +45,10 @@ static inline bool matches_lang_pseudo_class(DOM::Element const& element, Vector return false; if (language == "*"sv) return true; - if (!element_language.view().contains('-')) - return element_language.equals_ignoring_case(language); - auto parts = element_language.view().split_view('-'); - return parts[0].equals_ignoring_case(language); + if (!element_language.to_string().contains('-')) + return Infra::is_ascii_case_insensitive_match(element_language, language); + auto parts = element_language.to_string().split_limit('-', 2).release_value_but_fixme_should_propagate_errors(); + return Infra::is_ascii_case_insensitive_match(parts[0], language); } return false; } @@ -97,7 +98,7 @@ static inline bool matches_attribute(CSS::Selector::SimpleSelector::Attribute co { if (attribute.match_type == CSS::Selector::SimpleSelector::Attribute::MatchType::HasAttribute) { // Early way out in case of an attribute existence selector. - return element.has_attribute(attribute.name); + return element.has_attribute(attribute.name.to_string().to_deprecated_string()); } auto const case_insensitive_match = (attribute.case_type == CSS::Selector::SimpleSelector::Attribute::CaseType::CaseInsensitiveMatch); @@ -108,19 +109,19 @@ static inline bool matches_attribute(CSS::Selector::SimpleSelector::Attribute co switch (attribute.match_type) { case CSS::Selector::SimpleSelector::Attribute::MatchType::ExactValueMatch: return case_insensitive_match - ? element.attribute(attribute.name).equals_ignoring_case(attribute.value) - : element.attribute(attribute.name) == attribute.value; + ? Infra::is_ascii_case_insensitive_match(element.attribute(attribute.name.to_string().to_deprecated_string()), attribute.value) + : element.attribute(attribute.name.to_string().to_deprecated_string()) == attribute.value.to_deprecated_string(); case CSS::Selector::SimpleSelector::Attribute::MatchType::ContainsWord: { if (attribute.value.is_empty()) { // This selector is always false is match value is empty. return false; } - auto const view = element.attribute(attribute.name).split_view(' '); + auto const view = element.attribute(attribute.name.to_string().to_deprecated_string()).split_view(' '); auto const size = view.size(); for (size_t i = 0; i < size; ++i) { auto const value = view.at(i); if (case_insensitive_match - ? value.equals_ignoring_case(attribute.value) + ? Infra::is_ascii_case_insensitive_match(value, attribute.value) : value == attribute.value) { return true; } @@ -129,9 +130,9 @@ static inline bool matches_attribute(CSS::Selector::SimpleSelector::Attribute co } case CSS::Selector::SimpleSelector::Attribute::MatchType::ContainsString: return !attribute.value.is_empty() - && element.attribute(attribute.name).contains(attribute.value, case_sensitivity); + && element.attribute(attribute.name.to_string().to_deprecated_string()).contains(attribute.value, case_sensitivity); case CSS::Selector::SimpleSelector::Attribute::MatchType::StartsWithSegment: { - auto const element_attr_value = element.attribute(attribute.name); + auto const element_attr_value = element.attribute(attribute.name.to_string().to_deprecated_string()); if (element_attr_value.is_empty()) { // If the attribute value on element is empty, the selector is true // if the match value is also empty and false otherwise. @@ -142,15 +143,15 @@ static inline bool matches_attribute(CSS::Selector::SimpleSelector::Attribute co } auto segments = element_attr_value.split_view('-'); return case_insensitive_match - ? segments.first().equals_ignoring_case(attribute.value) + ? Infra::is_ascii_case_insensitive_match(segments.first(), attribute.value) : segments.first() == attribute.value; } case CSS::Selector::SimpleSelector::Attribute::MatchType::StartsWithString: return !attribute.value.is_empty() - && element.attribute(attribute.name).starts_with(attribute.value, case_sensitivity); + && element.attribute(attribute.name.to_string().to_deprecated_string()).starts_with(attribute.value, case_sensitivity); case CSS::Selector::SimpleSelector::Attribute::MatchType::EndsWithString: return !attribute.value.is_empty() - && element.attribute(attribute.name).ends_with(attribute.value, case_sensitivity); + && element.attribute(attribute.name.to_string().to_deprecated_string()).ends_with(attribute.value, case_sensitivity); default: break; } @@ -351,14 +352,14 @@ static inline bool matches(CSS::Selector::SimpleSelector const& component, DOM:: case CSS::Selector::SimpleSelector::Type::Universal: return true; case CSS::Selector::SimpleSelector::Type::Id: - return component.name() == element.attribute(HTML::AttributeNames::id); + return component.name() == element.attribute(HTML::AttributeNames::id).view(); case CSS::Selector::SimpleSelector::Type::Class: - return element.has_class(component.name()); + return element.has_class(component.name().bytes_as_string_view()); case CSS::Selector::SimpleSelector::Type::TagName: // See https://html.spec.whatwg.org/multipage/semantics-other.html#case-sensitivity-of-selectors if (element.document().document_type() == DOM::Document::Type::HTML) - return component.lowercase_name() == element.local_name(); - return component.name().equals_ignoring_case(element.local_name()); + return component.lowercase_name() == element.local_name().view(); + return Infra::is_ascii_case_insensitive_match(component.name(), element.local_name()); case CSS::Selector::SimpleSelector::Type::Attribute: return matches_attribute(component.attribute(), element); case CSS::Selector::SimpleSelector::Type::PseudoClass: diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index 6f6ca0f32b6..e1432e92792 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -1469,19 +1469,19 @@ void StyleComputer::build_rule_cache() if (!added_to_bucket) { for (auto const& simple_selector : selector.compound_selectors().last().simple_selectors) { if (simple_selector.type == CSS::Selector::SimpleSelector::Type::Id) { - m_rule_cache->rules_by_id.ensure(simple_selector.name()).append(move(matching_rule)); + m_rule_cache->rules_by_id.ensure(simple_selector.name().to_string().to_deprecated_string()).append(move(matching_rule)); ++num_id_rules; added_to_bucket = true; break; } if (simple_selector.type == CSS::Selector::SimpleSelector::Type::Class) { - m_rule_cache->rules_by_class.ensure(simple_selector.name()).append(move(matching_rule)); + m_rule_cache->rules_by_class.ensure(simple_selector.name().to_string().to_deprecated_string()).append(move(matching_rule)); ++num_class_rules; added_to_bucket = true; break; } if (simple_selector.type == CSS::Selector::SimpleSelector::Type::TagName) { - m_rule_cache->rules_by_tag_name.ensure(simple_selector.name()).append(move(matching_rule)); + m_rule_cache->rules_by_tag_name.ensure(simple_selector.name().to_string().to_deprecated_string()).append(move(matching_rule)); ++num_tag_name_rules; added_to_bucket = true; break;