Changeset 286169 in webkit


Ignore:
Timestamp:
Nov 25, 2021 1:14:17 PM (8 months ago)
Author:
Antti Koivisto
Message:

[:has() pseudo-class] Invalidation support for adding and removing nodes
https://bugs.webkit.org/show_bug.cgi?id=233489

Reviewed by Alan Bujtas.

LayoutTests/imported/w3c:

Add some additional cases to an existing test.

  • web-platform-tests/css/selectors/invalidation/attribute-or-elemental-selectors-in-has-expected.txt:
  • web-platform-tests/css/selectors/invalidation/attribute-or-elemental-selectors-in-has.html:

Source/WebCore:

We need to invalidate style when added or removed elements match :has() arguments.

This patch adds tag name invalidation rulesets for :has() case, along with the existing class
and attribute rulesets. It is still missing support for #id invalidation.

  • style/ChildChangeInvalidation.cpp:

(WebCore::Style::ChildChangeInvalidation::ChildChangeInvalidation):

See if we need to invalidate for the elements being removed before the mutation.

(WebCore::Style::ChildChangeInvalidation::~ChildChangeInvalidation):

See if we need to invalidate for the elements being added after the mutation.

(WebCore::Style::ChildChangeInvalidation::invalidateForChangedElement):

Find the relevant invalidation rulesets for attributes, classes and tags and invalidate using them.

(WebCore::Style::needsTraversal):

We only need to do anything in the presence of :has() rules.

(WebCore::Style::needsDescendantTraversal):

Full traversal is only needed in case there are :has() rules using descendant combinator.

(WebCore::Style::ChildChangeInvalidation::traverseRemovedElements):
(WebCore::Style::ChildChangeInvalidation::traverseAddedElements):

  • style/ChildChangeInvalidation.h:
  • style/RuleFeature.cpp:

(WebCore::Style::isHasPseudoClassMatchElement):
(WebCore::Style::RuleFeatureSet::recursivelyCollectFeaturesFromSelector):
(WebCore::Style::RuleFeatureSet::collectFeatures):

Collect tag invalidation rulesets for :has case only.

(WebCore::Style::RuleFeatureSet::add):
(WebCore::Style::RuleFeatureSet::clear):
(WebCore::Style::RuleFeatureSet::shrinkToFit):

  • style/RuleFeature.h:

(WebCore::Style::RuleFeatureSet::usesMatchElement const):
(WebCore::Style::RuleFeatureSet::setUsesMatchElement):

Keep track of what sort of match elements are being used.

  • style/StyleScopeRuleSets.cpp:

(WebCore::Style::ScopeRuleSets::collectFeatures const):
(WebCore::Style::ScopeRuleSets::tagInvalidationRuleSets const):

  • style/StyleScopeRuleSets.h:
Location:
trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r286168 r286169  
     12021-11-25  Antti Koivisto  <antti@apple.com>
     2
     3        [:has() pseudo-class] Invalidation support for adding and removing nodes
     4        https://bugs.webkit.org/show_bug.cgi?id=233489
     5
     6        Reviewed by Alan Bujtas.
     7
     8        Add some additional cases to an existing test.
     9
     10        * web-platform-tests/css/selectors/invalidation/attribute-or-elemental-selectors-in-has-expected.txt:
     11        * web-platform-tests/css/selectors/invalidation/attribute-or-elemental-selectors-in-has.html:
     12
    1132021-11-25  Sam Weinig  <weinig@apple.com>
    214
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/attribute-or-elemental-selectors-in-has-expected.txt

    r286135 r286169  
    1515FAIL change #div_grandchild to #div_descendant: div#div_subject.color assert_equals: expected "rgb(255, 255, 0)" but got "rgb(128, 128, 128)"
    1616PASS change #div_descendant to #div_grandchild: div#div_subject.color
    17 FAIL add descendant to #div_subject: div#div_subject.color assert_equals: expected "rgb(154, 205, 50)" but got "rgb(128, 128, 128)"
     17PASS add descendant to #div_subject: div#div_subject.color
    1818PASS remove descendant from #div_subject: div#div_subject.color
    19 FAIL add "div > descendant" to #div_subject: div#div_subject.color assert_equals: expected "rgb(154, 205, 50)" but got "rgb(128, 128, 128)"
     19PASS add "div > descendant" to #div_subject: div#div_subject.color
    2020PASS remove "div > descendant" from #div_subject: div#div_subject.color
     21PASS add div.child to #div_subject: div#div_subject.color
     22PASS remove div.child from #div_subject: div#div_subject.color
     23PASS add "div > div.descendant" to #div_subject: div#div_subject.color
     24PASS remove "div > div.descendant" from #div_subject: div#div_subject.color
     25FAIL add div#div_descendant to #div_subject: div#div_subject.color assert_equals: expected "rgb(255, 255, 0)" but got "rgb(128, 128, 128)"
     26PASS remove div#div_descendant from #div_subject: div#div_subject.color
     27FAIL add "div#div_descendant" to #div_subject: div#div_subject.color assert_equals: expected "rgb(255, 255, 0)" but got "rgb(128, 128, 128)"
     28PASS remove "div#div_descendant" from #div_subject: div#div_subject.color
     29PASS add div[attrname] to #div_subject: div#div_subject.color
     30PASS remove div[attrname] from #div_subject: div#div_subject.color
     31PASS add "div > div[attrname]" to #div_subject: div#div_subject.color
     32PASS remove "div > div[attrname]" from #div_subject: div#div_subject.color
    2133
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/attribute-or-elemental-selectors-in-has.html

    r285921 r286169  
    6969  test_div('change #div_descendant to #div_grandchild', div_subject, grey);
    7070
    71   descendant = document.createElement('descendant');
    72   div_subject.appendChild(descendant);
    73   test_div('add descendant to #div_subject', div_subject, yellowgreen);
    74   div_subject.removeChild(descendant);
    75   test_div('remove descendant from #div_subject', div_subject, grey);
     71  {
     72    const descendant = document.createElement('descendant');
     73    div_subject.appendChild(descendant);
     74    test_div('add descendant to #div_subject', div_subject, yellowgreen);
     75    div_subject.removeChild(descendant);
     76    test_div('remove descendant from #div_subject', div_subject, grey);
     77  }
    7678
    77   div = document.createElement('div');
    78   div.appendChild(descendant);
    79   div_subject.appendChild(div);
    80   test_div('add "div > descendant" to #div_subject', div_subject, yellowgreen);
    81   div_subject.removeChild(div);
    82   test_div('remove "div > descendant" from #div_subject', div_subject, grey);
     79  {
     80    const div = document.createElement('div');
     81    const descendant = document.createElement('descendant');
     82    div.appendChild(descendant);
     83    div_subject.appendChild(div);
     84    test_div('add "div > descendant" to #div_subject', div_subject, yellowgreen);
     85    div_subject.removeChild(div);
     86    test_div('remove "div > descendant" from #div_subject', div_subject, grey);
     87  }
     88
     89  {
     90    const child = document.createElement('div');
     91    child.classList.add('child');
     92    div_subject.appendChild(child);
     93    test_div('add div.child to #div_subject', div_subject, red);
     94    div_subject.removeChild(child);
     95    test_div('remove div.child from #div_subject', div_subject, grey);
     96  }
     97
     98  {
     99    const descendant = document.createElement('div');
     100    descendant.classList.add('descendant');
     101    const div = document.createElement('div');
     102    div.appendChild(descendant);
     103    div_subject.appendChild(div);
     104    test_div('add "div > div.descendant" to #div_subject', div_subject, green);
     105    div_subject.removeChild(div);
     106    test_div('remove "div > div.descendant" from #div_subject', div_subject, grey);
     107  }
     108
     109  {
     110    const child = document.createElement('div');
     111    child.id = 'div_descendant';
     112    div_subject.appendChild(child);
     113    test_div('add div#div_descendant to #div_subject', div_subject, yellow);
     114    div_subject.removeChild(child);
     115    test_div('remove div#div_descendant from #div_subject', div_subject, grey);
     116  }
     117
     118  {
     119    const descendant = document.createElement('div');
     120    descendant.id = 'div_descendant';
     121    const div = document.createElement('div');
     122    div.appendChild(descendant);
     123    div_subject.appendChild(div);
     124    test_div('add "div#div_descendant" to #div_subject', div_subject, yellow);
     125    div_subject.removeChild(div);
     126    test_div('remove "div#div_descendant" from #div_subject', div_subject, grey);
     127  }
     128
     129  {
     130    const child = document.createElement('div');
     131    child.setAttribute('attrname', 'descendant');
     132    div_subject.appendChild(child);
     133    test_div('add div[attrname] to #div_subject', div_subject, blue);
     134    div_subject.removeChild(child);
     135    test_div('remove div[attrname] from #div_subject', div_subject, grey);
     136  }
     137
     138  {
     139    const descendant = document.createElement('div');
     140    descendant.setAttribute('attrname', 'descendant');
     141    const div = document.createElement('div');
     142    div.appendChild(descendant);
     143    div_subject.appendChild(div);
     144    test_div('add "div > div[attrname]" to #div_subject', div_subject, blue);
     145    div_subject.removeChild(div);
     146    test_div('remove "div > div[attrname]" from #div_subject', div_subject, grey);
     147  }
    83148
    84149</script>
  • trunk/Source/WebCore/ChangeLog

    r286168 r286169  
     12021-11-25  Antti Koivisto  <antti@apple.com>
     2
     3        [:has() pseudo-class] Invalidation support for adding and removing nodes
     4        https://bugs.webkit.org/show_bug.cgi?id=233489
     5
     6        Reviewed by Alan Bujtas.
     7
     8        We need to invalidate style when added or removed elements match :has() arguments.
     9
     10        This patch adds tag name invalidation rulesets for :has() case, along with the existing class
     11        and attribute rulesets. It is still missing support for #id invalidation.
     12
     13        * style/ChildChangeInvalidation.cpp:
     14        (WebCore::Style::ChildChangeInvalidation::ChildChangeInvalidation):
     15
     16        See if we need to invalidate for the elements being removed before the mutation.
     17
     18        (WebCore::Style::ChildChangeInvalidation::~ChildChangeInvalidation):
     19
     20        See if we need to invalidate for the elements being added after the mutation.
     21
     22        (WebCore::Style::ChildChangeInvalidation::invalidateForChangedElement):
     23
     24        Find the relevant invalidation rulesets for attributes, classes and tags and invalidate using them.
     25
     26        (WebCore::Style::needsTraversal):
     27
     28        We only need to do anything in the presence of :has() rules.
     29
     30        (WebCore::Style::needsDescendantTraversal):
     31
     32        Full traversal is only needed in case there are :has() rules using descendant combinator.
     33
     34        (WebCore::Style::ChildChangeInvalidation::traverseRemovedElements):
     35        (WebCore::Style::ChildChangeInvalidation::traverseAddedElements):
     36        * style/ChildChangeInvalidation.h:
     37        * style/RuleFeature.cpp:
     38        (WebCore::Style::isHasPseudoClassMatchElement):
     39        (WebCore::Style::RuleFeatureSet::recursivelyCollectFeaturesFromSelector):
     40        (WebCore::Style::RuleFeatureSet::collectFeatures):
     41
     42        Collect tag invalidation rulesets for :has case only.
     43
     44        (WebCore::Style::RuleFeatureSet::add):
     45        (WebCore::Style::RuleFeatureSet::clear):
     46        (WebCore::Style::RuleFeatureSet::shrinkToFit):
     47        * style/RuleFeature.h:
     48        (WebCore::Style::RuleFeatureSet::usesMatchElement const):
     49        (WebCore::Style::RuleFeatureSet::setUsesMatchElement):
     50
     51        Keep track of what sort of match elements are being used.
     52
     53        * style/StyleScopeRuleSets.cpp:
     54        (WebCore::Style::ScopeRuleSets::collectFeatures const):
     55        (WebCore::Style::ScopeRuleSets::tagInvalidationRuleSets const):
     56        * style/StyleScopeRuleSets.h:
     57
    1582021-11-25  Sam Weinig  <weinig@apple.com>
    259
  • trunk/Source/WebCore/style/ChildChangeInvalidation.cpp

    r286138 r286169  
    3131#include "ShadowRoot.h"
    3232#include "SlotAssignment.h"
     33#include "StyleResolver.h"
     34#include "StyleScopeRuleSets.h"
     35#include "TypedElementDescendantIterator.h"
    3336
    3437namespace WebCore::Style {
     
    3942    , m_childChange(childChange)
    4043{
    41     // FIXME: Do smarter invalidation similar to ClassChangeInvalidation.
     44    if (!m_isEnabled)
     45        return;
     46
     47    traverseRemovedElements([&](auto& changedElement) {
     48        invalidateForChangedElement(changedElement);
     49    });
    4250}
    4351
     
    4755        return;
    4856
     57    traverseAddedElements([&](auto& changedElement) {
     58        invalidateForChangedElement(changedElement);
     59    });
     60   
    4961    invalidateAfterChange();
     62}
     63
     64void ChildChangeInvalidation::invalidateForChangedElement(Element& changedElement)
     65{
     66    auto& ruleSets = parentElement().styleResolver().ruleSets();
     67
     68    Invalidator::MatchElementRuleSets matchElementRuleSets;
     69
     70    auto addHasInvalidation = [&](const Vector<InvalidationRuleSet>* invalidationRuleSets)  {
     71        if (!invalidationRuleSets)
     72            return;
     73        for (auto& invalidationRuleSet : *invalidationRuleSets) {
     74            if (isHasPseudoClassMatchElement(invalidationRuleSet.matchElement))
     75                Invalidator::addToMatchElementRuleSets(matchElementRuleSets, invalidationRuleSet);
     76        }
     77    };
     78
     79    auto tagName = changedElement.localName().convertToASCIILowercase();
     80    addHasInvalidation(ruleSets.tagInvalidationRuleSets(tagName));
     81
     82    if (changedElement.hasAttributes()) {
     83        for (auto& attribute : changedElement.attributesIterator()) {
     84            auto attributeName = attribute.localName().convertToASCIILowercase();
     85            addHasInvalidation(ruleSets.attributeInvalidationRuleSets(attributeName));
     86        }
     87    }
     88
     89    if (changedElement.hasClass()) {
     90        auto count = changedElement.classNames().size();
     91        for (size_t i = 0; i < count; ++i) {
     92            auto& className = changedElement.classNames()[i];
     93            addHasInvalidation(ruleSets.classInvalidationRuleSets(className));
     94        }
     95    }
     96
     97    Invalidator::invalidateWithMatchElementRuleSets(changedElement, matchElementRuleSets);
     98}
     99
     100static bool needsTraversal(const RuleFeatureSet& features, const ContainerNode::ChildChange& childChange)
     101{
     102    if (features.usesMatchElement(MatchElement::HasChild))
     103        return true;
     104    if (features.usesMatchElement(MatchElement::HasDescendant))
     105        return true;
     106    return features.usesMatchElement(MatchElement::HasSibling) && childChange.previousSiblingElement;
     107};
     108
     109static bool needsDescendantTraversal(const RuleFeatureSet& features)
     110{
     111    return features.usesMatchElement(MatchElement::HasDescendant);
     112};
     113
     114template<typename Function>
     115void ChildChangeInvalidation::traverseRemovedElements(Function&& function)
     116{
     117    if (m_childChange.isInsertion() && m_childChange.type != ContainerNode::ChildChange::Type::AllChildrenReplaced)
     118        return;
     119
     120    auto& features = parentElement().styleResolver().ruleSets().features();
     121    if (!needsTraversal(features, m_childChange))
     122        return;
     123
     124    bool needsDescendantTraversal = Style::needsDescendantTraversal(features);
     125
     126    auto* toRemove = m_childChange.previousSiblingElement ? m_childChange.previousSiblingElement->nextElementSibling() : parentElement().firstElementChild();
     127    for (; toRemove != m_childChange.nextSiblingElement; toRemove = toRemove->nextElementSibling()) {
     128        function(*toRemove);
     129
     130        if (!needsDescendantTraversal)
     131            continue;
     132
     133        for (auto& descendant : descendantsOfType<Element>(*toRemove))
     134            function(descendant);
     135    }
     136}
     137
     138template<typename Function>
     139void ChildChangeInvalidation::traverseAddedElements(Function&& function)
     140{
     141    if (!m_childChange.isInsertion())
     142        return;
     143
     144    auto* newElement = [&] {
     145        auto* previous = m_childChange.previousSiblingElement;
     146        auto* candidate = previous ? ElementTraversal::nextSibling(*previous) : ElementTraversal::firstChild(parentElement());
     147        if (candidate == m_childChange.nextSiblingElement)
     148            candidate = nullptr;
     149        return candidate;
     150    }();
     151
     152    if (!newElement)
     153        return;
     154
     155    auto& features = parentElement().styleResolver().ruleSets().features();
     156    if (!needsTraversal(features, m_childChange))
     157        return;
     158
     159    function(*newElement);
     160
     161    if (!needsDescendantTraversal(features))
     162        return;
     163
     164    for (auto& descendant : descendantsOfType<Element>(*newElement))
     165        function(descendant);
    50166}
    51167
  • trunk/Source/WebCore/style/ChildChangeInvalidation.h

    r286112 r286169  
    2727
    2828#include "Element.h"
     29#include "StyleInvalidator.h"
    2930
    3031namespace WebCore {
     
    4142    void invalidateAfterChange();
    4243    void checkForSiblingStyleChanges();
     44    void invalidateForChangedElement(Element&);
     45
     46    template<typename Function> void traverseRemovedElements(Function&&);
     47    template<typename Function> void traverseAddedElements(Function&&);
    4348
    4449    Element& parentElement() { return *m_parentElement; }
  • trunk/Source/WebCore/style/RuleFeature.cpp

    r286135 r286169  
    5959}
    6060
    61 static bool isHasPseudoClassMatchElement(MatchElement matchElement)
     61bool isHasPseudoClassMatchElement(MatchElement matchElement)
    6262{
    6363    switch (matchElement) {
     
    173173        } else if (selector->match() == CSSSelector::Class)
    174174            selectorFeatures.classes.append(std::make_pair(selector->value(), matchElement));
    175         else if (selector->isAttributeSelector()) {
     175        else if (selector->match() == CSSSelector::Tag) {
     176            if (isHasPseudoClassMatchElement(matchElement))
     177                selectorFeatures.tags.append(std::make_pair(selector->tagLowercaseLocalName(), matchElement));
     178        } else if (selector->isAttributeSelector()) {
    176179            auto& canonicalLocalName = selector->attributeCanonicalLocalName();
    177180            auto& localName = selector->attribute().localName();
     
    220223        uncommonAttributeRules.append({ ruleData });
    221224
     225    for (auto& nameAndMatch : selectorFeatures.tags) {
     226        tagRules.ensure(nameAndMatch.first, [] {
     227            return makeUnique<RuleFeatureVector>();
     228        }).iterator->value->append({ ruleData, nameAndMatch.second });
     229        setUsesMatchElement(nameAndMatch.second);
     230    }
    222231    for (auto& nameAndMatch : selectorFeatures.classes) {
    223232        classRules.ensure(nameAndMatch.first, [] {
     
    226235        if (nameAndMatch.second == MatchElement::Host)
    227236            classesAffectingHost.add(nameAndMatch.first);
     237        setUsesMatchElement(nameAndMatch.second);
    228238    }
    229239    for (auto& selectorAndMatch : selectorFeatures.attributes) {
     
    235245        if (matchElement == MatchElement::Host)
    236246            attributesAffectingHost.add(selector->attribute().localName().convertToASCIILowercase());
     247        setUsesMatchElement(matchElement);
    237248    }
    238249    for (auto& keyAndMatch : selectorFeatures.pseudoClasses) {
     
    242253        if (keyAndMatch.second == MatchElement::Host)
    243254            pseudoClassesAffectingHost.add(keyAndMatch.first);
     255        setUsesMatchElement(keyAndMatch.second);
    244256    }
    245257}
     
    254266    siblingRules.appendVector(other.siblingRules);
    255267    uncommonAttributeRules.appendVector(other.uncommonAttributeRules);
     268
     269    for (auto& keyValuePair : other.tagRules) {
     270        tagRules.ensure(keyValuePair.key, [] {
     271            return makeUnique<RuleFeatureVector>();
     272        }).iterator->value->appendVector(*keyValuePair.value);
     273    }
     274
    256275    for (auto& keyValuePair : other.classRules) {
    257276        classRules.ensure(keyValuePair.key, [] {
     
    274293    }
    275294    pseudoClassesAffectingHost.add(other.pseudoClassesAffectingHost.begin(), other.pseudoClassesAffectingHost.end());
     295
     296    for (size_t i = 0; i < usedMatchElements.size(); ++i)
     297        usedMatchElements[i] = usedMatchElements[i] || other.usedMatchElements[i];
    276298
    277299    usesFirstLineRules = usesFirstLineRules || other.usesFirstLineRules;
     
    295317    siblingRules.clear();
    296318    uncommonAttributeRules.clear();
     319    tagRules.clear();
    297320    classRules.clear();
    298321    classesAffectingHost.clear();
     
    309332    siblingRules.shrinkToFit();
    310333    uncommonAttributeRules.shrinkToFit();
     334    for (auto& rules : tagRules.values())
     335        rules->shrinkToFit();
    311336    for (auto& rules : classRules.values())
    312337        rules->shrinkToFit();
  • trunk/Source/WebCore/style/RuleFeature.h

    r286135 r286169  
    6868    void registerContentAttribute(const AtomString&);
    6969
     70    bool usesMatchElement(MatchElement matchElement) const  { return usedMatchElements[static_cast<uint8_t>(matchElement)]; }
     71    void setUsesMatchElement(MatchElement matchElement) { usedMatchElements[static_cast<uint8_t>(matchElement)] = true; }
     72
    7073    HashSet<AtomString> idsInRules;
    7174    HashSet<AtomString> idsMatchingAncestorsInRules;
     
    7578    RuleFeatureVector siblingRules;
    7679    RuleFeatureVector uncommonAttributeRules;
    77    
     80
     81    HashMap<AtomString, std::unique_ptr<RuleFeatureVector>> tagRules;
    7882    HashMap<AtomString, std::unique_ptr<RuleFeatureVector>> classRules;
    7983    HashMap<AtomString, std::unique_ptr<Vector<RuleFeatureWithInvalidationSelector>>> attributeRules;
     
    8286    HashSet<AtomString> attributesAffectingHost;
    8387    HashSet<CSSSelector::PseudoClassType, IntHash<CSSSelector::PseudoClassType>, WTF::StrongEnumHashTraits<CSSSelector::PseudoClassType>> pseudoClassesAffectingHost;
     88
     89    std::array<bool, matchElementCount> usedMatchElements;
    8490
    8591    bool usesFirstLineRules { false };
     
    9399        bool hasSiblingSelector { false };
    94100
     101        Vector<std::pair<AtomString, MatchElement>, 32> tags;
    95102        Vector<std::pair<AtomString, MatchElement>, 32> classes;
    96103        Vector<std::pair<const CSSSelector*, MatchElement>, 32> attributes;
     
    100107};
    101108
     109bool isHasPseudoClassMatchElement(MatchElement);
     110
    102111} // namespace Style
    103112} // namespace WebCore
  • trunk/Source/WebCore/style/StyleScopeRuleSets.cpp

    r284078 r286169  
    221221    m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules);
    222222
     223    m_tagInvalidationRuleSets.clear();
    223224    m_classInvalidationRuleSets.clear();
    224225    m_attributeInvalidationRuleSets.clear();
     
    274275}
    275276
     277const Vector<InvalidationRuleSet>* ScopeRuleSets::tagInvalidationRuleSets(const AtomString& tagName) const
     278{
     279    return ensureInvalidationRuleSets(tagName, m_tagInvalidationRuleSets, m_features.tagRules);
     280}
     281
    276282const Vector<InvalidationRuleSet>* ScopeRuleSets::classInvalidationRuleSets(const AtomString& className) const
    277283{
  • trunk/Source/WebCore/style/StyleScopeRuleSets.h

    r284857 r286169  
    6464    RuleSet* uncommonAttribute() const { return m_uncommonAttributeRuleSet.get(); }
    6565
     66    const Vector<InvalidationRuleSet>* tagInvalidationRuleSets(const AtomString& tagName) const;
    6667    const Vector<InvalidationRuleSet>* classInvalidationRuleSets(const AtomString& className) const;
    6768    const Vector<InvalidationRuleSet>* attributeInvalidationRuleSets(const AtomString& attributeName) const;
    6869    const Vector<InvalidationRuleSet>* pseudoClassInvalidationRuleSets(CSSSelector::PseudoClassType) const;
     70
     71    const Vector<InvalidationRuleSet>* invalidationRuleSetsForChildChange(const Element&);
    6972
    7073    bool hasComplexSelectorsForStyleAttribute() const;
     
    99102    mutable RefPtr<RuleSet> m_siblingRuleSet;
    100103    mutable RefPtr<RuleSet> m_uncommonAttributeRuleSet;
     104    mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_tagInvalidationRuleSets;
    101105    mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_classInvalidationRuleSets;
    102106    mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_attributeInvalidationRuleSets;
Note: See TracChangeset for help on using the changeset viewer.