Bug 1334036 - Part 2: Restyle all elements with animations if there are non-animation restyles. draft
authorBoris Chiou <boris.chiou@gmail.com>
Wed, 17 May 2017 11:41:43 +0800
changeset 581935 c43c3ff1796e471c01a2b772c145b9ee56226e79
parent 581934 783b89bcc22cd660a670b0d0accfa90729919c8e
child 581936 be214edf900bb8fc36bf4efb0338a0c48633b107
push id59916
push userbmo:boris.chiou@gmail.com
push dateSat, 20 May 2017 06:48:29 +0000
bugs1334036
milestone55.0a1
Bug 1334036 - Part 2: Restyle all elements with animations if there are non-animation restyles. We restyle elements with non-animation restyles even if the animations are throttled. MozReview-Commit-ID: Exhd4qVx7su
dom/animation/EffectCompositor.cpp
--- a/dom/animation/EffectCompositor.cpp
+++ b/dom/animation/EffectCompositor.cpp
@@ -955,24 +955,30 @@ EffectCompositor::PreTraverse()
 }
 
 bool
 EffectCompositor::PreTraverseInSubtree(Element* aRoot)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mPresContext->RestyleManager()->IsServo());
 
+  // We need to force flush all throttled animations if there are any
+  // non-animation restyles.
+  bool flushThrottledRestyles = aRoot && aRoot->HasDirtyDescendantsForServo();
+
   using ElementsToRestyleIterType =
     nsDataHashtable<PseudoElementHashEntry, bool>::Iterator;
   auto getNeededRestyleTarget = [&](const ElementsToRestyleIterType& aIter)
                                 -> NonOwningAnimationTarget {
     NonOwningAnimationTarget returnTarget;
 
-    // Ignore throttled restyle.
-    if (!aIter.Data()) {
+    // If aIter.Data() is false, the element only requested a throttled
+    // (skippable) restyle, so we can skip it if flushThrottledRestyles is not
+    // true.
+    if (!flushThrottledRestyles && !aIter.Data()) {
       return returnTarget;
     }
 
     const NonOwningAnimationTarget& target = aIter.Key();
 
     // Ignore restyles that aren't in the flattened tree subtree rooted at
     // aRoot.
     if (aRoot &&
@@ -1065,22 +1071,31 @@ EffectCompositor::PreTraverse(dom::Eleme
   if (aPseudoType != CSSPseudoElementType::NotPseudo &&
       aPseudoType != CSSPseudoElementType::before &&
       aPseudoType != CSSPseudoElementType::after) {
     return found;
   }
 
   PseudoElementHashEntry::KeyType key = { aElement, aPseudoType };
 
+  // We need to flush all throttled animation restyles too if there are
+  // any non-animation restyles.
+  Element* elementToRestyle = GetElementToRestyle(aElement, aPseudoType);
+  bool flushThrottledRestyles = elementToRestyle &&
+                                elementToRestyle->HasDirtyDescendantsForServo();
+
   for (size_t i = 0; i < kCascadeLevelCount; ++i) {
     CascadeLevel cascadeLevel = CascadeLevel(i);
     auto& elementSet = mElementsToRestyle[cascadeLevel];
 
-    if (!elementSet.Get(key)) {
-      // Ignore throttled restyle and no restyle request.
+    // Skip if we don't have a restyle, or if we only have a throttled
+    // (skippable) restyle and we're not required to flush throttled restyles.
+    bool hasUnthrottledRestyle = false;
+    if (!elementSet.Get(key, &hasUnthrottledRestyle) ||
+        (!flushThrottledRestyles && !hasUnthrottledRestyle)) {
       continue;
     }
 
     mPresContext->RestyleManager()->AsServo()->
       PostRestyleEventForAnimations(aElement,
                                     cascadeLevel == CascadeLevel::Transitions
                                       ? eRestyle_CSSTransitions
                                       : eRestyle_CSSAnimations);