Title: [287818] trunk/Source/WebCore
Revision
287818
Author
an...@apple.com
Date
2022-01-09 01:01:48 -0800 (Sun, 09 Jan 2022)

Log Message

Use IsNegation bit for more efficient pseudo-class style invalidation
https://bugs.webkit.org/show_bug.cgi?id=235003

Reviewed by Simon Fraser.

We now know if a given invalidation ruleset is for negated context. We can use this to avoid
unnecessary traversal in pseudo-class invalidation, similar to what we already do with classes.

* dom/Document.cpp:
(WebCore::Document::updateHoverActiveState):
* dom/Element.cpp:
(WebCore::Element::setActive):
(WebCore::Element::setFocus):
(WebCore::Element::setHasFocusWithin):
(WebCore::Element::setHovered):
(WebCore::Element::setBeingDragged):

Provide the value for invalidation.

* html/HTMLFieldSetElement.cpp:
(WebCore::HTMLFieldSetElement::addInvalidDescendant):
(WebCore::HTMLFieldSetElement::removeInvalidDescendant):
* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::setAncestorDisabled):
(WebCore::HTMLFormControlElement::parseAttribute):
(WebCore::HTMLFormControlElement::updateValidity):
* html/HTMLFormElement.cpp:
(WebCore::HTMLFormElement::registerInvalidAssociatedFormControl):
(WebCore::HTMLFormElement::removeInvalidAssociatedFormControlIfNeeded):
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::setChecked):
* html/HTMLOptGroupElement.cpp:
(WebCore::HTMLOptGroupElement::parseAttribute):
* html/HTMLOptionElement.cpp:
(WebCore::HTMLOptionElement::parseAttribute):
(WebCore::HTMLOptionElement::setSelectedState):
* page/EventHandler.cpp:
(WebCore::EventHandler::internalKeyEvent):
* style/PseudoClassChangeInvalidation.cpp:
(WebCore::Style::PseudoClassChangeInvalidation::computeInvalidation):
(WebCore::Style::PseudoClassChangeInvalidation::collectRuleSets):

Setting a pseudo-class can only make a regular selector (not inside :not()) start matching.
Setting a pseudo-class can only make a negated selector (inside :not()) stop matching.
We only need to invalidate for the first case after the mutation has happened and for the second
case before it happens.

The cases are reversed when pseudo-class is unset.

(WebCore::Style::PseudoClassChangeInvalidation::invalidateBeforeChange):
(WebCore::Style::PseudoClassChangeInvalidation::invalidateAfterChange):
(WebCore::Style::PseudoClassChangeInvalidation::invalidateStyleWithRuleSets): Deleted.
* style/PseudoClassChangeInvalidation.h:
(WebCore::Style::emplace):

Add a helper since std::optional::emplace() is awkward to use with std::initializer_list.

(WebCore::Style::PseudoClassChangeInvalidation::PseudoClassChangeInvalidation):
(WebCore::Style::PseudoClassChangeInvalidation::~PseudoClassChangeInvalidation):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (287817 => 287818)


--- trunk/Source/WebCore/ChangeLog	2022-01-09 07:43:09 UTC (rev 287817)
+++ trunk/Source/WebCore/ChangeLog	2022-01-09 09:01:48 UTC (rev 287818)
@@ -1,3 +1,65 @@
+2022-01-09  Antti Koivisto  <an...@apple.com>
+
+        Use IsNegation bit for more efficient pseudo-class style invalidation
+        https://bugs.webkit.org/show_bug.cgi?id=235003
+
+        Reviewed by Simon Fraser.
+
+        We now know if a given invalidation ruleset is for negated context. We can use this to avoid
+        unnecessary traversal in pseudo-class invalidation, similar to what we already do with classes.
+
+        * dom/Document.cpp:
+        (WebCore::Document::updateHoverActiveState):
+        * dom/Element.cpp:
+        (WebCore::Element::setActive):
+        (WebCore::Element::setFocus):
+        (WebCore::Element::setHasFocusWithin):
+        (WebCore::Element::setHovered):
+        (WebCore::Element::setBeingDragged):
+
+        Provide the value for invalidation.
+
+        * html/HTMLFieldSetElement.cpp:
+        (WebCore::HTMLFieldSetElement::addInvalidDescendant):
+        (WebCore::HTMLFieldSetElement::removeInvalidDescendant):
+        * html/HTMLFormControlElement.cpp:
+        (WebCore::HTMLFormControlElement::setAncestorDisabled):
+        (WebCore::HTMLFormControlElement::parseAttribute):
+        (WebCore::HTMLFormControlElement::updateValidity):
+        * html/HTMLFormElement.cpp:
+        (WebCore::HTMLFormElement::registerInvalidAssociatedFormControl):
+        (WebCore::HTMLFormElement::removeInvalidAssociatedFormControlIfNeeded):
+        * html/HTMLInputElement.cpp:
+        (WebCore::HTMLInputElement::setChecked):
+        * html/HTMLOptGroupElement.cpp:
+        (WebCore::HTMLOptGroupElement::parseAttribute):
+        * html/HTMLOptionElement.cpp:
+        (WebCore::HTMLOptionElement::parseAttribute):
+        (WebCore::HTMLOptionElement::setSelectedState):
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::internalKeyEvent):
+        * style/PseudoClassChangeInvalidation.cpp:
+        (WebCore::Style::PseudoClassChangeInvalidation::computeInvalidation):
+        (WebCore::Style::PseudoClassChangeInvalidation::collectRuleSets):
+
+        Setting a pseudo-class can only make a regular selector (not inside :not()) start matching.
+        Setting a pseudo-class can only make a negated selector (inside :not()) stop matching.
+        We only need to invalidate for the first case after the mutation has happened and for the second
+        case before it happens.
+
+        The cases are reversed when pseudo-class is unset.
+
+        (WebCore::Style::PseudoClassChangeInvalidation::invalidateBeforeChange):
+        (WebCore::Style::PseudoClassChangeInvalidation::invalidateAfterChange):
+        (WebCore::Style::PseudoClassChangeInvalidation::invalidateStyleWithRuleSets): Deleted.
+        * style/PseudoClassChangeInvalidation.h:
+        (WebCore::Style::emplace):
+
+        Add a helper since std::optional::emplace() is awkward to use with std::initializer_list.
+
+        (WebCore::Style::PseudoClassChangeInvalidation::PseudoClassChangeInvalidation):
+        (WebCore::Style::PseudoClassChangeInvalidation::~PseudoClassChangeInvalidation):
+
 2022-01-08  Simon Fraser  <simon.fra...@apple.com>
 
         If the drop-shadow filter has no color, it should use the value of the color property

Modified: trunk/Source/WebCore/dom/Document.cpp (287817 => 287818)


--- trunk/Source/WebCore/dom/Document.cpp	2022-01-09 07:43:09 UTC (rev 287817)
+++ trunk/Source/WebCore/dom/Document.cpp	2022-01-09 09:01:48 UTC (rev 287818)
@@ -7457,17 +7457,17 @@
             elementsToSetHover.append(element);
     }
 
-    auto changeState = [](auto& elements, auto pseudoClassType, auto&& setter) {
+    auto changeState = [](auto& elements, auto pseudoClassType, auto value, auto&& setter) {
         if (elements.isEmpty())
             return;
 
-        Style::PseudoClassChangeInvalidation styleInvalidation { *elements.last(), pseudoClassType, Style::InvalidationScope::Descendants };
+        Style::PseudoClassChangeInvalidation styleInvalidation { *elements.last(), pseudoClassType, value, Style::InvalidationScope::Descendants };
 
         // We need to do descendant invalidation for each shadow tree separately as the style is per-scope.
         Vector<Style::PseudoClassChangeInvalidation> shadowDescendantStyleInvalidations;
         for (auto& element : elements) {
             if (hasShadowRootParent(*element))
-                shadowDescendantStyleInvalidations.append({ *element, pseudoClassType, Style::InvalidationScope::Descendants });
+                shadowDescendantStyleInvalidations.append({ *element, pseudoClassType, value, Style::InvalidationScope::Descendants });
         }
 
         for (auto& element : elements)
@@ -7474,16 +7474,16 @@
             setter(*element);
     };
 
-    changeState(elementsToClearActive, CSSSelector::PseudoClassActive, [](auto& element) {
+    changeState(elementsToClearActive, CSSSelector::PseudoClassActive, false, [](auto& element) {
         element.setActive(false, false, Style::InvalidationScope::SelfChildrenAndSiblings);
     });
-    changeState(elementsToSetActive, CSSSelector::PseudoClassActive, [](auto& element) {
+    changeState(elementsToSetActive, CSSSelector::PseudoClassActive, true, [](auto& element) {
         element.setActive(true, false, Style::InvalidationScope::SelfChildrenAndSiblings);
     });
-    changeState(elementsToClearHover, CSSSelector::PseudoClassHover, [](auto& element) {
+    changeState(elementsToClearHover, CSSSelector::PseudoClassHover, false, [](auto& element) {
         element.setHovered(false, Style::InvalidationScope::SelfChildrenAndSiblings);
     });
-    changeState(elementsToSetHover, CSSSelector::PseudoClassHover, [](auto& element) {
+    changeState(elementsToSetHover, CSSSelector::PseudoClassHover, true, [](auto& element) {
         element.setHovered(true, Style::InvalidationScope::SelfChildrenAndSiblings);
     });
 }

Modified: trunk/Source/WebCore/dom/Element.cpp (287817 => 287818)


--- trunk/Source/WebCore/dom/Element.cpp	2022-01-09 07:43:09 UTC (rev 287817)
+++ trunk/Source/WebCore/dom/Element.cpp	2022-01-09 09:01:48 UTC (rev 287818)
@@ -791,13 +791,13 @@
     return document().userActionElements().hasFocusWithin(*this);
 }
 
-void Element::setActive(bool flag, bool pause, Style::InvalidationScope invalidationScope)
+void Element::setActive(bool value, bool pause, Style::InvalidationScope invalidationScope)
 {
-    if (flag == active())
+    if (value == active())
         return;
     {
-        Style::PseudoClassChangeInvalidation styleInvalidation(*this, CSSSelector::PseudoClassActive, invalidationScope);
-        document().userActionElements().setActive(*this, flag);
+        Style::PseudoClassChangeInvalidation styleInvalidation(*this, CSSSelector::PseudoClassActive, value, invalidationScope);
+        document().userActionElements().setActive(*this, value);
     }
 
     if (!renderer())
@@ -843,59 +843,59 @@
     return element.isTextField() || element.isContentEditable() || is<HTMLSelectElement>(element);
 }
 
-void Element::setFocus(bool flag, FocusVisibility visibility)
+void Element::setFocus(bool value, FocusVisibility visibility)
 {
-    if (flag == focused())
+    if (value == focused())
         return;
     
-    Style::PseudoClassChangeInvalidation focusStyleInvalidation(*this, { CSSSelector::PseudoClassFocus, CSSSelector::PseudoClassFocusVisible });
-    document().userActionElements().setFocused(*this, flag);
+    Style::PseudoClassChangeInvalidation focusStyleInvalidation(*this, { { CSSSelector::PseudoClassFocus, value }, { CSSSelector::PseudoClassFocusVisible, value } });
+    document().userActionElements().setFocused(*this, value);
 
     // Shadow host with a slot that contain focused element is not considered focused.
     for (auto* root = containingShadowRoot(); root; root = root->host()->containingShadowRoot()) {
-        root->setContainsFocusedElement(flag);
+        root->setContainsFocusedElement(value);
         root->host()->invalidateStyle();
     }
 
     for (auto* element = this; element; element = element->parentElementInComposedTree())
-        element->setHasFocusWithin(flag);
+        element->setHasFocusWithin(value);
 
-    setHasFocusVisible(flag && (visibility == FocusVisibility::Visible || shouldAlwaysHaveFocusVisibleWhenFocused(*this)));
+    setHasFocusVisible(value && (visibility == FocusVisibility::Visible || shouldAlwaysHaveFocusVisibleWhenFocused(*this)));
 }
 
-void Element::setHasFocusVisible(bool flag)
+void Element::setHasFocusVisible(bool value)
 {
     if (!document().settings().focusVisibleEnabled())
         return;
 
 #if ASSERT_ENABLED
-    ASSERT(!flag || focused());
-    ASSERT(!focused() || !shouldAlwaysHaveFocusVisibleWhenFocused(*this) || flag);
+    ASSERT(!value || focused());
+    ASSERT(!focused() || !shouldAlwaysHaveFocusVisibleWhenFocused(*this) || value);
 #endif
 
-    if (hasFocusVisible() == flag)
+    if (hasFocusVisible() == value)
         return;
 
-    document().userActionElements().setHasFocusVisible(*this, flag);
+    document().userActionElements().setHasFocusVisible(*this, value);
 }
 
-void Element::setHasFocusWithin(bool flag)
+void Element::setHasFocusWithin(bool value)
 {
-    if (hasFocusWithin() == flag)
+    if (hasFocusWithin() == value)
         return;
     {
-        Style::PseudoClassChangeInvalidation styleInvalidation(*this, CSSSelector::PseudoClassFocusWithin);
-        document().userActionElements().setHasFocusWithin(*this, flag);
+        Style::PseudoClassChangeInvalidation styleInvalidation(*this, CSSSelector::PseudoClassFocusWithin, value);
+        document().userActionElements().setHasFocusWithin(*this, value);
     }
 }
 
-void Element::setHovered(bool flag, Style::InvalidationScope invalidationScope)
+void Element::setHovered(bool value, Style::InvalidationScope invalidationScope)
 {
-    if (flag == hovered())
+    if (value == hovered())
         return;
     {
-        Style::PseudoClassChangeInvalidation styleInvalidation(*this, CSSSelector::PseudoClassHover, invalidationScope);
-        document().userActionElements().setHovered(*this, flag);
+        Style::PseudoClassChangeInvalidation styleInvalidation(*this, CSSSelector::PseudoClassHover, value, invalidationScope);
+        document().userActionElements().setHovered(*this, value);
     }
 
     if (auto* style = renderStyle(); style && style->hasEffectiveAppearance())
@@ -902,13 +902,13 @@
         renderer()->theme().stateChanged(*renderer(), ControlStates::States::Hovered);
 }
 
-void Element::setBeingDragged(bool flag)
+void Element::setBeingDragged(bool value)
 {
-    if (flag == isBeingDragged())
+    if (value == isBeingDragged())
         return;
 
-    Style::PseudoClassChangeInvalidation styleInvalidation(*this, CSSSelector::PseudoClassDrag);
-    document().userActionElements().setBeingDragged(*this, flag);
+    Style::PseudoClassChangeInvalidation styleInvalidation(*this, CSSSelector::PseudoClassDrag, value);
+    document().userActionElements().setBeingDragged(*this, value);
 }
 
 inline ScrollAlignment toScrollAlignmentForInlineDirection(std::optional<ScrollLogicalPosition> position, WritingMode writingMode, bool isLTR)

Modified: trunk/Source/WebCore/html/HTMLFieldSetElement.cpp (287817 => 287818)


--- trunk/Source/WebCore/html/HTMLFieldSetElement.cpp	2022-01-09 07:43:09 UTC (rev 287817)
+++ trunk/Source/WebCore/html/HTMLFieldSetElement.cpp	2022-01-09 09:01:48 UTC (rev 287818)
@@ -183,7 +183,7 @@
 
     std::optional<Style::PseudoClassChangeInvalidation> styleInvalidation;
     if (m_invalidDescendants.computesEmpty())
-        styleInvalidation.emplace(*this, std::initializer_list<CSSSelector::PseudoClassType> { CSSSelector::PseudoClassValid, CSSSelector::PseudoClassInvalid });
+        emplace(styleInvalidation, *this, { { CSSSelector::PseudoClassValid, false }, { CSSSelector::PseudoClassInvalid, true } });
 
     m_invalidDescendants.add(invalidFormControlElement);
 }
@@ -195,7 +195,7 @@
 
     std::optional<Style::PseudoClassChangeInvalidation> styleInvalidation;
     if (m_invalidDescendants.computeSize() == 1)
-        styleInvalidation.emplace(*this, std::initializer_list<CSSSelector::PseudoClassType> { CSSSelector::PseudoClassValid, CSSSelector::PseudoClassInvalid });
+        emplace(styleInvalidation, *this, { { CSSSelector::PseudoClassValid, true }, { CSSSelector::PseudoClassInvalid, false } });
 
     m_invalidDescendants.remove(formControlElement);
 }

Modified: trunk/Source/WebCore/html/HTMLFormControlElement.cpp (287817 => 287818)


--- trunk/Source/WebCore/html/HTMLFormControlElement.cpp	2022-01-09 07:43:09 UTC (rev 287817)
+++ trunk/Source/WebCore/html/HTMLFormControlElement.cpp	2022-01-09 09:01:48 UTC (rev 287818)
@@ -147,7 +147,7 @@
     if (m_disabledByAncestorFieldset == isDisabled)
         return;
 
-    Style::PseudoClassChangeInvalidation disabledInvalidation(*this, { CSSSelector::PseudoClassDisabled, CSSSelector::PseudoClassEnabled });
+    Style::PseudoClassChangeInvalidation disabledInvalidation(*this, { { CSSSelector::PseudoClassDisabled, isDisabled }, { CSSSelector::PseudoClassEnabled, !isDisabled } });
 
     m_disabledByAncestorFieldset = isDisabled;
     disabledStateChanged();
@@ -161,7 +161,7 @@
         if (canBeActuallyDisabled()) {
             bool newDisabled = !value.isNull();
             if (m_disabled != newDisabled) {
-                Style::PseudoClassChangeInvalidation disabledInvalidation(*this, { CSSSelector::PseudoClassDisabled, CSSSelector::PseudoClassEnabled });
+                Style::PseudoClassChangeInvalidation disabledInvalidation(*this, { { CSSSelector::PseudoClassDisabled, newDisabled }, { CSSSelector::PseudoClassEnabled, !newDisabled } });
                 m_disabled = newDisabled;
                 disabledAttributeChanged();
             }
@@ -532,7 +532,7 @@
     bool newIsValid = this->computeValidity();
 
     if (newIsValid != m_isValid) {
-        Style::PseudoClassChangeInvalidation styleInvalidation(*this, { CSSSelector::PseudoClassValid, CSSSelector::PseudoClassInvalid });
+        Style::PseudoClassChangeInvalidation styleInvalidation(*this, { { CSSSelector::PseudoClassValid, newIsValid }, { CSSSelector::PseudoClassInvalid, !newIsValid } });
 
         m_isValid = newIsValid;
 

Modified: trunk/Source/WebCore/html/HTMLFormElement.cpp (287817 => 287818)


--- trunk/Source/WebCore/html/HTMLFormElement.cpp	2022-01-09 07:43:09 UTC (rev 287817)
+++ trunk/Source/WebCore/html/HTMLFormElement.cpp	2022-01-09 09:01:48 UTC (rev 287818)
@@ -668,7 +668,7 @@
 
     std::optional<Style::PseudoClassChangeInvalidation> styleInvalidation;
     if (m_invalidAssociatedFormControls.computesEmpty())
-        styleInvalidation.emplace(*this, std::initializer_list<CSSSelector::PseudoClassType> { CSSSelector::PseudoClassValid, CSSSelector::PseudoClassInvalid });
+        emplace(styleInvalidation, *this, { { CSSSelector::PseudoClassValid, false }, { CSSSelector::PseudoClassInvalid, true } });
 
     m_invalidAssociatedFormControls.add(const_cast<HTMLFormControlElement&>(formControlElement));
 }
@@ -680,7 +680,7 @@
 
     std::optional<Style::PseudoClassChangeInvalidation> styleInvalidation;
     if (m_invalidAssociatedFormControls.computeSize() == 1)
-        styleInvalidation.emplace(*this, std::initializer_list<CSSSelector::PseudoClassType> { CSSSelector::PseudoClassValid, CSSSelector::PseudoClassInvalid });
+        emplace(styleInvalidation, *this, { { CSSSelector::PseudoClassValid, true }, { CSSSelector::PseudoClassInvalid, false } });
 
     m_invalidAssociatedFormControls.remove(formControlElement);
 }

Modified: trunk/Source/WebCore/html/HTMLInputElement.cpp (287817 => 287818)


--- trunk/Source/WebCore/html/HTMLInputElement.cpp	2022-01-09 07:43:09 UTC (rev 287817)
+++ trunk/Source/WebCore/html/HTMLInputElement.cpp	2022-01-09 09:01:48 UTC (rev 287818)
@@ -975,17 +975,17 @@
     return m_inputType->isTextType();
 }
 
-void HTMLInputElement::setChecked(bool nowChecked)
+void HTMLInputElement::setChecked(bool isChecked)
 {
-    if (checked() == nowChecked)
+    if (checked() == isChecked)
         return;
 
-    m_inputType->willUpdateCheckedness(nowChecked);
+    m_inputType->willUpdateCheckedness(isChecked);
 
-    Style::PseudoClassChangeInvalidation checkedInvalidation(*this, CSSSelector::PseudoClassChecked);
+    Style::PseudoClassChangeInvalidation checkedInvalidation(*this, CSSSelector::PseudoClassChecked, isChecked);
 
     m_dirtyCheckednessFlag = true;
-    m_isChecked = nowChecked;
+    m_isChecked = isChecked;
 
     if (RadioButtonGroups* buttons = radioButtonGroups())
         buttons->updateCheckedState(*this);

Modified: trunk/Source/WebCore/html/HTMLOptGroupElement.cpp (287817 => 287818)


--- trunk/Source/WebCore/html/HTMLOptGroupElement.cpp	2022-01-09 07:43:09 UTC (rev 287817)
+++ trunk/Source/WebCore/html/HTMLOptGroupElement.cpp	2022-01-09 09:01:48 UTC (rev 287818)
@@ -89,11 +89,11 @@
     if (name == disabledAttr) {
         bool newDisabled = !value.isNull();
         if (m_isDisabled != newDisabled) {
-            Style::PseudoClassChangeInvalidation disabledInvalidation(*this, { CSSSelector::PseudoClassDisabled, CSSSelector::PseudoClassEnabled });
+            Style::PseudoClassChangeInvalidation disabledInvalidation(*this, { { CSSSelector::PseudoClassDisabled, newDisabled }, { CSSSelector::PseudoClassEnabled, !newDisabled } });
 
             Vector<Style::PseudoClassChangeInvalidation> optionInvalidation;
             for (auto& descendant : descendantsOfType<HTMLOptionElement>(*this))
-                optionInvalidation.append({ descendant, { CSSSelector::PseudoClassDisabled, CSSSelector::PseudoClassEnabled } });
+                optionInvalidation.append({ descendant, { { CSSSelector::PseudoClassDisabled, newDisabled }, { CSSSelector::PseudoClassEnabled, !newDisabled } } });
 
             m_isDisabled = newDisabled;
         }

Modified: trunk/Source/WebCore/html/HTMLOptionElement.cpp (287817 => 287818)


--- trunk/Source/WebCore/html/HTMLOptionElement.cpp	2022-01-09 07:43:09 UTC (rev 287817)
+++ trunk/Source/WebCore/html/HTMLOptionElement.cpp	2022-01-09 09:01:48 UTC (rev 287818)
@@ -178,7 +178,7 @@
     if (name == disabledAttr) {
         bool newDisabled = !value.isNull();
         if (m_disabled != newDisabled) {
-            Style::PseudoClassChangeInvalidation disabledInvalidation(*this, { CSSSelector::PseudoClassDisabled, CSSSelector::PseudoClassEnabled });
+            Style::PseudoClassChangeInvalidation disabledInvalidation(*this, { { CSSSelector::PseudoClassDisabled, newDisabled },  { CSSSelector::PseudoClassEnabled, !newDisabled } });
             m_disabled = newDisabled;
             if (renderer() && renderer()->style().hasEffectiveAppearance())
                 renderer()->theme().stateChanged(*renderer(), ControlStates::States::Enabled);
@@ -185,7 +185,7 @@
         }
     } else if (name == selectedAttr) {
         // FIXME: Use PseudoClassChangeInvalidation in other elements that implement matchesDefaultPseudoClass().
-        Style::PseudoClassChangeInvalidation defaultInvalidation(*this, CSSSelector::PseudoClassDefault);
+        Style::PseudoClassChangeInvalidation defaultInvalidation(*this, CSSSelector::PseudoClassDefault, !value.isNull());
         m_isDefault = !value.isNull();
 
         // FIXME: This doesn't match what the HTML specification says.
@@ -233,7 +233,7 @@
     if (m_isSelected == selected)
         return;
 
-    Style::PseudoClassChangeInvalidation checkedInvalidation(*this, CSSSelector::PseudoClassChecked);
+    Style::PseudoClassChangeInvalidation checkedInvalidation(*this, CSSSelector::PseudoClassChecked, selected);
 
     m_isSelected = selected;
 

Modified: trunk/Source/WebCore/page/EventHandler.cpp (287817 => 287818)


--- trunk/Source/WebCore/page/EventHandler.cpp	2022-01-09 07:43:09 UTC (rev 287817)
+++ trunk/Source/WebCore/page/EventHandler.cpp	2022-01-09 09:01:48 UTC (rev 287818)
@@ -3640,7 +3640,7 @@
         bool userHasInteractedViaKeyword = keydown->modifierKeys().isEmpty() || ((keydown->shiftKey() || keydown->capsLockKey()) && !initialKeyEvent.text().isEmpty());
 
         if (element.focused() && userHasInteractedViaKeyword) {
-            Style::PseudoClassChangeInvalidation focusVisibleStyleInvalidation(element, CSSSelector::PseudoClassFocusVisible);
+            Style::PseudoClassChangeInvalidation focusVisibleStyleInvalidation(element, CSSSelector::PseudoClassFocusVisible, true);
             element.setHasFocusVisible(true);
         }
     };

Modified: trunk/Source/WebCore/style/PseudoClassChangeInvalidation.cpp (287817 => 287818)


--- trunk/Source/WebCore/style/PseudoClassChangeInvalidation.cpp	2022-01-09 07:43:09 UTC (rev 287817)
+++ trunk/Source/WebCore/style/PseudoClassChangeInvalidation.cpp	2022-01-09 09:01:48 UTC (rev 287818)
@@ -51,7 +51,7 @@
     return keys;
 };
 
-void PseudoClassChangeInvalidation::computeInvalidation(CSSSelector::PseudoClassType pseudoClass, InvalidationScope invalidationScope)
+void PseudoClassChangeInvalidation::computeInvalidation(CSSSelector::PseudoClassType pseudoClass, bool value, InvalidationScope invalidationScope)
 {
     bool shouldInvalidateCurrent = false;
     bool mayAffectStyleInShadowTree = false;
@@ -72,10 +72,10 @@
         m_element.invalidateStyle();
 
     for (auto& key : makePseudoClassInvalidationKeys(pseudoClass, m_element))
-        collectRuleSets(key, invalidationScope);
+        collectRuleSets(key, value, invalidationScope);
 }
 
-void PseudoClassChangeInvalidation::collectRuleSets(const PseudoClassInvalidationKey& key, InvalidationScope invalidationScope)
+void PseudoClassChangeInvalidation::collectRuleSets(const PseudoClassInvalidationKey& key, bool value, InvalidationScope invalidationScope)
 {
     auto& ruleSets = m_element.styleResolver().ruleSets();
     auto* invalidationRuleSets = ruleSets.pseudoClassInvalidationRuleSets(key);
@@ -100,14 +100,24 @@
         if (!shouldInvalidate)
             continue;
 
-        Invalidator::addToMatchElementRuleSets(m_matchElementRuleSets, invalidationRuleSet);
+        bool invalidateBeforeChange = invalidationRuleSet.isNegation == IsNegation::Yes ? value : !value;
+        if (invalidateBeforeChange)
+            Invalidator::addToMatchElementRuleSets(m_beforeChangeRuleSets, invalidationRuleSet);
+        else
+            Invalidator::addToMatchElementRuleSets(m_afterChangeRuleSets, invalidationRuleSet);
     }
 }
 
-void PseudoClassChangeInvalidation::invalidateStyleWithRuleSets()
+void PseudoClassChangeInvalidation::invalidateBeforeChange()
 {
-    Invalidator::invalidateWithMatchElementRuleSets(m_element, m_matchElementRuleSets);
+    Invalidator::invalidateWithMatchElementRuleSets(m_element, m_beforeChangeRuleSets);
 }
 
+void PseudoClassChangeInvalidation::invalidateAfterChange()
+{
+    Invalidator::invalidateWithMatchElementRuleSets(m_element, m_afterChangeRuleSets);
 }
+
+
 }
+}

Modified: trunk/Source/WebCore/style/PseudoClassChangeInvalidation.h (287817 => 287818)


--- trunk/Source/WebCore/style/PseudoClassChangeInvalidation.h	2022-01-09 07:43:09 UTC (rev 287817)
+++ trunk/Source/WebCore/style/PseudoClassChangeInvalidation.h	2022-01-09 09:01:48 UTC (rev 287818)
@@ -35,23 +35,30 @@
 
 class PseudoClassChangeInvalidation {
 public:
-    PseudoClassChangeInvalidation(Element&, CSSSelector::PseudoClassType, InvalidationScope = InvalidationScope::All);
-    PseudoClassChangeInvalidation(Element&, std::initializer_list<CSSSelector::PseudoClassType>, InvalidationScope = InvalidationScope::All);
+    PseudoClassChangeInvalidation(Element&, CSSSelector::PseudoClassType, bool value, InvalidationScope = InvalidationScope::All);
+    PseudoClassChangeInvalidation(Element&, std::initializer_list<std::pair<CSSSelector::PseudoClassType, bool>>);
 
     ~PseudoClassChangeInvalidation();
 
 private:
-    void computeInvalidation(CSSSelector::PseudoClassType, Style::InvalidationScope);
-    void collectRuleSets(const PseudoClassInvalidationKey&, InvalidationScope);
-    void invalidateStyleWithRuleSets();
+    void computeInvalidation(CSSSelector::PseudoClassType, bool value, Style::InvalidationScope);
+    void collectRuleSets(const PseudoClassInvalidationKey&, bool value, InvalidationScope);
+    void invalidateBeforeChange();
+    void invalidateAfterChange();
 
     const bool m_isEnabled;
     Element& m_element;
 
-    Invalidator::MatchElementRuleSets m_matchElementRuleSets;
+    Invalidator::MatchElementRuleSets m_beforeChangeRuleSets;
+    Invalidator::MatchElementRuleSets m_afterChangeRuleSets;
 };
 
-inline PseudoClassChangeInvalidation::PseudoClassChangeInvalidation(Element& element, CSSSelector::PseudoClassType pseudoClassType, Style::InvalidationScope invalidationScope)
+inline void emplace(std::optional<PseudoClassChangeInvalidation>& invalidation, Element& element, std::initializer_list<std::pair<CSSSelector::PseudoClassType, bool>> pseudoClasses)
+{
+    invalidation.emplace(element, pseudoClasses);
+}
+
+inline PseudoClassChangeInvalidation::PseudoClassChangeInvalidation(Element& element, CSSSelector::PseudoClassType pseudoClass, bool value, Style::InvalidationScope invalidationScope)
     : m_isEnabled(element.needsStyleInvalidation())
     , m_element(element)
 
@@ -58,11 +65,11 @@
 {
     if (!m_isEnabled)
         return;
-    computeInvalidation(pseudoClassType, invalidationScope);
-    invalidateStyleWithRuleSets();
+    computeInvalidation(pseudoClass, value, invalidationScope);
+    invalidateBeforeChange();
 }
 
-inline PseudoClassChangeInvalidation::PseudoClassChangeInvalidation(Element& element, std::initializer_list<CSSSelector::PseudoClassType> pseudoClasses, Style::InvalidationScope invalidationScope)
+inline PseudoClassChangeInvalidation::PseudoClassChangeInvalidation(Element& element, std::initializer_list<std::pair<CSSSelector::PseudoClassType, bool>> pseudoClasses)
     : m_isEnabled(element.needsStyleInvalidation())
     , m_element(element)
 {
@@ -69,8 +76,8 @@
     if (!m_isEnabled)
         return;
     for (auto pseudoClass : pseudoClasses)
-        computeInvalidation(pseudoClass, invalidationScope);
-    invalidateStyleWithRuleSets();
+        computeInvalidation(pseudoClass.first, pseudoClass.second, Style::InvalidationScope::All);
+    invalidateBeforeChange();
 }
 
 inline PseudoClassChangeInvalidation::~PseudoClassChangeInvalidation()
@@ -77,7 +84,7 @@
 {
     if (!m_isEnabled)
         return;
-    invalidateStyleWithRuleSets();
+    invalidateAfterChange();
 }
 
 }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to