Bug 1438541 P3 Allow nsIGlobalObject::ForEachEventTargetObject() callback function to abort iteration. r=smaug
authorBen Kelly <ben@wanderview.com>
Wed, 21 Feb 2018 10:53:53 -0800
changeset 404683 26cad18f73fa3286a302abd18d648e2f577a26f0
parent 404682 9a2fc66acc13134ec5025fa65ed226e196e30a2e
child 404684 5675db58f9e9b343067a3afa12bb0d6b788875ab
push id100067
push userbkelly@mozilla.com
push dateWed, 21 Feb 2018 18:54:01 +0000
treeherdermozilla-inbound@5675db58f9e9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1438541
milestone60.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1438541 P3 Allow nsIGlobalObject::ForEachEventTargetObject() callback function to abort iteration. r=smaug
dom/base/nsGlobalWindowInner.cpp
dom/base/nsIGlobalObject.cpp
dom/base/nsIGlobalObject.h
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -6347,27 +6347,24 @@ nsGlobalWindowInner::GetController() con
   return Move(controller);
 }
 
 RefPtr<ServiceWorker>
 nsGlobalWindowInner::GetOrCreateServiceWorker(const ServiceWorkerDescriptor& aDescriptor)
 {
   MOZ_ASSERT(NS_IsMainThread());
   RefPtr<ServiceWorker> ref;
-  ForEachEventTargetObject([&] (DOMEventTargetHelper* aTarget) {
-    // TODO: allow short-cuts
-    if (ref) {
-      return;
-    }
-
+  ForEachEventTargetObject([&] (DOMEventTargetHelper* aTarget, bool* aDoneOut) {
     RefPtr<ServiceWorker> sw = do_QueryObject(aTarget);
     if (!sw || !sw->Descriptor().Matches(aDescriptor)) {
       return;
     }
+
     ref = sw.forget();
+    *aDoneOut = true;
   });
 
   if (!ref) {
     ref = ServiceWorker::Create(this, aDescriptor);
   }
 
   return ref.forget();
 }
@@ -6895,17 +6892,17 @@ nsGlobalWindowInner::AddSizeOfIncludingT
     }
   }
 
   if (mNavigator) {
     aWindowSizes.mDOMOtherSize +=
       mNavigator->SizeOfIncludingThis(aWindowSizes.mState.mMallocSizeOf);
   }
 
-  ForEachEventTargetObject([&] (DOMEventTargetHelper* et) {
+  ForEachEventTargetObject([&] (DOMEventTargetHelper* et, bool* aDoneOut) {
     if (nsCOMPtr<nsISizeOfEventTarget> iSizeOf = do_QueryObject(et)) {
       aWindowSizes.mDOMEventTargetsSize +=
         iSizeOf->SizeOfEventTargetIncludingThis(
           aWindowSizes.mState.mMallocSizeOf);
     }
     if (EventListenerManager* elm = et->GetExistingListenerManager()) {
       aWindowSizes.mDOMEventListenersCount += elm->ListenerCount();
     }
--- a/dom/base/nsIGlobalObject.cpp
+++ b/dom/base/nsIGlobalObject.cpp
@@ -136,36 +136,40 @@ void
 nsIGlobalObject::RemoveEventTargetObject(DOMEventTargetHelper* aObject)
 {
   MOZ_DIAGNOSTIC_ASSERT(aObject);
   MOZ_ASSERT(mEventTargetObjects.Contains(aObject));
   mEventTargetObjects.RemoveEntry(aObject);
 }
 
 void
-nsIGlobalObject::ForEachEventTargetObject(const std::function<void(DOMEventTargetHelper*)>& aFunc) const
+nsIGlobalObject::ForEachEventTargetObject(const std::function<void(DOMEventTargetHelper*, bool* aDoneOut)>& aFunc) const
 {
   // Protect against the function call triggering a mutation of the hash table
   // 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());
   }
 
   // Iterate the target list and call the function on each one.
+  bool done = false;
   for (auto target : targetList) {
-    aFunc(target);
+    aFunc(target, &done);
+    if (done) {
+      break;
+    }
   }
 }
 
 void
 nsIGlobalObject::DisconnectEventTargetObjects()
 {
-  ForEachEventTargetObject([&] (DOMEventTargetHelper* aTarget) {
+  ForEachEventTargetObject([&] (DOMEventTargetHelper* aTarget, bool* aDoneOut) {
     aTarget->DisconnectFromOwner();
 
     // Calling DisconnectFromOwner() should result in
     // RemoveEventTargetObject() being called.
     MOZ_DIAGNOSTIC_ASSERT(!mEventTargetObjects.Contains(aTarget));
   });
 }
 
--- a/dom/base/nsIGlobalObject.h
+++ b/dom/base/nsIGlobalObject.h
@@ -99,17 +99,17 @@ public:
   // called correctly.  RemoveEventTargetObject() must be called
   // before the DETH object is destroyed.
   void AddEventTargetObject(mozilla::DOMEventTargetHelper* aObject);
   void RemoveEventTargetObject(mozilla::DOMEventTargetHelper* aObject);
 
   // Iterate the registered DETH objects and call the given function
   // for each one.
   void
-  ForEachEventTargetObject(const std::function<void(mozilla::DOMEventTargetHelper*)>& aFunc) const;
+  ForEachEventTargetObject(const std::function<void(mozilla::DOMEventTargetHelper*, bool* aDoneOut)>& aFunc) const;
 
   virtual bool IsInSyncOperation() { return false; }
 
   virtual mozilla::Maybe<mozilla::dom::ClientInfo>
   GetClientInfo() const;
 
   virtual mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor>
   GetController() const;