Bug 1343753 - Part 6: Use NonOwningAnimationTarget in UpdateTransitions. draft
authorBoris Chiou <boris.chiou@gmail.com>
Thu, 09 Mar 2017 14:29:13 +0800
changeset 496692 b6e0444876e6113c0a295688df545c4a90e03ff6
parent 496691 4c049ec62769c7a4c13aab863943b3eccb599cda
child 496693 7282c6462f4fb6817b982e5cc7133dccb8e4200d
push id48655
push userbmo:boris.chiou@gmail.com
push dateFri, 10 Mar 2017 12:40:00 +0000
bugs1343753
milestone55.0a1
Bug 1343753 - Part 6: Use NonOwningAnimationTarget in UpdateTransitions. We use NonOwningAnimationTarget, so we can avoid using nsStyleContext to get the pseudo type. MozReview-Commit-ID: GSwxebE12CH
dom/animation/EffectSet.cpp
dom/animation/EffectSet.h
layout/style/nsTransitionManager.cpp
layout/style/nsTransitionManager.h
--- a/dom/animation/EffectSet.cpp
+++ b/dom/animation/EffectSet.cpp
@@ -42,16 +42,22 @@ EffectSet::Traverse(nsCycleCollectionTra
 EffectSet::GetEffectSet(const dom::Element* aElement,
                         CSSPseudoElementType aPseudoType)
 {
   nsIAtom* propName = GetEffectSetPropertyAtom(aPseudoType);
   return static_cast<EffectSet*>(aElement->GetProperty(propName));
 }
 
 /* static */ EffectSet*
+EffectSet::GetEffectSet(const NonOwningAnimationTarget& aTarget)
+{
+  return GetEffectSet(aTarget.mElement, aTarget.mPseudoType);
+}
+
+/* static */ EffectSet*
 EffectSet::GetEffectSet(const nsIFrame* aFrame)
 {
   Maybe<NonOwningAnimationTarget> target =
     EffectCompositor::GetAnimationElementAndPseudoForFrame(aFrame);
 
   if (!target) {
     return nullptr;
   }
--- a/dom/animation/EffectSet.h
+++ b/dom/animation/EffectSet.h
@@ -54,16 +54,17 @@ public:
   static void PropertyDtor(void* aObject, nsIAtom* aPropertyName,
                            void* aPropertyValue, void* aData);
 
   // Methods for supporting cycle-collection
   void Traverse(nsCycleCollectionTraversalCallback& aCallback);
 
   static EffectSet* GetEffectSet(const dom::Element* aElement,
                                  CSSPseudoElementType aPseudoType);
+  static EffectSet* GetEffectSet(const NonOwningAnimationTarget& aTarget);
   static EffectSet* GetEffectSet(const nsIFrame* aFrame);
   static EffectSet* GetOrCreateEffectSet(dom::Element* aElement,
                                          CSSPseudoElementType aPseudoType);
   static void DestroyEffectSet(dom::Element* aElement,
                                CSSPseudoElementType aPseudoType);
 
   void AddEffect(dom::KeyframeEffectReadOnly& aEffect);
   void RemoveEffect(dom::KeyframeEffectReadOnly& aEffect);
--- a/layout/style/nsTransitionManager.cpp
+++ b/layout/style/nsTransitionManager.cpp
@@ -580,17 +580,19 @@ nsTransitionManager::StyleContextChanged
   }
 
   nsAutoAnimationMutationBatch mb(aElement->OwnerDoc());
 
   DebugOnly<bool> startedAny = false;
   // We don't have to update transitions if display:none, although we will
   // cancel them after restyling.
   if (!afterChangeStyle->IsInDisplayNoneSubtree()) {
-    startedAny = UpdateTransitions(disp, aElement, collection,
+    NonOwningAnimationTarget target = { aElement,
+                                        afterChangeStyle->GetPseudoType() };
+    startedAny = UpdateTransitions(disp, target, collection,
                                    aOldStyleContext, afterChangeStyle);
   }
 
   MOZ_ASSERT(!startedAny || collection,
              "must have element transitions if we started any transitions");
 
   EffectCompositor::CascadeLevel cascadeLevel =
     EffectCompositor::CascadeLevel::Transitions;
@@ -614,24 +616,25 @@ nsTransitionManager::StyleContextChanged
                                                               pseudoType,
                                                               cascadeLevel);
   }
 }
 
 bool
 nsTransitionManager::UpdateTransitions(
   const nsStyleDisplay* aDisp,
-  dom::Element* aElement,
+  NonOwningAnimationTarget& aTarget,
   CSSTransitionCollection*& aElementTransitions,
   nsStyleContext* aOldStyleContext,
   nsStyleContext* aNewStyleContext)
 {
   MOZ_ASSERT(aDisp, "Null nsStyleDisplay");
   MOZ_ASSERT(!aElementTransitions ||
-             aElementTransitions->mElement == aElement, "Element mismatch");
+             aElementTransitions->mElement == aTarget.mElement,
+             "Element mismatch");
 
   // Per http://lists.w3.org/Archives/Public/www-style/2009Aug/0109.html
   // I'll consider only the transitions from the number of items in
   // 'transition-property' on down, and later ones will override earlier
   // ones (tracked using |whichStarted|).
   bool startedAny = false;
   nsCSSPropertyIDSet whichStarted;
   for (uint32_t i = aDisp->mTransitionPropertyCount; i-- != 0; ) {
@@ -648,31 +651,31 @@ nsTransitionManager::UpdateTransitions(
       if (property == eCSSPropertyExtra_no_properties ||
           property == eCSSPropertyExtra_variable ||
           property == eCSSProperty_UNKNOWN) {
         // Nothing to do, but need to exclude this from cases below.
       } else if (property == eCSSPropertyExtra_all_properties) {
         for (nsCSSPropertyID p = nsCSSPropertyID(0);
              p < eCSSProperty_COUNT_no_shorthands;
              p = nsCSSPropertyID(p + 1)) {
-          ConsiderInitiatingTransition(p, t, aElement, aElementTransitions,
+          ConsiderInitiatingTransition(p, t, aTarget, aElementTransitions,
                                        aOldStyleContext, aNewStyleContext,
                                        &startedAny, &whichStarted);
         }
       } else if (nsCSSProps::IsShorthand(property)) {
         CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(subprop, property,
                                              CSSEnabledState::eForAllContent)
         {
-          ConsiderInitiatingTransition(*subprop, t, aElement,
+          ConsiderInitiatingTransition(*subprop, t, aTarget,
                                        aElementTransitions,
                                        aOldStyleContext, aNewStyleContext,
                                        &startedAny, &whichStarted);
         }
       } else {
-        ConsiderInitiatingTransition(property, t, aElement, aElementTransitions,
+        ConsiderInitiatingTransition(property, t, aTarget, aElementTransitions,
                                      aOldStyleContext, aNewStyleContext,
                                      &startedAny, &whichStarted);
       }
     }
   }
 
   // Stop any transitions for properties that are no longer in
   // 'transition-property', including finished transitions.
@@ -729,19 +732,17 @@ nsTransitionManager::UpdateTransitions(
           // duration are both zero, or because the new value is not
           // interpolable); a new transition would have anim->ToValue()
           // matching currentValue
           !ExtractNonDiscreteComputedValue(anim->TransitionProperty(),
                                            aNewStyleContext, currentValue) ||
           currentValue != anim->ToValue()) {
         // stop the transition
         if (anim->HasCurrentEffect()) {
-          EffectSet* effectSet =
-            EffectSet::GetEffectSet(aElement,
-                                    aNewStyleContext->GetPseudoType());
+          EffectSet* effectSet = EffectSet::GetEffectSet(aTarget);
           if (effectSet) {
             effectSet->UpdateAnimationGeneration(mPresContext);
           }
         }
         anim->CancelFromStyle();
         animations.RemoveElementAt(i);
       }
     } while (i != 0);
@@ -798,28 +799,29 @@ GetTransitionKeyframes(nsCSSPropertyID a
 
   return keyframes;
 }
 
 void
 nsTransitionManager::ConsiderInitiatingTransition(
   nsCSSPropertyID aProperty,
   const StyleTransition& aTransition,
-  dom::Element* aElement,
+  NonOwningAnimationTarget& aTarget,
   CSSTransitionCollection*& aElementTransitions,
   nsStyleContext* aOldStyleContext,
   nsStyleContext* aNewStyleContext,
   bool* aStartedAny,
   nsCSSPropertyIDSet* aWhichStarted)
 {
   // IsShorthand itself will assert if aProperty is not a property.
   MOZ_ASSERT(!nsCSSProps::IsShorthand(aProperty),
              "property out of range");
   NS_ASSERTION(!aElementTransitions ||
-               aElementTransitions->mElement == aElement, "Element mismatch");
+               aElementTransitions->mElement == aTarget.mElement,
+               "Element mismatch");
 
   // Ignore disabled properties. We can arrive here if the transition-property
   // is 'all' and the disabled property has a default value which derives value
   // from another property, e.g. color.
   if (!nsCSSProps::IsEnabled(aProperty, CSSEnabledState::eForAllContent)) {
     return;
   }
 
@@ -830,18 +832,16 @@ nsTransitionManager::ConsiderInitiatingT
     // http://lists.w3.org/Archives/Public/www-style/2009Aug/0109.html .
     return;
   }
 
   if (nsCSSProps::kAnimTypeTable[aProperty] == eStyleAnimType_None) {
     return;
   }
 
-  dom::DocumentTimeline* timeline = aElement->OwnerDoc()->Timeline();
-
   AnimationValue startValue, endValue;
   bool haveValues =
     ExtractNonDiscreteComputedValue(aProperty, aOldStyleContext, startValue) &&
     ExtractNonDiscreteComputedValue(aProperty, aNewStyleContext, endValue);
 
   bool haveChange = startValue != endValue;
 
   bool shouldAnimate =
@@ -895,32 +895,32 @@ nsTransitionManager::ConsiderInitiatingT
       // in-progress value (which is particularly easy to cause when we're
       // currently in the 'transition-delay').  It also might happen because we
       // just got a style change to a value that can't be interpolated.
       OwningCSSTransitionPtrArray& animations =
         aElementTransitions->mAnimations;
       animations[currentIndex]->CancelFromStyle();
       oldPT = nullptr; // Clear pointer so it doesn't dangle
       animations.RemoveElementAt(currentIndex);
-      EffectSet* effectSet =
-        EffectSet::GetEffectSet(aElement, aNewStyleContext->GetPseudoType());
+      EffectSet* effectSet = EffectSet::GetEffectSet(aTarget);
       if (effectSet) {
         effectSet->UpdateAnimationGeneration(mPresContext);
       }
 
       if (animations.IsEmpty()) {
         aElementTransitions->Destroy();
         // |aElementTransitions| is now a dangling pointer!
         aElementTransitions = nullptr;
       }
       // GetAnimationRule already called RestyleForAnimation.
     }
     return;
   }
 
+  dom::DocumentTimeline* timeline = aTarget.mElement->OwnerDoc()->Timeline();
   const nsTimingFunction &tf = aTransition.GetTimingFunction();
   float delay = aTransition.GetDelay();
   float duration = aTransition.GetDuration();
   if (duration < 0.0) {
     // The spec says a negative duration is treated as zero.
     duration = 0.0;
   }
 
@@ -971,48 +971,48 @@ nsTransitionManager::ConsiderInitiatingT
   }
 
   TimingParams timing =
     TimingParamsFromCSSParams(duration, delay,
                               1.0 /* iteration count */,
                               dom::PlaybackDirection::Normal,
                               dom::FillMode::Backwards);
 
-  // aElement is non-null here, so we emplace it directly.
+  // aTarget.mElement is non-null here, so we emplace it directly.
   Maybe<OwningAnimationTarget> target;
-  target.emplace(aElement, aNewStyleContext->GetPseudoType());
+  target.emplace(aTarget.mElement, aTarget.mPseudoType);
   KeyframeEffectParams effectOptions;
   RefPtr<ElementPropertyTransition> pt =
-    new ElementPropertyTransition(aElement->OwnerDoc(), target, timing,
+    new ElementPropertyTransition(aTarget.mElement->OwnerDoc(), target, timing,
                                   startForReversingTest, reversePortion,
                                   effectOptions);
 
   pt->SetKeyframes(GetTransitionKeyframes(aProperty,
                                           Move(startValue), Move(endValue), tf),
                    aNewStyleContext);
 
   MOZ_ASSERT(mPresContext->RestyleManager()->IsGecko(),
              "ServoRestyleManager should not use nsTransitionManager "
              "for transitions");
 
   RefPtr<CSSTransition> animation =
     new CSSTransition(mPresContext->Document()->GetScopeObject());
   animation->SetOwningElement(
-    OwningElementRef(*aElement, aNewStyleContext->GetPseudoType()));
+    OwningElementRef(*aTarget.mElement, aTarget.mPseudoType));
   animation->SetTimelineNoUpdate(timeline);
   animation->SetCreationSequence(
     mPresContext->RestyleManager()->AsGecko()->GetAnimationGeneration());
   animation->SetEffectFromStyle(pt);
   animation->PlayFromStyle();
 
   if (!aElementTransitions) {
     bool createdCollection = false;
     aElementTransitions =
       CSSTransitionCollection::GetOrCreateAnimationCollection(
-        aElement, aNewStyleContext->GetPseudoType(), &createdCollection);
+        aTarget.mElement, aTarget.mPseudoType, &createdCollection);
     if (!aElementTransitions) {
       MOZ_ASSERT(!createdCollection, "outparam should agree with return value");
       NS_WARNING("allocating collection failed");
       return;
     }
 
     if (createdCollection) {
       AddElementCollection(aElementTransitions);
@@ -1057,18 +1057,17 @@ nsTransitionManager::ConsiderInitiatingT
     animations[currentIndex] = animation;
   } else {
     if (!animations.AppendElement(animation)) {
       NS_WARNING("out of memory");
       return;
     }
   }
 
-  EffectSet* effectSet =
-    EffectSet::GetEffectSet(aElement, aNewStyleContext->GetPseudoType());
+  EffectSet* effectSet = EffectSet::GetEffectSet(aTarget);
   if (effectSet) {
     effectSet->UpdateAnimationGeneration(mPresContext);
   }
 
   *aStartedAny = true;
   aWhichStarted->AddProperty(aProperty);
 }
 
--- a/layout/style/nsTransitionManager.h
+++ b/layout/style/nsTransitionManager.h
@@ -412,25 +412,25 @@ protected:
     OwningCSSTransitionPtrArray;
 
   // Update the transitions. It'd start new, replace, or stop current
   // transitions if need. aDisp and aElement shouldn't be nullptr.
   // aElementTransitions is the collection of current transitions, and it
   // could be a nullptr if we don't have any transitions.
   bool
   UpdateTransitions(const nsStyleDisplay* aDisp,
-                    mozilla::dom::Element* aElement,
+                    mozilla::NonOwningAnimationTarget& aTarget,
                     CSSTransitionCollection*& aElementTransitions,
                     nsStyleContext* aOldStyleContext,
                     nsStyleContext* aNewStyleContext);
 
   void
   ConsiderInitiatingTransition(nsCSSPropertyID aProperty,
                                const mozilla::StyleTransition& aTransition,
-                               mozilla::dom::Element* aElement,
+                               mozilla::NonOwningAnimationTarget& aTarget,
                                CSSTransitionCollection*& aElementTransitions,
                                nsStyleContext* aOldStyleContext,
                                nsStyleContext* aNewStyleContext,
                                bool* aStartedAny,
                                nsCSSPropertyIDSet* aWhichStarted);
 
   bool mInAnimationOnlyStyleUpdate;