Bug 1025638 - Traverse and unlink nsXBLPrototypeResources members. r=mccr8
authorWilliam Chen <wchen@mozilla.com>
Mon, 23 Jun 2014 19:09:36 -0700
changeset 190379 7591c7fdee63ec7a47e5b302af791c2ca0136d4e
parent 190378 40dee680339e53ea4a993e1edd939568b77665ad
child 190380 3a5789d0e7e010b951a92d3809ca26b2e6540ec4
push id27004
push useremorley@mozilla.com
push dateTue, 24 Jun 2014 15:52:34 +0000
treeherdermozilla-central@7b174d47f3cc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8
bugs1025638
milestone33.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 1025638 - Traverse and unlink nsXBLPrototypeResources members. r=mccr8
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
@@ -150,20 +150,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
@@ -236,17 +236,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(CSSStyleSheet* aSheet)
 {
   mStyleSheetList.AppendElement(aSheet);
 }
 
 void
 nsXBLPrototypeResources::RemoveStyleSheet(CSSStyleSheet* 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, CSSStyleSheet* aSheet)
 {
   mStyleSheetList.InsertElementAt(aIndex, aSheet);
 }
 
--- a/dom/xbl/nsXBLPrototypeResources.h
+++ b/dom/xbl/nsXBLPrototypeResources.h
@@ -30,17 +30,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(mozilla::CSSStyleSheet* aSheet);
   void RemoveStyleSheet(mozilla::CSSStyleSheet* aSheet);
   void InsertStyleSheetAt(size_t aIndex, mozilla::CSSStyleSheet* aSheet);
   mozilla::CSSStyleSheet* StyleSheetAt(size_t aIndex) const;
   size_t SheetCount() const;