ソースを参照

LibWeb: Support most simple pseudo classes in the fast selector matcher

Non-recursive pseudo classes are easy to evaluate, so let's allow them
on the fast path.

Increases fast path coverage when loading our GitHub repo from 48% to
56% of all selectors evaluated.
Andreas Kling 1 年間 前
コミット
7c9368f402
1 ファイル変更24 行追加1 行削除
  1. 24 1
      Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp

+ 24 - 1
Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp

@@ -686,6 +686,8 @@ static bool fast_matches_simple_selector(CSS::Selector::SimpleSelector const& si
         return simple_selector.name() == element.id();
         return simple_selector.name() == element.id();
     case CSS::Selector::SimpleSelector::Type::Attribute:
     case CSS::Selector::SimpleSelector::Type::Attribute:
         return matches_attribute(simple_selector.attribute(), style_sheet_for_rule, element);
         return matches_attribute(simple_selector.attribute(), style_sheet_for_rule, element);
+    case CSS::Selector::SimpleSelector::Type::PseudoClass:
+        return matches_pseudo_class(simple_selector.pseudo_class(), style_sheet_for_rule, element, nullptr);
     default:
     default:
         VERIFY_NOT_REACHED();
         VERIFY_NOT_REACHED();
     }
     }
@@ -765,7 +767,28 @@ bool can_use_fast_matches(CSS::Selector const& selector)
         }
         }
 
 
         for (auto const& simple_selector : compound_selector.simple_selectors) {
         for (auto const& simple_selector : compound_selector.simple_selectors) {
-            if (simple_selector.type != CSS::Selector::SimpleSelector::Type::TagName
+            if (simple_selector.type == CSS::Selector::SimpleSelector::Type::PseudoClass) {
+                auto const pseudo_class = simple_selector.pseudo_class().type;
+                if (pseudo_class != CSS::PseudoClass::FirstChild
+                    && pseudo_class != CSS::PseudoClass::LastChild
+                    && pseudo_class != CSS::PseudoClass::OnlyChild
+                    && pseudo_class != CSS::PseudoClass::Hover
+                    && pseudo_class != CSS::PseudoClass::Active
+                    && pseudo_class != CSS::PseudoClass::Focus
+                    && pseudo_class != CSS::PseudoClass::FocusVisible
+                    && pseudo_class != CSS::PseudoClass::FocusWithin
+                    && pseudo_class != CSS::PseudoClass::Link
+                    && pseudo_class != CSS::PseudoClass::AnyLink
+                    && pseudo_class != CSS::PseudoClass::Visited
+                    && pseudo_class != CSS::PseudoClass::LocalLink
+                    && pseudo_class != CSS::PseudoClass::Empty
+                    && pseudo_class != CSS::PseudoClass::Root
+                    && pseudo_class != CSS::PseudoClass::Enabled
+                    && pseudo_class != CSS::PseudoClass::Disabled
+                    && pseudo_class != CSS::PseudoClass::Checked) {
+                    return false;
+                }
+            } else if (simple_selector.type != CSS::Selector::SimpleSelector::Type::TagName
                 && simple_selector.type != CSS::Selector::SimpleSelector::Type::Universal
                 && simple_selector.type != CSS::Selector::SimpleSelector::Type::Universal
                 && simple_selector.type != CSS::Selector::SimpleSelector::Type::Class
                 && simple_selector.type != CSS::Selector::SimpleSelector::Type::Class
                 && simple_selector.type != CSS::Selector::SimpleSelector::Type::Id
                 && simple_selector.type != CSS::Selector::SimpleSelector::Type::Id