зеркало из https://github.com/mozilla/gecko-dev.git
bug 1457867, store DOMEventTargetHelper objects in global object as a linked list, r=bkelly
--HG-- extra : rebase_source : 415c03249bae1edc4313bcf15f91716a748565f9
This commit is contained in:
Родитель
5182b6ad11
Коммит
ed65a2bfc8
|
@ -48,8 +48,8 @@ void
|
|||
AnimationTimeline::RemoveAnimation(Animation* aAnimation)
|
||||
{
|
||||
MOZ_ASSERT(!aAnimation->GetTimeline() || aAnimation->GetTimeline() == this);
|
||||
if (aAnimation->isInList()) {
|
||||
aAnimation->remove();
|
||||
if (static_cast<LinkedListElement<Animation>*>(aAnimation)->isInList()) {
|
||||
static_cast<LinkedListElement<Animation>*>(aAnimation)->remove();
|
||||
}
|
||||
mAnimations.RemoveEntry(aAnimation);
|
||||
}
|
||||
|
|
|
@ -167,7 +167,8 @@ DocumentTimeline::WillRefresh(mozilla::TimeStamp aTime)
|
|||
nsAutoAnimationMutationBatch mb(mDocument);
|
||||
|
||||
for (Animation* animation = mAnimationOrder.getFirst(); animation;
|
||||
animation = animation->getNext()) {
|
||||
animation =
|
||||
static_cast<LinkedListElement<Animation>*>(animation)->getNext()) {
|
||||
// Skip any animations that are longer need associated with this timeline.
|
||||
if (animation->GetTimeline() != this) {
|
||||
// If animation has some other timeline, it better not be also in the
|
||||
|
|
|
@ -1959,7 +1959,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
|
|||
// We own only the items in mDOMMediaQueryLists that have listeners;
|
||||
// this reference is managed by their AddListener and RemoveListener
|
||||
// methods.
|
||||
for (auto mql : tmp->mDOMMediaQueryLists) {
|
||||
for (MediaQueryList* mql = tmp->mDOMMediaQueryLists.getFirst(); mql;
|
||||
mql = static_cast<LinkedListElement<MediaQueryList>*>(mql)->getNext()) {
|
||||
if (mql->HasListeners()) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mDOMMediaQueryLists item");
|
||||
cb.NoteXPCOMChild(mql);
|
||||
|
@ -2079,7 +2080,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
|
|||
// this reference is managed by their AddListener and RemoveListener
|
||||
// methods.
|
||||
for (MediaQueryList* mql = tmp->mDOMMediaQueryLists.getFirst(); mql;) {
|
||||
MediaQueryList* next = mql->getNext();
|
||||
MediaQueryList* next =
|
||||
static_cast<LinkedListElement<MediaQueryList>*>(mql)->getNext();
|
||||
mql->Disconnect();
|
||||
mql = next;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ nsIGlobalObject::~nsIGlobalObject()
|
|||
{
|
||||
UnlinkHostObjectURIs();
|
||||
DisconnectEventTargetObjects();
|
||||
MOZ_DIAGNOSTIC_ASSERT(mEventTargetObjects.IsEmpty());
|
||||
MOZ_DIAGNOSTIC_ASSERT(mEventTargetObjects.isEmpty());
|
||||
}
|
||||
|
||||
nsIPrincipal*
|
||||
|
@ -131,27 +131,29 @@ void
|
|||
nsIGlobalObject::AddEventTargetObject(DOMEventTargetHelper* aObject)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(aObject);
|
||||
MOZ_ASSERT(!mEventTargetObjects.Contains(aObject));
|
||||
mEventTargetObjects.PutEntry(aObject);
|
||||
MOZ_ASSERT(!aObject->isInList());
|
||||
mEventTargetObjects.insertBack(aObject);
|
||||
}
|
||||
|
||||
void
|
||||
nsIGlobalObject::RemoveEventTargetObject(DOMEventTargetHelper* aObject)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(aObject);
|
||||
MOZ_ASSERT(mEventTargetObjects.Contains(aObject));
|
||||
mEventTargetObjects.RemoveEntry(aObject);
|
||||
MOZ_ASSERT(aObject->isInList());
|
||||
MOZ_ASSERT(aObject->GetOwnerGlobal() == this);
|
||||
aObject->remove();
|
||||
}
|
||||
|
||||
void
|
||||
nsIGlobalObject::ForEachEventTargetObject(const std::function<void(DOMEventTargetHelper*, bool* aDoneOut)>& aFunc) const
|
||||
{
|
||||
// Protect against the function call triggering a mutation of the hash table
|
||||
// Protect against the function call triggering a mutation of the list
|
||||
// while we are iterating by copying the DETH references to a temporary
|
||||
// list.
|
||||
AutoTArray<DOMEventTargetHelper*, 64> targetList;
|
||||
for (auto iter = mEventTargetObjects.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
targetList.AppendElement(iter.Get()->GetKey());
|
||||
for (const DOMEventTargetHelper* deth = mEventTargetObjects.getFirst();
|
||||
deth; deth = deth->getNext()) {
|
||||
targetList.AppendElement(const_cast<DOMEventTargetHelper*>(deth));
|
||||
}
|
||||
|
||||
// Iterate the target list and call the function on each one.
|
||||
|
@ -159,7 +161,7 @@ nsIGlobalObject::ForEachEventTargetObject(const std::function<void(DOMEventTarge
|
|||
for (auto target : targetList) {
|
||||
// Check to see if a previous iteration's callback triggered the removal
|
||||
// of this target as a side-effect. If it did, then just ignore it.
|
||||
if (!mEventTargetObjects.Contains(target)) {
|
||||
if (target->GetOwnerGlobal() != this) {
|
||||
continue;
|
||||
}
|
||||
aFunc(target, &done);
|
||||
|
@ -177,7 +179,7 @@ nsIGlobalObject::DisconnectEventTargetObjects()
|
|||
|
||||
// Calling DisconnectFromOwner() should result in
|
||||
// RemoveEventTargetObject() being called.
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mEventTargetObjects.Contains(aTarget));
|
||||
MOZ_DIAGNOSTIC_ASSERT(aTarget->GetOwnerGlobal() != this);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -215,6 +217,5 @@ size_t
|
|||
nsIGlobalObject::ShallowSizeOfExcludingThis(MallocSizeOf aSizeOf) const
|
||||
{
|
||||
size_t rtn = mHostObjectURIs.ShallowSizeOfExcludingThis(aSizeOf);
|
||||
rtn += mEventTargetObjects.ShallowSizeOfExcludingThis(aSizeOf);
|
||||
return rtn;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#ifndef nsIGlobalObject_h__
|
||||
#define nsIGlobalObject_h__
|
||||
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/dom/ClientInfo.h"
|
||||
#include "mozilla/dom/DispatcherTrait.h"
|
||||
|
@ -41,10 +42,8 @@ class nsIGlobalObject : public nsISupports,
|
|||
nsTArray<nsCString> mHostObjectURIs;
|
||||
|
||||
// Raw pointers to bound DETH objects. These are added by
|
||||
// AddEventTargetObject(). The DETH object must call
|
||||
// RemoveEventTargetObject() before its destroyed to clear
|
||||
// its raw pointer here.
|
||||
nsTHashtable<nsPtrHashKey<mozilla::DOMEventTargetHelper>> mEventTargetObjects;
|
||||
// AddEventTargetObject().
|
||||
mozilla::LinkedList<mozilla::DOMEventTargetHelper> mEventTargetObjects;
|
||||
|
||||
bool mIsDying;
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "MainThreadUtils.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/EventListenerManager.h"
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/dom/EventTarget.h"
|
||||
|
||||
struct JSCompartment;
|
||||
|
@ -34,7 +35,8 @@ class Event;
|
|||
{ 0xa28385c6, 0x9451, 0x4d7e, \
|
||||
{ 0xa3, 0xdd, 0xf4, 0xb6, 0x87, 0x2f, 0xa4, 0x76 } }
|
||||
|
||||
class DOMEventTargetHelper : public dom::EventTarget
|
||||
class DOMEventTargetHelper : public dom::EventTarget,
|
||||
public LinkedListElement<DOMEventTargetHelper>
|
||||
{
|
||||
public:
|
||||
DOMEventTargetHelper()
|
||||
|
@ -172,7 +174,7 @@ public:
|
|||
|
||||
virtual void DisconnectFromOwner();
|
||||
using EventTarget::GetParentObject;
|
||||
virtual nsIGlobalObject* GetOwnerGlobal() const override
|
||||
virtual nsIGlobalObject* GetOwnerGlobal() const final
|
||||
{
|
||||
return mParentObject;
|
||||
}
|
||||
|
|
|
@ -2084,7 +2084,8 @@ nsPresContext::FlushPendingMediaFeatureValuesChanged()
|
|||
// Copy pointers to all the lists into a new array, in case one of our
|
||||
// notifications modifies the list.
|
||||
nsTArray<RefPtr<mozilla::dom::MediaQueryList>> localMediaQueryLists;
|
||||
for (auto* mql : mDocument->MediaQueryLists()) {
|
||||
for (MediaQueryList* mql = mDocument->MediaQueryLists().getFirst(); mql;
|
||||
mql = static_cast<LinkedListElement<MediaQueryList>*>(mql)->getNext()) {
|
||||
localMediaQueryLists.AppendElement(mql);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MediaQueryList,
|
||||
DOMEventTargetHelper)
|
||||
if (tmp->mDocument) {
|
||||
tmp->remove();
|
||||
static_cast<LinkedListElement<MediaQueryList>*>(tmp)->remove();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
|
||||
}
|
||||
tmp->Disconnect();
|
||||
|
|
Загрузка…
Ссылка в новой задаче