diff options
author | Sam Atkins <atkinssj@gmail.com> | 2021-07-12 17:58:47 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-07-14 13:31:00 +0200 |
commit | ffc81cbfad8af71674b8d63706b7166fa71509d5 (patch) | |
tree | ec83a4990ba11a2036bb7319486502414e1440e8 /Userland/Libraries/LibWeb/CSS | |
parent | 776b1f45487eb5f541f079239c209d1aa3c9e5cf (diff) | |
download | serenity-ffc81cbfad8af71674b8d63706b7166fa71509d5.zip |
LibWeb: Use Selectors instead of a String for :not() selectors
Rather than parsing the selector every time we want to check it, we
now parse it once at the beginning.
A bonus effect of this is that we now support a selector list in
:not(), instead of just a single selector, though only when using
the new parser.
Diffstat (limited to 'Userland/Libraries/LibWeb/CSS')
5 files changed, 15 insertions, 18 deletions
diff --git a/Userland/Libraries/LibWeb/CSS/Parser/DeprecatedCSSParser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/DeprecatedCSSParser.cpp index 6e7972d8f4..2fd9ed2b5a 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/DeprecatedCSSParser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/DeprecatedCSSParser.cpp @@ -606,7 +606,11 @@ public: pseudo_class.type = CSS::Selector::SimpleSelector::PseudoClass::Type::Checked; } else if (pseudo_name.starts_with("not", CaseSensitivity::CaseInsensitive)) { pseudo_class.type = CSS::Selector::SimpleSelector::PseudoClass::Type::Not; - pseudo_class.not_selector = capture_selector_args(pseudo_name); + auto not_selector = Web::parse_selector(m_context, capture_selector_args(pseudo_name)); + if (not_selector) { + pseudo_class.not_selector.clear(); + pseudo_class.not_selector.append(not_selector.release_nonnull()); + } } else { dbgln("Unknown pseudo class: '{}'", pseudo_name); return {}; diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 4e5480e147..679d28cfc6 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -469,7 +469,8 @@ RefPtr<Selector> Parser::parse_single_selector(TokenStream<T>& tokens, bool is_r } } else if (pseudo_function.name().equals_ignoring_case("not")) { pseudo_class.type = Selector::SimpleSelector::PseudoClass::Type::Not; - pseudo_class.not_selector = pseudo_function.values_as_string(); + auto function_token_stream = TokenStream(pseudo_function.values()); + pseudo_class.not_selector = parse_a_selector(function_token_stream); } else { dbgln("Unknown pseudo class: '{}'()", pseudo_function.name()); return {}; diff --git a/Userland/Libraries/LibWeb/CSS/Parser/StyleFunctionRule.h b/Userland/Libraries/LibWeb/CSS/Parser/StyleFunctionRule.h index 7934e9d1b1..ff7bebf517 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/StyleFunctionRule.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/StyleFunctionRule.h @@ -24,11 +24,6 @@ public: String const& name() const { return m_name; } Vector<StyleComponentValueRule> const& values() const { return m_values; } - // FIXME: This method is a temporary hack while much of the parser still expects a string, rather than tokens. - String values_as_string() const - { - return ""; - } String to_string() const; diff --git a/Userland/Libraries/LibWeb/CSS/Selector.h b/Userland/Libraries/LibWeb/CSS/Selector.h index b7c0f18e16..12f5f9f358 100644 --- a/Userland/Libraries/LibWeb/CSS/Selector.h +++ b/Userland/Libraries/LibWeb/CSS/Selector.h @@ -8,6 +8,7 @@ #pragma once #include <AK/FlyString.h> +#include <AK/NonnullRefPtrVector.h> #include <AK/RefCounted.h> #include <AK/String.h> #include <AK/Vector.h> @@ -64,8 +65,7 @@ public: // Only used when "pseudo_class" is "NthChild" or "NthLastChild". NthChildPattern nth_child_pattern; - // FIXME: This wants to be a Selector, rather than parsing it each time it is used. - String not_selector {}; + NonnullRefPtrVector<Selector> not_selector {}; }; PseudoClass pseudo_class; diff --git a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp index efd9938453..de5dd52b67 100644 --- a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp +++ b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp @@ -113,15 +113,12 @@ static bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoClass cons if (!element.has_attribute("checked")) return false; return true; - case CSS::Selector::SimpleSelector::PseudoClass::Type::Not: { - if (pseudo_class.not_selector.is_empty()) - return false; - auto not_selector = Web::parse_selector(CSS::DeprecatedParsingContext(element), pseudo_class.not_selector); - if (!not_selector) - return false; - auto not_matches = matches(not_selector.release_nonnull(), element); - return !not_matches; - } + case CSS::Selector::SimpleSelector::PseudoClass::Type::Not: + for (auto& selector : pseudo_class.not_selector) { + if (matches(selector, element)) + return false; + } + return true; case CSS::Selector::SimpleSelector::PseudoClass::Type::NthChild: case CSS::Selector::SimpleSelector::PseudoClass::Type::NthLastChild: auto const step_size = pseudo_class.nth_child_pattern.step_size; |