Animation.h (22632B)
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 "X11UndefineNone.h" 11 #include "mozilla/AnimatedPropertyIDSet.h" 12 #include "mozilla/AnimationPerformanceWarning.h" 13 #include "mozilla/Attributes.h" 14 #include "mozilla/BasePrincipal.h" 15 #include "mozilla/DOMEventTargetHelper.h" 16 #include "mozilla/EffectCompositor.h" // For EffectCompositor::CascadeLevel 17 #include "mozilla/LinkedList.h" 18 #include "mozilla/Maybe.h" 19 #include "mozilla/PostRestyleMode.h" 20 #include "mozilla/StickyTimeDuration.h" 21 #include "mozilla/TimeStamp.h" // for TimeStamp, TimeDuration 22 #include "mozilla/dom/AnimationBinding.h" // for AnimationPlayState 23 #include "mozilla/dom/AnimationTimeline.h" 24 #include "nsCycleCollectionParticipant.h" 25 26 struct JSContext; 27 class nsCSSPropertyIDSet; 28 class nsIFrame; 29 class nsIGlobalObject; 30 class nsAtom; 31 32 namespace mozilla { 33 34 struct AnimationRule; 35 class MicroTaskRunnable; 36 37 namespace dom { 38 39 class AnimationEffect; 40 class AsyncFinishNotification; 41 class CSSAnimation; 42 class CSSTransition; 43 class Document; 44 class Promise; 45 46 class Animation : public DOMEventTargetHelper, 47 public LinkedListElement<Animation> { 48 protected: 49 virtual ~Animation(); 50 51 public: 52 explicit Animation(nsIGlobalObject* aGlobal); 53 54 // Constructs a copy of |aOther| with a new effect and timeline. 55 // This is only intended to be used while making a static clone of a document 56 // during printing, and does not assume that |aOther| is in the same document 57 // as any of the other arguments. 58 static already_AddRefed<Animation> ClonePausedAnimation( 59 nsIGlobalObject* aGlobal, const Animation& aOther, 60 AnimationEffect& aEffect, AnimationTimeline& aTimeline); 61 62 NS_DECL_ISUPPORTS_INHERITED 63 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Animation, DOMEventTargetHelper) 64 65 nsIGlobalObject* GetParentObject() const { return GetOwnerGlobal(); } 66 67 /** 68 * Utility function to get the target (pseudo-)element associated with an 69 * animation. 70 */ 71 NonOwningAnimationTarget GetTargetForAnimation() const; 72 73 virtual JSObject* WrapObject(JSContext* aCx, 74 JS::Handle<JSObject*> aGivenProto) override; 75 76 virtual CSSAnimation* AsCSSAnimation() { return nullptr; } 77 virtual const CSSAnimation* AsCSSAnimation() const { return nullptr; } 78 virtual CSSTransition* AsCSSTransition() { return nullptr; } 79 virtual const CSSTransition* AsCSSTransition() const { return nullptr; } 80 81 /** 82 * Flag to pass to Play to indicate whether or not it should automatically 83 * rewind the current time to the start point if the animation is finished. 84 * For regular calls to play() from script we should do this, but when a CSS 85 * animation's animation-play-state changes we shouldn't rewind the animation. 86 */ 87 enum class LimitBehavior { AutoRewind, Continue }; 88 89 // Animation interface methods 90 static already_AddRefed<Animation> Constructor( 91 const GlobalObject& aGlobal, AnimationEffect* aEffect, 92 const Optional<AnimationTimeline*>& aTimeline, ErrorResult& aRv); 93 94 void GetId(nsAString& aResult) const { aResult = mId; } 95 void SetId(const nsAString& aId); 96 97 AnimationEffect* GetEffect() const { return mEffect; } 98 virtual void SetEffect(AnimationEffect* aEffect); 99 void SetEffectNoUpdate(AnimationEffect* aEffect); 100 101 // FIXME: Bug 1676794. This is a tentative solution before we implement 102 // ScrollTimeline interface. If the timeline is scroll/view timeline, we 103 // return null. Once we implement ScrollTimeline interface, we can drop this. 104 already_AddRefed<AnimationTimeline> GetTimelineFromJS() const { 105 return mTimeline && mTimeline->IsScrollTimeline() ? nullptr 106 : do_AddRef(mTimeline); 107 } 108 void SetTimelineFromJS(AnimationTimeline* aTimeline) { 109 SetTimeline(aTimeline); 110 } 111 112 AnimationTimeline* GetTimeline() const { return mTimeline; } 113 void SetTimeline(AnimationTimeline* aTimeline); 114 void SetTimelineNoUpdate(AnimationTimeline* aTimeline); 115 116 Nullable<TimeDuration> GetStartTime() const { return mStartTime; } 117 Nullable<double> GetStartTimeAsDouble() const; 118 void SetStartTime(const Nullable<TimeDuration>& aNewStartTime); 119 const TimeStamp& GetPendingReadyTime() const { return mPendingReadyTime; } 120 void SetPendingReadyTime(const TimeStamp& aReadyTime) { 121 mPendingReadyTime = aReadyTime; 122 } 123 virtual void SetStartTimeAsDouble(const Nullable<double>& aStartTime); 124 125 // This is deliberately _not_ called GetCurrentTime since that would clash 126 // with a macro defined in winbase.h 127 Nullable<TimeDuration> GetCurrentTimeAsDuration() const { 128 return GetCurrentTimeForHoldTime(mHoldTime); 129 } 130 Nullable<double> GetCurrentTimeAsDouble() const; 131 void SetCurrentTime(const TimeDuration& aSeekTime); 132 void SetCurrentTimeNoUpdate(const TimeDuration& aSeekTime); 133 void SetCurrentTimeAsDouble(const Nullable<double>& aCurrentTime, 134 ErrorResult& aRv); 135 136 Nullable<double> GetOverallProgress() const; 137 138 double PlaybackRate() const { return mPlaybackRate; } 139 void SetPlaybackRate(double aPlaybackRate); 140 141 AnimationPlayState PlayState() const; 142 virtual AnimationPlayState PlayStateFromJS() const { return PlayState(); } 143 144 bool Pending() const { return mPendingState != PendingState::NotPending; } 145 virtual bool PendingFromJS() const { return Pending(); } 146 AnimationReplaceState ReplaceState() const { return mReplaceState; } 147 148 virtual Promise* GetReady(ErrorResult& aRv); 149 Promise* GetFinished(ErrorResult& aRv); 150 151 IMPL_EVENT_HANDLER(finish); 152 IMPL_EVENT_HANDLER(cancel); 153 IMPL_EVENT_HANDLER(remove); 154 155 void Cancel(PostRestyleMode aPostRestyle = PostRestyleMode::IfNeeded); 156 157 void Finish(ErrorResult& aRv); 158 159 void Play(ErrorResult& aRv, LimitBehavior aLimitBehavior); 160 virtual void PlayFromJS(ErrorResult& aRv) { 161 Play(aRv, LimitBehavior::AutoRewind); 162 } 163 164 void Pause(ErrorResult& aRv); 165 virtual void PauseFromJS(ErrorResult& aRv) { Pause(aRv); } 166 167 void UpdatePlaybackRate(double aPlaybackRate); 168 virtual void Reverse(ErrorResult& aRv); 169 170 void Persist(); 171 MOZ_CAN_RUN_SCRIPT void CommitStyles(ErrorResult& aRv); 172 173 bool IsRunningOnCompositor() const; 174 175 using TickState = AnimationTimeline::TickState; 176 virtual void Tick(TickState&); 177 bool NeedsTicks() const { 178 return Pending() || 179 (PlayState() == AnimationPlayState::Running && 180 // An animation with a zero playback rate doesn't need ticks even if 181 // it is running since it effectively behaves as if it is paused. 182 // 183 // It's important we return false in this case since a zero playback 184 // rate animation in the before or after phase that doesn't fill 185 // won't be relevant and hence won't be returned by GetAnimations(). 186 // We don't want its timeline to keep it alive (which would happen 187 // if we return true) since otherwise it will effectively be leaked. 188 PlaybackRate() != 0.0) || 189 // Always return true for not idle animations attached to not 190 // monotonically increasing timelines even if the animation is 191 // finished. This is required to accommodate cases where timeline 192 // ticks back in time. 193 (mTimeline && !mTimeline->IsMonotonicallyIncreasing() && 194 PlayState() != AnimationPlayState::Idle); 195 } 196 /** 197 * For the monotonically increasing timeline, we use this only for testing: 198 * Start or pause a pending animation using the current timeline time. This 199 * is used to support existing tests that expect animations to begin 200 * immediately. Ideally we would rewrite the those tests and get rid of this 201 * method, but there are a lot of them. 202 */ 203 bool TryTriggerNow(); 204 /** 205 * As with the start time, we should use the pending playback rate when 206 * producing layer animations. 207 */ 208 double CurrentOrPendingPlaybackRate() const { 209 return mPendingPlaybackRate.valueOr(mPlaybackRate); 210 } 211 bool HasPendingPlaybackRate() const { return mPendingPlaybackRate.isSome(); } 212 213 /** 214 * The following relationship from the definition of the 'current time' is 215 * re-used in many algorithms so we extract it here into a static method that 216 * can be re-used: 217 * 218 * current time = (timeline time - start time) * playback rate 219 * 220 * As per https://drafts.csswg.org/web-animations-1/#current-time 221 */ 222 static TimeDuration CurrentTimeFromTimelineTime( 223 const TimeDuration& aTimelineTime, const TimeDuration& aStartTime, 224 float aPlaybackRate) { 225 return (aTimelineTime - aStartTime).MultDouble(aPlaybackRate); 226 } 227 228 /** 229 * As with calculating the current time, we often need to calculate a start 230 * time from a current time. The following method simply inverts the current 231 * time relationship. 232 * 233 * In each case where this is used, the desired behavior for playbackRate == 234 * 0 is to return the specified timeline time (often referred to as the ready 235 * time). 236 */ 237 static TimeDuration StartTimeFromTimelineTime( 238 const TimeDuration& aTimelineTime, const TimeDuration& aCurrentTime, 239 float aPlaybackRate) { 240 TimeDuration result = aTimelineTime; 241 if (aPlaybackRate == 0) { 242 return result; 243 } 244 245 result -= aCurrentTime.MultDouble(1.0 / aPlaybackRate); 246 return result; 247 } 248 249 /** 250 * Converts a time in the timescale of this Animation's currentTime, to a 251 * TimeStamp. Returns a null TimeStamp if the conversion cannot be performed 252 * because of the current state of this Animation (e.g. it has no timeline, a 253 * zero playbackRate, an unresolved start time etc.) or the value of the time 254 * passed-in (e.g. an infinite time). 255 */ 256 TimeStamp AnimationTimeToTimeStamp(const StickyTimeDuration& aTime) const; 257 258 // Converts an AnimationEvent's elapsedTime value to an equivalent TimeStamp 259 // that can be used to sort events by when they occurred. 260 TimeStamp ElapsedTimeToTimeStamp( 261 const StickyTimeDuration& aElapsedTime) const; 262 263 bool IsPausedOrPausing() const { 264 return PlayState() == AnimationPlayState::Paused; 265 } 266 267 bool HasCurrentEffect() const; 268 bool IsInEffect() const; 269 270 bool IsPlaying() const { 271 return mPlaybackRate != 0.0 && mTimeline && 272 !mTimeline->GetCurrentTimeAsDuration().IsNull() && 273 PlayState() == AnimationPlayState::Running; 274 } 275 276 bool ShouldBeSynchronizedWithMainThread( 277 const nsCSSPropertyIDSet& aPropertySet, const nsIFrame* aFrame, 278 AnimationPerformanceWarning::Type& aPerformanceWarning /* out */) const; 279 280 bool IsRelevant() const { return mIsRelevant; } 281 void UpdateRelevance(); 282 283 // https://drafts.csswg.org/web-animations-1/#replaceable-animation 284 bool IsReplaceable() const; 285 286 /** 287 * Returns true if this Animation satisfies the requirements for being 288 * removed when it is replaced. 289 * 290 * Returning true does not imply this animation _should_ be removed. 291 * Determining that depends on the other effects in the same EffectSet to 292 * which this animation's effect, if any, contributes. 293 */ 294 bool IsRemovable() const; 295 296 /** 297 * Make this animation's target effect no-longer part of the effect stack 298 * while preserving its timing information. 299 */ 300 void Remove(); 301 302 /** 303 * Returns true if this Animation has a lower composite order than aOther. 304 */ 305 struct EventContext { 306 NonOwningAnimationTarget mTarget; 307 uint64_t mIndex; 308 }; 309 // Note: we provide |aContext|/|aOtherContext| only when it is a cancelled 310 // transition or animation (for overridding the target and animation index). 311 int32_t CompareCompositeOrder(const Maybe<EventContext>& aContext, 312 const Animation& aOther, 313 const Maybe<EventContext>& aOtherContext, 314 nsContentUtils::NodeIndexCache&) const; 315 int32_t CompareCompositeOrder(const Animation& aOther, 316 nsContentUtils::NodeIndexCache& aCache) const { 317 return CompareCompositeOrder(Nothing(), aOther, Nothing(), aCache); 318 } 319 320 /** 321 * Returns the level at which the effect(s) associated with this Animation 322 * are applied to the CSS cascade. 323 */ 324 virtual EffectCompositor::CascadeLevel CascadeLevel() const { 325 return EffectCompositor::CascadeLevel::Animations; 326 } 327 328 /** 329 * Returns true if this animation does not currently need to update 330 * style on the main thread (e.g. because it is empty, or is 331 * running on the compositor). 332 */ 333 bool CanThrottle() const; 334 335 /** 336 * Updates various bits of state that we need to update as the result of 337 * running ComposeStyle(). 338 * See the comment of KeyframeEffect::WillComposeStyle for more detail. 339 */ 340 void WillComposeStyle(); 341 342 /** 343 * Updates |aComposeResult| with the animation values of this animation's 344 * effect, if any. 345 * Any properties contained in |aPropertiesToSkip| will not be added or 346 * updated in |aComposeResult|. 347 */ 348 void ComposeStyle( 349 StyleAnimationValueMap& aComposeResult, 350 const InvertibleAnimatedPropertyIDSet& aPropertiesToSkip, 351 EndpointBehavior aEndpointBehavior = EndpointBehavior::Exclusive); 352 353 void NotifyEffectTimingUpdated(); 354 void NotifyEffectPropertiesUpdated(); 355 void NotifyEffectTargetUpdated(); 356 357 /** 358 * Used by subclasses to synchronously queue a cancel event in situations 359 * where the Animation may have been cancelled. 360 * 361 * We need to do this synchronously because after a CSS animation/transition 362 * is canceled, it will be released by its owning element and may not still 363 * exist when we would normally go to queue events on the next tick. 364 */ 365 virtual void MaybeQueueCancelEvent(const StickyTimeDuration& aActiveTime) {}; 366 367 void SetPartialPrerendered(uint64_t aIdOnCompositor) { 368 mIdOnCompositor = aIdOnCompositor; 369 mIsPartialPrerendered = true; 370 } 371 bool IsPartialPrerendered() const { return mIsPartialPrerendered; } 372 uint64_t IdOnCompositor() const { return mIdOnCompositor; } 373 /** 374 * Needs to be called when the pre-rendered animation is going to no longer 375 * run on the compositor. 376 */ 377 void ResetPartialPrerendered() { 378 MOZ_ASSERT(mIsPartialPrerendered); 379 mIsPartialPrerendered = false; 380 mIdOnCompositor = 0; 381 } 382 /** 383 * Called via NotifyJankedAnimations IPC call from the compositor to update 384 * pre-rendered area on the main-thread. 385 */ 386 void UpdatePartialPrerendered() { 387 ResetPartialPrerendered(); 388 PostUpdate(); 389 } 390 391 bool UsingScrollTimeline() const { 392 return mTimeline && mTimeline->IsScrollTimeline(); 393 } 394 395 /** 396 * Returns true if this is at the progress timeline boundary. 397 * https://drafts.csswg.org/web-animations-2/#at-progress-timeline-boundary 398 */ 399 enum class ProgressTimelinePosition : uint8_t { Boundary, NotBoundary }; 400 static ProgressTimelinePosition AtProgressTimelineBoundary( 401 const Nullable<TimeDuration>& aTimelineDuration, 402 const Nullable<TimeDuration>& aCurrentTime, 403 const TimeDuration& aEffectStartTime, const double aPlaybackRate); 404 ProgressTimelinePosition AtProgressTimelineBoundary() const { 405 Nullable<TimeDuration> currentTime = GetUnconstrainedCurrentTime(); 406 return AtProgressTimelineBoundary( 407 mTimeline ? mTimeline->TimelineDuration() : nullptr, 408 // Set unlimited current time based on the first matching condition: 409 // 1. start time is resolved: 410 // (timeline time - start time) × playback rate 411 // 2. Otherwise: 412 // animation’s current time 413 !currentTime.IsNull() ? currentTime : GetCurrentTimeAsDuration(), 414 mStartTime.IsNull() ? TimeDuration() : mStartTime.Value(), 415 mPlaybackRate); 416 } 417 418 void SetHiddenByContentVisibility(bool hidden); 419 bool IsHiddenByContentVisibility() const { 420 return mHiddenByContentVisibility; 421 } 422 void UpdateHiddenByContentVisibility(); 423 424 DocGroup* GetDocGroup(); 425 426 protected: 427 void SilentlySetCurrentTime(const TimeDuration& aNewCurrentTime); 428 void CancelNoUpdate(); 429 void PlayNoUpdate(ErrorResult& aRv, LimitBehavior aLimitBehavior); 430 void ResumeAt(const TimeDuration& aReadyTime); 431 void PauseAt(const TimeDuration& aReadyTime); 432 void FinishPendingAt(const TimeDuration& aReadyTime) { 433 if (mPendingState == PendingState::PlayPending) { 434 ResumeAt(aReadyTime); 435 } else if (mPendingState == PendingState::PausePending) { 436 PauseAt(aReadyTime); 437 } else { 438 MOZ_ASSERT_UNREACHABLE( 439 "Can't finish pending if we're not in a pending state"); 440 } 441 } 442 void ApplyPendingPlaybackRate() { 443 if (mPendingPlaybackRate) { 444 mPlaybackRate = mPendingPlaybackRate.extract(); 445 } 446 } 447 448 /** 449 * Finishing behavior depends on if changes to timing occurred due 450 * to a seek or regular playback. 451 */ 452 enum class SeekFlag { NoSeek, DidSeek }; 453 454 enum class SyncNotifyFlag { Sync, Async }; 455 456 virtual void UpdateTiming(SeekFlag aSeekFlag, SyncNotifyFlag aSyncNotifyFlag); 457 void UpdateFinishedState(SeekFlag aSeekFlag, SyncNotifyFlag aSyncNotifyFlag); 458 void UpdateEffect(PostRestyleMode aPostRestyle); 459 /** 460 * Flush all pending styles other than throttled animation styles (e.g. 461 * animations running on the compositor). 462 */ 463 void FlushUnanimatedStyle() const; 464 void PostUpdate(); 465 void ResetFinishedPromise(); 466 void MaybeResolveFinishedPromise(); 467 void DoFinishNotification(SyncNotifyFlag aSyncNotifyFlag); 468 friend class AsyncFinishNotification; 469 void DoFinishNotificationImmediately(MicroTaskRunnable* aAsync = nullptr); 470 void QueuePlaybackEvent(nsAtom* aOnEvent, TimeStamp&& aScheduledEventTime); 471 472 /** 473 * Remove this animation from the pending animation tracker and reset 474 * mPendingState as necessary. The caller is responsible for resolving or 475 * aborting the mReady promise as necessary. 476 */ 477 void CancelPendingTasks(); 478 479 /** 480 * Performs the same steps as CancelPendingTasks and also rejects and 481 * recreates the ready promise if the animation was pending. 482 */ 483 void ResetPendingTasks(); 484 StickyTimeDuration EffectEnd() const; 485 486 Nullable<TimeDuration> GetCurrentTimeForHoldTime( 487 const Nullable<TimeDuration>& aHoldTime) const; 488 Nullable<TimeDuration> GetUnconstrainedCurrentTime() const { 489 return GetCurrentTimeForHoldTime(Nullable<TimeDuration>()); 490 } 491 492 void ScheduleReplacementCheck(); 493 void MaybeScheduleReplacementCheck(); 494 495 // Earlier side of the elapsed time range reported in CSS Animations and CSS 496 // Transitions events. 497 // 498 // https://drafts.csswg.org/css-animations-2/#interval-start 499 // https://drafts.csswg.org/css-transitions-2/#interval-start 500 StickyTimeDuration IntervalStartTime( 501 const StickyTimeDuration& aActiveDuration) const; 502 503 // Later side of the elapsed time range reported in CSS Animations and CSS 504 // Transitions events. 505 // 506 // https://drafts.csswg.org/css-animations-2/#interval-end 507 // https://drafts.csswg.org/css-transitions-2/#interval-end 508 StickyTimeDuration IntervalEndTime( 509 const StickyTimeDuration& aActiveDuration) const; 510 511 TimeStamp GetTimelineCurrentTimeAsTimeStamp() const { 512 return mTimeline ? mTimeline->GetCurrentTimeAsTimeStamp() : TimeStamp(); 513 } 514 515 Document* GetRenderedDocument() const; 516 Document* GetTimelineDocument() const; 517 518 bool HasFiniteTimeline() const { 519 return mTimeline && !mTimeline->IsMonotonicallyIncreasing(); 520 } 521 522 void UpdateScrollTimelineAnimationTracker(AnimationTimeline* aOldTimeline, 523 AnimationTimeline* aNewTimeline); 524 525 RefPtr<AnimationTimeline> mTimeline; 526 RefPtr<AnimationEffect> mEffect; 527 // The beginning of the delay period. 528 Nullable<TimeDuration> mStartTime; // Timeline timescale 529 Nullable<TimeDuration> mHoldTime; // Animation timescale 530 Nullable<TimeDuration> mPreviousCurrentTime; // Animation timescale 531 double mPlaybackRate = 1.0; 532 Maybe<double> mPendingPlaybackRate; 533 534 // A Promise that is replaced on each call to Play() 535 // and fulfilled when Play() is successfully completed. 536 // This object is lazily created by GetReady. 537 // See http://drafts.csswg.org/web-animations/#current-ready-promise 538 RefPtr<Promise> mReady; 539 540 // A Promise that is resolved when we reach the end of the effect, or 541 // 0 when playing backwards. The Promise is replaced if the animation is 542 // finished but then a state change makes it not finished. 543 // This object is lazily created by GetFinished. 544 // See http://drafts.csswg.org/web-animations/#current-finished-promise 545 RefPtr<Promise> mFinished; 546 547 static uint64_t sNextAnimationIndex; 548 549 // The relative position of this animation within the global animation list. 550 // 551 // Note that subclasses such as CSSTransition and CSSAnimation may repurpose 552 // this member to implement their own brand of sorting. As a result, it is 553 // possible for two different objects to have the same index. 554 uint64_t mAnimationIndex; 555 556 // Indicates if the animation is in the pending state (and what state it is 557 // waiting to enter when it finished pending). 558 enum class PendingState : uint8_t { NotPending, PlayPending, PausePending }; 559 PendingState mPendingState = PendingState::NotPending; 560 561 // Handling of this animation's target effect when filling while finished. 562 AnimationReplaceState mReplaceState = AnimationReplaceState::Active; 563 564 bool mFinishedAtLastComposeStyle = false; 565 bool mWasReplaceableAtLastTick = false; 566 567 bool mHiddenByContentVisibility = false; 568 569 // Indicates that the animation should be exposed in an element's 570 // getAnimations() list. 571 bool mIsRelevant = false; 572 573 // True if mFinished is resolved or would be resolved if mFinished has 574 // yet to be created. This is not set when mFinished is rejected since 575 // in that case mFinished is immediately reset to represent a new current 576 // finished promise. 577 bool mFinishedIsResolved = false; 578 579 RefPtr<MicroTaskRunnable> mFinishNotificationTask; 580 581 nsString mId; 582 583 bool mResetCurrentTimeOnResume = false; 584 585 // Whether the Animation is System, ResistFingerprinting, or neither 586 RTPCallerType mRTPCallerType; 587 588 // The time at which our animation should be ready. 589 TimeStamp mPendingReadyTime; 590 591 private: 592 // The id for this animation on the compositor. 593 uint64_t mIdOnCompositor = 0; 594 bool mIsPartialPrerendered = false; 595 }; 596 597 } // namespace dom 598 } // namespace mozilla 599 600 #endif // mozilla_dom_Animation_h