Modified: trunk/Source/WebCore/ChangeLog (229367 => 229368)
--- trunk/Source/WebCore/ChangeLog 2018-03-07 18:21:41 UTC (rev 229367)
+++ trunk/Source/WebCore/ChangeLog 2018-03-07 18:27:55 UTC (rev 229368)
@@ -1,3 +1,25 @@
+2018-03-07 Antti Koivisto <an...@apple.com>
+
+ checkForSiblingStyleChanges should use internal versions of the invalidation functions
+ https://bugs.webkit.org/show_bug.cgi?id=183405
+ <rdar://problem/38218310>
+
+ Reviewed by Zalan Bujtas.
+
+ Non-internal invalidateStyleForElement/Subtree() implement sibling combinator invalidation. Checking this
+ is only needed if the element in question changed somehow. In checkForSiblingStyleChanges we know that
+ another element changed and we really just want to invalidate.
+
+ * css/SelectorChecker.cpp:
+ (WebCore::isFirstOfType):
+ (WebCore::SelectorChecker::checkOne const):
+
+ Also make :first-of-type use ChildrenAffectedByForwardPositionalRules for invalidation similar to :last-of-type
+ for more correct invalidation.
+
+ * dom/Element.cpp:
+ (WebCore::checkForSiblingStyleChanges):
+
2018-03-07 Yusuke Suzuki <utatane....@gmail.com>
HTML `pattern` attribute should set `u` flag for regular expressions
Modified: trunk/Source/WebCore/css/SelectorChecker.cpp (229367 => 229368)
--- trunk/Source/WebCore/css/SelectorChecker.cpp 2018-03-07 18:21:41 UTC (rev 229367)
+++ trunk/Source/WebCore/css/SelectorChecker.cpp 2018-03-07 18:27:55 UTC (rev 229368)
@@ -103,11 +103,9 @@
return !ElementTraversal::nextSibling(element);
}
-static inline bool isFirstOfType(SelectorChecker::CheckingContext& checkingContext, const Element& element, const QualifiedName& type)
+static inline bool isFirstOfType(const Element& element, const QualifiedName& type)
{
for (const Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) {
- addStyleRelation(checkingContext, *sibling, Style::Relation::AffectsNextSibling);
-
if (sibling->hasTagName(type))
return false;
}
@@ -745,9 +743,9 @@
break;
case CSSSelector::PseudoClassFirstOfType:
// first-of-type matches the first element of its type
- if (element.parentElement()) {
- addStyleRelation(checkingContext, element, Style::Relation::AffectedByPreviousSibling);
- return isFirstOfType(checkingContext, element, element.tagQName());
+ if (auto* parentElement = element.parentElement()) {
+ addStyleRelation(checkingContext, *parentElement, Style::Relation::ChildrenAffectedByForwardPositionalRules);
+ return isFirstOfType(element, element.tagQName());
}
break;
case CSSSelector::PseudoClassLastChild:
@@ -785,11 +783,11 @@
case CSSSelector::PseudoClassOnlyOfType:
// FIXME: This selector is very slow.
if (Element* parentElement = element.parentElement()) {
- addStyleRelation(checkingContext, element, Style::Relation::AffectedByPreviousSibling);
+ addStyleRelation(checkingContext, *parentElement, Style::Relation::ChildrenAffectedByForwardPositionalRules);
addStyleRelation(checkingContext, *parentElement, Style::Relation::ChildrenAffectedByBackwardPositionalRules);
if (!parentElement->isFinishedParsingChildren())
return false;
- return isFirstOfType(checkingContext, element, element.tagQName()) && isLastOfType(element, element.tagQName());
+ return isFirstOfType(element, element.tagQName()) && isLastOfType(element, element.tagQName());
}
break;
case CSSSelector::PseudoClassMatches:
Modified: trunk/Source/WebCore/dom/Element.cpp (229367 => 229368)
--- trunk/Source/WebCore/dom/Element.cpp 2018-03-07 18:21:41 UTC (rev 229367)
+++ trunk/Source/WebCore/dom/Element.cpp 2018-03-07 18:27:55 UTC (rev 229368)
@@ -1480,6 +1480,16 @@
return styleResolver().styleForElement(*this, parentStyle);
}
+static void invalidateForSiblingCombinators(Element* sibling)
+{
+ for (; sibling; sibling = sibling->nextElementSibling()) {
+ if (sibling->styleIsAffectedByPreviousSibling())
+ sibling->invalidateStyleForSubtreeInternal();
+ if (!sibling->affectsNextSiblingElementStyle())
+ return;
+ }
+}
+
static void invalidateSiblingsIfNeeded(Element& element)
{
if (!element.affectsNextSiblingElementStyle())
@@ -1488,12 +1498,7 @@
if (parent && parent->styleValidity() >= Style::Validity::SubtreeInvalid)
return;
- for (auto* sibling = element.nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) {
- if (sibling->styleIsAffectedByPreviousSibling())
- sibling->invalidateStyleForSubtreeInternal();
- if (!sibling->affectsNextSiblingElementStyle())
- return;
- }
+ invalidateForSiblingCombinators(element.nextElementSibling());
}
void Element::invalidateStyle()
@@ -2027,7 +2032,7 @@
if (newFirstElement != elementAfterChange) {
auto* style = elementAfterChange->renderStyle();
if (!style || style->firstChildState())
- elementAfterChange->invalidateStyleForSubtree();
+ elementAfterChange->invalidateStyleForSubtreeInternal();
}
// We also have to handle node removal.
@@ -2034,7 +2039,7 @@
if (checkType == SiblingElementRemoved && newFirstElement == elementAfterChange && newFirstElement) {
auto* style = newFirstElement->renderStyle();
if (!style || !style->firstChildState())
- newFirstElement->invalidateStyleForSubtree();
+ newFirstElement->invalidateStyleForSubtreeInternal();
}
}
@@ -2047,7 +2052,7 @@
if (newLastElement != elementBeforeChange) {
auto* style = elementBeforeChange->renderStyle();
if (!style || style->lastChildState())
- elementBeforeChange->invalidateStyleForSubtree();
+ elementBeforeChange->invalidateStyleForSubtreeInternal();
}
// We also have to handle node removal. The parser callback case is similar to node removal as well in that we need to change the last child
@@ -2055,34 +2060,22 @@
if ((checkType == SiblingElementRemoved || checkType == FinishedParsingChildren) && newLastElement == elementBeforeChange && newLastElement) {
auto* style = newLastElement->renderStyle();
if (!style || !style->lastChildState())
- newLastElement->invalidateStyleForSubtree();
+ newLastElement->invalidateStyleForSubtreeInternal();
}
}
- if (elementAfterChange) {
- if (elementAfterChange->styleIsAffectedByPreviousSibling())
- elementAfterChange->invalidateStyleForSubtree();
- else if (elementAfterChange->affectsNextSiblingElementStyle()) {
- Element* elementToInvalidate = elementAfterChange;
- do {
- elementToInvalidate = elementToInvalidate->nextElementSibling();
- } while (elementToInvalidate && !elementToInvalidate->styleIsAffectedByPreviousSibling());
+ invalidateForSiblingCombinators(elementAfterChange);
- if (elementToInvalidate)
- elementToInvalidate->invalidateStyleForSubtree();
- }
- }
-
// We have to invalidate everything following the insertion point in the forward case, and everything before the insertion point in the
// backward case.
if (parent.childrenAffectedByForwardPositionalRules()) {
for (auto* next = elementAfterChange; next; next = next->nextElementSibling())
- next->invalidateStyleForSubtree();
+ next->invalidateStyleForSubtreeInternal();
}
// Backward positional selectors include nth-last-child, nth-last-of-type, last-of-type and only-of-type.
if (parent.childrenAffectedByBackwardPositionalRules()) {
for (auto* previous = elementBeforeChange; previous; previous = previous->previousElementSibling())
- previous->invalidateStyleForSubtree();
+ previous->invalidateStyleForSubtreeInternal();
}
}