Title: [286598] trunk/Source/WebCore
Revision
286598
Author
[email protected]
Date
2021-12-07 09:49:42 -0800 (Tue, 07 Dec 2021)

Log Message

Use more specific keys for pseudo-class invalidation
https://bugs.webkit.org/show_bug.cgi?id=233883

Reviewed by Simon Fraser.

Currently pseudo-class invalidation is keyed with pseudo-class type only. If we have rule like

.foo:hover { ... }

we end up considering this rule for every element whenever :hover state changes, whether the element has class 'foo' or not.

We can improve this by keying pseudo-class invalidation more narrowly with type/class, type/id or type/tag pairs.

* css/CSSSelector.cpp:
(WebCore::CSSSelector::CSSSelector):
(WebCore::CSSSelector::firstInCompound const):

Add a function to find the start of a compound selector.

* css/CSSSelector.h:
(WebCore::CSSSelector::tagHistory const):
(WebCore::CSSSelector::isFirstInTagHistory const):
(WebCore::CSSSelector::setNotFirstInTagHistory):

Add isFirstInTagHistory bit, similar to the isLastInTagHistory bit, to enable firstInCompound.

(WebCore::CSSSelector::CSSSelector):
* css/CSSSelectorList.cpp:
(WebCore::CSSSelectorList::CSSSelectorList):

Set the bit.

* style/PseudoClassChangeInvalidation.cpp:
(WebCore::Style::makePseudoClassInvalidationKeys):

Collect the id, tag and classes from the element and make keys out of them.

(WebCore::Style::PseudoClassChangeInvalidation::computeInvalidation):
(WebCore::Style::PseudoClassChangeInvalidation::collectRuleSets):

Use the keys to look up for matching invalidation rulesets.

* style/PseudoClassChangeInvalidation.h:
* style/RuleFeature.cpp:
(WebCore::Style::RuleFeatureSet::recursivelyCollectFeaturesFromSelector):
(WebCore::Style::makePseudoClassInvalidationKey):

Make a key out of a selector.
Search the compound for id, classes or tag.

(WebCore::Style::RuleFeatureSet::collectFeatures):
(WebCore::Style::RuleFeatureSet::add):
(WebCore::Style::RuleFeatureSet::clear):
* style/RuleFeature.h:
* style/StyleScopeRuleSets.cpp:
(WebCore::Style::ScopeRuleSets::pseudoClassInvalidationRuleSets const):
* style/StyleScopeRuleSets.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (286597 => 286598)


--- trunk/Source/WebCore/ChangeLog	2021-12-07 16:56:04 UTC (rev 286597)
+++ trunk/Source/WebCore/ChangeLog	2021-12-07 17:49:42 UTC (rev 286598)
@@ -1,3 +1,63 @@
+2021-12-07  Antti Koivisto  <[email protected]>
+
+        Use more specific keys for pseudo-class invalidation
+        https://bugs.webkit.org/show_bug.cgi?id=233883
+
+        Reviewed by Simon Fraser.
+
+        Currently pseudo-class invalidation is keyed with pseudo-class type only. If we have rule like
+
+        .foo:hover { ... }
+
+        we end up considering this rule for every element whenever :hover state changes, whether the element has class 'foo' or not.
+
+        We can improve this by keying pseudo-class invalidation more narrowly with type/class, type/id or type/tag pairs.
+
+        * css/CSSSelector.cpp:
+        (WebCore::CSSSelector::CSSSelector):
+        (WebCore::CSSSelector::firstInCompound const):
+
+        Add a function to find the start of a compound selector.
+
+        * css/CSSSelector.h:
+        (WebCore::CSSSelector::tagHistory const):
+        (WebCore::CSSSelector::isFirstInTagHistory const):
+        (WebCore::CSSSelector::setNotFirstInTagHistory):
+
+        Add isFirstInTagHistory bit, similar to the isLastInTagHistory bit, to enable firstInCompound.
+
+        (WebCore::CSSSelector::CSSSelector):
+        * css/CSSSelectorList.cpp:
+        (WebCore::CSSSelectorList::CSSSelectorList):
+
+        Set the bit.
+
+        * style/PseudoClassChangeInvalidation.cpp:
+        (WebCore::Style::makePseudoClassInvalidationKeys):
+
+        Collect the id, tag and classes from the element and make keys out of them.
+
+        (WebCore::Style::PseudoClassChangeInvalidation::computeInvalidation):
+        (WebCore::Style::PseudoClassChangeInvalidation::collectRuleSets):
+
+        Use the keys to look up for matching invalidation rulesets.
+
+        * style/PseudoClassChangeInvalidation.h:
+        * style/RuleFeature.cpp:
+        (WebCore::Style::RuleFeatureSet::recursivelyCollectFeaturesFromSelector):
+        (WebCore::Style::makePseudoClassInvalidationKey):
+
+        Make a key out of a selector.
+        Search the compound for id, classes or tag.
+
+        (WebCore::Style::RuleFeatureSet::collectFeatures):
+        (WebCore::Style::RuleFeatureSet::add):
+        (WebCore::Style::RuleFeatureSet::clear):
+        * style/RuleFeature.h:
+        * style/StyleScopeRuleSets.cpp:
+        (WebCore::Style::ScopeRuleSets::pseudoClassInvalidationRuleSets const):
+        * style/StyleScopeRuleSets.h:
+
 2021-12-07  Kimmo Kinnunen  <[email protected]>
 
         Cocoa WebGL should support UI side compositing

Modified: trunk/Source/WebCore/css/CSSSelector.cpp (286597 => 286598)


--- trunk/Source/WebCore/css/CSSSelector.cpp	2021-12-07 16:56:04 UTC (rev 286597)
+++ trunk/Source/WebCore/css/CSSSelector.cpp	2021-12-07 17:49:42 UTC (rev 286598)
@@ -56,6 +56,7 @@
     , m_match(Tag)
     , m_pseudoType(0)
     , m_isLastInSelectorList(false)
+    , m_isFirstInTagHistory(true)
     , m_isLastInTagHistory(true)
     , m_hasRareData(false)
     , m_hasNameWithCase(false)
@@ -288,6 +289,18 @@
     return type;
 }
 
+const CSSSelector* CSSSelector::firstInCompound() const
+{
+    auto* selector = this;
+    while (!selector->isFirstInTagHistory()) {
+        auto* previousSelector = selector - 1;
+        if (previousSelector->relation() != Subselector)
+            break;
+        selector = previousSelector;
+    }
+    return selector;
+}
+
 bool CSSSelector::operator==(const CSSSelector& other) const
 {
     const CSSSelector* sel1 = this;

Modified: trunk/Source/WebCore/css/CSSSelector.h (286597 => 286598)


--- trunk/Source/WebCore/css/CSSSelector.h	2021-12-07 16:56:04 UTC (rev 286597)
+++ trunk/Source/WebCore/css/CSSSelector.h	2021-12-07 17:49:42 UTC (rev 286598)
@@ -253,7 +253,8 @@
 
         // Selectors are kept in an array by CSSSelectorList. The next component of the selector is
         // the next item in the array.
-        const CSSSelector* tagHistory() const { return m_isLastInTagHistory ? 0 : const_cast<CSSSelector*>(this + 1); }
+        const CSSSelector* tagHistory() const { return m_isLastInTagHistory ? nullptr : this + 1; }
+        const CSSSelector* firstInCompound() const;
 
         const QualifiedName& tagQName() const;
         const AtomString& tagLowercaseLocalName() const;
@@ -339,7 +340,9 @@
 
         bool isLastInSelectorList() const { return m_isLastInSelectorList; }
         void setLastInSelectorList() { m_isLastInSelectorList = true; }
+        bool isFirstInTagHistory() const { return m_isFirstInTagHistory; }
         bool isLastInTagHistory() const { return m_isLastInTagHistory; }
+        void setNotFirstInTagHistory() { m_isFirstInTagHistory = false; }
         void setNotLastInTagHistory() { m_isLastInTagHistory = false; }
 
         bool isForPage() const { return m_isForPage; }
@@ -350,6 +353,7 @@
         mutable unsigned m_match         : 4; // enum Match.
         mutable unsigned m_pseudoType    : 8; // PseudoType.
         unsigned m_isLastInSelectorList  : 1;
+        unsigned m_isFirstInTagHistory   : 1;
         unsigned m_isLastInTagHistory    : 1;
         unsigned m_hasRareData           : 1;
         unsigned m_hasNameWithCase       : 1;
@@ -468,6 +472,21 @@
     return pseudoClassIsRelativeToSiblings(type) || type == CSSSelector::PseudoClassRoot;
 }
 
+inline bool isLogicalCombinationPseudoClass(CSSSelector::PseudoClassType pseudoClassType)
+{
+    switch (pseudoClassType) {
+    case CSSSelector::PseudoClassIs:
+    case CSSSelector::PseudoClassWhere:
+    case CSSSelector::PseudoClassNot:
+    case CSSSelector::PseudoClassAny:
+    case CSSSelector::PseudoClassMatches:
+    case CSSSelector::PseudoClassHas:
+        return true;
+    default:
+        return false;
+    }
+}
+
 inline bool CSSSelector::isSiblingSelector() const
 {
     return relation() == DirectAdjacent
@@ -511,6 +530,7 @@
     , m_match(Unknown)
     , m_pseudoType(0)
     , m_isLastInSelectorList(false)
+    , m_isFirstInTagHistory(true)
     , m_isLastInTagHistory(true)
     , m_hasRareData(false)
     , m_hasNameWithCase(false)
@@ -528,6 +548,7 @@
     , m_match(o.m_match)
     , m_pseudoType(o.m_pseudoType)
     , m_isLastInSelectorList(o.m_isLastInSelectorList)
+    , m_isFirstInTagHistory(o.m_isFirstInTagHistory)
     , m_isLastInTagHistory(o.m_isLastInTagHistory)
     , m_hasRareData(o.m_hasRareData)
     , m_hasNameWithCase(o.m_hasNameWithCase)

Modified: trunk/Source/WebCore/css/CSSSelectorList.cpp (286597 => 286598)


--- trunk/Source/WebCore/css/CSSSelectorList.cpp	2021-12-07 16:56:04 UTC (rev 286597)
+++ trunk/Source/WebCore/css/CSSSelectorList.cpp	2021-12-07 17:49:42 UTC (rev 286598)
@@ -55,7 +55,8 @@
     m_selectorArray = makeUniqueArray<CSSSelector>(flattenedSize);
     size_t arrayIndex = 0;
     for (size_t i = 0; i < selectorVector.size(); ++i) {
-        CSSParserSelector* current = selectorVector[i].get();
+        CSSParserSelector* first = selectorVector[i].get();
+        CSSParserSelector* current = first;
         while (current) {
             {
                 // Move item from the parser selector vector into m_selectorArray without invoking destructor (Ugh.)
@@ -65,6 +66,8 @@
                 // Free the underlying memory without invoking the destructor.
                 operator delete (currentSelector);
             }
+            if (current != first)
+                m_selectorArray[arrayIndex].setNotFirstInTagHistory();
             current = current->tagHistory();
             ASSERT(!m_selectorArray[arrayIndex].isLastInSelectorList());
             if (current)

Modified: trunk/Source/WebCore/css/parser/CSSSelectorParser.cpp (286597 => 286598)


--- trunk/Source/WebCore/css/parser/CSSSelectorParser.cpp	2021-12-07 16:56:04 UTC (rev 286597)
+++ trunk/Source/WebCore/css/parser/CSSSelectorParser.cpp	2021-12-07 17:49:42 UTC (rev 286598)
@@ -320,21 +320,6 @@
     }
 }
 
-static bool isLogicalCombinationPseudoClass(CSSSelector::PseudoClassType pseudo)
-{
-    switch (pseudo) {
-    case CSSSelector::PseudoClassIs:
-    case CSSSelector::PseudoClassWhere:
-    case CSSSelector::PseudoClassNot:
-    case CSSSelector::PseudoClassAny:
-    case CSSSelector::PseudoClassMatches:
-    case CSSSelector::PseudoClassHas:
-        return true;
-    default:
-        return false;
-    }
-}
-
 static bool isPseudoClassValidAfterPseudoElement(CSSSelector::PseudoClassType pseudoClass, CSSSelector::PseudoElementType compoundPseudoElement)
 {
     // Validity of these is determined by their content.

Modified: trunk/Source/WebCore/style/PseudoClassChangeInvalidation.cpp (286597 => 286598)


--- trunk/Source/WebCore/style/PseudoClassChangeInvalidation.cpp	2021-12-07 16:56:04 UTC (rev 286597)
+++ trunk/Source/WebCore/style/PseudoClassChangeInvalidation.cpp	2021-12-07 17:49:42 UTC (rev 286598)
@@ -32,6 +32,25 @@
 namespace WebCore {
 namespace Style {
 
+static Vector<PseudoClassInvalidationKey, 4> makePseudoClassInvalidationKeys(CSSSelector::PseudoClassType pseudoClass, const Element& element)
+{
+    Vector<PseudoClassInvalidationKey, 4> keys;
+
+    if (!element.idForStyleResolution().isEmpty())
+        keys.append(makePseudoClassInvalidationKey(pseudoClass, InvalidationKeyType::Id, element.idForStyleResolution()));
+
+    if (element.hasClass()) {
+        auto classCount = element.classNames().size();
+        for (size_t i = 0; i < classCount; ++i)
+            keys.append(makePseudoClassInvalidationKey(pseudoClass, InvalidationKeyType::Class, element.classNames()[i]));
+    }
+
+    keys.append(makePseudoClassInvalidationKey(pseudoClass, InvalidationKeyType::Tag, element.localName().convertToASCIILowercase()));
+    keys.append(makePseudoClassInvalidationKey(pseudoClass, InvalidationKeyType::Universal));
+
+    return keys;
+};
+
 void PseudoClassChangeInvalidation::computeInvalidation(CSSSelector::PseudoClassType pseudoClass, InvalidationScope invalidationScope)
 {
     bool shouldInvalidateCurrent = false;
@@ -38,7 +57,7 @@
     bool mayAffectStyleInShadowTree = false;
 
     traverseRuleFeatures(m_element, [&] (const RuleFeatureSet& features, bool mayAffectShadowTree) {
-        if (mayAffectShadowTree && features.pseudoClassRules.contains(pseudoClass))
+        if (mayAffectShadowTree && features.pseudoClassTypes.contains(pseudoClass))
             mayAffectStyleInShadowTree = true;
         if (m_element.shadowRoot() && features.pseudoClassesAffectingHost.contains(pseudoClass))
             shouldInvalidateCurrent = true;
@@ -52,26 +71,36 @@
     if (shouldInvalidateCurrent)
         m_element.invalidateStyle();
 
+    for (auto& key : makePseudoClassInvalidationKeys(pseudoClass, m_element))
+        collectRuleSets(key, invalidationScope);
+}
+
+void PseudoClassChangeInvalidation::collectRuleSets(const PseudoClassInvalidationKey& key, InvalidationScope invalidationScope)
+{
     auto& ruleSets = m_element.styleResolver().ruleSets();
-    if (auto* invalidationRuleSets = ruleSets.pseudoClassInvalidationRuleSets(pseudoClass)) {
-        for (auto& invalidationRuleSet : *invalidationRuleSets) {
-            // For focus/hover we flip the whole ancestor chain. We only need to do deep invalidation traversal in the change root.
-            auto shouldInvalidate = [&] {
-                switch (invalidationScope) {
-                case InvalidationScope::All:
-                    return true;
-                case InvalidationScope::SelfChildrenAndSiblings:
-                    return invalidationRuleSet.matchElement != MatchElement::Ancestor;
-                case InvalidationScope::Descendants:
-                    return invalidationRuleSet.matchElement == MatchElement::Ancestor;
-                }
-                ASSERT_NOT_REACHED();
+    auto* invalidationRuleSets = ruleSets.pseudoClassInvalidationRuleSets(key);
+    if (!invalidationRuleSets)
+        return;
+
+    for (auto& invalidationRuleSet : *invalidationRuleSets) {
+        // For focus/hover we flip the whole ancestor chain. We only need to do deep invalidation traversal in the change root.
+        auto shouldInvalidate = [&] {
+            bool invalidatesAllDescendants = invalidationRuleSet.matchElement == MatchElement::Ancestor && isUniversalInvalidation(key);
+            switch (invalidationScope) {
+            case InvalidationScope::All:
                 return true;
-            }();
-            if (!shouldInvalidate)
-                continue;
-            Invalidator::addToMatchElementRuleSets(m_matchElementRuleSets, invalidationRuleSet);
-        }
+            case InvalidationScope::SelfChildrenAndSiblings:
+                return !invalidatesAllDescendants;
+            case InvalidationScope::Descendants:
+                return invalidatesAllDescendants;
+            }
+            ASSERT_NOT_REACHED();
+            return true;
+        }();
+        if (!shouldInvalidate)
+            continue;
+
+        Invalidator::addToMatchElementRuleSets(m_matchElementRuleSets, invalidationRuleSet);
     }
 }
 

Modified: trunk/Source/WebCore/style/PseudoClassChangeInvalidation.h (286597 => 286598)


--- trunk/Source/WebCore/style/PseudoClassChangeInvalidation.h	2021-12-07 16:56:04 UTC (rev 286597)
+++ trunk/Source/WebCore/style/PseudoClassChangeInvalidation.h	2021-12-07 17:49:42 UTC (rev 286598)
@@ -40,6 +40,7 @@
 
 private:
     void computeInvalidation(CSSSelector::PseudoClassType, Style::InvalidationScope);
+    void collectRuleSets(const PseudoClassInvalidationKey&, InvalidationScope);
     void invalidateStyleWithRuleSets();
 
     const bool m_isEnabled;

Modified: trunk/Source/WebCore/style/RuleFeature.cpp (286597 => 286598)


--- trunk/Source/WebCore/style/RuleFeature.cpp	2021-12-07 16:56:04 UTC (rev 286597)
+++ trunk/Source/WebCore/style/RuleFeature.cpp	2021-12-07 17:49:42 UTC (rev 286598)
@@ -226,8 +226,10 @@
             default:
                 break;
             }
-        } else if (selector->match() == CSSSelector::PseudoClass)
-            selectorFeatures.pseudoClasses.append(std::make_pair(selector->pseudoClassType(), matchElement));
+        } else if (selector->match() == CSSSelector::PseudoClass) {
+            if (!isLogicalCombinationPseudoClass(selector->pseudoClassType()))
+                selectorFeatures.pseudoClasses.append(std::make_pair(selector, matchElement));
+        }
 
         if (!selectorFeatures.hasSiblingSelector && selector->isSiblingSelector())
             selectorFeatures.hasSiblingSelector = true;
@@ -247,6 +249,46 @@
     } while (selector);
 }
 
+PseudoClassInvalidationKey makePseudoClassInvalidationKey(CSSSelector::PseudoClassType pseudoClass, InvalidationKeyType keyType, const AtomString& keyString)
+{
+    ASSERT(keyType != InvalidationKeyType::Universal || keyString == starAtom());
+    return {
+        pseudoClass,
+        static_cast<uint8_t>(keyType),
+        keyString
+    };
+};
+
+static PseudoClassInvalidationKey makePseudoClassInvalidationKey(const CSSSelector& selector)
+{
+    ASSERT(selector.match() == CSSSelector::PseudoClass);
+
+    auto pseudoClassType = selector.pseudoClassType();
+
+    AtomString className;
+    AtomString tagName;
+    for (auto* simpleSelector = selector.firstInCompound(); simpleSelector; simpleSelector = simpleSelector->tagHistory()) {
+        if (simpleSelector->match() == CSSSelector::Id)
+            return makePseudoClassInvalidationKey(pseudoClassType, InvalidationKeyType::Id, simpleSelector->value());
+
+        if (simpleSelector->match() == CSSSelector::Class && className.isNull())
+            className = simpleSelector->value();
+
+        if (simpleSelector->match() == CSSSelector::Tag)
+            tagName = simpleSelector->tagLowercaseLocalName();
+
+        if (simpleSelector->relation() != CSSSelector::Subselector)
+            break;
+    }
+    if (!className.isEmpty())
+        return makePseudoClassInvalidationKey(pseudoClassType, InvalidationKeyType::Class, className);
+
+    if (!tagName.isEmpty() && tagName != starAtom())
+        return makePseudoClassInvalidationKey(pseudoClassType, InvalidationKeyType::Tag, tagName);
+
+    return makePseudoClassInvalidationKey(selector.pseudoClassType(), InvalidationKeyType::Universal);
+};
+
 void RuleFeatureSet::collectFeatures(const RuleData& ruleData)
 {
     SelectorFeatures selectorFeatures;
@@ -287,7 +329,19 @@
         setUsesMatchElement(matchElement);
     }
 
-    addToMap(pseudoClassRules, selectorFeatures.pseudoClasses, &pseudoClassesAffectingHost);
+    for (auto& selectorAndMatch : selectorFeatures.pseudoClasses) {
+        auto* selector = selectorAndMatch.first;
+        auto matchElement = selectorAndMatch.second;
+        pseudoClassRules.ensure(makePseudoClassInvalidationKey(*selector), [] {
+            return makeUnique<Vector<RuleFeature>>();
+        }).iterator->value->append({ ruleData, matchElement });
+
+        if (matchElement == MatchElement::Host)
+            pseudoClassesAffectingHost.add(selector->pseudoClassType());
+        pseudoClassTypes.add(selector->pseudoClassType());
+
+        setUsesMatchElement(matchElement);
+    }
 }
 
 void RuleFeatureSet::add(const RuleFeatureSet& other)
@@ -319,6 +373,7 @@
 
     addMap(pseudoClassRules, other.pseudoClassRules);
     pseudoClassesAffectingHost.add(other.pseudoClassesAffectingHost.begin(), other.pseudoClassesAffectingHost.end());
+    pseudoClassTypes.add(other.pseudoClassTypes.begin(), other.pseudoClassTypes.end());
 
     for (size_t i = 0; i < usedMatchElements.size(); ++i)
         usedMatchElements[i] = usedMatchElements[i] || other.usedMatchElements[i];
@@ -351,6 +406,7 @@
     attributesAffectingHost.clear();
     pseudoClassRules.clear();
     pseudoClassesAffectingHost.clear();
+    pseudoClassTypes.clear();
     usesFirstLineRules = false;
     usesFirstLetterRules = false;
 }

Modified: trunk/Source/WebCore/style/RuleFeature.h (286597 => 286598)


--- trunk/Source/WebCore/style/RuleFeature.h	2021-12-07 16:56:04 UTC (rev 286597)
+++ trunk/Source/WebCore/style/RuleFeature.h	2021-12-07 17:49:42 UTC (rev 286598)
@@ -74,6 +74,8 @@
     const CSSSelector* invalidationSelector { nullptr };
 };
 
+using PseudoClassInvalidationKey = std::tuple<unsigned, uint8_t, AtomString>;
+
 using RuleFeatureVector = Vector<RuleFeature>;
 
 struct RuleFeatureSet {
@@ -98,10 +100,11 @@
     HashMap<AtomString, std::unique_ptr<RuleFeatureVector>> idRules;
     HashMap<AtomString, std::unique_ptr<RuleFeatureVector>> classRules;
     HashMap<AtomString, std::unique_ptr<Vector<RuleFeatureWithInvalidationSelector>>> attributeRules;
-    HashMap<CSSSelector::PseudoClassType, std::unique_ptr<RuleFeatureVector>, IntHash<CSSSelector::PseudoClassType>, WTF::StrongEnumHashTraits<CSSSelector::PseudoClassType>> pseudoClassRules;
+    HashMap<PseudoClassInvalidationKey, std::unique_ptr<RuleFeatureVector>> pseudoClassRules;
     HashSet<AtomString> classesAffectingHost;
     HashSet<AtomString> attributesAffectingHost;
     HashSet<CSSSelector::PseudoClassType, IntHash<CSSSelector::PseudoClassType>, WTF::StrongEnumHashTraits<CSSSelector::PseudoClassType>> pseudoClassesAffectingHost;
+    HashSet<CSSSelector::PseudoClassType, IntHash<CSSSelector::PseudoClassType>, WTF::StrongEnumHashTraits<CSSSelector::PseudoClassType>> pseudoClassTypes;
 
     std::array<bool, matchElementCount> usedMatchElements { };
 
@@ -116,7 +119,7 @@
         Vector<std::pair<AtomString, MatchElement>, 32> ids;
         Vector<std::pair<AtomString, MatchElement>, 32> classes;
         Vector<std::pair<const CSSSelector*, MatchElement>, 32> attributes;
-        Vector<std::pair<CSSSelector::PseudoClassType, MatchElement>, 32> pseudoClasses;
+        Vector<std::pair<const CSSSelector*, MatchElement>, 32> pseudoClasses;
     };
     void recursivelyCollectFeaturesFromSelector(SelectorFeatures&, const CSSSelector&, MatchElement = MatchElement::Subject);
 };
@@ -124,5 +127,13 @@
 bool isHasPseudoClassMatchElement(MatchElement);
 MatchElement computeHasPseudoClassMatchElement(const CSSSelector&);
 
+enum class InvalidationKeyType : uint8_t { Universal = 1, Class, Id, Tag };
+PseudoClassInvalidationKey makePseudoClassInvalidationKey(CSSSelector::PseudoClassType, InvalidationKeyType, const AtomString& = starAtom());
+
+inline bool isUniversalInvalidation(const PseudoClassInvalidationKey& key)
+{
+    return static_cast<InvalidationKeyType>(std::get<1>(key)) == InvalidationKeyType::Universal;
+}
+
 } // namespace Style
 } // namespace WebCore

Modified: trunk/Source/WebCore/style/StyleScopeRuleSets.cpp (286597 => 286598)


--- trunk/Source/WebCore/style/StyleScopeRuleSets.cpp	2021-12-07 16:56:04 UTC (rev 286597)
+++ trunk/Source/WebCore/style/StyleScopeRuleSets.cpp	2021-12-07 17:49:42 UTC (rev 286598)
@@ -295,9 +295,9 @@
     return ensureInvalidationRuleSets(attributeName, m_attributeInvalidationRuleSets, m_features.attributeRules);
 }
 
-const Vector<InvalidationRuleSet>* ScopeRuleSets::pseudoClassInvalidationRuleSets(CSSSelector::PseudoClassType pseudoClass) const
+const Vector<InvalidationRuleSet>* ScopeRuleSets::pseudoClassInvalidationRuleSets(const PseudoClassInvalidationKey& pseudoClassKey) const
 {
-    return ensureInvalidationRuleSets(pseudoClass, m_pseudoClassInvalidationRuleSets, m_features.pseudoClassRules);
+    return ensureInvalidationRuleSets(pseudoClassKey, m_pseudoClassInvalidationRuleSets, m_features.pseudoClassRules);
 }
 
 bool ScopeRuleSets::hasComplexSelectorsForStyleAttribute() const

Modified: trunk/Source/WebCore/style/StyleScopeRuleSets.h (286597 => 286598)


--- trunk/Source/WebCore/style/StyleScopeRuleSets.h	2021-12-07 16:56:04 UTC (rev 286597)
+++ trunk/Source/WebCore/style/StyleScopeRuleSets.h	2021-12-07 17:49:42 UTC (rev 286598)
@@ -67,7 +67,7 @@
     const Vector<InvalidationRuleSet>* idInvalidationRuleSets(const AtomString&) const;
     const Vector<InvalidationRuleSet>* classInvalidationRuleSets(const AtomString&) const;
     const Vector<InvalidationRuleSet>* attributeInvalidationRuleSets(const AtomString&) const;
-    const Vector<InvalidationRuleSet>* pseudoClassInvalidationRuleSets(CSSSelector::PseudoClassType) const;
+    const Vector<InvalidationRuleSet>* pseudoClassInvalidationRuleSets(const PseudoClassInvalidationKey&) const;
 
     const Vector<InvalidationRuleSet>* invalidationRuleSetsForChildChange(const Element&);
 
@@ -106,7 +106,7 @@
     mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_idInvalidationRuleSets;
     mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_classInvalidationRuleSets;
     mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_attributeInvalidationRuleSets;
-    mutable HashMap<CSSSelector::PseudoClassType, std::unique_ptr<Vector<InvalidationRuleSet>>, IntHash<CSSSelector::PseudoClassType>, WTF::StrongEnumHashTraits<CSSSelector::PseudoClassType>> m_pseudoClassInvalidationRuleSets;
+    mutable HashMap<PseudoClassInvalidationKey, std::unique_ptr<Vector<InvalidationRuleSet>>> m_pseudoClassInvalidationRuleSets;
 
     mutable std::optional<bool> m_cachedHasComplexSelectorsForStyleAttribute;
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to