Diff
Modified: trunk/Source/WebCore/ChangeLog (287972 => 287973)
--- 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)
@@ -1,3 +1,43 @@
+2022-01-12 Antti Koivisto <an...@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:
+
2022-01-12 John Wilander <wilan...@apple.com>
PCM: Same-site triggering events should support ephemeral measurement
Modified: trunk/Source/WebCore/style/ChildChangeInvalidation.cpp (287972 => 287973)
--- 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)
@@ -28,6 +28,7 @@
#include "ElementTraversal.h"
#include "NodeRenderStyle.h"
+#include "PseudoClassChangeInvalidation.h"
#include "ShadowRoot.h"
#include "SlotAssignment.h"
#include "StyleResolver.h"
@@ -44,42 +45,27 @@
bool isDescendant = changedElement.parentElement() != &parentElement();
+ auto canAffectAncestors = [&](MatchElement matchElement) {
+ if (!isDescendant)
+ return true;
+ return matchElement == MatchElement::HasDescendant
+ || matchElement == MatchElement::HasSiblingDescendant
+ || matchElement == MatchElement::HasNonSubject;
+ };
+
auto addHasInvalidation = [&](const Vector<InvalidationRuleSet>* invalidationRuleSets) {
if (!invalidationRuleSets)
return;
for (auto& invalidationRuleSet : *invalidationRuleSets) {
- if (!isHasPseudoClassMatchElement(invalidationRuleSet.matchElement))
+ if (!canAffectAncestors(invalidationRuleSet.matchElement))
continue;
- 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;
- }
Invalidator::addToMatchElementRuleSets(matchElementRuleSets, invalidationRuleSet);
}
};
- auto tagName = changedElement.localName().convertToASCIILowercase();
- addHasInvalidation(ruleSets.tagInvalidationRuleSets(tagName));
+ for (auto key : makePseudoClassInvalidationKeys(CSSSelector::PseudoClassHas, changedElement))
+ addHasInvalidation(ruleSets.hasPseudoClassInvalidationRuleSets(key));
- 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));
- }
- }
-
Invalidator::invalidateWithMatchElementRuleSets(changedElement, matchElementRuleSets);
}
Modified: trunk/Source/WebCore/style/PseudoClassChangeInvalidation.cpp (287972 => 287973)
--- 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)
@@ -32,7 +32,7 @@
namespace WebCore {
namespace Style {
-static Vector<PseudoClassInvalidationKey, 4> makePseudoClassInvalidationKeys(CSSSelector::PseudoClassType pseudoClass, const Element& element)
+Vector<PseudoClassInvalidationKey, 4> makePseudoClassInvalidationKeys(CSSSelector::PseudoClassType pseudoClass, const Element& element)
{
Vector<PseudoClassInvalidationKey, 4> keys;
Modified: trunk/Source/WebCore/style/PseudoClassChangeInvalidation.h (287972 => 287973)
--- 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)
@@ -53,6 +53,8 @@
Invalidator::MatchElementRuleSets m_afterChangeRuleSets;
};
+Vector<PseudoClassInvalidationKey, 4> makePseudoClassInvalidationKeys(CSSSelector::PseudoClassType, const Element&);
+
inline void emplace(std::optional<PseudoClassChangeInvalidation>& invalidation, Element& element, std::initializer_list<std::pair<CSSSelector::PseudoClassType, bool>> pseudoClasses)
{
invalidation.emplace(element, pseudoClasses);
Modified: trunk/Source/WebCore/style/RuleFeature.cpp (287972 => 287973)
--- 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)
@@ -216,13 +216,10 @@
if (matchElement == MatchElement::Parent || matchElement == MatchElement::Ancestor)
idsMatchingAncestorsInRules.add(selector->value());
else if (isHasPseudoClassMatchElement(matchElement))
- selectorFeatures.ids.append({ selector->value(), matchElement, isNegation });
+ selectorFeatures.ids.append({ selector, matchElement, isNegation });
} else if (selector->match() == CSSSelector::Class)
- 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()) {
+ selectorFeatures.classes.append({ selector, matchElement, isNegation });
+ else if (selector->isAttributeSelector()) {
auto& canonicalLocalName = selector->attributeCanonicalLocalName();
auto& localName = selector->attribute().localName();
attributeCanonicalLocalNamesInRules.add(canonicalLocalName);
@@ -257,6 +254,9 @@
if (!selectorFeatures.hasSiblingSelector && selector->isSiblingSelector())
selectorFeatures.hasSiblingSelector = true;
recursivelyCollectFeaturesFromSelector(selectorFeatures, *subSelector, subSelectorMatchElement, subSelectorIsNegation);
+
+ if (selector->match() == CSSSelector::PseudoClass && selector->pseudoClassType() == CSSSelector::PseudoClassHas)
+ selectorFeatures.hasPseudoClasses.append({ subSelector, subSelectorMatchElement, isNegation });
}
}
@@ -276,12 +276,8 @@
};
};
-static PseudoClassInvalidationKey makePseudoClassInvalidationKey(const CSSSelector& selector)
+static PseudoClassInvalidationKey makePseudoClassInvalidationKey(CSSSelector::PseudoClassType pseudoClassType, const CSSSelector& selector)
{
- ASSERT(selector.match() == CSSSelector::PseudoClass);
-
- auto pseudoClassType = selector.pseudoClassType();
-
AtomString className;
AtomString tagName;
for (auto* simpleSelector = selector.firstInCompound(); simpleSelector; simpleSelector = simpleSelector->tagHistory()) {
@@ -303,7 +299,7 @@
if (!tagName.isEmpty() && tagName != starAtom())
return makePseudoClassInvalidationKey(pseudoClassType, InvalidationKeyType::Tag, tagName);
- return makePseudoClassInvalidationKey(selector.pseudoClassType(), InvalidationKeyType::Universal);
+ return makePseudoClassInvalidationKey(pseudoClassType, InvalidationKeyType::Universal);
};
void RuleFeatureSet::collectFeatures(const RuleData& ruleData)
@@ -317,7 +313,9 @@
auto addToMap = [&](auto& map, auto& entries, auto hostAffectingNames) {
for (auto& entry : entries) {
- auto& [name, matchElement, isNegation] = entry;
+ auto& [selector, matchElement, isNegation] = entry;
+ auto& name = selector->value();
+
map.ensure(name, [] {
return makeUnique<RuleFeatureVector>();
}).iterator->value->append({ ruleData, matchElement, isNegation });
@@ -331,7 +329,6 @@
}
};
- addToMap(tagRules, selectorFeatures.tags, nullptr);
addToMap(idRules, selectorFeatures.ids, nullptr);
addToMap(classRules, selectorFeatures.classes, &classesAffectingHost);
@@ -347,7 +344,7 @@
for (auto& entry : selectorFeatures.pseudoClasses) {
auto [selector, matchElement, isNegation] = entry;
- pseudoClassRules.ensure(makePseudoClassInvalidationKey(*selector), [] {
+ pseudoClassRules.ensure(makePseudoClassInvalidationKey(selector->pseudoClassType(), *selector), [] {
return makeUnique<Vector<RuleFeature>>();
}).iterator->value->append({ ruleData, matchElement, isNegation });
@@ -357,6 +354,16 @@
setUsesMatchElement(matchElement);
}
+
+ 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);
+ }
}
void RuleFeatureSet::add(const RuleFeatureSet& other)
@@ -377,7 +384,6 @@
}
};
- addMap(tagRules, other.tagRules);
addMap(idRules, other.idRules);
addMap(classRules, other.classRules);
@@ -390,6 +396,8 @@
pseudoClassesAffectingHost.add(other.pseudoClassesAffectingHost.begin(), other.pseudoClassesAffectingHost.end());
pseudoClassTypes.add(other.pseudoClassTypes.begin(), other.pseudoClassTypes.end());
+ addMap(hasPseudoClassRules, other.hasPseudoClassRules);
+
for (size_t i = 0; i < usedMatchElements.size(); ++i)
usedMatchElements[i] = usedMatchElements[i] || other.usedMatchElements[i];
@@ -413,9 +421,9 @@
contentAttributeNamesInRules.clear();
siblingRules.clear();
uncommonAttributeRules.clear();
- tagRules.clear();
idRules.clear();
classRules.clear();
+ hasPseudoClassRules.clear();
classesAffectingHost.clear();
attributeRules.clear();
attributesAffectingHost.clear();
@@ -430,8 +438,6 @@
{
siblingRules.shrinkToFit();
uncommonAttributeRules.shrinkToFit();
- for (auto& rules : tagRules.values())
- rules->shrinkToFit();
for (auto& rules : idRules.values())
rules->shrinkToFit();
for (auto& rules : classRules.values())
@@ -440,6 +446,8 @@
rules->shrinkToFit();
for (auto& rules : pseudoClassRules.values())
rules->shrinkToFit();
+ for (auto& rules : hasPseudoClassRules.values())
+ rules->shrinkToFit();
}
} // namespace Style
Modified: trunk/Source/WebCore/style/RuleFeature.h (287972 => 287973)
--- 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)
@@ -105,11 +105,12 @@
Vector<RuleAndSelector> siblingRules;
Vector<RuleAndSelector> uncommonAttributeRules;
- HashMap<AtomString, std::unique_ptr<RuleFeatureVector>> tagRules;
HashMap<AtomString, std::unique_ptr<RuleFeatureVector>> idRules;
HashMap<AtomString, std::unique_ptr<RuleFeatureVector>> classRules;
HashMap<AtomString, std::unique_ptr<Vector<RuleFeatureWithInvalidationSelector>>> attributeRules;
HashMap<PseudoClassInvalidationKey, std::unique_ptr<RuleFeatureVector>> pseudoClassRules;
+ HashMap<PseudoClassInvalidationKey, std::unique_ptr<Vector<RuleFeatureWithInvalidationSelector>>> hasPseudoClassRules;
+
HashSet<AtomString> classesAffectingHost;
HashSet<AtomString> attributesAffectingHost;
HashSet<CSSSelector::PseudoClassType, IntHash<CSSSelector::PseudoClassType>, WTF::StrongEnumHashTraits<CSSSelector::PseudoClassType>> pseudoClassesAffectingHost;
@@ -124,13 +125,15 @@
struct SelectorFeatures {
bool hasSiblingSelector { false };
- 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;
+ using InvalidationFeature = std::tuple<const CSSSelector*, MatchElement, IsNegation>;
+
+ Vector<InvalidationFeature> ids;
+ Vector<InvalidationFeature> classes;
+ Vector<InvalidationFeature> attributes;
+ Vector<InvalidationFeature> pseudoClasses;
+ Vector<InvalidationFeature> hasPseudoClasses;
};
- void recursivelyCollectFeaturesFromSelector(SelectorFeatures&, const CSSSelector&, MatchElement = MatchElement::Subject, IsNegation = IsNegation::No);
+ void recursivelyCollectFeaturesFromSelector(SelectorFeatures&, const CSSSelector&, MatchElement = MatchElement::Subject, IsNegation = IsNegation::No);
};
bool isHasPseudoClassMatchElement(MatchElement);
Modified: trunk/Source/WebCore/style/StyleScopeRuleSets.cpp (287972 => 287973)
--- 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)
@@ -221,11 +221,11 @@
m_siblingRuleSet = makeRuleSet(m_features.siblingRules);
m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules);
- m_tagInvalidationRuleSets.clear();
m_idInvalidationRuleSets.clear();
m_classInvalidationRuleSets.clear();
m_attributeInvalidationRuleSets.clear();
m_pseudoClassInvalidationRuleSets.clear();
+ m_hasPseudoClassInvalidationRuleSets.clear();
m_cachedHasComplexSelectorsForStyleAttribute = std::nullopt;
@@ -272,11 +272,6 @@
}).iterator->value.get();
}
-const Vector<InvalidationRuleSet>* ScopeRuleSets::tagInvalidationRuleSets(const AtomString& tagName) const
-{
- return ensureInvalidationRuleSets(tagName, m_tagInvalidationRuleSets, m_features.tagRules);
-}
-
const Vector<InvalidationRuleSet>* ScopeRuleSets::idInvalidationRuleSets(const AtomString& id) const
{
return ensureInvalidationRuleSets(id, m_idInvalidationRuleSets, m_features.idRules);
@@ -297,6 +292,11 @@
return ensureInvalidationRuleSets(pseudoClassKey, m_pseudoClassInvalidationRuleSets, m_features.pseudoClassRules);
}
+const Vector<InvalidationRuleSet>* ScopeRuleSets::hasPseudoClassInvalidationRuleSets(const PseudoClassInvalidationKey& key) const
+{
+ return ensureInvalidationRuleSets(key, m_hasPseudoClassInvalidationRuleSets, m_features.hasPseudoClassRules);
+}
+
bool ScopeRuleSets::hasComplexSelectorsForStyleAttribute() const
{
auto compute = [&] {
Modified: trunk/Source/WebCore/style/StyleScopeRuleSets.h (287972 => 287973)
--- 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)
@@ -62,14 +62,12 @@
RuleSet* sibling() const { return m_siblingRuleSet.get(); }
RuleSet* uncommonAttribute() const { return m_uncommonAttributeRuleSet.get(); }
- const Vector<InvalidationRuleSet>* tagInvalidationRuleSets(const AtomString&) const;
const Vector<InvalidationRuleSet>* idInvalidationRuleSets(const AtomString&) const;
const Vector<InvalidationRuleSet>* classInvalidationRuleSets(const AtomString&) const;
const Vector<InvalidationRuleSet>* attributeInvalidationRuleSets(const AtomString&) const;
const Vector<InvalidationRuleSet>* pseudoClassInvalidationRuleSets(const PseudoClassInvalidationKey&) const;
+ const Vector<InvalidationRuleSet>* hasPseudoClassInvalidationRuleSets(const PseudoClassInvalidationKey&) const;
- const Vector<InvalidationRuleSet>* invalidationRuleSetsForChildChange(const Element&);
-
bool hasComplexSelectorsForStyleAttribute() const;
void setUsesSharedUserStyle(bool b) { m_usesSharedUserStyle = b; }
@@ -101,11 +99,11 @@
mutable RuleFeatureSet m_features;
mutable RefPtr<RuleSet> m_siblingRuleSet;
mutable RefPtr<RuleSet> m_uncommonAttributeRuleSet;
- mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_tagInvalidationRuleSets;
mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_idInvalidationRuleSets;
mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_classInvalidationRuleSets;
mutable HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_attributeInvalidationRuleSets;
mutable HashMap<PseudoClassInvalidationKey, std::unique_ptr<Vector<InvalidationRuleSet>>> m_pseudoClassInvalidationRuleSets;
+ mutable HashMap<PseudoClassInvalidationKey, std::unique_ptr<Vector<InvalidationRuleSet>>> m_hasPseudoClassInvalidationRuleSets;
mutable std::optional<bool> m_cachedHasComplexSelectorsForStyleAttribute;