Просмотр исходного кода

LibWeb/CSS: Replace style-rule iteration methods with a generic one

I didn't want to add another set of boilerplatey tree-walking methods,
so here's a general-purpose one. :^)

`for_each_effective_rule()` walks the tree of effective style rules, and
runs the callback on each one, in either pre- or postorder.  The
previous `for_each_effective_style/keyframes_rule()` methods of
`CSSStyleSheet` are then reimplemented in terms of
`for_each_effective_rule()`, and we can get rid of their equivalents
elsewhere.
Sam Atkins 10 месяцев назад
Родитель
Сommit
cbb4be3e5e

+ 3 - 9
Userland/Libraries/LibWeb/CSS/CSSConditionRule.cpp

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org>
+ * Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org>
  * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
  *
  * SPDX-License-Identifier: BSD-2-Clause
@@ -16,16 +16,10 @@ CSSConditionRule::CSSConditionRule(JS::Realm& realm, CSSRuleList& rules)
 {
 }
 
-void CSSConditionRule::for_each_effective_style_rule(Function<void(CSSStyleRule const&)> const& callback) const
+void CSSConditionRule::for_each_effective_rule(TraversalOrder order, Function<void(Web::CSS::CSSRule const&)> const& callback) const
 {
     if (condition_matches())
-        CSSGroupingRule::for_each_effective_style_rule(callback);
-}
-
-void CSSConditionRule::for_each_effective_keyframes_at_rule(Function<void(CSSKeyframesRule const&)> const& callback) const
-{
-    if (condition_matches())
-        CSSGroupingRule::for_each_effective_keyframes_at_rule(callback);
+        CSSGroupingRule::for_each_effective_rule(order, callback);
 }
 
 void CSSConditionRule::initialize(JS::Realm& realm)

+ 2 - 3
Userland/Libraries/LibWeb/CSS/CSSConditionRule.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org>
+ * Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org>
  *
  * SPDX-License-Identifier: BSD-2-Clause
  */
@@ -21,8 +21,7 @@ public:
     virtual String condition_text() const = 0;
     virtual bool condition_matches() const = 0;
 
-    virtual void for_each_effective_style_rule(Function<void(CSSStyleRule const&)> const& callback) const override;
-    virtual void for_each_effective_keyframes_at_rule(Function<void(CSSKeyframesRule const&)> const& callback) const override;
+    virtual void for_each_effective_rule(TraversalOrder, Function<void(CSSRule const&)> const& callback) const override;
 
 protected:
     CSSConditionRule(JS::Realm&, CSSRuleList&);

+ 3 - 8
Userland/Libraries/LibWeb/CSS/CSSGroupingRule.cpp

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org>
+ * Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org>
  * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
  *
  * SPDX-License-Identifier: BSD-2-Clause
@@ -47,14 +47,9 @@ WebIDL::ExceptionOr<void> CSSGroupingRule::delete_rule(u32 index)
     return m_rules->remove_a_css_rule(index);
 }
 
-void CSSGroupingRule::for_each_effective_style_rule(Function<void(CSSStyleRule const&)> const& callback) const
+void CSSGroupingRule::for_each_effective_rule(TraversalOrder order, Function<void(Web::CSS::CSSRule const&)> const& callback) const
 {
-    m_rules->for_each_effective_style_rule(callback);
-}
-
-void CSSGroupingRule::for_each_effective_keyframes_at_rule(Function<void(CSSKeyframesRule const&)> const& callback) const
-{
-    m_rules->for_each_effective_keyframes_at_rule(callback);
+    m_rules->for_each_effective_rule(order, callback);
 }
 
 void CSSGroupingRule::set_parent_style_sheet(CSSStyleSheet* parent_style_sheet)

+ 2 - 3
Userland/Libraries/LibWeb/CSS/CSSGroupingRule.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org>
+ * Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org>
  *
  * SPDX-License-Identifier: BSD-2-Clause
  */
@@ -26,8 +26,7 @@ public:
     WebIDL::ExceptionOr<u32> insert_rule(StringView rule, u32 index = 0);
     WebIDL::ExceptionOr<void> delete_rule(u32 index);
 
-    virtual void for_each_effective_style_rule(Function<void(CSSStyleRule const&)> const& callback) const;
-    virtual void for_each_effective_keyframes_at_rule(Function<void(CSSKeyframesRule const&)> const& callback) const;
+    virtual void for_each_effective_rule(TraversalOrder, Function<void(CSSRule const&)> const& callback) const;
 
     virtual void set_parent_style_sheet(CSSStyleSheet*) override;
 

+ 9 - 36
Userland/Libraries/LibWeb/CSS/CSSRuleList.cpp

@@ -119,64 +119,37 @@ WebIDL::ExceptionOr<void> CSSRuleList::remove_a_css_rule(u32 index)
     return {};
 }
 
-void CSSRuleList::for_each_effective_style_rule(Function<void(CSSStyleRule const&)> const& callback) const
+void CSSRuleList::for_each_effective_rule(TraversalOrder order, Function<void(Web::CSS::CSSRule const&)> const& callback) const
 {
     for (auto const& rule : m_rules) {
-        switch (rule->type()) {
-        case CSSRule::Type::Import: {
-            auto const& import_rule = static_cast<CSSImportRule const&>(*rule);
-            if (import_rule.loaded_style_sheet())
-                import_rule.loaded_style_sheet()->for_each_effective_style_rule(callback);
-            break;
-        }
-
-        case CSSRule::Type::LayerBlock:
-        case CSSRule::Type::Media:
-        case CSSRule::Type::Supports:
-            static_cast<CSSGroupingRule const&>(*rule).for_each_effective_style_rule(callback);
-            break;
-
-        case CSSRule::Type::Style:
-            callback(static_cast<CSSStyleRule const&>(*rule));
-            break;
-
-        case CSSRule::Type::FontFace:
-        case CSSRule::Type::Keyframe:
-        case CSSRule::Type::Keyframes:
-        case CSSRule::Type::LayerStatement:
-        case CSSRule::Type::Namespace:
-            break;
-        }
-    }
-}
+        if (order == TraversalOrder::Preorder)
+            callback(rule);
 
-void CSSRuleList::for_each_effective_keyframes_at_rule(Function<void(CSSKeyframesRule const&)> const& callback) const
-{
-    for (auto const& rule : m_rules) {
         switch (rule->type()) {
         case CSSRule::Type::Import: {
             auto const& import_rule = static_cast<CSSImportRule const&>(*rule);
             if (import_rule.loaded_style_sheet())
-                import_rule.loaded_style_sheet()->for_each_effective_keyframes_at_rule(callback);
+                import_rule.loaded_style_sheet()->for_each_effective_rule(order, callback);
             break;
         }
 
         case CSSRule::Type::LayerBlock:
         case CSSRule::Type::Media:
         case CSSRule::Type::Supports:
-            static_cast<CSSGroupingRule const&>(*rule).for_each_effective_keyframes_at_rule(callback);
-            break;
-        case CSSRule::Type::Keyframes:
-            callback(static_cast<CSSKeyframesRule const&>(*rule));
+            static_cast<CSSGroupingRule const&>(*rule).for_each_effective_rule(order, callback);
             break;
 
         case CSSRule::Type::FontFace:
         case CSSRule::Type::Keyframe:
+        case CSSRule::Type::Keyframes:
         case CSSRule::Type::LayerStatement:
         case CSSRule::Type::Namespace:
         case CSSRule::Type::Style:
             break;
         }
+
+        if (order == TraversalOrder::Postorder)
+            callback(rule);
     }
 }
 

+ 3 - 3
Userland/Libraries/LibWeb/CSS/CSSRuleList.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org>
+ * Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org>
  * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
  * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
  *
@@ -14,6 +14,7 @@
 #include <LibWeb/Bindings/PlatformObject.h>
 #include <LibWeb/CSS/CSSRule.h>
 #include <LibWeb/Forward.h>
+#include <LibWeb/TraversalOrder.h>
 #include <LibWeb/WebIDL/ExceptionOr.h>
 
 namespace Web::CSS {
@@ -56,10 +57,9 @@ public:
     WebIDL::ExceptionOr<void> remove_a_css_rule(u32 index);
     WebIDL::ExceptionOr<unsigned> insert_a_css_rule(Variant<StringView, CSSRule*>, u32 index);
 
-    void for_each_effective_style_rule(Function<void(CSSStyleRule const&)> const& callback) const;
+    void for_each_effective_rule(TraversalOrder, Function<void(CSSRule const&)> const& callback) const;
     // Returns whether the match state of any media queries changed after evaluation.
     bool evaluate_media_queries(HTML::Window const&);
-    void for_each_effective_keyframes_at_rule(Function<void(CSSKeyframesRule const&)> const& callback) const;
 
     void set_rules(Badge<CSSStyleSheet>, Vector<JS::NonnullGCPtr<CSSRule>> rules) { m_rules = move(rules); }
 

+ 14 - 5
Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp

@@ -294,17 +294,26 @@ WebIDL::ExceptionOr<void> CSSStyleSheet::remove_rule(Optional<WebIDL::UnsignedLo
     return delete_rule(index.value_or(0));
 }
 
+void CSSStyleSheet::for_each_effective_rule(TraversalOrder order, Function<void(Web::CSS::CSSRule const&)> const& callback) const
+{
+    if (m_media->matches())
+        m_rules->for_each_effective_rule(order, callback);
+}
+
 void CSSStyleSheet::for_each_effective_style_rule(Function<void(CSSStyleRule const&)> const& callback) const
 {
-    if (m_media->matches()) {
-        m_rules->for_each_effective_style_rule(callback);
-    }
+    for_each_effective_rule(TraversalOrder::Preorder, [&](CSSRule const& rule) {
+        if (rule.type() == CSSRule::Type::Style)
+            callback(static_cast<CSSStyleRule const&>(rule));
+    });
 }
 
 void CSSStyleSheet::for_each_effective_keyframes_at_rule(Function<void(CSSKeyframesRule const&)> const& callback) const
 {
-    if (m_media->matches())
-        m_rules->for_each_effective_keyframes_at_rule(callback);
+    for_each_effective_rule(TraversalOrder::Preorder, [&](CSSRule const& rule) {
+        if (rule.type() == CSSRule::Type::Keyframes)
+            callback(static_cast<CSSKeyframesRule const&>(rule));
+    });
 }
 
 bool CSSStyleSheet::evaluate_media_queries(HTML::Window const& window)

+ 1 - 0
Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h

@@ -55,6 +55,7 @@ public:
     JS::NonnullGCPtr<JS::Promise> replace(String text);
     WebIDL::ExceptionOr<void> replace_sync(StringView text);
 
+    void for_each_effective_rule(TraversalOrder, Function<void(CSSRule const&)> const& callback) const;
     void for_each_effective_style_rule(Function<void(CSSStyleRule const&)> const& callback) const;
     // Returns whether the match state of any media queries changed after evaluation.
     bool evaluate_media_queries(HTML::Window const&);

+ 16 - 0
Userland/Libraries/LibWeb/TraversalOrder.h

@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2024, Sam Atkins <sam@ladybird.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+namespace Web {
+
+enum class TraversalOrder {
+    Preorder,
+    Postorder,
+};
+
+}