Bug 1202512 - Part 3: Restyle elements with attribute/state changes if we find a conditionally restyled ancestor while selector matching up the tree. r=bzbarsky
authorCameron McCormack <cam@mcc.id.au>
Sat, 12 Sep 2015 19:08:10 +1000
changeset 294762 ab69f1450786e0bee780b9160b05f641ccf76258
parent 294761 9a682ef7ea95814fc7f5781593d346931807c5da
child 294763 0105583c5ffd21c11f0e9f7afbba83e3a9b59653
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs1202512
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1202512 - Part 3: Restyle elements with attribute/state changes if we find a conditionally restyled ancestor while selector matching up the tree. r=bzbarsky
layout/style/nsCSSRuleProcessor.cpp
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -2386,16 +2386,21 @@ nsCSSRuleProcessor::RestrictedSelectorMa
 
 /**
  * Flags for SelectorMatchesTree.
  */
 enum SelectorMatchesTreeFlags {
   // Whether we still have not found the closest ancestor link element and
   // thus have to check the current element for it.
   eLookForRelevantLink = 0x1,
+
+  // Whether SelectorMatchesTree should check for, and return true upon
+  // finding, an ancestor element that has an eRestyle_SomeDescendants
+  // restyle hint pending.
+  eMatchOnConditionalRestyleAncestor = 0x2,
 };
 
 static bool
 SelectorMatchesTree(Element* aPrevElement,
                     nsCSSSelector* aSelector,
                     TreeMatchContext& aTreeMatchContext,
                     SelectorMatchesTreeFlags aFlags)
 {
@@ -2463,16 +2468,30 @@ SelectorMatchesTree(Element* aPrevElemen
           // and sets it to null.
           aTreeMatchContext.mCurrentStyleScope = styleScope;
         }
       }
     }
     if (!element) {
       return false;
     }
+    if ((aFlags & eMatchOnConditionalRestyleAncestor) &&
+        element->HasFlag(ELEMENT_IS_CONDITIONAL_RESTYLE_ANCESTOR)) {
+      // If we're looking at an element that we already generated an
+      // eRestyle_SomeDescendants restyle hint for, then we should pretend
+      // that we matched here, because we don't know what the values of
+      // attributes on |element| were at the time we generated the
+      // eRestyle_SomeDescendants.  This causes AttributeEnumFunc and
+      // HasStateDependentStyle below to generate a restyle hint for the
+      // change we're currently looking at, as we don't know whether the LHS
+      // of the selector we looked up matches or not.  (We only pass in aFlags
+      // to cause us to look for eRestyle_SomeDescendants here under
+      // AttributeEnumFunc and HasStateDependentStyle.)
+      return true;
+    }
     const bool isRelevantLink = (aFlags & eLookForRelevantLink) &&
                                 nsCSSRuleProcessor::IsLink(element);
     NodeMatchContext nodeContext(EventStates(), isRelevantLink);
     if (isRelevantLink) {
       // If we find an ancestor of the matched node that is a link
       // during the matching process, then it's the relevant link (see
       // constructor call above).
       // Since we are still matching against selectors that contain
@@ -2752,17 +2771,17 @@ nsCSSRuleProcessor::HasStateDependentSty
           (!isPseudoElement ||
            StateSelectorMatches(aStatefulElement, selectorForPseudo,
                                 nodeContext, aData->mTreeMatchContext,
                                 selectorFlags, nullptr, aStateMask)) &&
           SelectorMatches(aData->mElement, selector, nodeContext,
                           aData->mTreeMatchContext, selectorFlags) &&
           SelectorMatchesTree(aData->mElement, selector->mNext,
                               aData->mTreeMatchContext,
-                              SelectorMatchesTreeFlags(0)))
+                              eMatchOnConditionalRestyleAncestor))
       {
         hint = nsRestyleHint(hint | possibleChange);
       }
     }
   }
   return hint;
 }
 
@@ -2889,17 +2908,17 @@ AttributeEnumFunc(nsCSSSelector* aSelect
   // regardless as it might give us new selectors to append to
   // mSelectorsForDescendants.
   NodeMatchContext nodeContext(EventStates(), false);
   if (((possibleChange & (~(aData->change) | eRestyle_SomeDescendants))) &&
       SelectorMatches(data->mElement, aSelector, nodeContext,
                       data->mTreeMatchContext, SelectorMatchesFlags::UNKNOWN) &&
       SelectorMatchesTree(data->mElement, aSelector->mNext,
                           data->mTreeMatchContext,
-                          SelectorMatchesTreeFlags(0))) {
+                          eMatchOnConditionalRestyleAncestor)) {
     aData->change = nsRestyleHint(aData->change | possibleChange);
     if (possibleChange & eRestyle_SomeDescendants) {
       aData->hintData.mSelectorsForDescendants.AppendElement(aRightmostSelector);
     }
   }
 }
 
 static MOZ_ALWAYS_INLINE void