summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibWeb/CSS
diff options
context:
space:
mode:
authorSam Atkins <atkinssj@gmail.com>2021-07-12 17:58:47 +0100
committerAndreas Kling <kling@serenityos.org>2021-07-14 13:31:00 +0200
commitffc81cbfad8af71674b8d63706b7166fa71509d5 (patch)
treeec83a4990ba11a2036bb7319486502414e1440e8 /Userland/Libraries/LibWeb/CSS
parent776b1f45487eb5f541f079239c209d1aa3c9e5cf (diff)
downloadserenity-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')
-rw-r--r--Userland/Libraries/LibWeb/CSS/Parser/DeprecatedCSSParser.cpp6
-rw-r--r--Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp3
-rw-r--r--Userland/Libraries/LibWeb/CSS/Parser/StyleFunctionRule.h5
-rw-r--r--Userland/Libraries/LibWeb/CSS/Selector.h4
-rw-r--r--Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp15
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;