Bug 1415780 - Make AnimationEventDispatcher refcountable. r?birtles
In a subsequent patch in this patch series, we want to make nsPresContext
have an AnimationEventDispatcher as RefPtr<>.
Instead, if we were trying to make nsPresContext have the
AnimationEventDispatcher as data object (not RefPtr<>) just like we did in
CommonAnimationManager, we will fall into header inclusion hell since Element.h
includes nsPresContext.h and AnimationEventDispatcher.h ends up including
Element.h. Even if we could solve the inclusion hell, we will suffer from Rust
bindgen issues for some reasons.
MozReview-Commit-ID: B0nX2JzIRJD
new file mode 100644
--- /dev/null
+++ b/dom/animation/AnimationEventDispatcher.cpp
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/AnimationEventDispatcher.h"
+
+#include "mozilla/EventDispatcher.h"
+
+namespace mozilla {
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(AnimationEventDispatcher)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AnimationEventDispatcher)
+ tmp->ClearEventQueue();
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AnimationEventDispatcher)
+ for (auto& info : tmp->mPendingEvents) {
+ ImplCycleCollectionTraverse(cb, info.mElement,
+ "mozilla::AnimationEventDispatcher.mPendingEvents.mElement");
+ ImplCycleCollectionTraverse(cb, info.mAnimation,
+ "mozilla::AnimationEventDispatcher.mPendingEvents.mAnimation");
+ }
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AnimationEventDispatcher, AddRef)
+NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AnimationEventDispatcher, Release)
+
+} // namespace mozilla
+
--- a/dom/animation/AnimationEventDispatcher.h
+++ b/dom/animation/AnimationEventDispatcher.h
@@ -94,16 +94,19 @@ struct AnimationEventInfo
}
};
class AnimationEventDispatcher final
{
public:
AnimationEventDispatcher() : mIsSorted(true) { }
+ NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AnimationEventDispatcher)
+ NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(AnimationEventDispatcher)
+
void QueueEvents(nsTArray<AnimationEventInfo>&& aEvents)
{
mPendingEvents.AppendElements(Move(aEvents));
mIsSorted = false;
}
// This is exposed as a separate method so that when we are dispatching
// *both* transition events and animation events we can sort both lists
@@ -156,28 +159,19 @@ public:
void ClearEventQueue()
{
mPendingEvents.Clear();
mIsSorted = true;
}
bool HasQueuedEvents() const { return !mPendingEvents.IsEmpty(); }
- // Methods for supporting cycle-collection
- void Traverse(nsCycleCollectionTraversalCallback* aCallback,
- const char* aName)
- {
- for (AnimationEventInfo& info : mPendingEvents) {
- ImplCycleCollectionTraverse(*aCallback, info.mElement, aName);
- ImplCycleCollectionTraverse(*aCallback, info.mAnimation, aName);
- }
- }
- void Unlink() { ClearEventQueue(); }
+private:
+ ~AnimationEventDispatcher() = default;
-protected:
class AnimationEventInfoLessThan
{
public:
bool operator()(const AnimationEventInfo& a, const AnimationEventInfo& b) const
{
if (a.mTimeStamp != b.mTimeStamp) {
// Null timestamps sort first
if (a.mTimeStamp.IsNull() || b.mTimeStamp.IsNull()) {
@@ -192,26 +186,11 @@ protected:
}
};
typedef nsTArray<AnimationEventInfo> EventArray;
EventArray mPendingEvents;
bool mIsSorted;
};
-inline void
-ImplCycleCollectionUnlink(AnimationEventDispatcher& aField)
-{
- aField.Unlink();
-}
-
-inline void
-ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
- AnimationEventDispatcher& aField,
- const char* aName,
- uint32_t aFlags = 0)
-{
- aField.Traverse(&aCallback, aName);
-}
-
} // namespace mozilla
#endif // mozilla_AnimationEventDispatcher_h
--- a/dom/animation/moz.build
+++ b/dom/animation/moz.build
@@ -42,16 +42,17 @@ EXPORTS.mozilla += [
'TimingParams.h',
]
UNIFIED_SOURCES += [
'Animation.cpp',
'AnimationEffectReadOnly.cpp',
'AnimationEffectTiming.cpp',
'AnimationEffectTimingReadOnly.cpp',
+ 'AnimationEventDispatcher.cpp',
'AnimationPerformanceWarning.cpp',
'AnimationTimeline.cpp',
'AnimationUtils.cpp',
'AnimValuesStyleRule.cpp',
'ComputedTimingFunction.cpp',
'CSSPseudoElement.cpp',
'DocumentTimeline.cpp',
'EffectCompositor.cpp',
--- a/layout/style/AnimationCommon.h
+++ b/layout/style/AnimationCommon.h
@@ -28,16 +28,17 @@ class Element;
}
template <class AnimationType>
class CommonAnimationManager {
public:
explicit CommonAnimationManager(nsPresContext *aPresContext)
: mPresContext(aPresContext)
{
+ mEventDispatcher = new AnimationEventDispatcher();
}
// NOTE: This can return null after Disconnect().
nsPresContext* PresContext() const { return mPresContext; }
/**
* Notify the manager that the pres context is going away.
*/
@@ -69,21 +70,21 @@ public:
collection->Destroy();
}
/**
* Add pending events.
*/
void QueueEvents(nsTArray<AnimationEventInfo>&& aEvents)
{
- mEventDispatcher.QueueEvents(Move(aEvents));
+ mEventDispatcher->QueueEvents(Move(aEvents));
}
- void SortEvents() { mEventDispatcher.SortEvents(); }
- void ClearEventQueue() { mEventDispatcher.ClearEventQueue(); }
+ void SortEvents() { mEventDispatcher->SortEvents(); }
+ void ClearEventQueue() { mEventDispatcher->ClearEventQueue(); }
protected:
virtual ~CommonAnimationManager()
{
MOZ_ASSERT(!mPresContext, "Disconnect should have been called");
}
void AddElementCollection(AnimationCollection<AnimationType>* aCollection)
@@ -96,17 +97,17 @@ protected:
mElementCollections.getFirst()) {
head->Destroy(); // Note: this removes 'head' from mElementCollections.
}
}
LinkedList<AnimationCollection<AnimationType>> mElementCollections;
nsPresContext *mPresContext; // weak (non-null from ctor to Disconnect)
- mozilla::AnimationEventDispatcher mEventDispatcher;
+ RefPtr<mozilla::AnimationEventDispatcher> mEventDispatcher;
};
/**
* Utility class for referencing the element that created a CSS animation or
* transition. It is non-owning (i.e. it uses a raw pointer) since it is only
* expected to be set by the owned animation while it actually being managed
* by the owning element.
*
--- a/layout/style/nsAnimationManager.h
+++ b/layout/style/nsAnimationManager.h
@@ -308,17 +308,17 @@ public:
void UpdateAnimations(
mozilla::dom::Element* aElement,
mozilla::CSSPseudoElementType aPseudoType,
const mozilla::ServoStyleContext* aComputedValues);
void DispatchEvents()
{
RefPtr<nsAnimationManager> kungFuDeathGrip(this);
- mEventDispatcher.DispatchEvents(mPresContext);
+ mEventDispatcher->DispatchEvents(mPresContext);
}
// Utility function to walk through |aIter| to find the Keyframe with
// matching offset and timing function but stopping as soon as the offset
// differs from |aOffset| (i.e. it assumes a sorted iterator).
//
// If a matching Keyframe is found,
// Returns true and sets |aIndex| to the index of the matching Keyframe
--- a/layout/style/nsTransitionManager.h
+++ b/layout/style/nsTransitionManager.h
@@ -361,17 +361,17 @@ public:
bool InAnimationOnlyStyleUpdate() const {
return mInAnimationOnlyStyleUpdate;
}
void DispatchEvents()
{
RefPtr<nsTransitionManager> kungFuDeathGrip(this);
- mEventDispatcher.DispatchEvents(mPresContext);
+ mEventDispatcher->DispatchEvents(mPresContext);
}
protected:
virtual ~nsTransitionManager() {}
typedef nsTArray<RefPtr<mozilla::dom::CSSTransition>>
OwningCSSTransitionPtrArray;