Bug 1355758 - Update RestyleManager::mAnimationGeneration for non-animation update. draft
authorBoris Chiou <boris.chiou@gmail.com>
Fri, 21 Apr 2017 16:44:17 +0800
changeset 566839 7db574a95b920c51cd6db2ec75cea89cf116f041
parent 566789 8e969cc9aff49f845678cba5b35d9dd8aa340f16
child 625447 88fdc06e0b133a54fcc9cf2539b419eb6e8337f1
push id55360
push userbmo:boris.chiou@gmail.com
push dateMon, 24 Apr 2017 03:10:22 +0000
bugs1355758
milestone55.0a1
Bug 1355758 - Update RestyleManager::mAnimationGeneration for non-animation update. We use RestyleManager::mAnimationGeneration as the animation index of a new created transition, and Element.getAnimations() uses this index to sort the order of transitions. We increase mAnimationGeneration one per restyle cycle if there is any non-animation update. MozReview-Commit-ID: KmirBzI7CXi
layout/base/ServoRestyleManager.cpp
layout/base/ServoRestyleManager.h
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -50,32 +50,38 @@ ServoRestyleManager::PostRestyleEvent(El
   // Processing change hints sometimes causes new change hints to be generated,
   // and very occasionally, additional restyle hints. We collect the change
   // hints manually to avoid re-traversing the DOM to find them.
   if (mReentrantChanges && !aRestyleHint) {
     mReentrantChanges->AppendElement(ReentrantChange { aElement, aMinChangeHint });
     return;
   }
 
+  if (aRestyleHint & ~eRestyle_AllHintsWithAnimations) {
+    mHaveNonAnimationRestyles = true;
+  }
+
   Servo_NoteExplicitHints(aElement, aRestyleHint, aMinChangeHint);
 }
 
 /* static */ void
 ServoRestyleManager::PostRestyleEventForAnimations(Element* aElement,
                                                    nsRestyleHint aRestyleHint)
 {
   Servo_NoteExplicitHints(aElement, aRestyleHint, nsChangeHint(0));
 }
 
 void
 ServoRestyleManager::RebuildAllStyleData(nsChangeHint aExtraHint,
                                          nsRestyleHint aRestyleHint)
 {
   StyleSet()->RebuildData();
 
+  mHaveNonAnimationRestyles = true;
+
   // NOTE(emilio): GeckoRestlyeManager does a sync style flush, which seems
   // not to be needed in my testing.
   //
   // If it is, we can just do a content flush and call ProcessPendingRestyles.
   if (Element* root = mPresContext->Document()->GetRootElement()) {
     PostRestyleEvent(root, aRestyleHint, aExtraHint);
   }
 
@@ -382,16 +388,19 @@ ServoRestyleManager::ProcessPendingResty
   // mActiveTimer and mMostRecentRefresh time.
   PresContext()->RefreshDriver()->MostRecentRefresh();
 
 
   // Perform the Servo traversal, and the post-traversal if required. We do this
   // in a loop because certain rare paths in the frame constructor (like
   // uninstalling XBL bindings) can trigger additional style validations.
   mInStyleRefresh = true;
+  if (mHaveNonAnimationRestyles) {
+    ++mAnimationGeneration;
+  }
   while (styleSet->StyleDocument()) {
     // Recreate style contexts, and queue up change hints (which also handle
     // lazy frame construction).
     nsStyleChangeList currentChanges(StyleBackendType::Servo);
     DocumentStyleRootIterator iter(doc);
     while (Element* root = iter.GetNextStyleRoot()) {
       ProcessPostTraversal(root, nullptr, styleSet, currentChanges);
     }
@@ -414,16 +423,17 @@ ServoRestyleManager::ProcessPendingResty
     }
     mReentrantChanges = nullptr;
 
     IncrementRestyleGeneration();
   }
 
   FlushOverflowChangedTracker();
 
+  mHaveNonAnimationRestyles = false;
   mInStyleRefresh = false;
   styleSet->AssertTreeIsClean();
 
   // Note: We are in the scope of |animationsWithDestroyedFrame|, so
   //       |mAnimationsWithDestroyedFrame| is still valid.
   MOZ_ASSERT(mAnimationsWithDestroyedFrame);
   mAnimationsWithDestroyedFrame->StopAnimationsForElementsWithoutFrames();
 }
--- a/layout/base/ServoRestyleManager.h
+++ b/layout/base/ServoRestyleManager.h
@@ -143,13 +143,20 @@ private:
     nsCOMPtr<nsIContent> mContent;
     nsChangeHint mHint;
   };
   typedef AutoTArray<ReentrantChange, 10> ReentrantChangeList;
 
   // Only non-null while processing change hints. See the comment in
   // ProcessPendingRestyles.
   ReentrantChangeList* mReentrantChanges;
+
+  // We use this flag to track if the current restyle contains any non-animation
+  // update, which triggers a normal restyle, and so there might be any new
+  // transition created later. Therefore, if this flag is true, we need to
+  // increase mAnimationGeneration before creating new transitions, so their
+  // creation sequence will be correct.
+  bool mHaveNonAnimationRestyles = false;
 };
 
 } // namespace mozilla
 
 #endif // mozilla_ServoRestyleManager_h