Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/dom/Animation.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef mozilla_dom_Animation_h
8
#define mozilla_dom_Animation_h
9
10
#include "nsWrapperCache.h"
11
#include "nsCycleCollectionParticipant.h"
12
#include "mozilla/AnimationPerformanceWarning.h"
13
#include "mozilla/Attributes.h"
14
#include "mozilla/CycleCollectedJSContext.h"
15
#include "mozilla/DOMEventTargetHelper.h"
16
#include "mozilla/EffectCompositor.h" // For EffectCompositor::CascadeLevel
17
#include "mozilla/LinkedList.h"
18
#include "mozilla/TimeStamp.h" // for TimeStamp, TimeDuration
19
#include "mozilla/dom/AnimationBinding.h" // for AnimationPlayState
20
#include "mozilla/dom/AnimationEffect.h"
21
#include "mozilla/dom/AnimationTimeline.h"
22
#include "mozilla/dom/Promise.h"
23
#include "nsCSSPropertyID.h"
24
#include "nsIGlobalObject.h"
25
26
// X11 has a #define for CurrentTime.
27
#ifdef CurrentTime
28
#undef CurrentTime
29
#endif
30
31
// GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
32
// GetTickCount().
33
#ifdef GetCurrentTime
34
#undef GetCurrentTime
35
#endif
36
37
struct JSContext;
38
class nsCSSPropertyIDSet;
39
class nsIDocument;
40
class nsIFrame;
41
42
namespace mozilla {
43
44
struct AnimationRule;
45
46
namespace dom {
47
48
class AsyncFinishNotification;
49
class CSSAnimation;
50
class CSSTransition;
51
52
class Animation
53
  : public DOMEventTargetHelper
54
  , public LinkedListElement<Animation>
55
{
56
protected:
57
0
  virtual ~Animation() {}
58
59
public:
60
  explicit Animation(nsIGlobalObject* aGlobal)
61
    : DOMEventTargetHelper(aGlobal)
62
    , mPlaybackRate(1.0)
63
    , mAnimationIndex(sNextAnimationIndex++)
64
    , mCachedChildIndex(-1)
65
    , mPendingState(PendingState::NotPending)
66
    , mFinishedAtLastComposeStyle(false)
67
    , mIsRelevant(false)
68
    , mFinishedIsResolved(false)
69
    , mSyncWithGeometricAnimations(false)
70
0
  {
71
0
  }
72
73
  NS_DECL_ISUPPORTS_INHERITED
74
  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Animation,
75
                                           DOMEventTargetHelper)
76
77
0
  nsIGlobalObject* GetParentObject() const { return GetOwnerGlobal(); }
78
  virtual JSObject* WrapObject(JSContext* aCx,
79
                               JS::Handle<JSObject*> aGivenProto) override;
80
81
0
  virtual CSSAnimation* AsCSSAnimation() { return nullptr; }
82
0
  virtual const CSSAnimation* AsCSSAnimation() const { return nullptr; }
83
0
  virtual CSSTransition* AsCSSTransition() { return nullptr; }
84
0
  virtual const CSSTransition* AsCSSTransition() const { return nullptr; }
85
86
  /**
87
   * Flag to pass to Play to indicate whether or not it should automatically
88
   * rewind the current time to the start point if the animation is finished.
89
   * For regular calls to play() from script we should do this, but when a CSS
90
   * animation's animation-play-state changes we shouldn't rewind the animation.
91
   */
92
  enum class LimitBehavior {
93
    AutoRewind,
94
    Continue
95
  };
96
97
  // Animation interface methods
98
  static already_AddRefed<Animation>
99
  Constructor(const GlobalObject& aGlobal,
100
              AnimationEffect* aEffect,
101
              const Optional<AnimationTimeline*>& aTimeline,
102
              ErrorResult& aRv);
103
0
  void GetId(nsAString& aResult) const { aResult = mId; }
104
  void SetId(const nsAString& aId);
105
0
  AnimationEffect* GetEffect() const { return mEffect; }
106
  void SetEffect(AnimationEffect* aEffect);
107
0
  AnimationTimeline* GetTimeline() const { return mTimeline; }
108
  void SetTimeline(AnimationTimeline* aTimeline);
109
0
  Nullable<TimeDuration> GetStartTime() const { return mStartTime; }
110
  void SetStartTime(const Nullable<TimeDuration>& aNewStartTime);
111
0
  Nullable<TimeDuration> GetCurrentTime() const {
112
0
    return GetCurrentTimeForHoldTime(mHoldTime);
113
0
  }
114
  void SetCurrentTime(const TimeDuration& aNewCurrentTime);
115
0
  double PlaybackRate() const { return mPlaybackRate; }
116
  void SetPlaybackRate(double aPlaybackRate);
117
  AnimationPlayState PlayState() const;
118
0
  bool Pending() const { return mPendingState != PendingState::NotPending; }
119
  virtual Promise* GetReady(ErrorResult& aRv);
120
  Promise* GetFinished(ErrorResult& aRv);
121
  void Cancel();
122
  void Finish(ErrorResult& aRv);
123
  virtual void Play(ErrorResult& aRv, LimitBehavior aLimitBehavior);
124
  virtual void Pause(ErrorResult& aRv);
125
  void Reverse(ErrorResult& aRv);
126
  void UpdatePlaybackRate(double aPlaybackRate);
127
  bool IsRunningOnCompositor() const;
128
  IMPL_EVENT_HANDLER(finish);
129
  IMPL_EVENT_HANDLER(cancel);
130
131
  // Wrapper functions for Animation DOM methods when called
132
  // from script.
133
  //
134
  // We often use the same methods internally and from script but when called
135
  // from script we (or one of our subclasses) perform extra steps such as
136
  // flushing style or converting the return type.
137
  Nullable<double> GetStartTimeAsDouble() const;
138
  void SetStartTimeAsDouble(const Nullable<double>& aStartTime);
139
  Nullable<double> GetCurrentTimeAsDouble() const;
140
  void SetCurrentTimeAsDouble(const Nullable<double>& aCurrentTime,
141
                              ErrorResult& aRv);
142
0
  virtual AnimationPlayState PlayStateFromJS() const { return PlayState(); }
143
0
  virtual bool PendingFromJS() const { return Pending(); }
144
  virtual void PlayFromJS(ErrorResult& aRv)
145
0
  {
146
0
    Play(aRv, LimitBehavior::AutoRewind);
147
0
  }
148
  /**
149
   * PauseFromJS is currently only here for symmetry with PlayFromJS but
150
   * in future we will likely have to flush style in
151
   * CSSAnimation::PauseFromJS so we leave it for now.
152
   */
153
0
  void PauseFromJS(ErrorResult& aRv) { Pause(aRv); }
154
155
  // Wrapper functions for Animation DOM methods when called from style.
156
157
0
  virtual void CancelFromStyle() { CancelNoUpdate(); }
158
  void SetTimelineNoUpdate(AnimationTimeline* aTimeline);
159
  void SetEffectNoUpdate(AnimationEffect* aEffect);
160
161
  virtual void Tick();
162
  bool NeedsTicks() const
163
0
  {
164
0
    return Pending() || PlayState() == AnimationPlayState::Running;
165
0
  }
166
167
  /**
168
   * Set the time to use for starting or pausing a pending animation.
169
   *
170
   * Typically, when an animation is played, it does not start immediately but
171
   * is added to a table of pending animations on the document of its effect.
172
   * In the meantime it sets its hold time to the time from which playback
173
   * should begin.
174
   *
175
   * When the document finishes painting, any pending animations in its table
176
   * are marked as being ready to start by calling TriggerOnNextTick.
177
   * The moment when the paint completed is also recorded, converted to a
178
   * timeline time, and passed to StartOnTick. This is so that when these
179
   * animations do start, they can be timed from the point when painting
180
   * completed.
181
   *
182
   * After calling TriggerOnNextTick, animations remain in the pending state
183
   * until the next refresh driver tick. At that time they transition out of
184
   * the pending state using the time passed to TriggerOnNextTick as the
185
   * effective time at which they resumed.
186
   *
187
   * This approach means that any setup time required for performing the
188
   * initial paint of an animation such as layerization is not deducted from
189
   * the running time of the animation. Without this we can easily drop the
190
   * first few frames of an animation, or, on slower devices, the whole
191
   * animation.
192
   *
193
   * Furthermore:
194
   *
195
   * - Starting the animation immediately when painting finishes is problematic
196
   *   because the start time of the animation will be ahead of its timeline
197
   *   (since the timeline time is based on the refresh driver time).
198
   *   That's a problem because the animation is playing but its timing
199
   *   suggests it starts in the future. We could update the timeline to match
200
   *   the start time of the animation but then we'd also have to update the
201
   *   timing and style of all animations connected to that timeline or else be
202
   *   stuck in an inconsistent state until the next refresh driver tick.
203
   *
204
   * - If we simply use the refresh driver time on its next tick, the lag
205
   *   between triggering an animation and its effective start is unacceptably
206
   *   long.
207
   *
208
   * For pausing, we apply the same asynchronous approach. This is so that we
209
   * synchronize with animations that are running on the compositor. Otherwise
210
   * if the main thread lags behind the compositor there will be a noticeable
211
   * jump backwards when the main thread takes over. Even though main thread
212
   * animations could be paused immediately, we do it asynchronously for
213
   * consistency and so that animations paused together end up in step.
214
   *
215
   * Note that the caller of this method is responsible for removing the
216
   * animation from any PendingAnimationTracker it may have been added to.
217
   */
218
  void TriggerOnNextTick(const Nullable<TimeDuration>& aReadyTime);
219
  /**
220
   * Testing only: Start or pause a pending animation using the current
221
   * timeline time. This is used to support existing tests that expect
222
   * animations to begin immediately. Ideally we would rewrite the those tests
223
   * and get rid of this method, but there are a lot of them.
224
   *
225
   * As with TriggerOnNextTick, the caller of this method is responsible for
226
   * removing the animation from any PendingAnimationTracker it may have been
227
   * added to.
228
   */
229
  void TriggerNow();
230
  /**
231
   * When TriggerOnNextTick is called, we store the ready time but we don't
232
   * apply it until the next tick. In the meantime, GetStartTime() will return
233
   * null.
234
   *
235
   * However, if we build layer animations again before the next tick, we
236
   * should initialize them with the start time that GetStartTime() will return
237
   * on the next tick.
238
   *
239
   * If we were to simply set the start time of layer animations to null, their
240
   * start time would be updated to the current wallclock time when rendering
241
   * finishes, thus making them out of sync with the start time stored here.
242
   * This, in turn, will make the animation jump backwards when we build
243
   * animations on the next tick and apply the start time stored here.
244
   *
245
   * This method returns the start time, if resolved. Otherwise, if we have
246
   * a pending ready time, it returns the corresponding start time. If neither
247
   * of those are available, it returns null.
248
   */
249
  Nullable<TimeDuration> GetCurrentOrPendingStartTime() const;
250
251
  /**
252
   * As with the start time, we should use the pending playback rate when
253
   * producing layer animations.
254
   */
255
  double CurrentOrPendingPlaybackRate() const
256
0
  {
257
0
    return mPendingPlaybackRate.valueOr(mPlaybackRate);
258
0
  }
259
0
  bool HasPendingPlaybackRate() const { return mPendingPlaybackRate.isSome(); }
260
261
  /**
262
   * The following relationship from the definition of the 'current time' is
263
   * re-used in many algorithms so we extract it here into a static method that
264
   * can be re-used:
265
   *
266
   *   current time = (timeline time - start time) * playback rate
267
   *
268
   * As per https://drafts.csswg.org/web-animations-1/#current-time
269
   */
270
  static TimeDuration CurrentTimeFromTimelineTime(
271
    const TimeDuration& aTimelineTime,
272
    const TimeDuration& aStartTime,
273
    float aPlaybackRate)
274
0
  {
275
0
    return (aTimelineTime - aStartTime).MultDouble(aPlaybackRate);
276
0
  }
277
278
  /**
279
   * As with calculating the current time, we often need to calculate a start
280
   * time from a current time. The following method simply inverts the current
281
   * time relationship.
282
   *
283
   * In each case where this is used, the desired behavior for playbackRate ==
284
   * 0 is to return the specified timeline time (often referred to as the ready
285
   * time).
286
   */
287
  static TimeDuration StartTimeFromTimelineTime(
288
    const TimeDuration& aTimelineTime,
289
    const TimeDuration& aCurrentTime,
290
    float aPlaybackRate)
291
0
  {
292
0
    TimeDuration result = aTimelineTime;
293
0
    if (aPlaybackRate == 0) {
294
0
      return result;
295
0
    }
296
0
297
0
    result -= aCurrentTime.MultDouble(1.0 / aPlaybackRate);
298
0
    return result;
299
0
  }
300
301
  /**
302
   * Converts a time in the timescale of this Animation's currentTime, to a
303
   * TimeStamp. Returns a null TimeStamp if the conversion cannot be performed
304
   * because of the current state of this Animation (e.g. it has no timeline, a
305
   * zero playbackRate, an unresolved start time etc.) or the value of the time
306
   * passed-in (e.g. an infinite time).
307
   */
308
  TimeStamp AnimationTimeToTimeStamp(const StickyTimeDuration& aTime) const;
309
310
  // Converts an AnimationEvent's elapsedTime value to an equivalent TimeStamp
311
  // that can be used to sort events by when they occurred.
312
  TimeStamp ElapsedTimeToTimeStamp(const StickyTimeDuration& aElapsedTime) const;
313
314
  bool IsPausedOrPausing() const
315
0
  {
316
0
    return PlayState() == AnimationPlayState::Paused;
317
0
  }
318
319
  bool HasCurrentEffect() const
320
0
  {
321
0
    return GetEffect() && GetEffect()->IsCurrent();
322
0
  }
323
  bool IsInEffect() const
324
0
  {
325
0
    return GetEffect() && GetEffect()->IsInEffect();
326
0
  }
327
328
  bool IsPlaying() const
329
0
  {
330
0
    return mPlaybackRate != 0.0 &&
331
0
           mTimeline &&
332
0
           !mTimeline->GetCurrentTime().IsNull() &&
333
0
           PlayState() == AnimationPlayState::Running;
334
0
  }
335
336
  bool ShouldBeSynchronizedWithMainThread(
337
    nsCSSPropertyID aProperty,
338
    const nsIFrame* aFrame,
339
    AnimationPerformanceWarning::Type& aPerformanceWarning) const;
340
341
0
  bool IsRelevant() const { return mIsRelevant; }
342
  void UpdateRelevance();
343
344
  /**
345
   * Returns true if this Animation has a lower composite order than aOther.
346
   */
347
  bool HasLowerCompositeOrderThan(const Animation& aOther) const;
348
349
   /**
350
   * Returns the level at which the effect(s) associated with this Animation
351
   * are applied to the CSS cascade.
352
   */
353
  virtual EffectCompositor::CascadeLevel CascadeLevel() const
354
0
  {
355
0
    return EffectCompositor::CascadeLevel::Animations;
356
0
  }
357
358
  /**
359
   * Returns true if this animation does not currently need to update
360
   * style on the main thread (e.g. because it is empty, or is
361
   * running on the compositor).
362
   */
363
  bool CanThrottle() const;
364
365
  /**
366
   * Updates various bits of state that we need to update as the result of
367
   * running ComposeStyle().
368
   * See the comment of KeyframeEffect::WillComposeStyle for more detail.
369
   */
370
  void WillComposeStyle();
371
372
  /**
373
   * Updates |aComposeResult| with the animation values of this animation's
374
   * effect, if any.
375
   * Any properties contained in |aPropertiesToSkip| will not be added or
376
   * updated in |aComposeResult|.
377
   */
378
  void ComposeStyle(RawServoAnimationValueMap& aComposeResult,
379
                    const nsCSSPropertyIDSet& aPropertiesToSkip);
380
381
  void NotifyEffectTimingUpdated();
382
  void NotifyGeometricAnimationsStartingThisFrame();
383
384
  /**
385
   * Reschedule pending pause or pending play tasks when updating the target
386
   * effect.
387
   *
388
   * If we are pending, we will either be registered in the pending animation
389
   * tracker and have a null pending ready time, or, after our effect has been
390
   * painted, we will be removed from the tracker and assigned a pending ready
391
   * time.
392
   *
393
   * When the target effect is updated, we'll typically need to repaint so for
394
   * the latter case where we already have a pending ready time, clear it and put
395
   * ourselves back in the pending animation tracker.
396
   */
397
  void ReschedulePendingTasks();
398
399
  /**
400
   * Used by subclasses to synchronously queue a cancel event in situations
401
   * where the Animation may have been cancelled.
402
   *
403
   * We need to do this synchronously because after a CSS animation/transition
404
   * is canceled, it will be released by its owning element and may not still
405
   * exist when we would normally go to queue events on the next tick.
406
   */
407
0
  virtual void MaybeQueueCancelEvent(const StickyTimeDuration& aActiveTime) {};
408
409
0
  int32_t& CachedChildIndexRef() { return mCachedChildIndex; }
410
411
protected:
412
  void SilentlySetCurrentTime(const TimeDuration& aNewCurrentTime);
413
  void CancelNoUpdate();
414
  void PlayNoUpdate(ErrorResult& aRv, LimitBehavior aLimitBehavior);
415
  void ResumeAt(const TimeDuration& aReadyTime);
416
  void PauseAt(const TimeDuration& aReadyTime);
417
  void FinishPendingAt(const TimeDuration& aReadyTime)
418
0
  {
419
0
    if (mPendingState == PendingState::PlayPending) {
420
0
      ResumeAt(aReadyTime);
421
0
    } else if (mPendingState == PendingState::PausePending) {
422
0
      PauseAt(aReadyTime);
423
0
    } else {
424
0
      MOZ_ASSERT_UNREACHABLE("Can't finish pending if we're not in a pending state");
425
0
    }
426
0
  }
427
  void ApplyPendingPlaybackRate()
428
0
  {
429
0
    if (mPendingPlaybackRate) {
430
0
      mPlaybackRate = *mPendingPlaybackRate;
431
0
      mPendingPlaybackRate.reset();
432
0
    }
433
0
  }
434
435
  /**
436
   * Finishing behavior depends on if changes to timing occurred due
437
   * to a seek or regular playback.
438
   */
439
  enum class SeekFlag {
440
    NoSeek,
441
    DidSeek
442
  };
443
444
  enum class SyncNotifyFlag {
445
    Sync,
446
    Async
447
  };
448
449
  virtual void UpdateTiming(SeekFlag aSeekFlag,
450
                            SyncNotifyFlag aSyncNotifyFlag);
451
  void UpdateFinishedState(SeekFlag aSeekFlag,
452
                           SyncNotifyFlag aSyncNotifyFlag);
453
  void UpdateEffect();
454
  /**
455
   * Flush all pending styles other than throttled animation styles (e.g.
456
   * animations running on the compositor).
457
   */
458
  void FlushUnanimatedStyle() const;
459
  void PostUpdate();
460
  void ResetFinishedPromise();
461
  void MaybeResolveFinishedPromise();
462
  void DoFinishNotification(SyncNotifyFlag aSyncNotifyFlag);
463
  friend class AsyncFinishNotification;
464
  void DoFinishNotificationImmediately(MicroTaskRunnable* aAsync = nullptr);
465
  void QueuePlaybackEvent(const nsAString& aName,
466
                          TimeStamp&& aScheduledEventTime);
467
468
  /**
469
   * Remove this animation from the pending animation tracker and reset
470
   * mPendingState as necessary. The caller is responsible for resolving or
471
   * aborting the mReady promise as necessary.
472
   */
473
  void CancelPendingTasks();
474
475
  /**
476
   * Performs the same steps as CancelPendingTasks and also rejects and
477
   * recreates the ready promise if the animation was pending.
478
   */
479
  void ResetPendingTasks();
480
481
  /**
482
   * Returns true if this animation is not only play-pending, but has
483
   * yet to be given a pending ready time. This roughly corresponds to
484
   * animations that are waiting to be painted (since we set the pending
485
   * ready time at the end of painting). Identifying such animations is
486
   * useful because in some cases animations that are painted together
487
   * may need to be synchronized.
488
   *
489
   * We don't, however, want to include animations with a fixed start time such
490
   * as animations that are simply having their playbackRate updated or which
491
   * are resuming from an aborted pause.
492
   */
493
0
  bool IsNewlyStarted() const {
494
0
    return mPendingState == PendingState::PlayPending &&
495
0
           mPendingReadyTime.IsNull() &&
496
0
           mStartTime.IsNull();
497
0
  }
498
  bool IsPossiblyOrphanedPendingAnimation() const;
499
  StickyTimeDuration EffectEnd() const;
500
501
  Nullable<TimeDuration> GetCurrentTimeForHoldTime(
502
    const Nullable<TimeDuration>& aHoldTime) const;
503
  Nullable<TimeDuration> GetUnconstrainedCurrentTime() const
504
0
  {
505
0
    return GetCurrentTimeForHoldTime(Nullable<TimeDuration>());
506
0
  }
507
508
  // Earlier side of the elapsed time range reported in CSS Animations and CSS
509
  // Transitions events.
510
  //
511
  // https://drafts.csswg.org/css-animations-2/#interval-start
512
  // https://drafts.csswg.org/css-transitions-2/#interval-start
513
  StickyTimeDuration
514
  IntervalStartTime(const StickyTimeDuration& aActiveDuration) const
515
0
  {
516
0
    MOZ_ASSERT(AsCSSTransition() || AsCSSAnimation(),
517
0
               "Should be called for CSS animations or transitions");
518
0
    static constexpr StickyTimeDuration zeroDuration = StickyTimeDuration();
519
0
    return std::max(
520
0
      std::min(StickyTimeDuration(-mEffect->SpecifiedTiming().Delay()),
521
0
               aActiveDuration),
522
0
      zeroDuration);
523
0
  }
524
525
  // Later side of the elapsed time range reported in CSS Animations and CSS
526
  // Transitions events.
527
  //
528
  // https://drafts.csswg.org/css-animations-2/#interval-end
529
  // https://drafts.csswg.org/css-transitions-2/#interval-end
530
  StickyTimeDuration
531
  IntervalEndTime(const StickyTimeDuration& aActiveDuration) const
532
0
  {
533
0
    MOZ_ASSERT(AsCSSTransition() || AsCSSAnimation(),
534
0
               "Should be called for CSS animations or transitions");
535
0
536
0
    static constexpr StickyTimeDuration zeroDuration = StickyTimeDuration();
537
0
    return std::max(
538
0
      std::min((EffectEnd() - mEffect->SpecifiedTiming().Delay()),
539
0
               aActiveDuration),
540
0
      zeroDuration);
541
0
  }
542
543
  TimeStamp GetTimelineCurrentTimeAsTimeStamp() const
544
0
  {
545
0
    return mTimeline ? mTimeline->GetCurrentTimeAsTimeStamp() : TimeStamp();
546
0
  }
547
548
  nsIDocument* GetRenderedDocument() const;
549
  nsIDocument* GetTimelineDocument() const;
550
551
  RefPtr<AnimationTimeline> mTimeline;
552
  RefPtr<AnimationEffect> mEffect;
553
  // The beginning of the delay period.
554
  Nullable<TimeDuration> mStartTime; // Timeline timescale
555
  Nullable<TimeDuration> mHoldTime;  // Animation timescale
556
  Nullable<TimeDuration> mPendingReadyTime; // Timeline timescale
557
  Nullable<TimeDuration> mPreviousCurrentTime; // Animation timescale
558
  double mPlaybackRate;
559
  Maybe<double> mPendingPlaybackRate;
560
561
  // A Promise that is replaced on each call to Play()
562
  // and fulfilled when Play() is successfully completed.
563
  // This object is lazily created by GetReady.
564
  // See http://drafts.csswg.org/web-animations/#current-ready-promise
565
  RefPtr<Promise> mReady;
566
567
  // A Promise that is resolved when we reach the end of the effect, or
568
  // 0 when playing backwards. The Promise is replaced if the animation is
569
  // finished but then a state change makes it not finished.
570
  // This object is lazily created by GetFinished.
571
  // See http://drafts.csswg.org/web-animations/#current-finished-promise
572
  RefPtr<Promise> mFinished;
573
574
  static uint64_t sNextAnimationIndex;
575
576
  // The relative position of this animation within the global animation list.
577
  // This is kNoIndex while the animation is in the idle state and is updated
578
  // each time the animation transitions out of the idle state.
579
  //
580
  // Note that subclasses such as CSSTransition and CSSAnimation may repurpose
581
  // this member to implement their own brand of sorting. As a result, it is
582
  // possible for two different objects to have the same index.
583
  uint64_t mAnimationIndex;
584
585
  // While ordering Animation objects for event dispatch, the index of the
586
  // target node in its parent may be cached in mCachedChildIndex.
587
  int32_t mCachedChildIndex;
588
589
  // Indicates if the animation is in the pending state (and what state it is
590
  // waiting to enter when it finished pending). We use this rather than
591
  // checking if this animation is tracked by a PendingAnimationTracker because
592
  // the animation will continue to be pending even after it has been removed
593
  // from the PendingAnimationTracker while it is waiting for the next tick
594
  // (see TriggerOnNextTick for details).
595
  enum class PendingState : uint8_t
596
  {
597
    NotPending,
598
    PlayPending,
599
    PausePending
600
  };
601
  PendingState mPendingState;
602
603
  bool mFinishedAtLastComposeStyle;
604
  // Indicates that the animation should be exposed in an element's
605
  // getAnimations() list.
606
  bool mIsRelevant;
607
608
  // True if mFinished is resolved or would be resolved if mFinished has
609
  // yet to be created. This is not set when mFinished is rejected since
610
  // in that case mFinished is immediately reset to represent a new current
611
  // finished promise.
612
  bool mFinishedIsResolved;
613
614
  // True if this animation was triggered at the same time as one or more
615
  // geometric animations and hence we should run any transform animations on
616
  // the main thread.
617
  bool mSyncWithGeometricAnimations;
618
619
  RefPtr<MicroTaskRunnable> mFinishNotificationTask;
620
621
  nsString mId;
622
};
623
624
} // namespace dom
625
} // namespace mozilla
626
627
#endif // mozilla_dom_Animation_h