Bug 1025638 - Traverse and unlink nsXBLPrototypeResources members. r=mccr8, a=lmandel
authorWilliam Chen <wchen@mozilla.com>
Mon, 23 Jun 2014 19:09:36 -0700
changeset 208887 a917c02f214555d9acfee594255a22f32a15c2b9
parent 208886 9e809dfdf2ae4c5d2842e88e9debc320bd877e75
child 208888 58fd51655b270ec57a1503bcc88c509502d8052a
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8, lmandel
bugs1025638
milestone32.0a2
Bug 1025638 - Traverse and unlink nsXBLPrototypeResources members. r=mccr8, a=lmandel
content/base/crashtests/1026714.html
content/base/crashtests/crashtests.list
dom/xbl/nsXBLDocumentInfo.cpp
dom/xbl/nsXBLPrototypeBinding.cpp
dom/xbl/nsXBLPrototypeBinding.h
dom/xbl/nsXBLPrototypeResources.cpp
dom/xbl/nsXBLPrototypeResources.h
new file mode 100644
--- /dev/null
+++ b/content/base/crashtests/1026714.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<body onload="f()">
+  <div></div>
+  <style>
+    div { color: blue; }
+  </style>
+  <script>
+    function f() {
+      // This should not leak.
+      var div = document.querySelector("div");
+      var shadow = div.createShadowRoot();
+      shadow.innerHTML = '<div><style scoped>p { color: green; }</style>';
+    }
+  </script>
+</body>
--- a/content/base/crashtests/crashtests.list
+++ b/content/base/crashtests/crashtests.list
@@ -144,8 +144,9 @@ load 849727.html
 load 849732.html
 load 849601.html
 skip-if(Android) load 851353-1.html
 load 863950.html
 load 864448.html
 load 930250.html
 load 942979.html
 load 978646.html
+load 1026714.html
--- a/dom/xbl/nsXBLDocumentInfo.cpp
+++ b/dom/xbl/nsXBLDocumentInfo.cpp
@@ -46,19 +46,19 @@ TraverseProtos(const nsACString &aKey, n
 {
   nsCycleCollectionTraversalCallback *cb =
     static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
   aProto->Traverse(*cb);
   return PL_DHASH_NEXT;
 }
 
 static PLDHashOperator
-UnlinkProtoJSObjects(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure)
+UnlinkProto(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure)
 {
-  aProto->UnlinkJSObjects();
+  aProto->Unlink();
   return PL_DHASH_NEXT;
 }
 
 struct ProtoTracer
 {
   const TraceCallbacks &mCallbacks;
   void *mClosure;
 };
@@ -70,17 +70,17 @@ TraceProtos(const nsACString &aKey, nsXB
   aProto->Trace(closure->mCallbacks, closure->mClosure);
   return PL_DHASH_NEXT;
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLDocumentInfo)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLDocumentInfo)
   if (tmp->mBindingTable) {
-    tmp->mBindingTable->EnumerateRead(UnlinkProtoJSObjects, nullptr);
+    tmp->mBindingTable->EnumerateRead(UnlinkProto, nullptr);
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXBLDocumentInfo)
   if (tmp->mDocument &&
       nsCCUncollectableMarker::InGeneration(cb, tmp->mDocument->GetMarkedCCGeneration())) {
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
--- a/dom/xbl/nsXBLPrototypeBinding.cpp
+++ b/dom/xbl/nsXBLPrototypeBinding.cpp
@@ -149,20 +149,25 @@ nsXBLPrototypeBinding::Traverse(nsCycleC
   cb.NoteXPCOMChild(mBinding);
   if (mResources) {
     mResources->Traverse(cb);
   }
   ImplCycleCollectionTraverse(cb, mInterfaceTable, "proto mInterfaceTable");
 }
 
 void
-nsXBLPrototypeBinding::UnlinkJSObjects()
+nsXBLPrototypeBinding::Unlink()
 {
-  if (mImplementation)
+  if (mImplementation) {
     mImplementation->UnlinkJSObjects();
+  }
+
+  if (mResources) {
+    mResources->Unlink();
+  }
 }
 
 void
 nsXBLPrototypeBinding::Trace(const TraceCallbacks& aCallbacks, void *aClosure) const
 {
   if (mImplementation)
     mImplementation->Trace(aCallbacks, aClosure);
 }
--- a/dom/xbl/nsXBLPrototypeBinding.h
+++ b/dom/xbl/nsXBLPrototypeBinding.h
@@ -232,17 +232,17 @@ public:
   // this with the Initialize() method, which must be called after the
   // binding's handlers, properties, etc are all set.
   nsresult Init(const nsACString& aRef,
                 nsXBLDocumentInfo* aInfo,
                 nsIContent* aElement,
                 bool aFirstBinding = false);
 
   void Traverse(nsCycleCollectionTraversalCallback &cb) const;
-  void UnlinkJSObjects();
+  void Unlink();
   void Trace(const TraceCallbacks& aCallbacks, void *aClosure) const;
 
 // Internal member functions.
 public:
   /**
    * GetImmediateChild locates the immediate child of our binding element which
    * has the localname given by aTag and is in the XBL namespace.
    */
--- a/dom/xbl/nsXBLPrototypeResources.cpp
+++ b/dom/xbl/nsXBLPrototypeResources.cpp
@@ -112,20 +112,30 @@ nsresult
 nsXBLPrototypeResources::Write(nsIObjectOutputStream* aStream)
 {
   if (mLoader)
     return mLoader->Write(aStream);
   return NS_OK;
 }
 
 void
-nsXBLPrototypeResources::Traverse(nsCycleCollectionTraversalCallback &cb) const
+nsXBLPrototypeResources::Traverse(nsCycleCollectionTraversalCallback &cb)
 {
   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "proto mResources mLoader");
   cb.NoteXPCOMChild(mLoader);
+
+  CycleCollectionNoteChild(cb, mRuleProcessor.get(), "mRuleProcessor");
+  ImplCycleCollectionTraverse(cb, mStyleSheetList, "mStyleSheetList");
+}
+
+void
+nsXBLPrototypeResources::Unlink()
+{
+  mStyleSheetList.Clear();
+  mRuleProcessor = nullptr;
 }
 
 void
 nsXBLPrototypeResources::ClearLoader()
 {
   mLoader = nullptr;
 }
 
@@ -141,18 +151,17 @@ void
 nsXBLPrototypeResources::AppendStyleSheet(nsCSSStyleSheet* aSheet)
 {
   mStyleSheetList.AppendElement(aSheet);
 }
 
 void
 nsXBLPrototypeResources::RemoveStyleSheet(nsCSSStyleSheet* aSheet)
 {
-  DebugOnly<bool> found = mStyleSheetList.RemoveElement(aSheet);
-  MOZ_ASSERT(found, "Trying to remove a sheet that does not exist.");
+  mStyleSheetList.RemoveElement(aSheet);
 }
 
 void
 nsXBLPrototypeResources::InsertStyleSheetAt(size_t aIndex, nsCSSStyleSheet* aSheet)
 {
   mStyleSheetList.InsertElementAt(aIndex, aSheet);
 }
 
--- a/dom/xbl/nsXBLPrototypeResources.h
+++ b/dom/xbl/nsXBLPrototypeResources.h
@@ -27,17 +27,18 @@ public:
 
   void LoadResources(bool* aResult);
   void AddResource(nsIAtom* aResourceType, const nsAString& aSrc);
   void AddResourceListener(nsIContent* aElement);
   nsresult FlushSkinSheets();
 
   nsresult Write(nsIObjectOutputStream* aStream);
 
-  void Traverse(nsCycleCollectionTraversalCallback &cb) const;
+  void Traverse(nsCycleCollectionTraversalCallback &cb);
+  void Unlink();
 
   void ClearLoader();
 
   void AppendStyleSheet(nsCSSStyleSheet* aSheet);
   void RemoveStyleSheet(nsCSSStyleSheet* aSheet);
   void InsertStyleSheetAt(size_t aIndex, nsCSSStyleSheet* aSheet);
   nsCSSStyleSheet* StyleSheetAt(size_t aIndex) const;
   size_t SheetCount() const;