Make XUL prototype elements set mNumChildren to 0 when they stop owning their children in ReleaseSubtree. b=386947 r+sr=sicking
authordbaron@dbaron.org
Thu, 05 Jul 2007 15:40:26 -0700
changeset 3175 2fa526b3d4a13744ec0e01576aeebda68eabc1f5
parent 3174 05f8604dfd126f2d7564395469abe327dfdefcc6
child 3176 61fefadbf64bc584b77ce613c7d19b49bbfb5ba4
push idunknown
push userunknown
push dateunknown
bugs386947
milestone1.9a7pre
Make XUL prototype elements set mNumChildren to 0 when they stop owning their children in ReleaseSubtree. b=386947 r+sr=sicking
content/xul/content/src/nsXULElement.h
--- a/content/xul/content/src/nsXULElement.h
+++ b/content/xul/content/src/nsXULElement.h
@@ -215,16 +215,24 @@ public:
     }
     void Release()
     {
         --mRefCnt;
         NS_LOG_RELEASE(this, mRefCnt, ClassName());
         if (mRefCnt == 0)
             delete this;
     }
+    /**
+     * The prototype document must call ReleaseSubtree when it is going
+     * away.  This makes the parents through the tree stop owning their
+     * children, whether or not the parent's reference count is zero.
+     * Individual elements may still own individual prototypes, but
+     * those prototypes no longer remember their children to allow them
+     * to be constructed.
+     */
     virtual void ReleaseSubtree() { Release(); }
 
     NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsXULPrototypeNode)
 
 protected:
     nsXULPrototypeNode(Type aType)
         : mType(aType), mRefCnt(1) {}
 };
@@ -244,31 +252,35 @@ public:
     }
 
     virtual ~nsXULPrototypeElement()
     {
         PRUint32 i;
         for (i = 0; i < mNumAttributes; i++)
             mAttributes[i].Finalize(mScriptTypeID);
         delete[] mAttributes;
-        delete[] mChildren;
+        NS_ASSERTION(!mChildren && mNumChildren == 0,
+                     "ReleaseSubtree not called");
     }
 
 #ifdef NS_BUILD_REFCNT_LOGGING
     virtual const char* ClassName() { return "nsXULPrototypeElement"; }
     virtual PRUint32 ClassSize() { return sizeof(*this); }
 #endif
 
     virtual void ReleaseSubtree()
     {
       if (mChildren) {
         for (PRInt32 i = mNumChildren-1; i >= 0; i--) {
           if (mChildren[i])
             mChildren[i]->ReleaseSubtree();
         }
+        mNumChildren = 0;
+        delete[] mChildren;
+        mChildren = nsnull;
       }
 
       nsXULPrototypeNode::ReleaseSubtree();
     }
 
     virtual nsresult Serialize(nsIObjectOutputStream* aStream,
                                nsIScriptGlobalObject* aGlobal,
                                const nsCOMArray<nsINodeInfo> *aNodeInfos);