Преглед на файлове

LibWeb: Make CSS::Selector reference counted

The end goal is to make the PseudoClass::not_selector be a Selector
instead of a String that is repeatedly re-parsed. But since Selector
contains a Vector of ComplexSelectors, which each have a Vector of
SimpleSelectors, it's probably a good idea to not be passing them
around by value anyway. :^)
Sam Atkins преди 4 години
родител
ревизия
776b1f4548

+ 1 - 1
Userland/Libraries/LibWeb/CSS/CSSStyleRule.cpp

@@ -8,7 +8,7 @@
 
 namespace Web::CSS {
 
-CSSStyleRule::CSSStyleRule(Vector<Selector>&& selectors, NonnullRefPtr<CSSStyleDeclaration>&& declaration)
+CSSStyleRule::CSSStyleRule(NonnullRefPtrVector<Selector>&& selectors, NonnullRefPtr<CSSStyleDeclaration>&& declaration)
     : m_selectors(move(selectors))
     , m_declaration(move(declaration))
 {

+ 5 - 4
Userland/Libraries/LibWeb/CSS/CSSStyleRule.h

@@ -7,6 +7,7 @@
 
 #pragma once
 
+#include <AK/NonnullRefPtr.h>
 #include <AK/NonnullRefPtrVector.h>
 #include <LibWeb/CSS/CSSRule.h>
 #include <LibWeb/CSS/CSSStyleDeclaration.h>
@@ -19,23 +20,23 @@ class CSSStyleRule : public CSSRule {
     AK_MAKE_NONMOVABLE(CSSStyleRule);
 
 public:
-    static NonnullRefPtr<CSSStyleRule> create(Vector<Selector>&& selectors, NonnullRefPtr<CSSStyleDeclaration>&& declaration)
+    static NonnullRefPtr<CSSStyleRule> create(NonnullRefPtrVector<Selector>&& selectors, NonnullRefPtr<CSSStyleDeclaration>&& declaration)
     {
         return adopt_ref(*new CSSStyleRule(move(selectors), move(declaration)));
     }
 
     ~CSSStyleRule();
 
-    const Vector<Selector>& selectors() const { return m_selectors; }
+    const NonnullRefPtrVector<Selector>& selectors() const { return m_selectors; }
     const CSSStyleDeclaration& declaration() const { return m_declaration; }
 
     virtual StringView class_name() const { return "CSSStyleRule"; };
     virtual Type type() const { return Type::Style; };
 
 private:
-    CSSStyleRule(Vector<Selector>&&, NonnullRefPtr<CSSStyleDeclaration>&&);
+    CSSStyleRule(NonnullRefPtrVector<Selector>&&, NonnullRefPtr<CSSStyleDeclaration>&&);
 
-    Vector<Selector> m_selectors;
+    NonnullRefPtrVector<Selector> m_selectors;
     NonnullRefPtr<CSSStyleDeclaration> m_declaration;
 };
 

+ 4 - 4
Userland/Libraries/LibWeb/CSS/Parser/DeprecatedCSSParser.cpp

@@ -683,10 +683,10 @@ public:
             return;
         complex_selectors.first().relation = CSS::Selector::ComplexSelector::Relation::None;
 
-        current_rule.selectors.append(CSS::Selector(move(complex_selectors)));
+        current_rule.selectors.append(CSS::Selector::create(move(complex_selectors)));
     }
 
-    Optional<CSS::Selector> parse_individual_selector()
+    RefPtr<CSS::Selector> parse_individual_selector()
     {
         parse_selector();
         if (current_rule.selectors.is_empty())
@@ -1037,7 +1037,7 @@ private:
     NonnullRefPtrVector<CSS::CSSRule> rules;
 
     struct CurrentRule {
-        Vector<CSS::Selector> selectors;
+        NonnullRefPtrVector<CSS::Selector> selectors;
         Vector<CSS::StyleProperty> properties;
         HashMap<String, CSS::StyleProperty> custom_properties;
     };
@@ -1050,7 +1050,7 @@ private:
     StringView css;
 };
 
-Optional<CSS::Selector> parse_selector(const CSS::DeprecatedParsingContext& context, const StringView& selector_text)
+RefPtr<CSS::Selector> parse_selector(const CSS::DeprecatedParsingContext& context, const StringView& selector_text)
 {
     CSSParser parser(context, selector_text);
     return parser.parse_individual_selector();

+ 1 - 1
Userland/Libraries/LibWeb/CSS/Parser/DeprecatedCSSParser.h

@@ -31,7 +31,7 @@ namespace Web {
 RefPtr<CSS::CSSStyleSheet> parse_css(const CSS::DeprecatedParsingContext&, const StringView&);
 RefPtr<CSS::CSSStyleDeclaration> parse_css_declaration(const CSS::DeprecatedParsingContext&, const StringView&);
 RefPtr<CSS::StyleValue> parse_css_value(const CSS::DeprecatedParsingContext&, const StringView&, CSS::PropertyID property_id = CSS::PropertyID::Invalid);
-Optional<CSS::Selector> parse_selector(const CSS::DeprecatedParsingContext&, const StringView&);
+RefPtr<CSS::Selector> parse_selector(const CSS::DeprecatedParsingContext&, const StringView&);
 
 RefPtr<CSS::LengthStyleValue> parse_line_width(const CSS::DeprecatedParsingContext&, const StringView&);
 RefPtr<CSS::ColorStyleValue> parse_color(const CSS::DeprecatedParsingContext&, const StringView&);

+ 13 - 13
Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

@@ -171,55 +171,55 @@ NonnullRefPtr<CSSStyleSheet> Parser::parse_as_stylesheet(TokenStream<T>& tokens)
     return stylesheet;
 }
 
-Vector<Selector> Parser::parse_a_selector()
+NonnullRefPtrVector<Selector> Parser::parse_a_selector()
 {
     return parse_a_selector(m_token_stream);
 }
 
 template<typename T>
-Vector<Selector> Parser::parse_a_selector(TokenStream<T>& tokens)
+NonnullRefPtrVector<Selector> Parser::parse_a_selector(TokenStream<T>& tokens)
 {
     dbgln_if(CSS_PARSER_TRACE, "Parser::parse_a_selector");
 
     auto comma_separated_lists = parse_as_comma_separated_list_of_component_values(tokens);
-    Vector<Selector> selectors;
+    NonnullRefPtrVector<Selector> selectors;
 
     for (auto& selector_parts : comma_separated_lists) {
         auto stream = TokenStream(selector_parts);
         auto selector = parse_single_selector(stream);
-        if (selector.has_value())
-            selectors.append(selector.value());
+        if (selector)
+            selectors.append(selector.release_nonnull());
     }
 
     return selectors;
 }
 
-Vector<Selector> Parser::parse_a_relative_selector()
+NonnullRefPtrVector<Selector> Parser::parse_a_relative_selector()
 {
     return parse_a_relative_selector(m_token_stream);
 }
 
 template<typename T>
-Vector<Selector> Parser::parse_a_relative_selector(TokenStream<T>& tokens)
+NonnullRefPtrVector<Selector> Parser::parse_a_relative_selector(TokenStream<T>& tokens)
 {
     dbgln_if(CSS_PARSER_TRACE, "Parser::parse_a_relative_selector");
 
     auto comma_separated_lists = parse_as_comma_separated_list_of_component_values(tokens);
 
-    Vector<Selector> selectors;
+    NonnullRefPtrVector<Selector> selectors;
 
     for (auto& selector_parts : comma_separated_lists) {
         auto stream = TokenStream(selector_parts);
         auto selector = parse_single_selector(stream, true);
-        if (selector.has_value())
-            selectors.append(selector.value());
+        if (selector)
+            selectors.append(selector.release_nonnull());
     }
 
     return selectors;
 }
 
 template<typename T>
-Optional<Selector> Parser::parse_single_selector(TokenStream<T>& tokens, bool is_relative)
+RefPtr<Selector> Parser::parse_single_selector(TokenStream<T>& tokens, bool is_relative)
 {
     dbgln_if(CSS_PARSER_TRACE, "Parser::parse_single_selector");
 
@@ -555,7 +555,7 @@ Optional<Selector> Parser::parse_single_selector(TokenStream<T>& tokens, bool is
     if (!is_relative)
         selectors.first().relation = Selector::ComplexSelector::Relation::None;
 
-    return Selector(move(selectors));
+    return Selector::create(move(selectors));
 }
 
 NonnullRefPtrVector<StyleRule> Parser::consume_a_list_of_rules(bool top_level)
@@ -1145,7 +1145,7 @@ RefPtr<CSSRule> Parser::convert_to_rule(NonnullRefPtr<StyleRule> rule)
 
     } else {
         auto prelude_stream = TokenStream(rule->m_prelude);
-        Vector<Selector> selectors = parse_a_selector(prelude_stream);
+        auto selectors = parse_a_selector(prelude_stream);
         auto declaration = convert_to_declaration(*rule->m_block);
         if (declaration && !selectors.is_empty())
             return CSSStyleRule::create(move(selectors), move(*declaration));

+ 7 - 5
Userland/Libraries/LibWeb/CSS/Parser/Parser.h

@@ -8,6 +8,8 @@
 #pragma once
 
 #include <AK/NonnullOwnPtrVector.h>
+#include <AK/NonnullRefPtrVector.h>
+#include <AK/RefPtr.h>
 #include <AK/Vector.h>
 #include <LibWeb/CSS/Parser/DeclarationOrAtRule.h>
 #include <LibWeb/CSS/Parser/StyleBlockRule.h>
@@ -110,19 +112,19 @@ public:
     Vector<Vector<StyleComponentValueRule>> parse_as_comma_separated_list_of_component_values(TokenStream<T>&);
 
     template<typename T>
-    Optional<Selector> parse_single_selector(TokenStream<T>&, bool is_relative = false);
+    RefPtr<Selector> parse_single_selector(TokenStream<T>&, bool is_relative = false);
 
     Optional<Selector::SimpleSelector::NthChildPattern> parse_nth_child_pattern(TokenStream<StyleComponentValueRule>&);
 
     // FIXME: https://www.w3.org/TR/selectors-4/
     // Contrary to the name, these parse a comma-separated list of selectors, according to the spec.
-    Vector<Selector> parse_a_selector();
+    NonnullRefPtrVector<Selector> parse_a_selector();
     template<typename T>
-    Vector<Selector> parse_a_selector(TokenStream<T>&);
+    NonnullRefPtrVector<Selector> parse_a_selector(TokenStream<T>&);
 
-    Vector<Selector> parse_a_relative_selector();
+    NonnullRefPtrVector<Selector> parse_a_relative_selector();
     template<typename T>
-    Vector<Selector> parse_a_relative_selector(TokenStream<T>&);
+    NonnullRefPtrVector<Selector> parse_a_relative_selector(TokenStream<T>&);
 
     RefPtr<StyleValue> parse_css_value(PropertyID, TokenStream<StyleComponentValueRule>&);
 

+ 9 - 2
Userland/Libraries/LibWeb/CSS/Selector.h

@@ -8,12 +8,13 @@
 #pragma once
 
 #include <AK/FlyString.h>
+#include <AK/RefCounted.h>
 #include <AK/String.h>
 #include <AK/Vector.h>
 
 namespace Web::CSS {
 
-class Selector {
+class Selector : public RefCounted<Selector> {
 public:
     struct SimpleSelector {
         enum class Type {
@@ -112,7 +113,11 @@ public:
         CompoundSelector compound_selector;
     };
 
-    explicit Selector(Vector<ComplexSelector>&&);
+    static NonnullRefPtr<Selector> create(Vector<ComplexSelector>&& complex_selectors)
+    {
+        return adopt_ref(*new Selector(move(complex_selectors)));
+    }
+
     ~Selector();
 
     Vector<ComplexSelector> const& complex_selectors() const { return m_complex_selectors; }
@@ -120,6 +125,8 @@ public:
     u32 specificity() const;
 
 private:
+    explicit Selector(Vector<ComplexSelector>&&);
+
     Vector<ComplexSelector> m_complex_selectors;
 };
 

+ 2 - 2
Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp

@@ -117,9 +117,9 @@ static bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoClass cons
         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.has_value())
+        if (!not_selector)
             return false;
-        auto not_matches = matches(not_selector.value(), element);
+        auto not_matches = matches(not_selector.release_nonnull(), element);
         return !not_matches;
     }
     case CSS::Selector::SimpleSelector::PseudoClass::Type::NthChild:

+ 6 - 6
Userland/Libraries/LibWeb/DOM/ParentNode.cpp

@@ -14,14 +14,14 @@ namespace Web::DOM {
 RefPtr<Element> ParentNode::query_selector(const StringView& selector_text)
 {
     auto selector = parse_selector(CSS::DeprecatedParsingContext(*this), selector_text);
-    if (!selector.has_value())
+    if (!selector)
         return {};
 
-    dump_selector(selector.value());
+    dump_selector(selector.release_nonnull());
 
     RefPtr<Element> result;
     for_each_in_inclusive_subtree_of_type<Element>([&](auto& element) {
-        if (SelectorEngine::matches(selector.value(), element)) {
+        if (SelectorEngine::matches(selector.release_nonnull(), element)) {
             result = element;
             return IterationDecision::Break;
         }
@@ -34,14 +34,14 @@ RefPtr<Element> ParentNode::query_selector(const StringView& selector_text)
 NonnullRefPtrVector<Element> ParentNode::query_selector_all(const StringView& selector_text)
 {
     auto selector = parse_selector(CSS::DeprecatedParsingContext(*this), selector_text);
-    if (!selector.has_value())
+    if (!selector)
         return {};
 
-    dump_selector(selector.value());
+    dump_selector(selector.release_nonnull());
 
     NonnullRefPtrVector<Element> elements;
     for_each_in_inclusive_subtree_of_type<Element>([&](auto& element) {
-        if (SelectorEngine::matches(selector.value(), element)) {
+        if (SelectorEngine::matches(selector.release_nonnull(), element)) {
             elements.append(element);
         }
         return IterationDecision::Continue;