Bug 1229760 - CustomElement registry keeps strong reference to the unresolved elements, r=wchen, a=lizzard
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Tue, 08 Dec 2015 12:13:14 -0800
changeset 305791 fcbcabd1ca3bf53ee7efd9a9fa490ec3596315c1
parent 305790 e575218cea33b886d764752d6819b067c76f2c4b
child 305792 bf585498f2a04a8e284f75281cc1b48e24f0a157
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswchen, lizzard
bugs1229760
milestone44.0a2
Bug 1229760 - CustomElement registry keeps strong reference to the unresolved elements, r=wchen, a=lizzard
dom/base/nsDocument.cpp
dom/base/nsDocument.h
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -374,30 +374,16 @@ CustomDefinitionsTraverse(CustomElementH
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
       "mCustomDefinitions->mCallbacks->mDetachedCallback");
     cb->NoteXPCOMChild(aDefinition->mCallbacks->mDetachedCallback.Value());
   }
 
   return PL_DHASH_NEXT;
 }
 
-static PLDHashOperator
-CandidatesTraverse(CustomElementHashKey* aKey,
-                   nsTArray<RefPtr<Element>>* aData,
-                   void* aArg)
-{
-  nsCycleCollectionTraversalCallback *cb =
-    static_cast<nsCycleCollectionTraversalCallback*>(aArg);
-  for (size_t i = 0; i < aData->Length(); ++i) {
-    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mCandidatesMap->Element");
-    cb->NoteXPCOMChild(aData->ElementAt(i));
-  }
-  return PL_DHASH_NEXT;
-}
-
 struct CustomDefinitionTraceArgs
 {
   const TraceCallbacks& callbacks;
   void* closure;
 };
 
 static PLDHashOperator
 CustomDefinitionTrace(CustomElementHashKey *aKey,
@@ -416,23 +402,21 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(Registry)
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Registry)
   CustomDefinitionTraceArgs customDefinitionArgs = { aCallbacks, aClosure };
   tmp->mCustomDefinitions.EnumerateRead(CustomDefinitionTrace,
                                         &customDefinitionArgs);
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Registry)
   tmp->mCustomDefinitions.EnumerateRead(CustomDefinitionsTraverse, &cb);
-  tmp->mCandidatesMap.EnumerateRead(CandidatesTraverse, &cb);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Registry)
   tmp->mCustomDefinitions.Clear();
-  tmp->mCandidatesMap.Clear();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Registry)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Registry)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Registry)
@@ -5911,26 +5895,26 @@ nsDocument::RegisterUnresolvedElement(El
     typeName = info->NameAtom();
   }
 
   CustomElementHashKey key(info->NamespaceID(), typeName);
   if (mRegistry->mCustomDefinitions.Get(&key)) {
     return NS_OK;
   }
 
-  nsTArray<RefPtr<Element>>* unresolved;
+  nsTArray<nsWeakPtr>* unresolved;
   mRegistry->mCandidatesMap.Get(&key, &unresolved);
   if (!unresolved) {
-    unresolved = new nsTArray<RefPtr<Element>>();
+    unresolved = new nsTArray<nsWeakPtr>();
     // Ownership of unresolved is taken by mCandidatesMap.
     mRegistry->mCandidatesMap.Put(&key, unresolved);
   }
 
-  RefPtr<Element>* elem = unresolved->AppendElement();
-  *elem = aElement;
+  nsWeakPtr* elem = unresolved->AppendElement();
+  *elem = do_GetWeakReference(aElement);
   aElement->AddStates(NS_EVENT_STATE_UNRESOLVED);
 
   return NS_OK;
 }
 
 void
 nsDocument::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
                                      Element* aCustomElement,
@@ -6304,21 +6288,24 @@ nsDocument::RegisterElement(JSContext* a
                                 typeAtom,
                                 nameAtom,
                                 callbacks,
                                 namespaceID,
                                 0 /* TODO dependent on HTML imports. Bug 877072 */);
   definitions.Put(&key, definition);
 
   // Do element upgrade.
-  nsAutoPtr<nsTArray<RefPtr<Element>>> candidates;
+  nsAutoPtr<nsTArray<nsWeakPtr>> candidates;
   mRegistry->mCandidatesMap.RemoveAndForget(&key, candidates);
   if (candidates) {
     for (size_t i = 0; i < candidates->Length(); ++i) {
-      Element *elem = candidates->ElementAt(i);
+      nsCOMPtr<Element> elem = do_QueryReferent(candidates->ElementAt(i));
+      if (!elem) {
+        continue;
+      }
 
       elem->RemoveStates(NS_EVENT_STATE_UNRESOLVED);
 
       // Make sure that the element name matches the name in the definition.
       // (e.g. a definition for x-button extending button should match
       // <button is="x-button"> but not <x-button>.
       if (elem->NodeInfo()->NameAtom() != nameAtom) {
         //Skip over this element because definition does not apply.
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -422,17 +422,17 @@ public:
 
 protected:
   virtual ~Registry();
 
   typedef nsClassHashtable<mozilla::dom::CustomElementHashKey,
                            mozilla::dom::CustomElementDefinition>
     DefinitionMap;
   typedef nsClassHashtable<mozilla::dom::CustomElementHashKey,
-                           nsTArray<RefPtr<mozilla::dom::Element>>>
+                           nsTArray<nsWeakPtr>>
     CandidateMap;
 
   // Hashtable for custom element definitions in web components.
   // Custom prototypes are stored in the compartment where
   // registerElement was called.
   DefinitionMap mCustomDefinitions;
 
   // The "upgrade candidates map" from the web components spec. Maps from a