Diff
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (286134 => 286135)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2021-11-23 15:47:14 UTC (rev 286134)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2021-11-23 15:47:54 UTC (rev 286135)
@@ -1,3 +1,12 @@
+2021-11-23 Antti Koivisto <[email protected]>
+
+ [:has() pseudo-class] Basic invalidation support
+ https://bugs.webkit.org/show_bug.cgi?id=233443
+
+ Reviewed by Alan Bujtas.
+
+ * web-platform-tests/css/selectors/invalidation/attribute-or-elemental-selectors-in-has-expected.txt:
+
2021-11-20 Carlos Garcia Campos <[email protected]>
Report the initiating url instead of the redirected one
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/attribute-or-elemental-selectors-in-has-expected.txt (286134 => 286135)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/attribute-or-elemental-selectors-in-has-expected.txt 2021-11-23 15:47:14 UTC (rev 286134)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/attribute-or-elemental-selectors-in-has-expected.txt 2021-11-23 15:47:54 UTC (rev 286135)
@@ -2,15 +2,15 @@
PASS initial_color: div#div_subject.color
PASS initial_color: div#div_child.color
PASS initial_color: div#div_grandchild.color
-FAIL add .child to #div_child: div#div_subject.color assert_equals: expected "rgb(255, 0, 0)" but got "rgb(128, 128, 128)"
+PASS add .child to #div_child: div#div_subject.color
PASS remove .child from #div_child: div#div_subject.color
PASS add .child to #div_grandchild: div#div_subject.color
PASS remove .child from #div_grandchild: div#div_subject.color
-FAIL add .descendant to #div_child: div#div_subject.color assert_equals: expected "rgb(0, 128, 0)" but got "rgb(128, 128, 128)"
+PASS add .descendant to #div_child: div#div_subject.color
PASS remove .descendant from #div_child: div#div_subject.color
-FAIL add .descendant to #div_grandchild: div#div_subject.color assert_equals: expected "rgb(0, 128, 0)" but got "rgb(128, 128, 128)"
+PASS add .descendant to #div_grandchild: div#div_subject.color
PASS remove .descendant from #div_grandchild: div#div_subject.color
-FAIL set descendant to #div_grandchild[attrname]: div#div_subject.color assert_equals: expected "rgb(0, 0, 255)" but got "rgb(128, 128, 128)"
+PASS set descendant to #div_grandchild[attrname]: div#div_subject.color
PASS clear #div_grandchild[attrname]: div#div_subject.color
FAIL change #div_grandchild to #div_descendant: div#div_subject.color assert_equals: expected "rgb(255, 255, 0)" but got "rgb(128, 128, 128)"
PASS change #div_descendant to #div_grandchild: div#div_subject.color
Modified: trunk/Source/WebCore/ChangeLog (286134 => 286135)
--- trunk/Source/WebCore/ChangeLog 2021-11-23 15:47:14 UTC (rev 286134)
+++ trunk/Source/WebCore/ChangeLog 2021-11-23 15:47:54 UTC (rev 286135)
@@ -1,5 +1,33 @@
2021-11-23 Antti Koivisto <[email protected]>
+ [:has() pseudo-class] Basic invalidation support
+ https://bugs.webkit.org/show_bug.cgi?id=233443
+
+ Reviewed by Alan Bujtas.
+
+ Adde RuleSet based invalidation for :has(). This covers class/attribute/pseudo-class cases.
+
+ There is also a basic optimization that limits the invalidation scope based on :has() selector
+ matching child/descedant/sibling.
+
+ * style/RuleFeature.cpp:
+ (WebCore::Style::isSiblingOrSubject):
+ (WebCore::Style::isHasPseudoClassMatchElement):
+ (WebCore::Style::RuleFeatureSet::computeNextMatchElement):
+ (WebCore::Style::RuleFeatureSet::computeSubSelectorMatchElement):
+
+ Add new MatchElement types for :has and compute the value. This enables automatic
+ creation of the required invalidation rule sets.
+
+ (WebCore::Style::RuleFeatureSet::recursivelyCollectFeaturesFromSelector):
+ * style/RuleFeature.h:
+ * style/StyleInvalidator.cpp:
+ (WebCore::Style::Invalidator::invalidateStyleWithMatchElement):
+
+ Traverse appropriate parent/ancestors/siblings to invalidate.
+
+2021-11-23 Antti Koivisto <[email protected]>
+
Add :focus-visible to focus bucket in RuleSet
https://bugs.webkit.org/show_bug.cgi?id=233178
Modified: trunk/Source/WebCore/style/RuleFeature.cpp (286134 => 286135)
--- trunk/Source/WebCore/style/RuleFeature.cpp 2021-11-23 15:47:14 UTC (rev 286134)
+++ trunk/Source/WebCore/style/RuleFeature.cpp 2021-11-23 15:47:54 UTC (rev 286135)
@@ -43,6 +43,7 @@
case MatchElement::IndirectSibling:
case MatchElement::DirectSibling:
case MatchElement::AnySibling:
+ case MatchElement::HasSibling:
case MatchElement::Host:
return true;
case MatchElement::Parent:
@@ -49,6 +50,8 @@
case MatchElement::Ancestor:
case MatchElement::ParentSibling:
case MatchElement::AncestorSibling:
+ case MatchElement::HasChild:
+ case MatchElement::HasDescendant:
return false;
}
ASSERT_NOT_REACHED();
@@ -55,6 +58,18 @@
return false;
}
+static bool isHasPseudoClassMatchElement(MatchElement matchElement)
+{
+ switch (matchElement) {
+ case MatchElement::HasSibling:
+ case MatchElement::HasChild:
+ case MatchElement::HasDescendant:
+ return true;
+ default:
+ return false;
+ }
+}
+
RuleFeature::RuleFeature(const RuleData& ruleData, std::optional<MatchElement> matchElement)
: styleRule(&ruleData.styleRule())
, selectorIndex(ruleData.selectorIndex())
@@ -67,6 +82,9 @@
MatchElement RuleFeatureSet::computeNextMatchElement(MatchElement matchElement, CSSSelector::RelationType relation)
{
+ if (isHasPseudoClassMatchElement(matchElement))
+ return matchElement;
+
if (isSiblingOrSubject(matchElement)) {
switch (relation) {
case CSSSelector::Subselector:
@@ -111,10 +129,8 @@
return matchElement;
};
-MatchElement RuleFeatureSet::computeSubSelectorMatchElement(MatchElement matchElement, const CSSSelector& selector)
+MatchElement RuleFeatureSet::computeSubSelectorMatchElement(MatchElement matchElement, const CSSSelector& selector, const CSSSelector& childSelector)
{
- ASSERT(selector.selectorList());
-
if (selector.match() == CSSSelector::PseudoClass) {
auto type = selector.pseudoClassType();
// For :nth-child(n of .some-subselector) where an element change may affect other elements similar to sibling combinators.
@@ -124,6 +140,18 @@
// Similarly for :host().
if (type == CSSSelector::PseudoClassHost)
return MatchElement::Host;
+
+ if (type == CSSSelector::PseudoClassHas) {
+ auto hasMatchElement = MatchElement::Subject;
+ for (auto* simpleSelector = &childSelector; simpleSelector->tagHistory(); simpleSelector = simpleSelector->tagHistory())
+ hasMatchElement = computeNextMatchElement(hasMatchElement, simpleSelector->relation());
+
+ if (hasMatchElement == MatchElement::Parent)
+ return MatchElement::HasChild;
+ if (isSiblingOrSubject(hasMatchElement))
+ return MatchElement::HasSibling;
+ return MatchElement::HasDescendant;
+ }
}
if (selector.match() == CSSSelector::PseudoElement) {
// Similarly for ::slotted().
@@ -168,9 +196,8 @@
selectorFeatures.hasSiblingSelector = true;
if (const CSSSelectorList* selectorList = selector->selectorList()) {
- auto subSelectorMatchElement = computeSubSelectorMatchElement(matchElement, *selector);
-
for (const CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) {
+ auto subSelectorMatchElement = computeSubSelectorMatchElement(matchElement, *selector, *subSelector);
if (!selectorFeatures.hasSiblingSelector && selector->isSiblingSelector())
selectorFeatures.hasSiblingSelector = true;
recursivelyCollectFeaturesFromSelector(selectorFeatures, *subSelector, subSelectorMatchElement);
Modified: trunk/Source/WebCore/style/RuleFeature.h (286134 => 286135)
--- trunk/Source/WebCore/style/RuleFeature.h 2021-11-23 15:47:14 UTC (rev 286134)
+++ trunk/Source/WebCore/style/RuleFeature.h 2021-11-23 15:47:54 UTC (rev 286135)
@@ -36,7 +36,7 @@
class RuleData;
-enum class MatchElement : uint8_t { Subject, Parent, Ancestor, DirectSibling, IndirectSibling, AnySibling, ParentSibling, AncestorSibling, Host };
+enum class MatchElement : uint8_t { Subject, Parent, Ancestor, DirectSibling, IndirectSibling, AnySibling, ParentSibling, AncestorSibling, HasChild, HasDescendant, HasSibling, Host };
constexpr unsigned matchElementCount = static_cast<unsigned>(MatchElement::Host) + 1;
struct RuleFeature {
@@ -87,7 +87,7 @@
private:
static MatchElement computeNextMatchElement(MatchElement, CSSSelector::RelationType);
- static MatchElement computeSubSelectorMatchElement(MatchElement, const CSSSelector&);
+ static MatchElement computeSubSelectorMatchElement(MatchElement, const CSSSelector&, const CSSSelector& childSelector);
struct SelectorFeatures {
bool hasSiblingSelector { false };
Modified: trunk/Source/WebCore/style/StyleInvalidator.cpp (286134 => 286135)
--- trunk/Source/WebCore/style/StyleInvalidator.cpp 2021-11-23 15:47:14 UTC (rev 286134)
+++ trunk/Source/WebCore/style/StyleInvalidator.cpp 2021-11-23 15:47:54 UTC (rev 286135)
@@ -304,6 +304,31 @@
}
break;
}
+ case MatchElement::HasChild: {
+ if (auto* parent = element.parentElement())
+ invalidateIfNeeded(*parent, nullptr);
+ break;
+ }
+ case MatchElement::HasDescendant: {
+ Vector<Element*, 16> ancestors;
+ for (auto* parent = element.parentElement(); parent; parent = parent->parentElement())
+ ancestors.append(parent);
+
+ SelectorMatchingState selectorMatchingState;
+ for (auto* ancestor : makeReversedRange(ancestors)) {
+ invalidateIfNeeded(*ancestor, &selectorMatchingState);
+ selectorMatchingState.selectorFilter.pushParent(ancestor);
+ }
+ break;
+ }
+ case MatchElement::HasSibling: {
+ SelectorMatchingState selectorMatchingState;
+ for (auto* sibling = element.previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) {
+ selectorMatchingState.selectorFilter.popParentsUntil(element.parentElement());
+ invalidateStyleForDescendants(*sibling, &selectorMatchingState);
+ }
+ break;
+ }
case MatchElement::Host:
invalidateInShadowTreeIfNeeded(element);
break;