Bug 1334036 - Part 13: Factor out ProcessPendingRestyles. draft
authorBoris Chiou <boris.chiou@gmail.com>
Thu, 18 May 2017 17:19:21 +0800
changeset 580330 16592aaf3b26988a8f95697c33d59edbe3c21828
parent 580329 e2f95dd815ef8f881fa394888d6d437d4d967589
child 580331 1a7bbb1b5e32a1a1aa8e64daf447db39d58069fd
push id59516
push userbmo:boris.chiou@gmail.com
push dateThu, 18 May 2017 11:00:50 +0000
bugs1334036
milestone55.0a1
Bug 1334036 - Part 13: Factor out ProcessPendingRestyles. ProcessPendingRestyles and UpdateOnlyAnimationStyles do similar thing, so we factor them out to a new function, DoProcessPendingRestyles, which has one argument to indicate what kind of restyle we want. MozReview-Commit-ID: D1urkIeJCHQ
layout/base/ServoRestyleManager.cpp
layout/base/ServoRestyleManager.h
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -439,17 +439,18 @@ ServoRestyleManager::FrameForPseudoEleme
   }
 
   MOZ_CRASH("Unkown pseudo-element given to "
             "ServoRestyleManager::FrameForPseudoElement");
   return nullptr;
 }
 
 void
-ServoRestyleManager::ProcessPendingRestyles()
+ServoRestyleManager::DoProcessPendingRestyles(TraversalRestyleBehavior
+                                                aRestyleBehavior)
 {
   MOZ_ASSERT(PresContext()->Document(), "No document?  Pshaw!");
   MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(), "Missing a script blocker!");
   MOZ_ASSERT(!mInStyleRefresh, "Reentrant call?");
 
   if (MOZ_UNLIKELY(!PresContext()->PresShell()->DidInitialize())) {
     // PresShell::FlushPendingNotifications doesn't early-return in the case
     // where the PreShell hasn't yet been initialized (and therefore we haven't
@@ -461,98 +462,38 @@ ServoRestyleManager::ProcessPendingResty
 
   // Create a AnimationsWithDestroyedFrame during restyling process to
   // stop animations and transitions on elements that have no frame at the end
   // of the restyling process.
   AnimationsWithDestroyedFrame animationsWithDestroyedFrame(this);
 
   ServoStyleSet* styleSet = StyleSet();
   nsIDocument* doc = PresContext()->Document();
+  bool animationOnly = aRestyleBehavior ==
+                         TraversalRestyleBehavior::ForAnimationOnly;
 
   // Ensure the refresh driver is active during traversal to avoid mutating
   // 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) {
+  if (mHaveNonAnimationRestyles && !animationOnly) {
     ++mAnimationGeneration;
   }
 
-  while (styleSet->StyleDocument()) {
-    ClearSnapshots();
-
-    // 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);
+  while (animationOnly ? styleSet->StyleDocumentForAnimationOnly()
+                       : styleSet->StyleDocument()) {
+    if (!animationOnly) {
+      ClearSnapshots();
     }
 
-    // Process the change hints.
-    //
-    // Unfortunately, the frame constructor can generate new change hints while
-    // processing existing ones. We redirect those into a secondary queue and
-    // iterate until there's nothing left.
-    ReentrantChangeList newChanges;
-    mReentrantChanges = &newChanges;
-    while (!currentChanges.IsEmpty()) {
-      ProcessRestyledFrames(currentChanges);
-      MOZ_ASSERT(currentChanges.IsEmpty());
-      for (ReentrantChange& change: newChanges)  {
-        currentChanges.AppendChange(change.mContent->GetPrimaryFrame(),
-                                    change.mContent, change.mHint);
-      }
-      newChanges.Clear();
-    }
-    mReentrantChanges = nullptr;
-
-    IncrementRestyleGeneration();
-  }
-
-  ClearSnapshots();
-  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();
-}
-
-void
-ServoRestyleManager::UpdateOnlyAnimationStyles()
-{
-  MOZ_ASSERT(!mInStyleRefresh);
-
-  // Bug 1365855: We also need to implement this for SMIL.
-  bool doCSS = PresContext()->EffectCompositor()->HasPendingStyleUpdates();
-  if (!doCSS) {
-    return;
-  }
-
-  AnimationsWithDestroyedFrame animationsWithDestroyedFrame(this);
-
-  ServoStyleSet* styleSet = StyleSet();
-  nsIDocument* doc = PresContext()->Document();
-  MOZ_ASSERT(doc, "Invalid document");
-
-  // Ensure the refresh driver is active during traversal to avoid mutating
-  // mActiveTimer and mMostRecentRefresh time.
-  PresContext()->RefreshDriver()->MostRecentRefresh();
-
-  mInStyleRefresh = true;
-  while (styleSet->StyleDocumentForAnimationOnly()) {
     // 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);
     }
 
@@ -574,23 +515,48 @@ ServoRestyleManager::UpdateOnlyAnimation
     }
     mReentrantChanges = nullptr;
 
     IncrementRestyleGeneration();
   }
 
   FlushOverflowChangedTracker();
 
+  if (!animationOnly) {
+    ClearSnapshots();
+    styleSet->AssertTreeIsClean();
+    mHaveNonAnimationRestyles = false;
+  }
   mInStyleRefresh = false;
 
+  // Note: We are in the scope of |animationsWithDestroyedFrame|, so
+  //       |mAnimationsWithDestroyedFrame| is still valid.
   MOZ_ASSERT(mAnimationsWithDestroyedFrame);
   mAnimationsWithDestroyedFrame->StopAnimationsForElementsWithoutFrames();
 }
 
 void
+ServoRestyleManager::ProcessPendingRestyles()
+{
+  DoProcessPendingRestyles(TraversalRestyleBehavior::Normal);
+}
+
+void
+ServoRestyleManager::UpdateOnlyAnimationStyles()
+{
+  // Bug 1365855: We also need to implement this for SMIL.
+  bool doCSS = PresContext()->EffectCompositor()->HasPendingStyleUpdates();
+  if (!doCSS) {
+    return;
+  }
+
+  DoProcessPendingRestyles(TraversalRestyleBehavior::ForAnimationOnly);
+}
+
+void
 ServoRestyleManager::RestyleForInsertOrChange(nsINode* aContainer,
                                               nsIContent* aChild)
 {
   //
   // XXXbholley: We need the Gecko logic here to correctly restyle for things
   // like :empty and positional selectors (though we may not need to post
   // restyle events as agressively as the Gecko path does).
   //
--- a/layout/base/ServoRestyleManager.h
+++ b/layout/base/ServoRestyleManager.h
@@ -135,16 +135,18 @@ private:
                "style backend");
     return PresContext()->StyleSet()->AsServo();
   }
 
   const SnapshotTable& Snapshots() const { return mSnapshots; }
   void ClearSnapshots();
   ServoElementSnapshot& SnapshotFor(mozilla::dom::Element* aElement);
 
+  void DoProcessPendingRestyles(TraversalRestyleBehavior aRestyleBehavior);
+
   // We use a separate data structure from nsStyleChangeList because we need a
   // frame to create nsStyleChangeList entries, and the primary frame may not be
   // attached yet.
   struct ReentrantChange {
     nsCOMPtr<nsIContent> mContent;
     nsChangeHint mHint;
   };
   typedef AutoTArray<ReentrantChange, 10> ReentrantChangeList;