Bug 1341985 - Trigger the second traversal for updating CSS animations in the case of Servo_ResolveStyleLazily. r=heycam
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Fri, 10 Mar 2017 11:53:19 +0900
changeset 395015 ce96353dd04058f362e5f5f652ab1606225788da
parent 395014 ffe615ac2f20364ffa7e610c4cfa8d18e77c6b69
child 395016 03f4ba0942c7613968970eb34f875f367b83a80c
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1341985
milestone55.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 1341985 - Trigger the second traversal for updating CSS animations in the case of Servo_ResolveStyleLazily. r=heycam MozReview-Commit-ID: 7E4unP9M7FQ
dom/animation/EffectCompositor.cpp
dom/animation/EffectCompositor.h
layout/style/ServoStyleSet.cpp
--- a/dom/animation/EffectCompositor.cpp
+++ b/dom/animation/EffectCompositor.cpp
@@ -330,16 +330,18 @@ EffectCompositor::PostRestyleForAnimatio
       // In that case PreTraverse() will return true so that we know to do the
       // second traversal so we don't need to post any restyle requests to the
       // PresShell.
       return;
     } else if (!mPresContext->RestyleManager()->IsInStyleRefresh()) {
       // FIXME: stylo only supports Self and Subtree hints now, so we override
       // it for stylo if we are not in process of restyling.
       hint = eRestyle_Self | eRestyle_Subtree;
+    } else {
+      MOZ_ASSERT_UNREACHABLE("Should not request restyle");
     }
   }
   mPresContext->PresShell()->RestyleForAnimation(element, hint);
 }
 
 void
 EffectCompositor::PostRestyleForThrottledAnimations()
 {
@@ -991,49 +993,55 @@ EffectCompositor::PreTraverse()
       // Remove the element from the list of elements to restyle since we are
       // about to restyle it.
       iter.Remove();
     }
   }
   return foundElementsNeedingRestyle;
 }
 
-void
+bool
 EffectCompositor::PreTraverse(dom::Element* aElement, nsIAtom* aPseudoTagOrNull)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mPresContext->RestyleManager()->IsServo());
 
+  bool found = false;
   if (aPseudoTagOrNull &&
       aPseudoTagOrNull != nsGkAtoms::cssPseudoElementBeforeProperty &&
       aPseudoTagOrNull != nsGkAtoms::cssPseudoElementAfterProperty) {
-    return;
+    return found;
   }
 
   CSSPseudoElementType pseudoType =
     nsCSSPseudoElements::GetPseudoType(aPseudoTagOrNull,
                                        CSSEnabledState::eForAllContent);
 
   PseudoElementHashEntry::KeyType key = { aElement, pseudoType };
 
   for (auto& elementsToRestyle : mElementsToRestyle) {
     if (!elementsToRestyle.Get(key)) {
       // Ignore throttled restyle and no restyle request.
       continue;
     }
 
+    mPresContext->RestyleManager()->AsServo()->
+      PostRestyleEventForAnimations(aElement, eRestyle_Self);
+
     EffectSet* effects = EffectSet::GetEffectSet(aElement, pseudoType);
     if (effects) {
       for (KeyframeEffectReadOnly* effect : *effects) {
         effect->GetAnimation()->WillComposeStyle();
       }
     }
 
     elementsToRestyle.Remove(key);
+    found = true;
   }
+  return found;
 }
 
 // ---------------------------------------------------------
 //
 // Nested class: AnimationStyleRuleProcessor
 //
 // ---------------------------------------------------------
 
--- a/dom/animation/EffectCompositor.h
+++ b/dom/animation/EffectCompositor.h
@@ -228,17 +228,17 @@ public:
 
   // Do a bunch of stuff that we should avoid doing during the parallel
   // traversal (e.g. changing member variables) for all elements that we expect
   // to restyle on the next traversal.
   // Returns true if there are elements needing a restyle for animation.
   bool PreTraverse();
 
   // Similar to the above but only for the (pseudo-)element.
-  void PreTraverse(dom::Element* aElement, nsIAtom* aPseudoTagOrNull);
+  bool PreTraverse(dom::Element* aElement, nsIAtom* aPseudoTagOrNull);
 
 private:
   ~EffectCompositor() = default;
 
   // Rebuilds the animation rule corresponding to |aCascadeLevel| on the
   // EffectSet associated with the specified (pseudo-)element.
   static void ComposeAnimationRule(dom::Element* aElement,
                                    CSSPseudoElementType aPseudoType,
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -757,12 +757,23 @@ ServoStyleSet::ClearNonInheritingStyleCo
   }  
 }
 
 already_AddRefed<ServoComputedValues>
 ServoStyleSet::ResolveStyleLazily(Element* aElement, nsIAtom* aPseudoTag)
 {
   mPresContext->EffectCompositor()->PreTraverse(aElement, aPseudoTag);
 
-  return Servo_ResolveStyleLazily(aElement, aPseudoTag, mRawSet.get()).Consume();
+  MOZ_ASSERT(!sInServoTraversal);
+  sInServoTraversal = true;
+  RefPtr<ServoComputedValues> computedValues =
+    Servo_ResolveStyleLazily(aElement, aPseudoTag, mRawSet.get()).Consume();
+
+  if (mPresContext->EffectCompositor()->PreTraverse(aElement, aPseudoTag)) {
+    computedValues =
+      Servo_ResolveStyleLazily(aElement, aPseudoTag, mRawSet.get()).Consume();
+  }
+  sInServoTraversal = false;
+
+  return computedValues.forget();
 }
 
 bool ServoStyleSet::sInServoTraversal = false;