Changeset 287973 in webkit


Ignore:
Timestamp:
Jan 12, 2022 11:31:50 PM (6 months ago)
Author:
Antti Koivisto
Message:

[: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:
Location:
trunk/Source/WebCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r287970 r287973  
     12022-01-12  Antti Koivisto  <antti@apple.com>
     2
     3        [:has() pseudo-class] Collect invalidation selectors for child invalidation
     4        https://bugs.webkit.org/show_bug.cgi?id=235103
     5
     6        Reviewed by Dean Jackson.
     7
     8        Collect selectors we can use to test if :has status actually changed before invalidating.
     9
     10        This patch doesn't yet use the the selector.
     11
     12        * style/ChildChangeInvalidation.cpp:
     13        (WebCore::Style::ChildChangeInvalidation::invalidateForChangedElement):
     14
     15        Use the pseudo class invalidation keys for looking up :has selectors too
     16        instead of having a custom mechanism for doing the same thing.
     17
     18        * style/PseudoClassChangeInvalidation.cpp:
     19        (WebCore::Style::makePseudoClassInvalidationKeys):
     20        * style/PseudoClassChangeInvalidation.h:
     21        * style/RuleFeature.cpp:
     22        (WebCore::Style::RuleFeatureSet::recursivelyCollectFeaturesFromSelector):
     23
     24        Always return a selector for consistency.
     25
     26        (WebCore::Style::makePseudoClassInvalidationKey):
     27        (WebCore::Style::RuleFeatureSet::collectFeatures):
     28        (WebCore::Style::RuleFeatureSet::add):
     29        (WebCore::Style::RuleFeatureSet::clear):
     30        (WebCore::Style::RuleFeatureSet::shrinkToFit):
     31        * style/RuleFeature.h:
     32        * style/StyleScopeRuleSets.cpp:
     33        (WebCore::Style::ScopeRuleSets::collectFeatures const):
     34        (WebCore::Style::ScopeRuleSets::hasPseudoClassInvalidationRuleSets const):
     35        (WebCore::Style::ScopeRuleSets::tagInvalidationRuleSets const): Deleted.
     36
     37        We don't need keep around tag rule sets anymore.
     38
     39        * style/StyleScopeRuleSets.h:
     40
    1412022-01-12  John Wilander  <wilander@apple.com>
    242
  • trunk/Source/WebCore/style/ChildChangeInvalidation.cpp

    r287325 r287973  
    2929#include "ElementTraversal.h"
    3030#include "NodeRenderStyle.h"
     31#include "PseudoClassChangeInvalidation.h"
    3132#include "ShadowRoot.h"
    3233#include "SlotAssignment.h"
     
    4546    bool isDescendant = changedElement.parentElement() != &parentElement();
    4647
     48    auto canAffectAncestors = [&](MatchElement matchElement) {
     49        if (!isDescendant)
     50            return true;
     51        return matchElement == MatchElement::HasDescendant
     52            || matchElement == MatchElement::HasSiblingDescendant
     53            || matchElement == MatchElement::HasNonSubject;
     54    };
     55
    4756    auto addHasInvalidation = [&](const Vector<InvalidationRuleSet>* invalidationRuleSets)  {
    4857        if (!invalidationRuleSets)
    4958            return;
    5059        for (auto& invalidationRuleSet : *invalidationRuleSets) {
    51             if (!isHasPseudoClassMatchElement(invalidationRuleSet.matchElement))
     60            if (!canAffectAncestors(invalidationRuleSet.matchElement))
    5261                continue;
    53             if (isDescendant) {
    54                 // Elements deeper in the tree can't affect anything except when :has() selector uses descendant combinator.
    55                 if (invalidationRuleSet.matchElement != MatchElement::HasDescendant && invalidationRuleSet.matchElement != MatchElement::HasNonSubject)
    56                     continue;
    57             }
    5862            Invalidator::addToMatchElementRuleSets(matchElementRuleSets, invalidationRuleSet);
    5963        }
    6064    };
    6165
    62     auto tagName = changedElement.localName().convertToASCIILowercase();
    63     addHasInvalidation(ruleSets.tagInvalidationRuleSets(tagName));
    64 
    65     if (changedElement.hasID())
    66         addHasInvalidation(ruleSets.idInvalidationRuleSets(changedElement.idForStyleResolution()));
    67 
    68     if (changedElement.hasAttributes()) {
    69         for (auto& attribute : changedElement.attributesIterator()) {
    70             auto attributeName = attribute.localName().convertToASCIILowercase();
    71             addHasInvalidation(ruleSets.attributeInvalidationRuleSets(attributeName));
    72         }
    73     }
    74 
    75     if (changedElement.hasClass()) {
    76         auto count = changedElement.classNames().size();
    77         for (size_t i = 0; i < count; ++i) {
    78             auto& className = changedElement.classNames()[i];
    79             addHasInvalidation(ruleSets.classInvalidationRuleSets(className));
    80         }
    81     }
     66    for (auto key : makePseudoClassInvalidationKeys(CSSSelector::PseudoClassHas, changedElement))
     67        addHasInvalidation(ruleSets.hasPseudoClassInvalidationRuleSets(key));
    8268
    8369    Invalidator::invalidateWithMatchElementRuleSets(changedElement, matchElementRuleSets);
  • trunk/Source/WebCore/style/PseudoClassChangeInvalidation.cpp

    r287818 r287973  
    3333namespace Style {
    3434
    35 static Vector<PseudoClassInvalidationKey, 4> makePseudoClassInvalidationKeys(CSSSelector::PseudoClassType pseudoClass, const Element& element)
     35Vector<PseudoClassInvalidationKey, 4> makePseudoClassInvalidationKeys(CSSSelector::PseudoClassType pseudoClass, const Element& element)
    3636{
    3737    Vector<PseudoClassInvalidationKey, 4> keys;
  • trunk/Source/WebCore/style/PseudoClassChangeInvalidation.h

    r287818 r287973  
    5454};
    5555
     56Vector<PseudoClassInvalidationKey, 4> makePseudoClassInvalidationKeys(CSSSelector::PseudoClassType, const Element&);
     57
    5658inline void emplace(std::optional<PseudoClassChangeInvalidation>& invalidation, Element& element, std::initializer_list<std::pair<CSSSelector::PseudoClassType, bool>> pseudoClasses)
    5759{
  • trunk/Source/WebCore/style/RuleFeature.cpp

    r287772 r287973  
    217217                idsMatchingAncestorsInRules.add(selector->value());
    218218            else if (isHasPseudoClassMatchElement(matchElement))
    219                 selectorFeatures.ids.append({ selector->value(), matchElement, isNegation });
     219                selectorFeatures.ids.append({ selector, matchElement, isNegation });
    220220        } else if (selector->match() == CSSSelector::Class)
    221             selectorFeatures.classes.append({ selector->value(), matchElement, isNegation });
    222         else if (selector->match() == CSSSelector::Tag) {
    223             if (isHasPseudoClassMatchElement(matchElement))
    224                 selectorFeatures.tags.append({ selector->tagLowercaseLocalName(), matchElement, isNegation });
    225         } else if (selector->isAttributeSelector()) {
     221            selectorFeatures.classes.append({ selector, matchElement, isNegation });
     222        else if (selector->isAttributeSelector()) {
    226223            auto& canonicalLocalName = selector->attributeCanonicalLocalName();
    227224            auto& localName = selector->attribute().localName();
     
    258255                    selectorFeatures.hasSiblingSelector = true;
    259256                recursivelyCollectFeaturesFromSelector(selectorFeatures, *subSelector, subSelectorMatchElement, subSelectorIsNegation);
     257
     258                if (selector->match() == CSSSelector::PseudoClass && selector->pseudoClassType() == CSSSelector::PseudoClassHas)
     259                    selectorFeatures.hasPseudoClasses.append({ subSelector, subSelectorMatchElement, isNegation });
    260260            }
    261261        }
     
    277277};
    278278
    279 static PseudoClassInvalidationKey makePseudoClassInvalidationKey(const CSSSelector& selector)
    280 {
    281     ASSERT(selector.match() == CSSSelector::PseudoClass);
    282 
    283     auto pseudoClassType = selector.pseudoClassType();
    284 
     279static PseudoClassInvalidationKey makePseudoClassInvalidationKey(CSSSelector::PseudoClassType pseudoClassType, const CSSSelector& selector)
     280{
    285281    AtomString className;
    286282    AtomString tagName;
     
    304300        return makePseudoClassInvalidationKey(pseudoClassType, InvalidationKeyType::Tag, tagName);
    305301
    306     return makePseudoClassInvalidationKey(selector.pseudoClassType(), InvalidationKeyType::Universal);
     302    return makePseudoClassInvalidationKey(pseudoClassType, InvalidationKeyType::Universal);
    307303};
    308304
     
    318314    auto addToMap = [&](auto& map, auto& entries, auto hostAffectingNames) {
    319315        for (auto& entry : entries) {
    320             auto& [name, matchElement, isNegation] = entry;
     316            auto& [selector, matchElement, isNegation] = entry;
     317            auto& name = selector->value();
     318
    321319            map.ensure(name, [] {
    322320                return makeUnique<RuleFeatureVector>();
     
    332330    };
    333331
    334     addToMap(tagRules, selectorFeatures.tags, nullptr);
    335332    addToMap(idRules, selectorFeatures.ids, nullptr);
    336333    addToMap(classRules, selectorFeatures.classes, &classesAffectingHost);
     
    348345    for (auto& entry : selectorFeatures.pseudoClasses) {
    349346        auto [selector, matchElement, isNegation] = entry;
    350         pseudoClassRules.ensure(makePseudoClassInvalidationKey(*selector), [] {
     347        pseudoClassRules.ensure(makePseudoClassInvalidationKey(selector->pseudoClassType(), *selector), [] {
    351348            return makeUnique<Vector<RuleFeature>>();
    352349        }).iterator->value->append({ ruleData, matchElement, isNegation });
     
    355352            pseudoClassesAffectingHost.add(selector->pseudoClassType());
    356353        pseudoClassTypes.add(selector->pseudoClassType());
     354
     355        setUsesMatchElement(matchElement);
     356    }
     357
     358    for (auto& entry : selectorFeatures.hasPseudoClasses) {
     359        auto [selector, matchElement, isNegation] = entry;
     360        // The selector argument points to a selector inside :has() selector list instead of :has() itself.
     361        hasPseudoClassRules.ensure(makePseudoClassInvalidationKey(CSSSelector::PseudoClassHas, *selector), [] {
     362            return makeUnique<Vector<RuleFeatureWithInvalidationSelector>>();
     363        }).iterator->value->append({ ruleData, matchElement, isNegation, selector });
    357364
    358365        setUsesMatchElement(matchElement);
     
    378385    };
    379386
    380     addMap(tagRules, other.tagRules);
    381387    addMap(idRules, other.idRules);
    382388
     
    390396    pseudoClassesAffectingHost.add(other.pseudoClassesAffectingHost.begin(), other.pseudoClassesAffectingHost.end());
    391397    pseudoClassTypes.add(other.pseudoClassTypes.begin(), other.pseudoClassTypes.end());
     398
     399    addMap(hasPseudoClassRules, other.hasPseudoClassRules);
    392400
    393401    for (size_t i = 0; i < usedMatchElements.size(); ++i)
     
    414422    siblingRules.clear();
    415423    uncommonAttributeRules.clear();
    416     tagRules.clear();
    417424    idRules.clear();
    418425    classRules.clear();
     426    hasPseudoClassRules.clear();
    419427    classesAffectingHost.clear();
    420428    attributeRules.clear();
     
    431439    siblingRules.shrinkToFit();
    432440    uncommonAttributeRules.shrinkToFit();
    433     for (auto& rules : tagRules.values())
    434         rules->shrinkToFit();
    435441    for (auto& rules : idRules.values())
    436442        rules->shrinkToFit();
     
    441447    for (auto& rules : pseudoClassRules.values())
    442448        rules->shrinkToFit();
     449    for (auto& rules : hasPseudoClassRules.values())
     450        rules->shrinkToFit();
    443451}
    444452
  • trunk/Source/WebCore/style/RuleFeature.h

    r287772 r287973  
    106106    Vector<RuleAndSelector> uncommonAttributeRules;
    107107
    108     HashMap<AtomString, std::unique_ptr<RuleFeatureVector>> tagRules;
    109108    HashMap<AtomString, std::unique_ptr<RuleFeatureVector>> idRules;
    110109    HashMap<AtomString, std::unique_ptr<RuleFeatureVector>> classRules;
    111110    HashMap<AtomString, std::unique_ptr<Vector<RuleFeatureWithInvalidationSelector>>> attributeRules;
    112111    HashMap<PseudoClassInvalidationKey, std::unique_ptr<RuleFeatureVector>> pseudoClassRules;
     112    HashMap<PseudoClassInvalidationKey, std::unique_ptr<Vector<RuleFeatureWithInvalidationSelector>>> hasPseudoClassRules;
     113
    113114    HashSet<AtomString> classesAffectingHost;
    114115    HashSet<AtomString> attributesAffectingHost;
     
    125126        bool hasSiblingSelector { false };
    126127
    127         Vector<std::tuple<AtomString, MatchElement, IsNegation>, 32> tags;
    128         Vector<std::tuple<AtomString, MatchElement, IsNegation>, 32> ids;
    129         Vector<std::tuple<AtomString, MatchElement, IsNegation>, 32> classes;
    130         Vector<std::tuple<const CSSSelector*, MatchElement, IsNegation>, 32> attributes;
    131         Vector<std::tuple<const CSSSelector*, MatchElement, IsNegation>, 32> pseudoClasses;
     128        using InvalidationFeature = std::tuple<const CSSSelector*, MatchElement, IsNegation>;
     129
     130        Vector<InvalidationFeature> ids;
     131        Vector<InvalidationFeature> classes;
     132        Vector<InvalidationFeature> attributes;
     133        Vector<InvalidationFeature> pseudoClasses;
     134        Vector<InvalidationFeature> hasPseudoClasses;
    132135    };
    133     void recursivelyCollectFeaturesFromSelector(SelectorFeatures&, const CSSSelector&, MatchElement = MatchElement::Subject, IsNegation =  IsNegation::No);
     136    void recursivelyCollectFeaturesFromSelector(SelectorFeatures&, const CSSSelector&, MatchElement = MatchElement::Subject, IsNegation = IsNegation::No);
    134137};
    135138
  • trunk/Source/WebCore/style/StyleScopeRuleSets.cpp

    r287772 r287973  
    222222    m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules);
    223223
    224     m_tagInvalidationRuleSets.clear();
    225224    m_idInvalidationRuleSets.clear();
    226225    m_classInvalidationRuleSets.clear();
    227226    m_attributeInvalidationRuleSets.clear();
    228227    m_pseudoClassInvalidationRuleSets.clear();
     228    m_hasPseudoClassInvalidationRuleSets.clear();
    229229
    230230    m_cachedHasComplexSelectorsForStyleAttribute = std::nullopt;
     
    273273}
    274274
    275 const Vector<InvalidationRuleSet>* ScopeRuleSets::tagInvalidationRuleSets(const AtomString& tagName) const
    276 {
    277     return ensureInvalidationRuleSets(tagName, m_tagInvalidationRuleSets, m_features.tagRules);
    278 }
    279 
    280275const Vector<InvalidationRuleSet>* ScopeRuleSets::idInvalidationRuleSets(const AtomString& id) const
    281276{
     
    296291{
    297292    return ensureInvalidationRuleSets(pseudoClassKey, m_pseudoClassInvalidationRuleSets, m_features.pseudoClassRules);
     293}
     294
     295const Vector<InvalidationRuleSet>* ScopeRuleSets::hasPseudoClassInvalidationRuleSets(const PseudoClassInvalidationKey& key) const
     296{
     297    return ensureInvalidationRuleSets(key, m_hasPseudoClassInvalidationRuleSets, m_features.hasPseudoClassRules);
    298298}
    299299
  • trunk/Source/WebCore/style/StyleScopeRuleSets.h

    r287772 r287973  
    6363    RuleSet* uncommonAttribute() const { return m_uncommonAttributeRuleSet.get(); }
    6464
    65     const Vector<InvalidationRuleSet>* tagInvalidationRuleSets(const AtomString&) const;
    6665    const Vector<InvalidationRuleSet>* idInvalidationRuleSets(const AtomString&) const;
    6766    const Vector<InvalidationRuleSet>* classInvalidationRuleSets(const AtomString&) const;
    6867    const Vector<InvalidationRuleSet>* attributeInvalidationRuleSets(const AtomString&) const;
    6968    const Vector<InvalidationRuleSet>* pseudoClassInvalidationRuleSets(const PseudoClassInvalidationKey&) const;
    70 
    71     const Vector<InvalidationRuleSet>* invalidationRuleSetsForChildChange(const Element&);
     69    const Vector<InvalidationRuleSet>* hasPseudoClassInvalidationRuleSets(const PseudoClassInvalidationKey&) const;
    7270
    7371    bool hasComplexSelectorsForStyleAttribute() const;
     
    102100    mutable RefPtr<RuleSet> m_siblingRuleSet;
    103101    mutable RefPtr<RuleSet> m_uncommonAttributeRuleSet;
    104     mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_tagInvalidationRuleSets;
    105102    mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_idInvalidationRuleSets;
    106103    mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_classInvalidationRuleSets;
    107104    mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_attributeInvalidationRuleSets;
    108105    mutable HashMap<PseudoClassInvalidationKey, std::unique_ptr<Vector<InvalidationRuleSet>>> m_pseudoClassInvalidationRuleSets;
     106    mutable HashMap<PseudoClassInvalidationKey, std::unique_ptr<Vector<InvalidationRuleSet>>> m_hasPseudoClassInvalidationRuleSets;
    109107
    110108    mutable std::optional<bool> m_cachedHasComplexSelectorsForStyleAttribute;
Note: See TracChangeset for help on using the changeset viewer.