Bug 1324691 - Part 2: Move AnimationsWithDestroyedFrame into RestyleManagerBase. draft
authorBoris Chiou <boris.chiou@gmail.com>
Thu, 26 Jan 2017 17:05:53 +0800
changeset 467192 12f1364c9458ba311fb615c1a1f12acfaca7a535
parent 467191 e5db69d2c0467cf1629a945ef10097e3f4586425
child 467193 2c6439cf6bbb5349469d660df218b0a799fae490
push id43119
push userbmo:boris.chiou@gmail.com
push dateFri, 27 Jan 2017 10:05:05 +0000
bugs1324691
milestone54.0a1
Bug 1324691 - Part 2: Move AnimationsWithDestroyedFrame into RestyleManagerBase. Both ServoRestyleManager and RestyleManager need AnimationsWithDestroyedFrame, so move it to the base class. MozReview-Commit-ID: BswoDYm0gS1
layout/base/RestyleManager.cpp
layout/base/RestyleManager.h
layout/base/RestyleManagerBase.cpp
layout/base/RestyleManagerBase.h
layout/generic/nsFrame.cpp
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -88,17 +88,16 @@ RestyleManager::RestyleManager(nsPresCon
   , mDoRebuildAllStyleData(false)
   , mInRebuildAllStyleData(false)
   , mSkipAnimationRules(false)
   , mHavePendingNonAnimationRestyles(false)
   , mRebuildAllExtraHint(nsChangeHint(0))
   , mRebuildAllRestyleHint(nsRestyleHint(0))
   , mAnimationGeneration(0)
   , mReframingStyleContexts(nullptr)
-  , mAnimationsWithDestroyedFrame(nullptr)
   , mPendingRestyles(ELEMENT_HAS_PENDING_RESTYLE |
                      ELEMENT_IS_POTENTIAL_RESTYLE_ROOT |
                      ELEMENT_IS_CONDITIONAL_RESTYLE_ANCESTOR)
   , mIsProcessingRestyles(false)
 #ifdef RESTYLE_LOGGING
   , mLoggingDepth(0)
 #endif
 {
@@ -188,63 +187,16 @@ RestyleManager::ReframingStyleContexts::
   // Before we go away, we need to flush out any frame construction that
   // was enqueued, so that we initiate transitions.
   // Note that this is a little bit evil in that we're calling into code
   // that calls our member functions from our destructor, but it's at
   // the beginning of our destructor, so it shouldn't be too bad.
   mRestyleManager->PresContext()->FrameConstructor()->CreateNeededFrames();
 }
 
-RestyleManager::AnimationsWithDestroyedFrame::AnimationsWithDestroyedFrame(
-                                          RestyleManager* aRestyleManager)
-  : mRestyleManager(aRestyleManager)
-  , mRestorePointer(mRestyleManager->mAnimationsWithDestroyedFrame)
-{
-  MOZ_ASSERT(!mRestyleManager->mAnimationsWithDestroyedFrame,
-             "shouldn't construct recursively");
-  mRestyleManager->mAnimationsWithDestroyedFrame = this;
-}
-
-void
-RestyleManager::AnimationsWithDestroyedFrame::StopAnimationsForElementsWithoutFrames()
-{
-  StopAnimationsWithoutFrame(mContents, CSSPseudoElementType::NotPseudo);
-  StopAnimationsWithoutFrame(mBeforeContents, CSSPseudoElementType::before);
-  StopAnimationsWithoutFrame(mAfterContents, CSSPseudoElementType::after);
-}
-
-void
-RestyleManager::AnimationsWithDestroyedFrame::StopAnimationsWithoutFrame(
-  nsTArray<RefPtr<nsIContent>>& aArray,
-  CSSPseudoElementType aPseudoType)
-{
-  nsAnimationManager* animationManager =
-    mRestyleManager->PresContext()->AnimationManager();
-  nsTransitionManager* transitionManager =
-    mRestyleManager->PresContext()->TransitionManager();
-  for (nsIContent* content : aArray) {
-    if (content->GetPrimaryFrame()) {
-      continue;
-    }
-    dom::Element* element = content->AsElement();
-
-    animationManager->StopAnimationsForElement(element, aPseudoType);
-    transitionManager->StopTransitionsForElement(element, aPseudoType);
-
-    // All other animations should keep running but not running on the
-    // *compositor* at this point.
-    EffectSet* effectSet = EffectSet::GetEffectSet(element, aPseudoType);
-    if (effectSet) {
-      for (KeyframeEffectReadOnly* effect : *effectSet) {
-        effect->ResetIsRunningOnCompositor();
-      }
-    }
-  }
-}
-
 static inline dom::Element*
 ElementForStyleContext(nsIContent* aParentContent,
                        nsIFrame* aFrame,
                        CSSPseudoElementType aPseudoType);
 
 // Forwarded nsIDocumentObserver method, to handle restyling (and
 // passing the notification to the frame).
 nsresult
--- a/layout/base/RestyleManager.h
+++ b/layout/base/RestyleManager.h
@@ -45,18 +45,16 @@ public:
   explicit RestyleManager(nsPresContext* aPresContext);
 
 private:
   // Private destructor, to discourage deletion outside of Release():
   ~RestyleManager()
   {
     MOZ_ASSERT(!mReframingStyleContexts,
                "temporary member should be nulled out before destruction");
-    MOZ_ASSERT(!mAnimationsWithDestroyedFrame,
-               "leaving dangling pointers from AnimationsWithDestroyedFrame");
   }
 
 public:
   NS_INLINE_DECL_REFCOUNTING(mozilla::RestyleManager)
 
   // Forwarded nsIDocumentObserver method, to handle restyling (and
   // passing the notification to the frame).
   nsresult ContentStateChanged(nsIContent*   aContent,
@@ -216,72 +214,16 @@ public:
    * For the pseudo-elements, aContent must be the anonymous content
    * that we're creating for that pseudo-element, not the real element.
    */
   static bool
   TryInitiatingTransition(nsPresContext* aPresContext, nsIContent* aContent,
                           nsStyleContext* aOldStyleContext,
                           RefPtr<nsStyleContext>* aNewStyleContext /* inout */);
 
-  // AnimationsWithDestroyedFrame is used to stop animations and transitions
-  // on elements that have no frame at the end of the restyling process.
-  // It only lives during the restyling process.
-  class MOZ_STACK_CLASS AnimationsWithDestroyedFrame final {
-  public:
-    // Construct a AnimationsWithDestroyedFrame object.  The caller must
-    // ensure that aRestyleManager lives at least as long as the
-    // object.  (This is generally easy since the caller is typically a
-    // method of RestyleManager.)
-    explicit AnimationsWithDestroyedFrame(RestyleManager* aRestyleManager);
-
-    // This method takes the content node for the generated content for
-    // animation/transition on ::before and ::after, rather than the
-    // content node for the real element.
-    void Put(nsIContent* aContent, nsStyleContext* aStyleContext) {
-      MOZ_ASSERT(aContent);
-      CSSPseudoElementType pseudoType = aStyleContext->GetPseudoType();
-      if (pseudoType == CSSPseudoElementType::NotPseudo) {
-        mContents.AppendElement(aContent);
-      } else if (pseudoType == CSSPseudoElementType::before) {
-        MOZ_ASSERT(aContent->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentbefore);
-        mBeforeContents.AppendElement(aContent->GetParent());
-      } else if (pseudoType == CSSPseudoElementType::after) {
-        MOZ_ASSERT(aContent->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentafter);
-        mAfterContents.AppendElement(aContent->GetParent());
-      }
-    }
-
-    void StopAnimationsForElementsWithoutFrames();
-
-  private:
-    void StopAnimationsWithoutFrame(nsTArray<RefPtr<nsIContent>>& aArray,
-                                    CSSPseudoElementType aPseudoType);
-
-    RestyleManager* mRestyleManager;
-    AutoRestore<AnimationsWithDestroyedFrame*> mRestorePointer;
-
-    // Below three arrays might include elements that have already had their
-    // animations or transitions stopped.
-    //
-    // mBeforeContents and mAfterContents hold the real element rather than
-    // the content node for the generated content (which might change during
-    // a reframe)
-    nsTArray<RefPtr<nsIContent>> mContents;
-    nsTArray<RefPtr<nsIContent>> mBeforeContents;
-    nsTArray<RefPtr<nsIContent>> mAfterContents;
-  };
-
-  /**
-   * Return the current AnimationsWithDestroyedFrame struct, or null if we're
-   * not currently in a restyling operation.
-   */
-  AnimationsWithDestroyedFrame* GetAnimationsWithDestroyedFrame() {
-    return mAnimationsWithDestroyedFrame;
-  }
-
 private:
   void RestyleForEmptyChange(Element* aContainer);
 
 public:
   // Handle ContentInserted notifications.
   void ContentInserted(nsINode* aContainer, nsIContent* aChild)
   {
     RestyleForInsertOrChange(aContainer, aChild);
@@ -504,17 +446,16 @@ private:
   nsChangeHint mRebuildAllExtraHint;
   nsRestyleHint mRebuildAllRestyleHint;
 
   // The total number of animation flushes by this frame constructor.
   // Used to keep the layer and animation manager in sync.
   uint64_t mAnimationGeneration;
 
   ReframingStyleContexts* mReframingStyleContexts;
-  AnimationsWithDestroyedFrame* mAnimationsWithDestroyedFrame;
 
   RestyleTracker mPendingRestyles;
 
   // Are we currently in the middle of a call to ProcessRestyles?
   // This flag is used both as a debugging aid to assert that we are not
   // performing nested calls to ProcessPendingRestyles, as well as to ignore
   // redundant calls to IncrementAnimationGeneration.
   bool mIsProcessingRestyles;
--- a/layout/base/RestyleManagerBase.cpp
+++ b/layout/base/RestyleManagerBase.cpp
@@ -1369,9 +1369,59 @@ RestyleManagerBase::ProcessRestyledFrame
     }
 #endif
   }
 
   aChangeList.Clear();
   return NS_OK;
 }
 
+RestyleManagerBase::AnimationsWithDestroyedFrame
+                  ::AnimationsWithDestroyedFrame(
+                      RestyleManagerBase* aRestyleManager)
+  : mRestyleManager(aRestyleManager)
+  , mRestorePointer(mRestyleManager->mAnimationsWithDestroyedFrame)
+{
+  MOZ_ASSERT(!mRestyleManager->mAnimationsWithDestroyedFrame,
+             "shouldn't construct recursively");
+  mRestyleManager->mAnimationsWithDestroyedFrame = this;
+}
+
+void
+RestyleManagerBase::AnimationsWithDestroyedFrame
+                  ::StopAnimationsForElementsWithoutFrames()
+{
+  StopAnimationsWithoutFrame(mContents, CSSPseudoElementType::NotPseudo);
+  StopAnimationsWithoutFrame(mBeforeContents, CSSPseudoElementType::before);
+  StopAnimationsWithoutFrame(mAfterContents, CSSPseudoElementType::after);
+}
+
+void
+RestyleManagerBase::AnimationsWithDestroyedFrame
+                  ::StopAnimationsWithoutFrame(
+                      nsTArray<RefPtr<nsIContent>>& aArray,
+                      CSSPseudoElementType aPseudoType)
+{
+  nsAnimationManager* animationManager =
+    mRestyleManager->PresContext()->AnimationManager();
+  nsTransitionManager* transitionManager =
+    mRestyleManager->PresContext()->TransitionManager();
+  for (nsIContent* content : aArray) {
+    if (content->GetPrimaryFrame()) {
+      continue;
+    }
+    dom::Element* element = content->AsElement();
+
+    animationManager->StopAnimationsForElement(element, aPseudoType);
+    transitionManager->StopTransitionsForElement(element, aPseudoType);
+
+    // All other animations should keep running but not running on the
+    // *compositor* at this point.
+    EffectSet* effectSet = EffectSet::GetEffectSet(element, aPseudoType);
+    if (effectSet) {
+      for (KeyframeEffectReadOnly* effect : *effectSet) {
+        effect->ResetIsRunningOnCompositor();
+      }
+    }
+  }
+}
+
 } // namespace mozilla
--- a/layout/base/RestyleManagerBase.h
+++ b/layout/base/RestyleManagerBase.h
@@ -78,17 +78,80 @@ public:
   // ProcessRestyledFrames call in a view update batch and a script blocker.
   // This function does not call ProcessAttachedQueue() on the binding manager.
   // If the caller wants that to happen synchronously, it needs to handle that
   // itself.
   nsresult ProcessRestyledFrames(nsStyleChangeList& aChangeList);
 
   bool IsInStyleRefresh() const { return mInStyleRefresh; }
 
+  // AnimationsWithDestroyedFrame is used to stop animations and transitions
+  // on elements that have no frame at the end of the restyling process.
+  // It only lives during the restyling process.
+  class MOZ_STACK_CLASS AnimationsWithDestroyedFrame final {
+  public:
+    // Construct a AnimationsWithDestroyedFrame object.  The caller must
+    // ensure that aRestyleManager lives at least as long as the
+    // object.  (This is generally easy since the caller is typically a
+    // method of RestyleManager.)
+    explicit AnimationsWithDestroyedFrame(RestyleManagerBase* aRestyleManager);
+
+    // This method takes the content node for the generated content for
+    // animation/transition on ::before and ::after, rather than the
+    // content node for the real element.
+    void Put(nsIContent* aContent, nsStyleContext* aStyleContext) {
+      MOZ_ASSERT(aContent);
+      CSSPseudoElementType pseudoType = aStyleContext->GetPseudoType();
+      if (pseudoType == CSSPseudoElementType::NotPseudo) {
+        mContents.AppendElement(aContent);
+      } else if (pseudoType == CSSPseudoElementType::before) {
+        MOZ_ASSERT(aContent->NodeInfo()->NameAtom() ==
+                     nsGkAtoms::mozgeneratedcontentbefore);
+        mBeforeContents.AppendElement(aContent->GetParent());
+      } else if (pseudoType == CSSPseudoElementType::after) {
+        MOZ_ASSERT(aContent->NodeInfo()->NameAtom() ==
+                     nsGkAtoms::mozgeneratedcontentafter);
+        mAfterContents.AppendElement(aContent->GetParent());
+      }
+    }
+
+    void StopAnimationsForElementsWithoutFrames();
+
+  private:
+    void StopAnimationsWithoutFrame(nsTArray<RefPtr<nsIContent>>& aArray,
+                                    CSSPseudoElementType aPseudoType);
+
+    RestyleManagerBase* mRestyleManager;
+    AutoRestore<AnimationsWithDestroyedFrame*> mRestorePointer;
+
+    // Below three arrays might include elements that have already had their
+    // animations or transitions stopped.
+    //
+    // mBeforeContents and mAfterContents hold the real element rather than
+    // the content node for the generated content (which might change during
+    // a reframe)
+    nsTArray<RefPtr<nsIContent>> mContents;
+    nsTArray<RefPtr<nsIContent>> mBeforeContents;
+    nsTArray<RefPtr<nsIContent>> mAfterContents;
+  };
+
+  /**
+   * Return the current AnimationsWithDestroyedFrame struct, or null if we're
+   * not currently in a restyling operation.
+   */
+  AnimationsWithDestroyedFrame* GetAnimationsWithDestroyedFrame() {
+    return mAnimationsWithDestroyedFrame;
+  }
+
 protected:
+  ~RestyleManagerBase() {
+    MOZ_ASSERT(!mAnimationsWithDestroyedFrame,
+               "leaving dangling pointers from AnimationsWithDestroyedFrame");
+  }
+
   void ContentStateChangedInternal(Element* aElement,
                                    EventStates aStateMask,
                                    nsChangeHint* aOutChangeHint,
                                    nsRestyleHint* aOutRestyleHint);
 
   bool IsDisconnected() { return mPresContext == nullptr; }
 
   void IncrementHoverGeneration() {
@@ -159,13 +222,15 @@ protected:
    * the same.  When it is used in other contexts (i.e., where the next
    * continuation would already have the new style context), the current
    * style context should be passed.
    */
   static nsIFrame*
   GetNextContinuationWithSameStyle(nsIFrame* aFrame,
                                    nsStyleContext* aOldStyleContext,
                                    bool* aHaveMoreContinuations = nullptr);
+
+  AnimationsWithDestroyedFrame* mAnimationsWithDestroyedFrame = nullptr;
 };
 
 } // namespace mozilla
 
 #endif
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -696,18 +696,19 @@ nsFrame::DestroyFrom(nsIFrame* aDestruct
     }
   }
 
   if (HasCSSAnimations() || HasCSSTransitions() ||
       EffectSet::GetEffectSet(this)) {
     // If no new frame for this element is created by the end of the
     // restyling process, stop animations and transitions for this frame
     if (presContext->RestyleManager()->IsGecko()) {
-      RestyleManager::AnimationsWithDestroyedFrame* adf =
-        presContext->RestyleManager()->AsGecko()->GetAnimationsWithDestroyedFrame();
+      RestyleManagerBase::AnimationsWithDestroyedFrame* adf =
+        presContext->RestyleManager()->AsGecko()
+                   ->GetAnimationsWithDestroyedFrame();
       // AnimationsWithDestroyedFrame only lives during the restyling process.
       if (adf) {
         adf->Put(mContent, mStyleContext);
       }
     } else {
       NS_ERROR("stylo: ServoRestyleManager does not support animations yet");
     }
   }