diff --git a/content/xbl/src/nsXBLContentSink.cpp b/content/xbl/src/nsXBLContentSink.cpp index aa0d628d8516..77bb5dee48d7 100644 --- a/content/xbl/src/nsXBLContentSink.cpp +++ b/content/xbl/src/nsXBLContentSink.cpp @@ -355,12 +355,19 @@ nsXBLContentSink::CreateElement(const nsIParserNode& aNode, PRInt32 aNameSpaceID if (!prototype) return NS_ERROR_OUT_OF_MEMORY; - prototype->mType = nsXULPrototypeNode::eType_RefCounted_Element; prototype->mNodeInfo = aNodeInfo; - + + // Reset the refcnt to 0. Normally XUL prototype elements get a refcnt of 1 + // to represent ownership by the XUL prototype document. In our case we have + // no prototype document, and our initial ref count of 1 will come from being + // wrapped by a real XUL element in the Create call below. + prototype->mRefCnt = 0; + AddAttributesToXULPrototype(aNode, prototype); + // Following this function call, the prototype's ref count will be 1. nsresult rv = nsXULElement::Create(prototype, mDocument, PR_FALSE, aResult); + if (NS_FAILED(rv)) return rv; return NS_OK; } diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp index 687c2d714ea8..8180484602a5 100644 --- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -515,11 +515,8 @@ nsXULElement::Init() nsXULElement::~nsXULElement() { - if (mPrototype && mPrototype->mType == nsXULPrototypeNode::eType_RefCounted_Element) { - mPrototype->mRefCnt--; - if (mPrototype->mRefCnt == 0) - delete mPrototype; - } + if (mPrototype) + mPrototype->Release(); delete mSlots; @@ -578,8 +575,7 @@ nsXULElement::Create(nsXULPrototypeElement* aPrototype, element->mPrototype = aPrototype; element->mDocument = aDocument; - if (aPrototype->mType == nsXULPrototypeNode::eType_RefCounted_Element) - aPrototype->mRefCnt++; + aPrototype->AddRef(); if (aIsScriptable) { // Check each attribute on the prototype to see if we need to do @@ -4760,13 +4756,7 @@ nsresult nsXULElement::MakeHeavyweight() } } - if (proto->mType == nsXULPrototypeNode::eType_RefCounted_Element) { - proto->mRefCnt--; - if (proto->mRefCnt == 0) - delete proto; - } - - + proto->Release(); return NS_OK; } diff --git a/content/xul/content/src/nsXULElement.h b/content/xul/content/src/nsXULElement.h index f37a66b613da..b31de7f61c9f 100644 --- a/content/xul/content/src/nsXULElement.h +++ b/content/xul/content/src/nsXULElement.h @@ -186,24 +186,31 @@ public: class nsXULPrototypeNode { public: - enum Type { eType_Element, eType_RefCounted_Element, eType_Script, eType_Text }; + enum Type { eType_Element, eType_Script, eType_Text }; Type mType; - union { - PRInt32 mLineNo; - PRInt32 mRefCnt; - }; - + PRInt32 mLineNo; + PRInt32 mRefCnt; + virtual ~nsXULPrototypeNode() {} virtual nsresult Serialize(nsIObjectOutputStream* aStream, nsIScriptContext* aContext); virtual nsresult Deserialize(nsIObjectInputStream* aStream, nsIScriptContext* aContext); + void AddRef() { mRefCnt++; }; + void Release() + { + mRefCnt--; + if (mRefCnt == 0) + delete this; + }; + virtual void ReleaseSubtree() { Release(); }; + protected: nsXULPrototypeNode(Type aType, PRInt32 aLineNo) - : mType(aType), mLineNo(aLineNo) {} + : mType(aType), mLineNo(aLineNo), mRefCnt(1) {} }; class nsXULPrototypeElement : public nsXULPrototypeNode @@ -226,13 +233,19 @@ public: delete[] mAttributes; delete mClassList; - - for (PRInt32 i = mNumChildren - 1; i >= 0; --i) - delete mChildren[i]; - delete[] mChildren; } + virtual void ReleaseSubtree() + { + if (mChildren) { + for (PRInt32 i = mNumChildren-1; i >= 0; i--) + mChildren[i]->ReleaseSubtree(); + } + + nsXULPrototypeNode::ReleaseSubtree(); + } + virtual nsresult Serialize(nsIObjectOutputStream* aStream, nsIScriptContext* aContext); virtual nsresult Deserialize(nsIObjectInputStream* aStream, diff --git a/content/xul/document/src/nsXULContentSink.cpp b/content/xul/document/src/nsXULContentSink.cpp index 48fb6c167f5c..0477e591e2d6 100644 --- a/content/xul/document/src/nsXULContentSink.cpp +++ b/content/xul/document/src/nsXULContentSink.cpp @@ -1399,7 +1399,7 @@ XULContentSinkImpl::CreateElement(nsINodeInfo *aNodeInfo, return NS_ERROR_OUT_OF_MEMORY; element->mNodeInfo = aNodeInfo; - + *aResult = element; return NS_OK; } diff --git a/content/xul/document/src/nsXULPrototypeDocument.cpp b/content/xul/document/src/nsXULPrototypeDocument.cpp index 470fac288df2..2b7c700db11a 100644 --- a/content/xul/document/src/nsXULPrototypeDocument.cpp +++ b/content/xul/document/src/nsXULPrototypeDocument.cpp @@ -238,14 +238,15 @@ nsXULPrototypeDocument::Init() return NS_OK; } - nsXULPrototypeDocument::~nsXULPrototypeDocument() { if (mGlobalObject) { mGlobalObject->SetContext(nsnull); // remove circular reference mGlobalObject->SetGlobalObjectOwner(nsnull); // just in case } - delete mRoot; + + if (mRoot) + mRoot->ReleaseSubtree(); } NS_IMPL_ISUPPORTS3(nsXULPrototypeDocument,