From 8ce81994af260dd6967e2082f8ea782c91f5fd04 Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Tue, 6 Jan 2009 21:37:28 +0200 Subject: [PATCH] Bug 472212, r+sr=bz --- content/xbl/src/nsXBLBinding.cpp | 67 ++++++++++++------------- content/xbl/src/nsXBLBinding.h | 2 + content/xbl/src/nsXBLInsertionPoint.cpp | 26 +++++----- 3 files changed, 46 insertions(+), 49 deletions(-) diff --git a/content/xbl/src/nsXBLBinding.cpp b/content/xbl/src/nsXBLBinding.cpp index 6576781ca26..602681d771a 100644 --- a/content/xbl/src/nsXBLBinding.cpp +++ b/content/xbl/src/nsXBLBinding.cpp @@ -283,6 +283,9 @@ nsXBLBinding::nsXBLBinding(nsXBLPrototypeBinding* aBinding) nsXBLBinding::~nsXBLBinding(void) { + if (mContent) { + nsXBLBinding::UninstallAnonymousContent(mContent->GetOwnerDoc(), mContent); + } delete mInsertionPointTable; nsIXBLDocumentInfo* info = mPrototypeBinding->XBLDocumentInfo(); NS_RELEASE(info); @@ -307,6 +310,10 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLBinding) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLBinding) // XXX Probably can't unlink mPrototypeBinding->XBLDocumentInfo(), because // mPrototypeBinding is weak. + if (tmp->mContent) { + nsXBLBinding::UninstallAnonymousContent(tmp->mContent->GetOwnerDoc(), + tmp->mContent); + } NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContent) // XXX What about mNextBinding and mInsertionPointTable? NS_IMPL_CYCLE_COLLECTION_UNLINK_END @@ -372,6 +379,29 @@ nsXBLBinding::InstallAnonymousContent(nsIContent* aAnonParent, nsIContent* aElem } } +void +nsXBLBinding::UninstallAnonymousContent(nsIDocument* aDocument, + nsIContent* aAnonParent) +{ + nsAutoScriptBlocker scriptBlocker; + // Hold a strong ref while doing this, just in case. + nsCOMPtr anonParent = aAnonParent; +#ifdef MOZ_XUL + nsCOMPtr xuldoc = + do_QueryInterface(aDocument); +#endif + PRUint32 childCount = aAnonParent->GetChildCount(); + for (PRUint32 i = 0; i < childCount; ++i) { + nsIContent* child = aAnonParent->GetChildAt(i); + child->UnbindFromTree(); +#ifdef MOZ_XUL + if (xuldoc) { + xuldoc->RemoveSubtreeFromDocument(child); + } +#endif + } +} + void nsXBLBinding::SetBoundElement(nsIContent* aElement) { @@ -726,19 +756,7 @@ nsXBLBinding::GenerateAnonymousContent() (localName != nsGkAtoms::observes && localName != nsGkAtoms::_template)) { // Undo InstallAnonymousContent - PRUint32 childCount = mContent->GetChildCount(); -#ifdef MOZ_XUL - nsCOMPtr xuldoc(do_QueryInterface(doc)); -#endif - for (PRUint32 k = 0; k < childCount; ++k) { - nsIContent* child = mContent->GetChildAt(k); - child->UnbindFromTree(); -#ifdef MOZ_XUL - if (xuldoc) { - xuldoc->RemoveSubtreeFromDocument(child); - } -#endif - } + UninstallAnonymousContent(doc, mContent); // Kill all anonymous content. mContent = nsnull; @@ -1153,28 +1171,7 @@ nsXBLBinding::ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocumen mInsertionPointTable->Enumerate(ChangeDocumentForDefaultContent, nsnull); -#ifdef MOZ_XUL - nsCOMPtr xuldoc(do_QueryInterface(aOldDocument)); -#endif - - nsAutoScriptBlocker scriptBlocker; - // Unbind the _kids_ of the anonymous content, not just the anonymous - // content itself, since they are bound to some other parent. Basically - // we want to undo the mess that InstallAnonymousContent created. - PRUint32 childCount = anonymous->GetChildCount(); - for (PRUint32 i = 0; i < childCount; i++) { - anonymous->GetChildAt(i)->UnbindFromTree(); - } - - anonymous->UnbindFromTree(); // Kill it. - -#ifdef MOZ_XUL - // To make XUL templates work (and other XUL-specific stuff), - // we'll need to notify it using its add & remove APIs. Grab the - // interface now... - if (xuldoc) - xuldoc->RemoveSubtreeFromDocument(anonymous); -#endif + nsXBLBinding::UninstallAnonymousContent(aOldDocument, anonymous); } // Make sure that henceforth we don't claim that mBoundElement's children diff --git a/content/xbl/src/nsXBLBinding.h b/content/xbl/src/nsXBLBinding.h index c61f18bb2b1..d13ed1baa5e 100644 --- a/content/xbl/src/nsXBLBinding.h +++ b/content/xbl/src/nsXBLBinding.h @@ -120,6 +120,8 @@ public: void GenerateAnonymousContent(); void InstallAnonymousContent(nsIContent* aAnonParent, nsIContent* aElement); + static void UninstallAnonymousContent(nsIDocument* aDocument, + nsIContent* aAnonParent); void InstallEventHandlers(); nsresult InstallImplementation(); diff --git a/content/xbl/src/nsXBLInsertionPoint.cpp b/content/xbl/src/nsXBLInsertionPoint.cpp index 51addde7285..62e70319508 100644 --- a/content/xbl/src/nsXBLInsertionPoint.cpp +++ b/content/xbl/src/nsXBLInsertionPoint.cpp @@ -38,6 +38,7 @@ #include "nsXBLInsertionPoint.h" #include "nsContentUtils.h" +#include "nsXBLBinding.h" nsXBLInsertionPoint::nsXBLInsertionPoint(nsIContent* aParentElement, PRUint32 aIndex, @@ -50,6 +51,10 @@ nsXBLInsertionPoint::nsXBLInsertionPoint(nsIContent* aParentElement, nsXBLInsertionPoint::~nsXBLInsertionPoint() { + if (mDefaultContent) { + nsXBLBinding::UninstallAnonymousContent(mDefaultContent->GetOwnerDoc(), + mDefaultContent); + } } nsrefcnt @@ -69,6 +74,10 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLInsertionPoint) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLInsertionPoint) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mElements) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDefaultContentTemplate) + if (tmp->mDefaultContent) { + nsXBLBinding::UninstallAnonymousContent(tmp->mDefaultContent->GetOwnerDoc(), + tmp->mDefaultContent); + } NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDefaultContent) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsXBLInsertionPoint) @@ -116,18 +125,7 @@ nsXBLInsertionPoint::UnbindDefaultContent() return; } - // Hold a strong ref while doing this, just in case - nsCOMPtr defContent = mDefaultContent; - - nsAutoScriptBlocker scriptBlocker; - - // Unbind the _kids_ of the default content, not just the default content - // itself, since they are bound to some other parent. Basically we want to - // undo the mess that InstallAnonymousContent created. - PRUint32 childCount = mDefaultContent->GetChildCount(); - for (PRUint32 i = 0; i < childCount; i++) { - defContent->GetChildAt(i)->UnbindFromTree(); - } - - defContent->UnbindFromTree(); + // Undo InstallAnonymousContent. + nsXBLBinding::UninstallAnonymousContent(mDefaultContent->GetOwnerDoc(), + mDefaultContent); }