bug 1457867, store DOMEventTargetHelper objects in global object as a linked list, r=bkelly

--HG--
extra : rebase_source : 415c03249bae1edc4313bcf15f91716a748565f9
This commit is contained in:
Olli Pettay 2018-05-04 19:25:05 +03:00
Родитель 5182b6ad11
Коммит ed65a2bfc8
8 изменённых файлов: 30 добавлений и 24 удалений

Просмотреть файл

@ -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();