Changeset 287973 in webkit
- Timestamp:
- Jan 12, 2022 11:31:50 PM (6 months ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 8 edited
-
ChangeLog (modified) (1 diff)
-
style/ChildChangeInvalidation.cpp (modified) (2 diffs)
-
style/PseudoClassChangeInvalidation.cpp (modified) (1 diff)
-
style/PseudoClassChangeInvalidation.h (modified) (1 diff)
-
style/RuleFeature.cpp (modified) (13 diffs)
-
style/RuleFeature.h (modified) (2 diffs)
-
style/StyleScopeRuleSets.cpp (modified) (3 diffs)
-
style/StyleScopeRuleSets.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r287970 r287973 1 2022-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 1 41 2022-01-12 John Wilander <wilander@apple.com> 2 42 -
trunk/Source/WebCore/style/ChildChangeInvalidation.cpp
r287325 r287973 29 29 #include "ElementTraversal.h" 30 30 #include "NodeRenderStyle.h" 31 #include "PseudoClassChangeInvalidation.h" 31 32 #include "ShadowRoot.h" 32 33 #include "SlotAssignment.h" … … 45 46 bool isDescendant = changedElement.parentElement() != &parentElement(); 46 47 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 47 56 auto addHasInvalidation = [&](const Vector<InvalidationRuleSet>* invalidationRuleSets) { 48 57 if (!invalidationRuleSets) 49 58 return; 50 59 for (auto& invalidationRuleSet : *invalidationRuleSets) { 51 if (! isHasPseudoClassMatchElement(invalidationRuleSet.matchElement))60 if (!canAffectAncestors(invalidationRuleSet.matchElement)) 52 61 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 }58 62 Invalidator::addToMatchElementRuleSets(matchElementRuleSets, invalidationRuleSet); 59 63 } 60 64 }; 61 65 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)); 82 68 83 69 Invalidator::invalidateWithMatchElementRuleSets(changedElement, matchElementRuleSets); -
trunk/Source/WebCore/style/PseudoClassChangeInvalidation.cpp
r287818 r287973 33 33 namespace Style { 34 34 35 staticVector<PseudoClassInvalidationKey, 4> makePseudoClassInvalidationKeys(CSSSelector::PseudoClassType pseudoClass, const Element& element)35 Vector<PseudoClassInvalidationKey, 4> makePseudoClassInvalidationKeys(CSSSelector::PseudoClassType pseudoClass, const Element& element) 36 36 { 37 37 Vector<PseudoClassInvalidationKey, 4> keys; -
trunk/Source/WebCore/style/PseudoClassChangeInvalidation.h
r287818 r287973 54 54 }; 55 55 56 Vector<PseudoClassInvalidationKey, 4> makePseudoClassInvalidationKeys(CSSSelector::PseudoClassType, const Element&); 57 56 58 inline void emplace(std::optional<PseudoClassChangeInvalidation>& invalidation, Element& element, std::initializer_list<std::pair<CSSSelector::PseudoClassType, bool>> pseudoClasses) 57 59 { -
trunk/Source/WebCore/style/RuleFeature.cpp
r287772 r287973 217 217 idsMatchingAncestorsInRules.add(selector->value()); 218 218 else if (isHasPseudoClassMatchElement(matchElement)) 219 selectorFeatures.ids.append({ selector ->value(), matchElement, isNegation });219 selectorFeatures.ids.append({ selector, matchElement, isNegation }); 220 220 } 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()) { 226 223 auto& canonicalLocalName = selector->attributeCanonicalLocalName(); 227 224 auto& localName = selector->attribute().localName(); … … 258 255 selectorFeatures.hasSiblingSelector = true; 259 256 recursivelyCollectFeaturesFromSelector(selectorFeatures, *subSelector, subSelectorMatchElement, subSelectorIsNegation); 257 258 if (selector->match() == CSSSelector::PseudoClass && selector->pseudoClassType() == CSSSelector::PseudoClassHas) 259 selectorFeatures.hasPseudoClasses.append({ subSelector, subSelectorMatchElement, isNegation }); 260 260 } 261 261 } … … 277 277 }; 278 278 279 static PseudoClassInvalidationKey makePseudoClassInvalidationKey(const CSSSelector& selector) 280 { 281 ASSERT(selector.match() == CSSSelector::PseudoClass); 282 283 auto pseudoClassType = selector.pseudoClassType(); 284 279 static PseudoClassInvalidationKey makePseudoClassInvalidationKey(CSSSelector::PseudoClassType pseudoClassType, const CSSSelector& selector) 280 { 285 281 AtomString className; 286 282 AtomString tagName; … … 304 300 return makePseudoClassInvalidationKey(pseudoClassType, InvalidationKeyType::Tag, tagName); 305 301 306 return makePseudoClassInvalidationKey( selector.pseudoClassType(), InvalidationKeyType::Universal);302 return makePseudoClassInvalidationKey(pseudoClassType, InvalidationKeyType::Universal); 307 303 }; 308 304 … … 318 314 auto addToMap = [&](auto& map, auto& entries, auto hostAffectingNames) { 319 315 for (auto& entry : entries) { 320 auto& [name, matchElement, isNegation] = entry; 316 auto& [selector, matchElement, isNegation] = entry; 317 auto& name = selector->value(); 318 321 319 map.ensure(name, [] { 322 320 return makeUnique<RuleFeatureVector>(); … … 332 330 }; 333 331 334 addToMap(tagRules, selectorFeatures.tags, nullptr);335 332 addToMap(idRules, selectorFeatures.ids, nullptr); 336 333 addToMap(classRules, selectorFeatures.classes, &classesAffectingHost); … … 348 345 for (auto& entry : selectorFeatures.pseudoClasses) { 349 346 auto [selector, matchElement, isNegation] = entry; 350 pseudoClassRules.ensure(makePseudoClassInvalidationKey( *selector), [] {347 pseudoClassRules.ensure(makePseudoClassInvalidationKey(selector->pseudoClassType(), *selector), [] { 351 348 return makeUnique<Vector<RuleFeature>>(); 352 349 }).iterator->value->append({ ruleData, matchElement, isNegation }); … … 355 352 pseudoClassesAffectingHost.add(selector->pseudoClassType()); 356 353 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 }); 357 364 358 365 setUsesMatchElement(matchElement); … … 378 385 }; 379 386 380 addMap(tagRules, other.tagRules);381 387 addMap(idRules, other.idRules); 382 388 … … 390 396 pseudoClassesAffectingHost.add(other.pseudoClassesAffectingHost.begin(), other.pseudoClassesAffectingHost.end()); 391 397 pseudoClassTypes.add(other.pseudoClassTypes.begin(), other.pseudoClassTypes.end()); 398 399 addMap(hasPseudoClassRules, other.hasPseudoClassRules); 392 400 393 401 for (size_t i = 0; i < usedMatchElements.size(); ++i) … … 414 422 siblingRules.clear(); 415 423 uncommonAttributeRules.clear(); 416 tagRules.clear();417 424 idRules.clear(); 418 425 classRules.clear(); 426 hasPseudoClassRules.clear(); 419 427 classesAffectingHost.clear(); 420 428 attributeRules.clear(); … … 431 439 siblingRules.shrinkToFit(); 432 440 uncommonAttributeRules.shrinkToFit(); 433 for (auto& rules : tagRules.values())434 rules->shrinkToFit();435 441 for (auto& rules : idRules.values()) 436 442 rules->shrinkToFit(); … … 441 447 for (auto& rules : pseudoClassRules.values()) 442 448 rules->shrinkToFit(); 449 for (auto& rules : hasPseudoClassRules.values()) 450 rules->shrinkToFit(); 443 451 } 444 452 -
trunk/Source/WebCore/style/RuleFeature.h
r287772 r287973 106 106 Vector<RuleAndSelector> uncommonAttributeRules; 107 107 108 HashMap<AtomString, std::unique_ptr<RuleFeatureVector>> tagRules;109 108 HashMap<AtomString, std::unique_ptr<RuleFeatureVector>> idRules; 110 109 HashMap<AtomString, std::unique_ptr<RuleFeatureVector>> classRules; 111 110 HashMap<AtomString, std::unique_ptr<Vector<RuleFeatureWithInvalidationSelector>>> attributeRules; 112 111 HashMap<PseudoClassInvalidationKey, std::unique_ptr<RuleFeatureVector>> pseudoClassRules; 112 HashMap<PseudoClassInvalidationKey, std::unique_ptr<Vector<RuleFeatureWithInvalidationSelector>>> hasPseudoClassRules; 113 113 114 HashSet<AtomString> classesAffectingHost; 114 115 HashSet<AtomString> attributesAffectingHost; … … 125 126 bool hasSiblingSelector { false }; 126 127 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; 132 135 }; 133 void recursivelyCollectFeaturesFromSelector(SelectorFeatures&, const CSSSelector&, MatchElement = MatchElement::Subject, IsNegation = IsNegation::No);136 void recursivelyCollectFeaturesFromSelector(SelectorFeatures&, const CSSSelector&, MatchElement = MatchElement::Subject, IsNegation = IsNegation::No); 134 137 }; 135 138 -
trunk/Source/WebCore/style/StyleScopeRuleSets.cpp
r287772 r287973 222 222 m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules); 223 223 224 m_tagInvalidationRuleSets.clear();225 224 m_idInvalidationRuleSets.clear(); 226 225 m_classInvalidationRuleSets.clear(); 227 226 m_attributeInvalidationRuleSets.clear(); 228 227 m_pseudoClassInvalidationRuleSets.clear(); 228 m_hasPseudoClassInvalidationRuleSets.clear(); 229 229 230 230 m_cachedHasComplexSelectorsForStyleAttribute = std::nullopt; … … 273 273 } 274 274 275 const Vector<InvalidationRuleSet>* ScopeRuleSets::tagInvalidationRuleSets(const AtomString& tagName) const276 {277 return ensureInvalidationRuleSets(tagName, m_tagInvalidationRuleSets, m_features.tagRules);278 }279 280 275 const Vector<InvalidationRuleSet>* ScopeRuleSets::idInvalidationRuleSets(const AtomString& id) const 281 276 { … … 296 291 { 297 292 return ensureInvalidationRuleSets(pseudoClassKey, m_pseudoClassInvalidationRuleSets, m_features.pseudoClassRules); 293 } 294 295 const Vector<InvalidationRuleSet>* ScopeRuleSets::hasPseudoClassInvalidationRuleSets(const PseudoClassInvalidationKey& key) const 296 { 297 return ensureInvalidationRuleSets(key, m_hasPseudoClassInvalidationRuleSets, m_features.hasPseudoClassRules); 298 298 } 299 299 -
trunk/Source/WebCore/style/StyleScopeRuleSets.h
r287772 r287973 63 63 RuleSet* uncommonAttribute() const { return m_uncommonAttributeRuleSet.get(); } 64 64 65 const Vector<InvalidationRuleSet>* tagInvalidationRuleSets(const AtomString&) const;66 65 const Vector<InvalidationRuleSet>* idInvalidationRuleSets(const AtomString&) const; 67 66 const Vector<InvalidationRuleSet>* classInvalidationRuleSets(const AtomString&) const; 68 67 const Vector<InvalidationRuleSet>* attributeInvalidationRuleSets(const AtomString&) const; 69 68 const Vector<InvalidationRuleSet>* pseudoClassInvalidationRuleSets(const PseudoClassInvalidationKey&) const; 70 71 const Vector<InvalidationRuleSet>* invalidationRuleSetsForChildChange(const Element&); 69 const Vector<InvalidationRuleSet>* hasPseudoClassInvalidationRuleSets(const PseudoClassInvalidationKey&) const; 72 70 73 71 bool hasComplexSelectorsForStyleAttribute() const; … … 102 100 mutable RefPtr<RuleSet> m_siblingRuleSet; 103 101 mutable RefPtr<RuleSet> m_uncommonAttributeRuleSet; 104 mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_tagInvalidationRuleSets;105 102 mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_idInvalidationRuleSets; 106 103 mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_classInvalidationRuleSets; 107 104 mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_attributeInvalidationRuleSets; 108 105 mutable HashMap<PseudoClassInvalidationKey, std::unique_ptr<Vector<InvalidationRuleSet>>> m_pseudoClassInvalidationRuleSets; 106 mutable HashMap<PseudoClassInvalidationKey, std::unique_ptr<Vector<InvalidationRuleSet>>> m_hasPseudoClassInvalidationRuleSets; 109 107 110 108 mutable std::optional<bool> m_cachedHasComplexSelectorsForStyleAttribute;
Note: See TracChangeset
for help on using the changeset viewer.