<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[287973] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/287973">287973</a></dd>
<dt>Author</dt> <dd>antti@apple.com</dd>
<dt>Date</dt> <dd>2022-01-12 23:31:50 -0800 (Wed, 12 Jan 2022)</dd>
</dl>

<h3>Log Message</h3>
<pre>[:has() pseudo-class] Collect invalidation selectors for child invalidation
https://bugs.webkit.org/show_bug.cgi?id=235103

Reviewed by Dean Jackson.

Collect selectors we can use to test if :has status actually changed before invalidating.

This patch doesn't yet use the the selector.

* style/ChildChangeInvalidation.cpp:
(WebCore::Style::ChildChangeInvalidation::invalidateForChangedElement):

Use the pseudo class invalidation keys for looking up :has selectors too
instead of having a custom mechanism for doing the same thing.

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

Always return a selector for consistency.

(WebCore::Style::makePseudoClassInvalidationKey):
(WebCore::Style::RuleFeatureSet::collectFeatures):
(WebCore::Style::RuleFeatureSet::add):
(WebCore::Style::RuleFeatureSet::clear):
(WebCore::Style::RuleFeatureSet::shrinkToFit):
* style/RuleFeature.h:
* style/StyleScopeRuleSets.cpp:
(WebCore::Style::ScopeRuleSets::collectFeatures const):
(WebCore::Style::ScopeRuleSets::hasPseudoClassInvalidationRuleSets const):
(WebCore::Style::ScopeRuleSets::tagInvalidationRuleSets const): Deleted.

We don't need keep around tag rule sets anymore.

* style/StyleScopeRuleSets.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorestyleChildChangeInvalidationcpp">trunk/Source/WebCore/style/ChildChangeInvalidation.cpp</a></li>
<li><a href="#trunkSourceWebCorestylePseudoClassChangeInvalidationcpp">trunk/Source/WebCore/style/PseudoClassChangeInvalidation.cpp</a></li>
<li><a href="#trunkSourceWebCorestylePseudoClassChangeInvalidationh">trunk/Source/WebCore/style/PseudoClassChangeInvalidation.h</a></li>
<li><a href="#trunkSourceWebCorestyleRuleFeaturecpp">trunk/Source/WebCore/style/RuleFeature.cpp</a></li>
<li><a href="#trunkSourceWebCorestyleRuleFeatureh">trunk/Source/WebCore/style/RuleFeature.h</a></li>
<li><a href="#trunkSourceWebCorestyleStyleScopeRuleSetscpp">trunk/Source/WebCore/style/StyleScopeRuleSets.cpp</a></li>
<li><a href="#trunkSourceWebCorestyleStyleScopeRuleSetsh">trunk/Source/WebCore/style/StyleScopeRuleSets.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (287972 => 287973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2022-01-13 07:10:04 UTC (rev 287972)
+++ trunk/Source/WebCore/ChangeLog      2022-01-13 07:31:50 UTC (rev 287973)
</span><span class="lines">@@ -1,3 +1,43 @@
</span><ins>+2022-01-12  Antti Koivisto  <antti@apple.com>
+
+        [:has() pseudo-class] Collect invalidation selectors for child invalidation
+        https://bugs.webkit.org/show_bug.cgi?id=235103
+
+        Reviewed by Dean Jackson.
+
+        Collect selectors we can use to test if :has status actually changed before invalidating.
+
+        This patch doesn't yet use the the selector.
+
+        * style/ChildChangeInvalidation.cpp:
+        (WebCore::Style::ChildChangeInvalidation::invalidateForChangedElement):
+
+        Use the pseudo class invalidation keys for looking up :has selectors too
+        instead of having a custom mechanism for doing the same thing.
+
+        * style/PseudoClassChangeInvalidation.cpp:
+        (WebCore::Style::makePseudoClassInvalidationKeys):
+        * style/PseudoClassChangeInvalidation.h:
+        * style/RuleFeature.cpp:
+        (WebCore::Style::RuleFeatureSet::recursivelyCollectFeaturesFromSelector):
+
+        Always return a selector for consistency.
+
+        (WebCore::Style::makePseudoClassInvalidationKey):
+        (WebCore::Style::RuleFeatureSet::collectFeatures):
+        (WebCore::Style::RuleFeatureSet::add):
+        (WebCore::Style::RuleFeatureSet::clear):
+        (WebCore::Style::RuleFeatureSet::shrinkToFit):
+        * style/RuleFeature.h:
+        * style/StyleScopeRuleSets.cpp:
+        (WebCore::Style::ScopeRuleSets::collectFeatures const):
+        (WebCore::Style::ScopeRuleSets::hasPseudoClassInvalidationRuleSets const):
+        (WebCore::Style::ScopeRuleSets::tagInvalidationRuleSets const): Deleted.
+
+        We don't need keep around tag rule sets anymore.
+
+        * style/StyleScopeRuleSets.h:
+
</ins><span class="cx"> 2022-01-12  John Wilander  <wilander@apple.com>
</span><span class="cx"> 
</span><span class="cx">         PCM: Same-site triggering events should support ephemeral measurement
</span></span></pre></div>
<a id="trunkSourceWebCorestyleChildChangeInvalidationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/style/ChildChangeInvalidation.cpp (287972 => 287973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/style/ChildChangeInvalidation.cpp   2022-01-13 07:10:04 UTC (rev 287972)
+++ trunk/Source/WebCore/style/ChildChangeInvalidation.cpp      2022-01-13 07:31:50 UTC (rev 287973)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include "ElementTraversal.h"
</span><span class="cx"> #include "NodeRenderStyle.h"
</span><ins>+#include "PseudoClassChangeInvalidation.h"
</ins><span class="cx"> #include "ShadowRoot.h"
</span><span class="cx"> #include "SlotAssignment.h"
</span><span class="cx"> #include "StyleResolver.h"
</span><span class="lines">@@ -44,42 +45,27 @@
</span><span class="cx"> 
</span><span class="cx">     bool isDescendant = changedElement.parentElement() != &parentElement();
</span><span class="cx"> 
</span><ins>+    auto canAffectAncestors = [&](MatchElement matchElement) {
+        if (!isDescendant)
+            return true;
+        return matchElement == MatchElement::HasDescendant
+            || matchElement == MatchElement::HasSiblingDescendant
+            || matchElement == MatchElement::HasNonSubject;
+    };
+
</ins><span class="cx">     auto addHasInvalidation = [&](const Vector<InvalidationRuleSet>* invalidationRuleSets)  {
</span><span class="cx">         if (!invalidationRuleSets)
</span><span class="cx">             return;
</span><span class="cx">         for (auto& invalidationRuleSet : *invalidationRuleSets) {
</span><del>-            if (!isHasPseudoClassMatchElement(invalidationRuleSet.matchElement))
</del><ins>+            if (!canAffectAncestors(invalidationRuleSet.matchElement))
</ins><span class="cx">                 continue;
</span><del>-            if (isDescendant) {
-                // Elements deeper in the tree can't affect anything except when :has() selector uses descendant combinator.
-                if (invalidationRuleSet.matchElement != MatchElement::HasDescendant && invalidationRuleSet.matchElement != MatchElement::HasNonSubject)
-                    continue;
-            }
</del><span class="cx">             Invalidator::addToMatchElementRuleSets(matchElementRuleSets, invalidationRuleSet);
</span><span class="cx">         }
</span><span class="cx">     };
</span><span class="cx"> 
</span><del>-    auto tagName = changedElement.localName().convertToASCIILowercase();
-    addHasInvalidation(ruleSets.tagInvalidationRuleSets(tagName));
</del><ins>+    for (auto key : makePseudoClassInvalidationKeys(CSSSelector::PseudoClassHas, changedElement))
+        addHasInvalidation(ruleSets.hasPseudoClassInvalidationRuleSets(key));
</ins><span class="cx"> 
</span><del>-    if (changedElement.hasID())
-        addHasInvalidation(ruleSets.idInvalidationRuleSets(changedElement.idForStyleResolution()));
-
-    if (changedElement.hasAttributes()) {
-        for (auto& attribute : changedElement.attributesIterator()) {
-            auto attributeName = attribute.localName().convertToASCIILowercase();
-            addHasInvalidation(ruleSets.attributeInvalidationRuleSets(attributeName));
-        }
-    }
-
-    if (changedElement.hasClass()) {
-        auto count = changedElement.classNames().size();
-        for (size_t i = 0; i < count; ++i) {
-            auto& className = changedElement.classNames()[i];
-            addHasInvalidation(ruleSets.classInvalidationRuleSets(className));
-        }
-    }
-
</del><span class="cx">     Invalidator::invalidateWithMatchElementRuleSets(changedElement, matchElementRuleSets);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorestylePseudoClassChangeInvalidationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/style/PseudoClassChangeInvalidation.cpp (287972 => 287973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/style/PseudoClassChangeInvalidation.cpp     2022-01-13 07:10:04 UTC (rev 287972)
+++ trunk/Source/WebCore/style/PseudoClassChangeInvalidation.cpp        2022-01-13 07:31:50 UTC (rev 287973)
</span><span class="lines">@@ -32,7 +32,7 @@
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> namespace Style {
</span><span class="cx"> 
</span><del>-static Vector<PseudoClassInvalidationKey, 4> makePseudoClassInvalidationKeys(CSSSelector::PseudoClassType pseudoClass, const Element& element)
</del><ins>+Vector<PseudoClassInvalidationKey, 4> makePseudoClassInvalidationKeys(CSSSelector::PseudoClassType pseudoClass, const Element& element)
</ins><span class="cx"> {
</span><span class="cx">     Vector<PseudoClassInvalidationKey, 4> keys;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorestylePseudoClassChangeInvalidationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/style/PseudoClassChangeInvalidation.h (287972 => 287973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/style/PseudoClassChangeInvalidation.h       2022-01-13 07:10:04 UTC (rev 287972)
+++ trunk/Source/WebCore/style/PseudoClassChangeInvalidation.h  2022-01-13 07:31:50 UTC (rev 287973)
</span><span class="lines">@@ -53,6 +53,8 @@
</span><span class="cx">     Invalidator::MatchElementRuleSets m_afterChangeRuleSets;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+Vector<PseudoClassInvalidationKey, 4> makePseudoClassInvalidationKeys(CSSSelector::PseudoClassType, const Element&);
+
</ins><span class="cx"> inline void emplace(std::optional<PseudoClassChangeInvalidation>& invalidation, Element& element, std::initializer_list<std::pair<CSSSelector::PseudoClassType, bool>> pseudoClasses)
</span><span class="cx"> {
</span><span class="cx">     invalidation.emplace(element, pseudoClasses);
</span></span></pre></div>
<a id="trunkSourceWebCorestyleRuleFeaturecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/style/RuleFeature.cpp (287972 => 287973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/style/RuleFeature.cpp       2022-01-13 07:10:04 UTC (rev 287972)
+++ trunk/Source/WebCore/style/RuleFeature.cpp  2022-01-13 07:31:50 UTC (rev 287973)
</span><span class="lines">@@ -216,13 +216,10 @@
</span><span class="cx">             if (matchElement == MatchElement::Parent || matchElement == MatchElement::Ancestor)
</span><span class="cx">                 idsMatchingAncestorsInRules.add(selector->value());
</span><span class="cx">             else if (isHasPseudoClassMatchElement(matchElement))
</span><del>-                selectorFeatures.ids.append({ selector->value(), matchElement, isNegation });
</del><ins>+                selectorFeatures.ids.append({ selector, matchElement, isNegation });
</ins><span class="cx">         } else if (selector->match() == CSSSelector::Class)
</span><del>-            selectorFeatures.classes.append({ selector->value(), matchElement, isNegation });
-        else if (selector->match() == CSSSelector::Tag) {
-            if (isHasPseudoClassMatchElement(matchElement))
-                selectorFeatures.tags.append({ selector->tagLowercaseLocalName(), matchElement, isNegation });
-        } else if (selector->isAttributeSelector()) {
</del><ins>+            selectorFeatures.classes.append({ selector, matchElement, isNegation });
+        else if (selector->isAttributeSelector()) {
</ins><span class="cx">             auto& canonicalLocalName = selector->attributeCanonicalLocalName();
</span><span class="cx">             auto& localName = selector->attribute().localName();
</span><span class="cx">             attributeCanonicalLocalNamesInRules.add(canonicalLocalName);
</span><span class="lines">@@ -257,6 +254,9 @@
</span><span class="cx">                 if (!selectorFeatures.hasSiblingSelector && selector->isSiblingSelector())
</span><span class="cx">                     selectorFeatures.hasSiblingSelector = true;
</span><span class="cx">                 recursivelyCollectFeaturesFromSelector(selectorFeatures, *subSelector, subSelectorMatchElement, subSelectorIsNegation);
</span><ins>+
+                if (selector->match() == CSSSelector::PseudoClass && selector->pseudoClassType() == CSSSelector::PseudoClassHas)
+                    selectorFeatures.hasPseudoClasses.append({ subSelector, subSelectorMatchElement, isNegation });
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -276,12 +276,8 @@
</span><span class="cx">     };
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-static PseudoClassInvalidationKey makePseudoClassInvalidationKey(const CSSSelector& selector)
</del><ins>+static PseudoClassInvalidationKey makePseudoClassInvalidationKey(CSSSelector::PseudoClassType pseudoClassType, const CSSSelector& selector)
</ins><span class="cx"> {
</span><del>-    ASSERT(selector.match() == CSSSelector::PseudoClass);
-
-    auto pseudoClassType = selector.pseudoClassType();
-
</del><span class="cx">     AtomString className;
</span><span class="cx">     AtomString tagName;
</span><span class="cx">     for (auto* simpleSelector = selector.firstInCompound(); simpleSelector; simpleSelector = simpleSelector->tagHistory()) {
</span><span class="lines">@@ -303,7 +299,7 @@
</span><span class="cx">     if (!tagName.isEmpty() && tagName != starAtom())
</span><span class="cx">         return makePseudoClassInvalidationKey(pseudoClassType, InvalidationKeyType::Tag, tagName);
</span><span class="cx"> 
</span><del>-    return makePseudoClassInvalidationKey(selector.pseudoClassType(), InvalidationKeyType::Universal);
</del><ins>+    return makePseudoClassInvalidationKey(pseudoClassType, InvalidationKeyType::Universal);
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> void RuleFeatureSet::collectFeatures(const RuleData& ruleData)
</span><span class="lines">@@ -317,7 +313,9 @@
</span><span class="cx"> 
</span><span class="cx">     auto addToMap = [&](auto& map, auto& entries, auto hostAffectingNames) {
</span><span class="cx">         for (auto& entry : entries) {
</span><del>-            auto& [name, matchElement, isNegation] = entry;
</del><ins>+            auto& [selector, matchElement, isNegation] = entry;
+            auto& name = selector->value();
+
</ins><span class="cx">             map.ensure(name, [] {
</span><span class="cx">                 return makeUnique<RuleFeatureVector>();
</span><span class="cx">             }).iterator->value->append({ ruleData, matchElement, isNegation });
</span><span class="lines">@@ -331,7 +329,6 @@
</span><span class="cx">         }
</span><span class="cx">     };
</span><span class="cx"> 
</span><del>-    addToMap(tagRules, selectorFeatures.tags, nullptr);
</del><span class="cx">     addToMap(idRules, selectorFeatures.ids, nullptr);
</span><span class="cx">     addToMap(classRules, selectorFeatures.classes, &classesAffectingHost);
</span><span class="cx"> 
</span><span class="lines">@@ -347,7 +344,7 @@
</span><span class="cx"> 
</span><span class="cx">     for (auto& entry : selectorFeatures.pseudoClasses) {
</span><span class="cx">         auto [selector, matchElement, isNegation] = entry;
</span><del>-        pseudoClassRules.ensure(makePseudoClassInvalidationKey(*selector), [] {
</del><ins>+        pseudoClassRules.ensure(makePseudoClassInvalidationKey(selector->pseudoClassType(), *selector), [] {
</ins><span class="cx">             return makeUnique<Vector<RuleFeature>>();
</span><span class="cx">         }).iterator->value->append({ ruleData, matchElement, isNegation });
</span><span class="cx"> 
</span><span class="lines">@@ -357,6 +354,16 @@
</span><span class="cx"> 
</span><span class="cx">         setUsesMatchElement(matchElement);
</span><span class="cx">     }
</span><ins>+
+    for (auto& entry : selectorFeatures.hasPseudoClasses) {
+        auto [selector, matchElement, isNegation] = entry;
+        // The selector argument points to a selector inside :has() selector list instead of :has() itself.
+        hasPseudoClassRules.ensure(makePseudoClassInvalidationKey(CSSSelector::PseudoClassHas, *selector), [] {
+            return makeUnique<Vector<RuleFeatureWithInvalidationSelector>>();
+        }).iterator->value->append({ ruleData, matchElement, isNegation, selector });
+
+        setUsesMatchElement(matchElement);
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RuleFeatureSet::add(const RuleFeatureSet& other)
</span><span class="lines">@@ -377,7 +384,6 @@
</span><span class="cx">         }
</span><span class="cx">     };
</span><span class="cx"> 
</span><del>-    addMap(tagRules, other.tagRules);
</del><span class="cx">     addMap(idRules, other.idRules);
</span><span class="cx"> 
</span><span class="cx">     addMap(classRules, other.classRules);
</span><span class="lines">@@ -390,6 +396,8 @@
</span><span class="cx">     pseudoClassesAffectingHost.add(other.pseudoClassesAffectingHost.begin(), other.pseudoClassesAffectingHost.end());
</span><span class="cx">     pseudoClassTypes.add(other.pseudoClassTypes.begin(), other.pseudoClassTypes.end());
</span><span class="cx"> 
</span><ins>+    addMap(hasPseudoClassRules, other.hasPseudoClassRules);
+
</ins><span class="cx">     for (size_t i = 0; i < usedMatchElements.size(); ++i)
</span><span class="cx">         usedMatchElements[i] = usedMatchElements[i] || other.usedMatchElements[i];
</span><span class="cx"> 
</span><span class="lines">@@ -413,9 +421,9 @@
</span><span class="cx">     contentAttributeNamesInRules.clear();
</span><span class="cx">     siblingRules.clear();
</span><span class="cx">     uncommonAttributeRules.clear();
</span><del>-    tagRules.clear();
</del><span class="cx">     idRules.clear();
</span><span class="cx">     classRules.clear();
</span><ins>+    hasPseudoClassRules.clear();
</ins><span class="cx">     classesAffectingHost.clear();
</span><span class="cx">     attributeRules.clear();
</span><span class="cx">     attributesAffectingHost.clear();
</span><span class="lines">@@ -430,8 +438,6 @@
</span><span class="cx"> {
</span><span class="cx">     siblingRules.shrinkToFit();
</span><span class="cx">     uncommonAttributeRules.shrinkToFit();
</span><del>-    for (auto& rules : tagRules.values())
-        rules->shrinkToFit();
</del><span class="cx">     for (auto& rules : idRules.values())
</span><span class="cx">         rules->shrinkToFit();
</span><span class="cx">     for (auto& rules : classRules.values())
</span><span class="lines">@@ -440,6 +446,8 @@
</span><span class="cx">         rules->shrinkToFit();
</span><span class="cx">     for (auto& rules : pseudoClassRules.values())
</span><span class="cx">         rules->shrinkToFit();
</span><ins>+    for (auto& rules : hasPseudoClassRules.values())
+        rules->shrinkToFit();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace Style
</span></span></pre></div>
<a id="trunkSourceWebCorestyleRuleFeatureh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/style/RuleFeature.h (287972 => 287973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/style/RuleFeature.h 2022-01-13 07:10:04 UTC (rev 287972)
+++ trunk/Source/WebCore/style/RuleFeature.h    2022-01-13 07:31:50 UTC (rev 287973)
</span><span class="lines">@@ -105,11 +105,12 @@
</span><span class="cx">     Vector<RuleAndSelector> siblingRules;
</span><span class="cx">     Vector<RuleAndSelector> uncommonAttributeRules;
</span><span class="cx"> 
</span><del>-    HashMap<AtomString, std::unique_ptr<RuleFeatureVector>> tagRules;
</del><span class="cx">     HashMap<AtomString, std::unique_ptr<RuleFeatureVector>> idRules;
</span><span class="cx">     HashMap<AtomString, std::unique_ptr<RuleFeatureVector>> classRules;
</span><span class="cx">     HashMap<AtomString, std::unique_ptr<Vector<RuleFeatureWithInvalidationSelector>>> attributeRules;
</span><span class="cx">     HashMap<PseudoClassInvalidationKey, std::unique_ptr<RuleFeatureVector>> pseudoClassRules;
</span><ins>+    HashMap<PseudoClassInvalidationKey, std::unique_ptr<Vector<RuleFeatureWithInvalidationSelector>>> hasPseudoClassRules;
+
</ins><span class="cx">     HashSet<AtomString> classesAffectingHost;
</span><span class="cx">     HashSet<AtomString> attributesAffectingHost;
</span><span class="cx">     HashSet<CSSSelector::PseudoClassType, IntHash<CSSSelector::PseudoClassType>, WTF::StrongEnumHashTraits<CSSSelector::PseudoClassType>> pseudoClassesAffectingHost;
</span><span class="lines">@@ -124,13 +125,15 @@
</span><span class="cx">     struct SelectorFeatures {
</span><span class="cx">         bool hasSiblingSelector { false };
</span><span class="cx"> 
</span><del>-        Vector<std::tuple<AtomString, MatchElement, IsNegation>, 32> tags;
-        Vector<std::tuple<AtomString, MatchElement, IsNegation>, 32> ids;
-        Vector<std::tuple<AtomString, MatchElement, IsNegation>, 32> classes;
-        Vector<std::tuple<const CSSSelector*, MatchElement, IsNegation>, 32> attributes;
-        Vector<std::tuple<const CSSSelector*, MatchElement, IsNegation>, 32> pseudoClasses;
</del><ins>+        using InvalidationFeature = std::tuple<const CSSSelector*, MatchElement, IsNegation>;
+
+        Vector<InvalidationFeature> ids;
+        Vector<InvalidationFeature> classes;
+        Vector<InvalidationFeature> attributes;
+        Vector<InvalidationFeature> pseudoClasses;
+        Vector<InvalidationFeature> hasPseudoClasses;
</ins><span class="cx">     };
</span><del>-    void recursivelyCollectFeaturesFromSelector(SelectorFeatures&, const CSSSelector&, MatchElement = MatchElement::Subject, IsNegation =  IsNegation::No);
</del><ins>+    void recursivelyCollectFeaturesFromSelector(SelectorFeatures&, const CSSSelector&, MatchElement = MatchElement::Subject, IsNegation = IsNegation::No);
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> bool isHasPseudoClassMatchElement(MatchElement);
</span></span></pre></div>
<a id="trunkSourceWebCorestyleStyleScopeRuleSetscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/style/StyleScopeRuleSets.cpp (287972 => 287973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/style/StyleScopeRuleSets.cpp        2022-01-13 07:10:04 UTC (rev 287972)
+++ trunk/Source/WebCore/style/StyleScopeRuleSets.cpp   2022-01-13 07:31:50 UTC (rev 287973)
</span><span class="lines">@@ -221,11 +221,11 @@
</span><span class="cx">     m_siblingRuleSet = makeRuleSet(m_features.siblingRules);
</span><span class="cx">     m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules);
</span><span class="cx"> 
</span><del>-    m_tagInvalidationRuleSets.clear();
</del><span class="cx">     m_idInvalidationRuleSets.clear();
</span><span class="cx">     m_classInvalidationRuleSets.clear();
</span><span class="cx">     m_attributeInvalidationRuleSets.clear();
</span><span class="cx">     m_pseudoClassInvalidationRuleSets.clear();
</span><ins>+    m_hasPseudoClassInvalidationRuleSets.clear();
</ins><span class="cx"> 
</span><span class="cx">     m_cachedHasComplexSelectorsForStyleAttribute = std::nullopt;
</span><span class="cx"> 
</span><span class="lines">@@ -272,11 +272,6 @@
</span><span class="cx">     }).iterator->value.get();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-const Vector<InvalidationRuleSet>* ScopeRuleSets::tagInvalidationRuleSets(const AtomString& tagName) const
-{
-    return ensureInvalidationRuleSets(tagName, m_tagInvalidationRuleSets, m_features.tagRules);
-}
-
</del><span class="cx"> const Vector<InvalidationRuleSet>* ScopeRuleSets::idInvalidationRuleSets(const AtomString& id) const
</span><span class="cx"> {
</span><span class="cx">     return ensureInvalidationRuleSets(id, m_idInvalidationRuleSets, m_features.idRules);
</span><span class="lines">@@ -297,6 +292,11 @@
</span><span class="cx">     return ensureInvalidationRuleSets(pseudoClassKey, m_pseudoClassInvalidationRuleSets, m_features.pseudoClassRules);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+const Vector<InvalidationRuleSet>* ScopeRuleSets::hasPseudoClassInvalidationRuleSets(const PseudoClassInvalidationKey& key) const
+{
+    return ensureInvalidationRuleSets(key, m_hasPseudoClassInvalidationRuleSets, m_features.hasPseudoClassRules);
+}
+
</ins><span class="cx"> bool ScopeRuleSets::hasComplexSelectorsForStyleAttribute() const
</span><span class="cx"> {
</span><span class="cx">     auto compute = [&] {
</span></span></pre></div>
<a id="trunkSourceWebCorestyleStyleScopeRuleSetsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/style/StyleScopeRuleSets.h (287972 => 287973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/style/StyleScopeRuleSets.h  2022-01-13 07:10:04 UTC (rev 287972)
+++ trunk/Source/WebCore/style/StyleScopeRuleSets.h     2022-01-13 07:31:50 UTC (rev 287973)
</span><span class="lines">@@ -62,14 +62,12 @@
</span><span class="cx">     RuleSet* sibling() const { return m_siblingRuleSet.get(); }
</span><span class="cx">     RuleSet* uncommonAttribute() const { return m_uncommonAttributeRuleSet.get(); }
</span><span class="cx"> 
</span><del>-    const Vector<InvalidationRuleSet>* tagInvalidationRuleSets(const AtomString&) const;
</del><span class="cx">     const Vector<InvalidationRuleSet>* idInvalidationRuleSets(const AtomString&) const;
</span><span class="cx">     const Vector<InvalidationRuleSet>* classInvalidationRuleSets(const AtomString&) const;
</span><span class="cx">     const Vector<InvalidationRuleSet>* attributeInvalidationRuleSets(const AtomString&) const;
</span><span class="cx">     const Vector<InvalidationRuleSet>* pseudoClassInvalidationRuleSets(const PseudoClassInvalidationKey&) const;
</span><ins>+    const Vector<InvalidationRuleSet>* hasPseudoClassInvalidationRuleSets(const PseudoClassInvalidationKey&) const;
</ins><span class="cx"> 
</span><del>-    const Vector<InvalidationRuleSet>* invalidationRuleSetsForChildChange(const Element&);
-
</del><span class="cx">     bool hasComplexSelectorsForStyleAttribute() const;
</span><span class="cx"> 
</span><span class="cx">     void setUsesSharedUserStyle(bool b) { m_usesSharedUserStyle = b; }
</span><span class="lines">@@ -101,11 +99,11 @@
</span><span class="cx">     mutable RuleFeatureSet m_features;
</span><span class="cx">     mutable RefPtr<RuleSet> m_siblingRuleSet;
</span><span class="cx">     mutable RefPtr<RuleSet> m_uncommonAttributeRuleSet;
</span><del>-    mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_tagInvalidationRuleSets;
</del><span class="cx">     mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_idInvalidationRuleSets;
</span><span class="cx">     mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_classInvalidationRuleSets;
</span><span class="cx">     mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_attributeInvalidationRuleSets;
</span><span class="cx">     mutable HashMap<PseudoClassInvalidationKey, std::unique_ptr<Vector<InvalidationRuleSet>>> m_pseudoClassInvalidationRuleSets;
</span><ins>+    mutable HashMap<PseudoClassInvalidationKey, std::unique_ptr<Vector<InvalidationRuleSet>>> m_hasPseudoClassInvalidationRuleSets;
</ins><span class="cx"> 
</span><span class="cx">     mutable std::optional<bool> m_cachedHasComplexSelectorsForStyleAttribute;
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>