Bug 1264125 part 6 - Queue CSS related event when setting null target effect. r?birtles draft
authorMantaroh Yoshinaga <mantaroh@gmail.com>
Tue, 20 Dec 2016 16:03:29 +0900
changeset 451400 681aa145dd88653ba3781cfd9ad68e3021724c96
parent 451399 c12e5b747c495205aa6a94940c7614244c3e4c86
child 451401 5b5d7a7f57fa84174ef317a20eec6df36fe8351e
push id39153
push usermantaroh@gmail.com
push dateTue, 20 Dec 2016 07:36:10 +0000
reviewersbirtles
bugs1264125
milestone53.0a1
Bug 1264125 part 6 - Queue CSS related event when setting null target effect. r?birtles MozReview-Commit-ID: 6KILkmNInbm
dom/animation/Animation.cpp
layout/style/nsTransitionManager.cpp
layout/style/nsTransitionManager.h
--- a/dom/animation/Animation.cpp
+++ b/dom/animation/Animation.cpp
@@ -724,18 +724,20 @@ Animation::AnimationTimeToTimeStamp(cons
   result = mTimeline->ToTimeStamp(timelineTime);
   return result;
 }
 
 TimeStamp
 Animation::ElapsedTimeToTimeStamp(
   const StickyTimeDuration& aElapsedTime) const
 {
-  return AnimationTimeToTimeStamp(aElapsedTime +
-                                  mEffect->SpecifiedTiming().mDelay);
+  TimeDuration delay = mEffect
+                       ? mEffect->SpecifiedTiming().mDelay
+                       : TimeDuration();
+  return AnimationTimeToTimeStamp(aElapsedTime + delay);
 }
 
 // https://w3c.github.io/web-animations/#silently-set-the-current-time
 void
 Animation::SilentlySetCurrentTime(const TimeDuration& aSeekTime)
 {
   if (!mHoldTime.IsNull() ||
       mStartTime.IsNull() ||
--- a/layout/style/nsTransitionManager.cpp
+++ b/layout/style/nsTransitionManager.cpp
@@ -177,57 +177,66 @@ CSSTransition::UpdateTiming(SeekFlag aSe
   }
 
   Animation::UpdateTiming(aSeekFlag, aSyncNotifyFlag);
 }
 
 void
 CSSTransition::QueueEvents(StickyTimeDuration aActiveTime)
 {
-  if (!mEffect ||
-      !mOwningElement.IsSet()) {
+  if (!mOwningElement.IsSet()) {
     return;
   }
 
   dom::Element* owningElement;
   CSSPseudoElementType owningPseudoType;
   mOwningElement.GetElement(owningElement, owningPseudoType);
   MOZ_ASSERT(owningElement, "Owning element should be set");
 
   nsPresContext* presContext = mOwningElement.GetRenderedPresContext();
   if (!presContext) {
     return;
   }
 
-  ComputedTiming computedTiming = mEffect->GetComputedTiming();
-  const StickyTimeDuration zeroDuration;
-  StickyTimeDuration intervalStartTime =
-    std::max(std::min(StickyTimeDuration(-mEffect->SpecifiedTiming().mDelay),
-                      computedTiming.mActiveDuration), zeroDuration);
-  StickyTimeDuration intervalEndTime =
-    std::max(std::min((EffectEnd() - mEffect->SpecifiedTiming().mDelay),
-                      computedTiming.mActiveDuration), zeroDuration);
+  const StickyTimeDuration zeroDuration = StickyTimeDuration();
+
+  TransitionPhase currentPhase;
+  StickyTimeDuration intervalStartTime;
+  StickyTimeDuration intervalEndTime;
+
+  if (!mEffect) {
+    currentPhase      = GetTransitionPhaseWithoutEffect();
+    intervalStartTime = zeroDuration;
+    intervalEndTime   = zeroDuration;
+  } else {
+    ComputedTiming computedTiming = mEffect->GetComputedTiming();
+
+    currentPhase = static_cast<TransitionPhase>(computedTiming.mPhase);
+    intervalStartTime =
+      std::max(std::min(StickyTimeDuration(-mEffect->SpecifiedTiming().mDelay),
+                        computedTiming.mActiveDuration), zeroDuration);
+    intervalEndTime =
+      std::max(std::min((EffectEnd() - mEffect->SpecifiedTiming().mDelay),
+                        computedTiming.mActiveDuration), zeroDuration);
+  }
 
   // TimeStamps to use for ordering the events when they are dispatched. We
   // use a TimeStamp so we can compare events produced by different elements,
   // perhaps even with different timelines.
   // The zero timestamp is for transitionrun events where we ignore the delay
   // for the purpose of ordering events.
   TimeStamp zeroTimeStamp   = AnimationTimeToTimeStamp(zeroDuration);
   TimeStamp startTimeStamp  = ElapsedTimeToTimeStamp(intervalStartTime);
   TimeStamp endTimeStamp    = ElapsedTimeToTimeStamp(intervalEndTime);
 
-  TransitionPhase currentPhase;
   if (mPendingState != PendingState::NotPending &&
       (mPreviousTransitionPhase == TransitionPhase::Idle ||
        mPreviousTransitionPhase == TransitionPhase::Pending))
   {
     currentPhase = TransitionPhase::Pending;
-  } else {
-    currentPhase = static_cast<TransitionPhase>(computedTiming.mPhase);
   }
 
   AutoTArray<TransitionEventParams, 3> events;
 
   // Handle cancel events firts
   if (mPreviousTransitionPhase != TransitionPhase::Idle &&
       currentPhase == TransitionPhase::Idle) {
     TimeStamp activeTimeStamp = ElapsedTimeToTimeStamp(aActiveTime);
@@ -315,16 +324,33 @@ CSSTransition::QueueEvents(StickyTimeDur
                                             evt.mMessage,
                                             TransitionProperty(),
                                             evt.mElapsedTime,
                                             evt.mTimeStamp,
                                             this));
   }
 }
 
+CSSTransition::TransitionPhase
+CSSTransition::GetTransitionPhaseWithoutEffect() const
+{
+  MOZ_ASSERT(!mEffect, "Should only be called when we do not have an effect");
+
+  Nullable<TimeDuration> currentTime = GetCurrentTime();
+  if (currentTime.IsNull()) {
+    return TransitionPhase::Idle;
+  }
+
+  // If we don't have a target effect, the duration will be zero so the phase is
+  // 'before' if the current time is less than zero.
+  return currentTime.Value() < TimeDuration()
+         ? TransitionPhase::Before
+         : TransitionPhase::After;
+}
+
 void
 CSSTransition::Tick()
 {
   Animation::Tick();
   QueueEvents();
 }
 
 nsCSSPropertyID
--- a/layout/style/nsTransitionManager.h
+++ b/layout/style/nsTransitionManager.h
@@ -238,16 +238,22 @@ protected:
   }
 
   // Animation overrides
   void UpdateTiming(SeekFlag aSeekFlag,
                     SyncNotifyFlag aSyncNotifyFlag) override;
 
   void QueueEvents(StickyTimeDuration activeTime = StickyTimeDuration());
 
+
+  enum class TransitionPhase;
+  // Return the TransitionPhase to use when the transition doesn't have a target
+  // effect.
+  TransitionPhase GetTransitionPhaseWithoutEffect() const;
+
   // The (pseudo-)element whose computed transition-property refers to this
   // transition (if any).
   //
   // This is used for determining the relative composite order of transitions
   // generated from CSS markup.
   //
   // Typically this will be the same as the target element of the keyframe
   // effect associated with this transition. However, it can differ in the