Bug 508473 part III: Pass destruction root to frame destruction methods r=bz sr=roc
authorfantasai <fantasai.cvs@inkedblade.net>
Thu, 24 Dec 2009 00:21:15 -0500
changeset 36647 1e37be566afa2f59aae7a09e8571f0350bc14542
parent 36646 912c5206ca3e735bb39494edcc0e489d5baea510
child 36648 36ea022cd2a228924571f02a1a7ddceed1a40d8b
push idunknown
push userunknown
push dateunknown
reviewersbz, roc
bugs508473
milestone1.9.3a1pre
Bug 508473 part III: Pass destruction root to frame destruction methods r=bz sr=roc
layout/forms/nsComboboxControlFrame.cpp
layout/forms/nsComboboxControlFrame.h
layout/forms/nsFileControlFrame.cpp
layout/forms/nsFileControlFrame.h
layout/forms/nsFormControlFrame.cpp
layout/forms/nsFormControlFrame.h
layout/forms/nsGfxButtonControlFrame.cpp
layout/forms/nsGfxButtonControlFrame.h
layout/forms/nsHTMLButtonControlFrame.cpp
layout/forms/nsHTMLButtonControlFrame.h
layout/forms/nsImageControlFrame.cpp
layout/forms/nsIsIndexFrame.cpp
layout/forms/nsIsIndexFrame.h
layout/forms/nsLegendFrame.cpp
layout/forms/nsLegendFrame.h
layout/forms/nsListControlFrame.cpp
layout/forms/nsListControlFrame.h
layout/forms/nsTextControlFrame.cpp
layout/forms/nsTextControlFrame.h
layout/generic/nsAbsoluteContainingBlock.cpp
layout/generic/nsAbsoluteContainingBlock.h
layout/generic/nsBlockFrame.cpp
layout/generic/nsBlockFrame.h
layout/generic/nsBulletFrame.cpp
layout/generic/nsBulletFrame.h
layout/generic/nsCanvasFrame.cpp
layout/generic/nsCanvasFrame.h
layout/generic/nsContainerFrame.cpp
layout/generic/nsContainerFrame.h
layout/generic/nsFrame.cpp
layout/generic/nsFrame.h
layout/generic/nsFrameFrame.cpp
layout/generic/nsFrameList.cpp
layout/generic/nsFrameList.h
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsGfxScrollFrame.h
layout/generic/nsIFrame.h
layout/generic/nsImageFrame.cpp
layout/generic/nsImageFrame.h
layout/generic/nsInlineFrame.cpp
layout/generic/nsInlineFrame.h
layout/generic/nsLineBox.cpp
layout/generic/nsLineBox.h
layout/generic/nsObjectFrame.cpp
layout/generic/nsObjectFrame.h
layout/generic/nsPlaceholderFrame.cpp
layout/generic/nsPlaceholderFrame.h
layout/generic/nsSplittableFrame.cpp
layout/generic/nsSplittableFrame.h
layout/generic/nsTextFrame.h
layout/generic/nsTextFrameThebes.cpp
layout/generic/nsVideoFrame.cpp
layout/generic/nsVideoFrame.h
layout/generic/nsViewportFrame.cpp
layout/generic/nsViewportFrame.h
layout/svg/base/src/nsSVGForeignObjectFrame.cpp
layout/svg/base/src/nsSVGForeignObjectFrame.h
layout/svg/base/src/nsSVGUseFrame.cpp
layout/tables/nsTableFrame.cpp
layout/tables/nsTableFrame.h
layout/tables/nsTableOuterFrame.cpp
layout/tables/nsTableOuterFrame.h
layout/xul/base/src/nsBoxFrame.cpp
layout/xul/base/src/nsBoxFrame.h
layout/xul/base/src/nsDocElementBoxFrame.cpp
layout/xul/base/src/nsImageBoxFrame.cpp
layout/xul/base/src/nsImageBoxFrame.h
layout/xul/base/src/nsListBoxBodyFrame.cpp
layout/xul/base/src/nsListBoxBodyFrame.h
layout/xul/base/src/nsMenuBarFrame.cpp
layout/xul/base/src/nsMenuBarFrame.h
layout/xul/base/src/nsMenuFrame.cpp
layout/xul/base/src/nsMenuFrame.h
layout/xul/base/src/nsMenuPopupFrame.cpp
layout/xul/base/src/nsMenuPopupFrame.h
layout/xul/base/src/nsPopupSetFrame.cpp
layout/xul/base/src/nsPopupSetFrame.h
layout/xul/base/src/nsScrollBoxFrame.cpp
layout/xul/base/src/nsScrollbarButtonFrame.cpp
layout/xul/base/src/nsScrollbarButtonFrame.h
layout/xul/base/src/nsSliderFrame.cpp
layout/xul/base/src/nsSliderFrame.h
layout/xul/base/src/nsSplitterFrame.cpp
layout/xul/base/src/nsSplitterFrame.h
layout/xul/base/src/nsTextBoxFrame.cpp
layout/xul/base/src/nsTextBoxFrame.h
layout/xul/base/src/nsXULLabelFrame.cpp
layout/xul/base/src/nsXULLabelFrame.h
layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
layout/xul/base/src/tree/src/nsTreeBodyFrame.h
layout/xul/base/src/tree/src/nsTreeColFrame.cpp
layout/xul/base/src/tree/src/nsTreeColFrame.h
--- a/layout/forms/nsComboboxControlFrame.cpp
+++ b/layout/forms/nsComboboxControlFrame.cpp
@@ -1205,17 +1205,17 @@ nsComboboxControlFrame::CreateFrameFor(n
   }
 
   nsFrameList textList(mTextFrame, mTextFrame);
   mDisplayFrame->SetInitialChildList(nsnull, textList);
   return mDisplayFrame;
 }
 
 void
-nsComboboxControlFrame::Destroy()
+nsComboboxControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // Revoke any pending RedisplayTextEvent
   mRedisplayTextEvent.Revoke();
 
   nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), PR_FALSE);
 
   if (mDroppedDown) {
     // Get parent view
@@ -1227,20 +1227,20 @@ nsComboboxControlFrame::Destroy()
         nsIWidget* widget = view->GetWidget();
         if (widget)
           widget->CaptureRollupEvents(this, PR_FALSE, PR_TRUE);
       }
     }
   }
 
   // Cleanup frames in popup child list
-  mPopupFrames.DestroyFrames();
+  mPopupFrames.DestroyFramesFrom(aDestructRoot);
   nsContentUtils::DestroyAnonymousContent(&mDisplayContent);
   nsContentUtils::DestroyAnonymousContent(&mButtonContent);
-  nsBlockFrame::Destroy();
+  nsBlockFrame::DestroyFrom(aDestructRoot);
 }
 
 
 nsFrameList
 nsComboboxControlFrame::GetChildList(nsIAtom* aListName) const
 {
   if (nsGkAtoms::selectPopupList == aListName) {
     return mPopupFrames;
--- a/layout/forms/nsComboboxControlFrame.h
+++ b/layout/forms/nsComboboxControlFrame.h
@@ -136,17 +136,17 @@ public:
   {
     return nsBlockFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
   }
 
 #ifdef NS_DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
   virtual nsFrameList GetChildList(nsIAtom* aListName) const;
   NS_IMETHOD SetInitialChildList(nsIAtom*        aListName,
                                  nsFrameList&    aChildList);
   virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
 
   virtual nsIFrame* GetContentInsertionFrame();
 
   // nsIFormControlFrame
--- a/layout/forms/nsFileControlFrame.cpp
+++ b/layout/forms/nsFileControlFrame.cpp
@@ -118,17 +118,17 @@ nsFileControlFrame::Init(nsIContent* aCo
 
   mMouseListener = new MouseListener(this);
   NS_ENSURE_TRUE(mMouseListener, NS_ERROR_OUT_OF_MEMORY);
 
   return rv;
 }
 
 void
-nsFileControlFrame::Destroy()
+nsFileControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   mTextFrame = nsnull;
   ENSURE_TRUE(mContent);
 
   // remove mMouseListener as a mouse event listener (bug 40533, bug 355931)
   NS_NAMED_LITERAL_STRING(click, "click");
 
   nsCOMPtr<nsIDOMEventGroup> systemGroup;
@@ -144,17 +144,17 @@ nsFileControlFrame::Destroy()
     do_QueryInterface(mTextContent);
   if (dom3TextContent) {
     dom3TextContent->RemoveGroupedEventListener(click, mMouseListener, PR_FALSE,
                                                 systemGroup);
     nsContentUtils::DestroyAnonymousContent(&mTextContent);
   }
 
   mMouseListener->ForgetFrame();
-  nsBlockFrame::Destroy();
+  nsBlockFrame::DestroyFrom(aDestructRoot);
 }
 
 nsresult
 nsFileControlFrame::CreateAnonymousContent(nsTArray<nsIContent*>& aElements)
 {
   // Get the NodeInfoManager and tag necessary to create input elements
   nsCOMPtr<nsIDocument> doc = mContent->GetDocument();
 
--- a/layout/forms/nsFileControlFrame.h
+++ b/layout/forms/nsFileControlFrame.h
@@ -73,17 +73,17 @@ public:
 
   virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
   
   NS_IMETHOD Reflow(nsPresContext*          aCX,
                     nsHTMLReflowMetrics&     aDesiredSize,
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus&          aStatus);
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
 #ifdef NS_DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
 
   NS_IMETHOD AttributeChanged(PRInt32         aNameSpaceID,
                               nsIAtom*        aAttribute,
                               PRInt32         aModType);
--- a/layout/forms/nsFormControlFrame.cpp
+++ b/layout/forms/nsFormControlFrame.cpp
@@ -50,21 +50,21 @@ nsFormControlFrame::nsFormControlFrame(n
 {
 }
 
 nsFormControlFrame::~nsFormControlFrame()
 {
 }
 
 void
-nsFormControlFrame::Destroy()
+nsFormControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // Unregister the access key registered in reflow
   nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), PR_FALSE);
-  nsLeafFrame::Destroy();
+  nsLeafFrame::DestroyFrom(aDestructRoot);
 }
 
 NS_QUERYFRAME_HEAD(nsFormControlFrame)
   NS_QUERYFRAME_ENTRY(nsIFormControlFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsLeafFrame)
 
 NS_IMPL_FRAMEARENA_HELPERS(nsFormControlFrame)
 
--- a/layout/forms/nsFormControlFrame.h
+++ b/layout/forms/nsFormControlFrame.h
@@ -80,17 +80,17 @@ public:
     * Respond to the request to resize and/or reflow
     * @see nsIFrame::Reflow
     */
   NS_IMETHOD Reflow(nsPresContext*      aCX,
                     nsHTMLReflowMetrics& aDesiredSize,
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus&      aStatus);
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   // new behavior
 
   virtual void SetFocus(PRBool aOn = PR_TRUE, PRBool aRepaint = PR_FALSE);
 
   // nsIFormControlFrame
   virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue);
 
--- a/layout/forms/nsGfxButtonControlFrame.cpp
+++ b/layout/forms/nsGfxButtonControlFrame.cpp
@@ -67,20 +67,20 @@ nsGfxButtonControlFrame::nsGfxButtonCont
 nsIFrame*
 NS_NewGfxButtonControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsGfxButtonControlFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsGfxButtonControlFrame)
 
-void nsGfxButtonControlFrame::Destroy()
+void nsGfxButtonControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   nsContentUtils::DestroyAnonymousContent(&mTextContent);
-  nsHTMLButtonControlFrame::Destroy();
+  nsHTMLButtonControlFrame::DestroyFrom(aDestructRoot);
 }
 
 nsIAtom*
 nsGfxButtonControlFrame::GetType() const
 {
   return nsGkAtoms::gfxButtonControlFrame;
 }
 
--- a/layout/forms/nsGfxButtonControlFrame.h
+++ b/layout/forms/nsGfxButtonControlFrame.h
@@ -55,17 +55,17 @@ class nsIAccessible;
 class nsGfxButtonControlFrame : public nsHTMLButtonControlFrame,
                                 public nsIAnonymousContentCreator
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   nsGfxButtonControlFrame(nsStyleContext* aContext);
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   NS_IMETHOD HandleEvent(nsPresContext* aPresContext, 
                          nsGUIEvent* aEvent,
                          nsEventStatus* aEventStatus);
 
  
 #ifdef ACCESSIBILITY
   NS_IMETHOD GetAccessible(nsIAccessible** aAccessible);
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -81,20 +81,20 @@ nsHTMLButtonControlFrame::nsHTMLButtonCo
 {
 }
 
 nsHTMLButtonControlFrame::~nsHTMLButtonControlFrame()
 {
 }
 
 void
-nsHTMLButtonControlFrame::Destroy()
+nsHTMLButtonControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), PR_FALSE);
-  nsHTMLContainerFrame::Destroy();
+  nsHTMLContainerFrame::DestroyFrom(aDestructRoot);
 }
 
 NS_IMETHODIMP
 nsHTMLButtonControlFrame::Init(
               nsIContent*      aContent,
               nsIFrame*        aParent,
               nsIFrame*        aPrevInFlow)
 {
--- a/layout/forms/nsHTMLButtonControlFrame.h
+++ b/layout/forms/nsHTMLButtonControlFrame.h
@@ -57,17 +57,17 @@ class nsIRenderingContext;
 
 class nsHTMLButtonControlFrame : public nsHTMLContainerFrame,
                                  public nsIFormControlFrame 
 {
 public:
   nsHTMLButtonControlFrame(nsStyleContext* aContext);
   ~nsHTMLButtonControlFrame();
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists);
 
--- a/layout/forms/nsImageControlFrame.cpp
+++ b/layout/forms/nsImageControlFrame.cpp
@@ -71,17 +71,17 @@ IntPointDtorFunc(void *aObject, nsIAtom 
 #define nsImageControlFrameSuper nsImageFrame
 class nsImageControlFrame : public nsImageControlFrameSuper,
                             public nsIFormControlFrame
 {
 public:
   nsImageControlFrame(nsStyleContext* aContext);
   ~nsImageControlFrame();
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
 
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
   NS_IMETHOD Reflow(nsPresContext*          aPresContext,
@@ -119,22 +119,22 @@ nsImageControlFrame::nsImageControlFrame
 {
 }
 
 nsImageControlFrame::~nsImageControlFrame()
 {
 }
 
 void
-nsImageControlFrame::Destroy()
+nsImageControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   if (!GetPrevInFlow()) {
     nsFormControlFrame::RegUnRegAccessKey(this, PR_FALSE);
   }
-  nsImageControlFrameSuper::Destroy();
+  nsImageControlFrameSuper::DestroyFrom(aDestructRoot);
 }
 
 nsIFrame*
 NS_NewImageControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsImageControlFrame(aContext);
 }
 
--- a/layout/forms/nsIsIndexFrame.cpp
+++ b/layout/forms/nsIsIndexFrame.cpp
@@ -92,29 +92,29 @@ nsIsIndexFrame::nsIsIndexFrame(nsStyleCo
   SetFlags(NS_BLOCK_FLOAT_MGR);
 }
 
 nsIsIndexFrame::~nsIsIndexFrame()
 {
 }
 
 void
-nsIsIndexFrame::Destroy()
+nsIsIndexFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // remove ourself as a listener of the text control (bug 40533)
   if (mInputContent) {
     if (mListener) {
       mInputContent->RemoveEventListenerByIID(mListener, NS_GET_IID(nsIDOMKeyListener));
     }
     nsContentUtils::DestroyAnonymousContent(&mInputContent);
   }
   nsContentUtils::DestroyAnonymousContent(&mTextContent);
   nsContentUtils::DestroyAnonymousContent(&mPreHr);
   nsContentUtils::DestroyAnonymousContent(&mPostHr);
-  nsBlockFrame::Destroy();
+  nsBlockFrame::DestroyFrom(aDestructRoot);
 }
 
 // REVIEW: We don't need to override BuildDisplayList, nsBlockFrame will honour
 // our visibility setting
 
 nsresult
 nsIsIndexFrame::UpdatePromptLabel(PRBool aNotify)
 {
--- a/layout/forms/nsIsIndexFrame.h
+++ b/layout/forms/nsIsIndexFrame.h
@@ -51,17 +51,17 @@ typedef   nsTextControlFrame nsNewFrame;
 class nsIsIndexFrame : public nsBlockFrame,
                        public nsIAnonymousContentCreator,
                        public nsIStatefulFrame
 {
 public:
   nsIsIndexFrame(nsStyleContext* aContext);
   virtual ~nsIsIndexFrame();
 
-  virtual void Destroy(); 
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
 private:
   void KeyPress(nsIDOMEvent* aKeyEvent);
 
   class KeyListener : public nsIDOMKeyListener
   {
     NS_DECL_ISUPPORTS
 
--- a/layout/forms/nsLegendFrame.cpp
+++ b/layout/forms/nsLegendFrame.cpp
@@ -64,20 +64,20 @@ NS_IMPL_FRAMEARENA_HELPERS(nsLegendFrame
 
 nsIAtom*
 nsLegendFrame::GetType() const
 {
   return nsGkAtoms::legendFrame; 
 }
 
 void
-nsLegendFrame::Destroy()
+nsLegendFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), PR_FALSE);
-  nsBlockFrame::Destroy();
+  nsBlockFrame::DestroyFrom(aDestructRoot);
 }
 
 NS_QUERYFRAME_HEAD(nsLegendFrame)
   NS_QUERYFRAME_ENTRY(nsLegendFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsBlockFrame)
 
 NS_IMETHODIMP 
 nsLegendFrame::Reflow(nsPresContext*          aPresContext,
--- a/layout/forms/nsLegendFrame.h
+++ b/layout/forms/nsLegendFrame.h
@@ -48,17 +48,17 @@ public:
 
   nsLegendFrame(nsStyleContext* aContext) : nsBlockFrame(aContext) {}
 
   NS_IMETHOD Reflow(nsPresContext*           aPresContext,
                     nsHTMLReflowMetrics&     aDesiredSize,
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus&          aStatus);
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   virtual nsIAtom* GetType() const;
 
 #ifdef NS_DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
 
   PRInt32 GetAlign();
--- a/layout/forms/nsListControlFrame.cpp
+++ b/layout/forms/nsListControlFrame.cpp
@@ -190,17 +190,17 @@ nsListControlFrame::nsListControlFrame(
 //---------------------------------------------------------
 nsListControlFrame::~nsListControlFrame()
 {
   mComboboxFrame = nsnull;
 }
 
 // for Bug 47302 (remove this comment later)
 void
-nsListControlFrame::Destroy()
+nsListControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // get the receiver interface from the browser button's content node
   ENSURE_TRUE(mContent);
 
   // Clear the frame pointer on our event listener, just in case the
   // event listener can outlive the frame.
 
   mEventListener->SetFrame(nsnull);
@@ -213,17 +213,17 @@ nsListControlFrame::Destroy()
                                                 (mEventListener),
                                      NS_GET_IID(nsIDOMMouseMotionListener));
 
   mContent->RemoveEventListenerByIID(static_cast<nsIDOMKeyListener*>
                                                 (mEventListener),
                                      NS_GET_IID(nsIDOMKeyListener));
 
   nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), PR_FALSE);
-  nsHTMLScrollFrame::Destroy();
+  nsHTMLScrollFrame::DestroyFrom(aDestructRoot);
 }
 
 NS_IMETHODIMP
 nsListControlFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                      const nsRect&           aDirtyRect,
                                      const nsDisplayListSet& aLists)
 {
   // We allow visibility:hidden <select>s to contain visible options.
--- a/layout/forms/nsListControlFrame.h
+++ b/layout/forms/nsListControlFrame.h
@@ -98,17 +98,17 @@ public:
 
   NS_IMETHOD Init(nsIContent*      aContent,
                    nsIFrame*        aParent,
                    nsIFrame*        aPrevInFlow);
 
   NS_IMETHOD DidReflow(nsPresContext*           aPresContext, 
                        const nsHTMLReflowState*  aReflowState, 
                        nsDidReflowStatus         aStatus);
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists);
 
   virtual nsIFrame* GetContentInsertionFrame();
 
   /**
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -1099,29 +1099,29 @@ nsTextControlFrame::PreDestroy()
                                            listener, PR_FALSE, systemGroup);
     }
   }
 
   mDidPreDestroy = PR_TRUE; 
 }
 
 void
-nsTextControlFrame::Destroy()
+nsTextControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   if (mInSecureKeyboardInputMode) {
     MaybeEndSecureKeyboardInput();
   }
   if (!mDidPreDestroy) {
     PreDestroy();
   }
   if (mFrameSel) {
     mFrameSel->SetScrollableViewProvider(nsnull);
   }
   nsContentUtils::DestroyAnonymousContent(&mAnonymousDiv);
-  nsBoxFrame::Destroy();
+  nsBoxFrame::DestroyFrom(aDestructRoot);
 }
 
 nsIAtom*
 nsTextControlFrame::GetType() const 
 { 
   return nsGkAtoms::textInputFrame;
 } 
 
--- a/layout/forms/nsTextControlFrame.h
+++ b/layout/forms/nsTextControlFrame.h
@@ -69,17 +69,17 @@ class nsTextControlFrame : public nsStac
 
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   nsTextControlFrame(nsIPresShell* aShell, nsStyleContext* aContext);
   virtual ~nsTextControlFrame();
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   virtual nscoord GetMinWidth(nsIRenderingContext* aRenderingContext);
   virtual nsSize ComputeAutoSize(nsIRenderingContext *aRenderingContext,
                                  nsSize aCBSize, nscoord aAvailableWidth,
                                  nsSize aMargin, nsSize aBorder,
                                  nsSize aPadding, PRBool aShrinkWrap);
 
   NS_IMETHOD Reflow(nsPresContext*          aPresContext,
--- a/layout/generic/nsAbsoluteContainingBlock.cpp
+++ b/layout/generic/nsAbsoluteContainingBlock.cpp
@@ -340,19 +340,20 @@ nsAbsoluteContainingBlock::FrameDependsO
     if (!IsFixedOffset(pos->mOffset.GetTopUnit())) {
       return PR_TRUE;
     }
   }
   return PR_FALSE;
 }
 
 void
-nsAbsoluteContainingBlock::DestroyFrames(nsIFrame* aDelegatingFrame)
+nsAbsoluteContainingBlock::DestroyFrames(nsIFrame* aDelegatingFrame,
+                                         nsIFrame* aDestructRoot)
 {
-  mAbsoluteFrames.DestroyFrames();
+  mAbsoluteFrames.DestroyFramesFrom(aDestructRoot);
 }
 
 void
 nsAbsoluteContainingBlock::MarkSizeDependentFramesDirty()
 {
   DoMarkFramesDirty(PR_FALSE);
 }
 
--- a/layout/generic/nsAbsoluteContainingBlock.h
+++ b/layout/generic/nsAbsoluteContainingBlock.h
@@ -118,17 +118,18 @@ public:
                   nscoord                  aContainingBlockWidth,
                   nscoord                  aContainingBlockHeight,
                   PRBool                   aConstrainHeight,
                   PRBool                   aCBWidthChanged,
                   PRBool                   aCBHeightChanged,
                   nsRect*                  aChildBounds = nsnull);
 
 
-  void DestroyFrames(nsIFrame* aDelegatingFrame);
+  void DestroyFrames(nsIFrame* aDelegatingFrame,
+                     nsIFrame* aDestructRoot);
 
   PRBool  HasAbsoluteFrames() {return mAbsoluteFrames.NotEmpty();}
 
   // Mark our size-dependent absolute frames with NS_FRAME_HAS_DIRTY_CHILDREN
   // so that we'll make sure to reflow them.
   void MarkSizeDependentFramesDirty();
 
   // Mark all our absolute frames with NS_FRAME_IS_DIRTY
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -279,48 +279,48 @@ NS_NewBlockFrame(nsIPresShell* aPresShel
 
 NS_IMPL_FRAMEARENA_HELPERS(nsBlockFrame)
 
 nsBlockFrame::~nsBlockFrame()
 {
 }
 
 void
-nsBlockFrame::Destroy()
+nsBlockFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
-  mAbsoluteContainer.DestroyFrames(this);
+  mAbsoluteContainer.DestroyFrames(this, aDestructRoot);
   // Outside bullets are not in our child-list so check for them here
   // and delete them when present.
   if (mBullet && HaveOutsideBullet()) {
-    mBullet->Destroy();
+    mBullet->DestroyFrom(aDestructRoot);
     mBullet = nsnull;
   }
 
-  mFloats.DestroyFrames();
+  mFloats.DestroyFramesFrom(aDestructRoot);
 
   nsPresContext* presContext = PresContext();
 
-  nsLineBox::DeleteLineList(presContext, mLines);
+  nsLineBox::DeleteLineList(presContext, mLines, aDestructRoot);
   // Now clear mFrames, since we've destroyed all the frames in it.
   mFrames.Clear();
 
   // destroy overflow lines now
   nsLineList* overflowLines = RemoveOverflowLines();
   if (overflowLines) {
-    nsLineBox::DeleteLineList(presContext, *overflowLines);
+    nsLineBox::DeleteLineList(presContext, *overflowLines, aDestructRoot);
     delete overflowLines;
   }
 
   {
     nsAutoOOFFrameList oofs(this);
-    oofs.mList.DestroyFrames();
+    oofs.mList.DestroyFramesFrom(aDestructRoot);
     // oofs is now empty and will remove the frame list property
   }
 
-  nsBlockFrameSuper::Destroy();
+  nsBlockFrameSuper::DestroyFrom(aDestructRoot);
 }
 
 /* virtual */ nsILineIterator*
 nsBlockFrame::GetLineIterator()
 {
   nsLineIterator* it = new nsLineIterator;
   if (!it)
     return nsnull;
@@ -4543,17 +4543,17 @@ static void
 DestroyOverflowLines(void*           aFrame,
                      nsIAtom*        aPropertyName,
                      void*           aPropertyValue,
                      void*           aDtorData)
 {
   if (aPropertyValue) {
     nsLineList* lines = static_cast<nsLineList*>(aPropertyValue);
     nsPresContext *context = static_cast<nsPresContext*>(aDtorData);
-    nsLineBox::DeleteLineList(context, *lines);
+    nsLineBox::DeleteLineList(context, *lines, nsnull);
     delete lines;
   }
 }
 
 // This takes ownership of aOverflowLines.
 // XXX We should allocate overflowLines from presShell arena!
 nsresult
 nsBlockFrame::SetOverflowLines(nsLineList* aOverflowLines)
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -170,17 +170,17 @@ public:
   NS_IMETHOD  InsertFrames(nsIAtom*        aListName,
                            nsIFrame*       aPrevFrame,
                            nsFrameList&    aFrameList);
   NS_IMETHOD  RemoveFrame(nsIAtom*        aListName,
                           nsIFrame*       aOldFrame);
   virtual nsFrameList GetChildList(nsIAtom* aListName) const;
   virtual nscoord GetBaseline() const;
   virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
   virtual nsSplittableType GetSplittableType() const;
   virtual PRBool IsContainingBlock() const;
   virtual PRBool IsFloatContainingBlock() const;
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists);
   virtual void InvalidateInternal(const nsRect& aDamageRect,
                                   nscoord aX, nscoord aY, nsIFrame* aForChild,
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -86,29 +86,29 @@ private:
 
 NS_IMPL_FRAMEARENA_HELPERS(nsBulletFrame)
 
 nsBulletFrame::~nsBulletFrame()
 {
 }
 
 void
-nsBulletFrame::Destroy()
+nsBulletFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // Stop image loading first
   if (mImageRequest) {
     mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
     mImageRequest = nsnull;
   }
 
   if (mListener)
     reinterpret_cast<nsBulletListener*>(mListener.get())->SetFrame(nsnull);
 
   // Let base class do the rest
-  nsFrame::Destroy();
+  nsFrame::DestroyFrom(aDestructRoot);
 }
 
 #ifdef NS_DEBUG
 NS_IMETHODIMP
 nsBulletFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("Bullet"), aResult);
 }
--- a/layout/generic/nsBulletFrame.h
+++ b/layout/generic/nsBulletFrame.h
@@ -53,17 +53,17 @@
 class nsBulletFrame : public nsFrame {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   nsBulletFrame(nsStyleContext* aContext) : nsFrame(aContext) {}
   virtual ~nsBulletFrame();
 
   // nsIFrame
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists);
   virtual nsIAtom* GetType() const;
   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
 #ifdef NS_DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
--- a/layout/generic/nsCanvasFrame.cpp
+++ b/layout/generic/nsCanvasFrame.cpp
@@ -99,27 +99,27 @@ nsCanvasFrame::Init(nsIContent*      aCo
   if (scrollingView) {
     scrollingView->AddScrollPositionListener(this);
   }
 
   return rv;
 }
 
 void
-nsCanvasFrame::Destroy()
+nsCanvasFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
-  mAbsoluteContainer.DestroyFrames(this);
+  mAbsoluteContainer.DestroyFrames(this, aDestructRoot);
 
   nsIScrollableView* scrollingView = nsnull;
   mViewManager->GetRootScrollableView(&scrollingView);
   if (scrollingView) {
     scrollingView->RemoveScrollPositionListener(this);
   }
 
-  nsHTMLContainerFrame::Destroy();
+  nsHTMLContainerFrame::DestroyFrom(aDestructRoot);
 }
 
 NS_IMETHODIMP
 nsCanvasFrame::ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY)
 {
 #ifdef DEBUG_CANVAS_FOCUS
   {
     PRBool hasFocus = PR_FALSE;
--- a/layout/generic/nsCanvasFrame.h
+++ b/layout/generic/nsCanvasFrame.h
@@ -76,17 +76,17 @@ public:
   NS_DECL_FRAMEARENA_HELPERS
 
   // nsISupports (nsIScrollPositionListener)
   NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
 
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   NS_IMETHOD SetInitialChildList(nsIAtom*        aListName,
                                  nsFrameList&    aChildList);
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
                           nsFrameList&    aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
                           nsFrameList&    aFrameList);
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -252,41 +252,41 @@ nsContainerFrame::RemoveFrame(nsIAtom*  
                          NS_FRAME_HAS_DIRTY_CHILDREN);
     }
   }
 
   return NS_OK;
 }
 
 void
-nsContainerFrame::Destroy()
+nsContainerFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // Prevent event dispatch during destruction
   if (HasView()) {
     GetView()->SetClientData(nsnull);
   }
 
   // Delete the primary child list
-  mFrames.DestroyFrames();
+  mFrames.DestroyFramesFrom(aDestructRoot);
 
   // Destroy auxiliary frame lists
   nsPresContext* prescontext = PresContext();
 
-  DestroyOverflowList(prescontext);
+  DestroyOverflowList(prescontext, aDestructRoot);
 
   if (IsFrameOfType(nsIFrame::eCanContainOverflowContainers)) {
     nsFrameList* frameList = RemovePropTableFrames(prescontext,
                                nsGkAtoms::overflowContainersProperty);
     if (frameList)
-      frameList->Destroy();
+      frameList->DestroyFrom(aDestructRoot);
 
     frameList = RemovePropTableFrames(prescontext,
                   nsGkAtoms::excessOverflowContainersProperty);
     if (frameList)
-      frameList->Destroy();
+      frameList->DestroyFrom(aDestructRoot);
   }
 
   if (IsGeneratedContentFrame()) {
     // Make sure all the content nodes for the generated content inside
     // this frame know it's going away.
     // See also nsCSSFrameConstructor::CreateGeneratedContentFrame which
     // created this frame.
     nsCOMArray<nsIContent>* generatedContent =
@@ -302,17 +302,17 @@ nsContainerFrame::Destroy()
           ContentRemoved(content->GetCurrentDoc(), content);
         content->UnbindFromTree();
       }
       delete generatedContent;
     }
   }
 
   // Destroy the frame and remove the flow pointers
-  nsSplittableFrame::Destroy();
+  nsSplittableFrame::DestroyFrom(aDestructRoot);
 }
 
 /////////////////////////////////////////////////////////////////////////////
 // Child frame enumeration
 
 nsFrameList
 nsContainerFrame::GetChildList(nsIAtom* aListName) const
 {
@@ -1113,22 +1113,23 @@ nsContainerFrame::StealFramesAfter(nsIFr
     }
   }
 
   NS_ERROR("StealFramesAfter: can't find aChild");
   return nsFrameList::EmptyList();
 }
 
 void
-nsContainerFrame::DestroyOverflowList(nsPresContext* aPresContext)
+nsContainerFrame::DestroyOverflowList(nsPresContext* aPresContext,
+                                      nsIFrame*      aDestructRoot)
 {
   nsFrameList* list =
     RemovePropTableFrames(aPresContext, nsGkAtoms::overflowProperty);
   if (list)
-    list->Destroy();
+    list->DestroyFrom(aDestructRoot);
 }
 
 /**
  * Remove and delete aNextInFlow and its next-in-flows. Updates the sibling and flow
  * pointers
  */
 void
 nsContainerFrame::DeleteNextInFlowChild(nsPresContext* aPresContext,
--- a/layout/generic/nsContainerFrame.h
+++ b/layout/generic/nsContainerFrame.h
@@ -88,17 +88,17 @@ public:
   NS_IMETHOD InsertFrames(nsIAtom*  aListName,
                           nsIFrame* aPrevFrame,
                           nsFrameList& aFrameList);
   NS_IMETHOD RemoveFrame(nsIAtom*  aListName,
                          nsIFrame* aOldFrame);
 
   virtual nsFrameList GetChildList(nsIAtom* aListName) const;
   virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
   virtual void ChildIsDirty(nsIFrame* aChild);
 
   virtual PRBool IsLeaf() const;
   virtual PRBool PeekOffsetNoAmount(PRBool aForward, PRInt32* aOffset);
   virtual PRBool PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset);
   
 #ifdef DEBUG
   NS_IMETHOD List(FILE* out, PRInt32 aIndent) const;
@@ -378,17 +378,18 @@ protected:
    * Set the overflow list.  aOverflowFrames must not be an empty list.
    */
   nsresult SetOverflowFrames(nsPresContext*  aPresContext,
                              const nsFrameList& aOverflowFrames);
 
   /**
    * Destroy the overflow list and any frames that are on  it.
    */
-  void DestroyOverflowList(nsPresContext* aPresContext);
+  void DestroyOverflowList(nsPresContext* aPresContext,
+                           nsIFrame*      aDestructRoot = nsnull);
 
   /**
    * Moves any frames on both the prev-in-flow's overflow list and the
    * receiver's overflow to the receiver's child list.
    *
    * Resets the overlist pointers to nsnull, and updates the receiver's child
    * count and content mapping.
    *
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -409,36 +409,43 @@ NS_IMETHODIMP
 nsFrame::RemoveFrame(nsIAtom*        aListName,
                      nsIFrame*       aOldFrame)
 {
   NS_PRECONDITION(PR_FALSE, "not a container");
   return NS_ERROR_UNEXPECTED;
 }
 
 void
-nsFrame::Destroy()
+nsFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
     "destroy called on frame while scripts not blocked");
   NS_ASSERTION(!GetNextSibling() && !GetPrevSibling(),
                "Frames should be removed before destruction.");
+  NS_ASSERTION(aDestructRoot, "Must specify destruct root");
 
 #ifdef MOZ_SVG
   nsSVGEffects::InvalidateDirectRenderingObservers(this);
 #endif
 
   // Get the view pointer now before the frame properties disappear
   // when we call NotifyDestroyingFrame()
   nsIView* view = GetView();
   nsPresContext* presContext = PresContext();
 
   nsIPresShell *shell = presContext->GetPresShell();
   if (mState & NS_FRAME_OUT_OF_FLOW) {
     nsPlaceholderFrame* placeholder =
       shell->FrameManager()->GetPlaceholderFrameFor(this);
+    NS_ASSERTION(!placeholder || (aDestructRoot != this),
+                 "Don't call Destroy() on OOFs, call Destroy() on the placeholder.");
+    NS_ASSERTION(!placeholder ||
+                 nsLayoutUtils::IsProperAncestorFrame(aDestructRoot, placeholder),
+                 "Placeholder relationship should have been torn down already; "
+                 "this might mean we have a stray placeholder in the tree.");
     if (placeholder) {
       shell->FrameManager()->UnregisterPlaceholderFrame(placeholder);
       placeholder->SetOutOfFlowFrame(nsnull);
     }
   }
 
   shell->NotifyDestroyingFrame(this);
 
--- a/layout/generic/nsFrame.h
+++ b/layout/generic/nsFrame.h
@@ -178,17 +178,17 @@ public:
                                   nsFrameList&       aChildList);
   NS_IMETHOD  AppendFrames(nsIAtom*        aListName,
                            nsFrameList&    aFrameList);
   NS_IMETHOD  InsertFrames(nsIAtom*        aListName,
                            nsIFrame*       aPrevFrame,
                            nsFrameList&    aFrameList);
   NS_IMETHOD  RemoveFrame(nsIAtom*        aListName,
                           nsIFrame*       aOldFrame);
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
   virtual nsStyleContext* GetAdditionalStyleContext(PRInt32 aIndex) const;
   virtual void SetAdditionalStyleContext(PRInt32 aIndex,
                                          nsStyleContext* aStyleContext);
   NS_IMETHOD  SetParent(const nsIFrame* aParent);
   virtual nscoord GetBaseline() const;
   virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
   virtual nsFrameList GetChildList(nsIAtom* aListName) const;
   NS_IMETHOD  HandleEvent(nsPresContext* aPresContext, 
--- a/layout/generic/nsFrameFrame.cpp
+++ b/layout/generic/nsFrameFrame.cpp
@@ -131,17 +131,17 @@ public:
     return nsLeafFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
   }
 
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
   virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
 
   virtual IntrinsicSize GetIntrinsicSize();
   virtual nsSize  GetIntrinsicRatio();
 
   virtual nsSize ComputeAutoSize(nsIRenderingContext *aRenderingContext,
@@ -778,26 +778,26 @@ nsIFrame*
 NS_NewSubDocumentFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsSubDocumentFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsSubDocumentFrame)
 
 void
-nsSubDocumentFrame::Destroy()
+nsSubDocumentFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   if (mPostedReflowCallback) {
     PresContext()->PresShell()->CancelReflowCallback(this);
     mPostedReflowCallback = PR_FALSE;
   }
   
   HideViewer();
 
-  nsLeafFrame::Destroy();
+  nsLeafFrame::DestroyFrom(aDestructRoot);
 }
 
 void
 nsSubDocumentFrame::HideViewer()
 {
   if (mFrameLoader && mDidCreateDoc)
     mFrameLoader->Hide();
 }
--- a/layout/generic/nsFrameList.cpp
+++ b/layout/generic/nsFrameList.cpp
@@ -67,22 +67,41 @@ nsFrameList::Destroy()
 {
   NS_PRECONDITION(this != sEmptyList, "Shouldn't Destroy() sEmptyList");
 
   DestroyFrames();
   delete this;
 }
 
 void
+nsFrameList::DestroyFrom(nsIFrame* aDestructRoot)
+{
+  NS_PRECONDITION(this != sEmptyList, "Shouldn't Destroy() sEmptyList");
+
+  DestroyFramesFrom(aDestructRoot);
+  delete this;
+}
+
+void
 nsFrameList::DestroyFrames()
 {
   while (nsIFrame* frame = RemoveFirstChild()) {
     frame->Destroy();
   }
+  mLastChild = nsnull;
+}
 
+void
+nsFrameList::DestroyFramesFrom(nsIFrame* aDestructRoot)
+{
+  NS_PRECONDITION(aDestructRoot, "Missing destruct root");
+
+  while (nsIFrame* frame = RemoveFirstChild()) {
+    frame->DestroyFrom(aDestructRoot);
+  }
   mLastChild = nsnull;
 }
 
 void
 nsFrameList::SetFrames(nsIFrame* aFrameList)
 {
   NS_PRECONDITION(!mFirstChild, "Losing frames");
 
--- a/layout/generic/nsFrameList.h
+++ b/layout/generic/nsFrameList.h
@@ -80,20 +80,34 @@ public:
   /**
    * For each frame in this list: remove it from the list then call
    * Destroy() on it.
    */
   void DestroyFrames();
 
   /**
    * For each frame in this list: remove it from the list then call
+   * DestroyFrom() on it.
+   */
+  void DestroyFramesFrom(nsIFrame* aDestructRoot);
+
+  /**
+   * For each frame in this list: remove it from the list then call
    * Destroy() on it. Finally <code>delete this</code>.
+   * 
    */
   void Destroy();
 
+  /**
+   * For each frame in this list: remove it from the list then call
+   * DestroyFrom() on it. Finally <code>delete this</code>.
+   *
+   */
+  void DestroyFrom(nsIFrame* aDestructRoot);
+
   void Clear() { mFirstChild = mLastChild = nsnull; }
 
   void SetFrames(nsIFrame* aFrameList);
 
   void SetFrames(nsFrameList& aFrameList) {
     NS_PRECONDITION(!mFirstChild, "Losing frames");
 
     mFirstChild = aFrameList.FirstChild();
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -149,20 +149,20 @@ nsIBox* nsHTMLScrollFrame::GetScrollbarB
 
 nsresult
 nsHTMLScrollFrame::CreateAnonymousContent(nsTArray<nsIContent*>& aElements)
 {
   return mInner.CreateAnonymousContent(aElements);
 }
 
 void
-nsHTMLScrollFrame::Destroy()
+nsHTMLScrollFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   mInner.Destroy();
-  nsHTMLContainerFrame::Destroy();
+  nsHTMLContainerFrame::DestroyFrom(aDestructRoot);
 }
 
 NS_IMETHODIMP
 nsHTMLScrollFrame::SetInitialChildList(nsIAtom*     aListName,
                                        nsFrameList& aChildList)
 {
   nsresult rv = nsHTMLContainerFrame::SetInitialChildList(aListName, aChildList);
   mInner.CreateScrollableView();
@@ -1052,20 +1052,20 @@ nsIBox* nsXULScrollFrame::GetScrollbarBo
 
 nsresult
 nsXULScrollFrame::CreateAnonymousContent(nsTArray<nsIContent*>& aElements)
 {
   return mInner.CreateAnonymousContent(aElements);
 }
 
 void
-nsXULScrollFrame::Destroy()
+nsXULScrollFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   mInner.Destroy();
-  nsBoxFrame::Destroy();
+  nsBoxFrame::DestroyFrom(aDestructRoot);
 }
 
 NS_IMETHODIMP
 nsXULScrollFrame::SetInitialChildList(nsIAtom*        aListName,
                                       nsFrameList&    aChildList)
 {
   nsresult rv = nsBoxFrame::SetInitialChildList(aListName, aChildList);
 
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -315,17 +315,17 @@ public:
   // Because there can be only one child frame, these two function return
   // NS_ERROR_FAILURE
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
                           nsFrameList&    aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
                           nsFrameList&    aFrameList);
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
 
   virtual nsIView* GetParentViewForChildFrame(nsIFrame* aFrame) const {
     return mInner.GetParentViewForChildFrame(aFrame);
   }
 
@@ -486,17 +486,17 @@ public:
   // Because there can be only one child frame, these two function return
   // NS_ERROR_FAILURE
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
                           nsFrameList&    aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
                           nsFrameList&    aFrameList);
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
 
   virtual nsIView* GetParentViewForChildFrame(nsIFrame* aFrame) const {
     return mInner.GetParentViewForChildFrame(aFrame);
   }
 
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -522,17 +522,28 @@ public:
   /**
    * Destroys this frame and each of its child frames (recursively calls
    * Destroy() for each child). If this frame is a first-continuation, this
    * also removes the frame from the primary frame man and clears undisplayed
    * content for its content node.
    * If the frame is a placeholder, it also ensures the out-of-flow frame's
    * removal and destruction.
    */
-  virtual void Destroy() = 0;
+  void Destroy() { DestroyFrom(this); }
+
+protected:
+  /**
+   * Implements Destroy(). Do not call this directly except from within a
+   * DestroyFrom() implementation.
+   * @param  aDestructRoot is the root of the subtree being destroyed
+   */
+  virtual void DestroyFrom(nsIFrame* aDestructRoot) = 0;
+  friend class nsFrameList; // needed to pass aDestructRoot through to children
+  friend class nsLineBox;   // needed to pass aDestructRoot through to children
+public:
 
   /**
    * Called to set the initial list of frames. This happens after the frame
    * has been initialized.
    *
    * This is only called once for a given child list, and won't be called
    * at all for child lists with no initial list of frames.
    *
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -191,17 +191,17 @@ NS_IMETHODIMP nsImageFrame::GetAccessibl
     return accService->CreateHTMLImageAccessible(static_cast<nsIFrame*>(this), aAccessible);
   }
 
   return NS_ERROR_FAILURE;
 }
 #endif
 
 void
-nsImageFrame::Destroy()
+nsImageFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // Tell our image map, if there is one, to clean up
   // This causes the nsImageMap to unregister itself as
   // a DOM listener.
   if (mImageMap) {
     mImageMap->Destroy();
     NS_RELEASE(mImageMap);
   }
@@ -217,17 +217,17 @@ nsImageFrame::Destroy()
   }
   
   mListener = nsnull;
 
   // If we were displaying an icon, take ourselves off the list
   if (mDisplayingIcon)
     gIconLoad->RemoveIconObserver(this);
 
-  nsSplittableFrame::Destroy();
+  nsSplittableFrame::DestroyFrom(aDestructRoot);
 }
 
 
 
 NS_IMETHODIMP
 nsImageFrame::Init(nsIContent*      aContent,
                    nsIFrame*        aParent,
                    nsIFrame*        aPrevInFlow)
--- a/layout/generic/nsImageFrame.h
+++ b/layout/generic/nsImageFrame.h
@@ -95,17 +95,17 @@ private:
 class nsImageFrame : public ImageFrameSuper, public nsIImageFrame {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   nsImageFrame(nsStyleContext* aContext);
 
   NS_DECL_QUERYFRAME
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists);
   virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
   virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -1112,20 +1112,20 @@ nsIFrame*
 NS_NewPositionedInlineFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsPositionedInlineFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsPositionedInlineFrame)
 
 void
-nsPositionedInlineFrame::Destroy()
+nsPositionedInlineFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
-  mAbsoluteContainer.DestroyFrames(this);
-  nsInlineFrame::Destroy();
+  mAbsoluteContainer.DestroyFrames(this, aDestructRoot);
+  nsInlineFrame::DestroyFrom(aDestructRoot);
 }
 
 NS_IMETHODIMP
 nsPositionedInlineFrame::SetInitialChildList(nsIAtom*        aListName,
                                              nsFrameList&    aChildList)
 {
   nsresult  rv;
 
--- a/layout/generic/nsInlineFrame.h
+++ b/layout/generic/nsInlineFrame.h
@@ -247,17 +247,17 @@ public:
 
   nsPositionedInlineFrame(nsStyleContext* aContext)
     : nsInlineFrame(aContext)
     , mAbsoluteContainer(nsGkAtoms::absoluteList)
   {}
 
   virtual ~nsPositionedInlineFrame() { } // useful for debugging
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   NS_IMETHOD SetInitialChildList(nsIAtom*        aListName,
                                  nsFrameList&    aChildList);
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
                           nsFrameList&    aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
                           nsFrameList&    aFrameList);
--- a/layout/generic/nsLineBox.cpp
+++ b/layout/generic/nsLineBox.cpp
@@ -315,29 +315,30 @@ nsLineBox::CachedIsEmpty()
   }
 
   mFlags.mEmptyCacheValid = PR_TRUE;
   mFlags.mEmptyCacheState = result;
   return result;
 }
 
 void
-nsLineBox::DeleteLineList(nsPresContext* aPresContext, nsLineList& aLines)
+nsLineBox::DeleteLineList(nsPresContext* aPresContext, nsLineList& aLines,
+                          nsIFrame* aDestructRoot)
 {
   if (! aLines.empty()) {
     // Delete our child frames before doing anything else. In particular
     // we do all of this before our base class releases it's hold on the
     // view.
 #ifdef DEBUG
     PRInt32 numFrames = 0;
 #endif
     for (nsIFrame* child = aLines.front()->mFirstChild; child; ) {
       nsIFrame* nextChild = child->GetNextSibling();
       child->SetNextSibling(nsnull);
-      child->Destroy();
+      child->DestroyFrom((aDestructRoot) ? aDestructRoot : child);
       child = nextChild;
 #ifdef DEBUG
       numFrames++;
 #endif
     }
 
     nsIPresShell *shell = aPresContext->PresShell();
 
--- a/layout/generic/nsLineBox.h
+++ b/layout/generic/nsLineBox.h
@@ -426,17 +426,18 @@ public:
    */
   nscoord GetAscent() const { return mAscent; }
   void SetAscent(nscoord aAscent) { mAscent = aAscent; }
 
   nscoord GetHeight() const {
     return mBounds.height;
   }
 
-  static void DeleteLineList(nsPresContext* aPresContext, nsLineList& aLines);
+  static void DeleteLineList(nsPresContext* aPresContext, nsLineList& aLines,
+                             nsIFrame* aDestructRoot);
 
   // search from beginning to end
   // XXX Should switch to API below
   static nsLineBox* FindLineContaining(nsLineList& aLines, nsIFrame* aFrame,
                                        PRInt32* aFrameIndexInLine);
 
   // search from end to beginning of [aBegin, aEnd)
   // Returns PR_TRUE if it found the line and PR_FALSE if not.
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -608,17 +608,17 @@ nsObjectFrame::Init(nsIContent*      aCo
   }
 #ifdef XP_WIN
   mDoublePassEvent = 0;
 #endif
   return rv;
 }
 
 void
-nsObjectFrame::Destroy()
+nsObjectFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   NS_ASSERTION(!mPreventInstantiation ||
                (mContent && mContent->GetCurrentDoc()->GetDisplayDocument()),
                "about to crash due to bug 136927");
 
   NotifyPluginEventObservers(NS_LITERAL_STRING("destroy").get());
 
   PresContext()->RootPresContext()->UnregisterPluginForGeometryUpdates(this);
@@ -629,17 +629,17 @@ nsObjectFrame::Destroy()
 
   // StopPluginInternal might have disowned the widget; if it has,
   // mWidget will be null.
   if (mWidget) {
     mInnerView->DetachWidgetEventHandler(mWidget);
     mWidget->Destroy();
   }
 
-  nsObjectFrameSuper::Destroy();
+  nsObjectFrameSuper::DestroyFrom(aDestructRoot);
 }
 
 /* virtual */ void
 nsObjectFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
   if (HasView()) {
     nsIView* view = GetView();
     nsIViewManager* vm = view->GetViewManager();
--- a/layout/generic/nsObjectFrame.h
+++ b/layout/generic/nsObjectFrame.h
@@ -98,17 +98,17 @@ public:
   }
 
   virtual PRBool NeedsView() { return PR_TRUE; }
 
 #ifdef DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
 
   NS_IMETHOD GetPluginInstance(nsIPluginInstance*& aPluginInstance);
   virtual nsresult Instantiate(nsIChannel* aChannel, nsIStreamListener** aStreamListener);
   virtual nsresult Instantiate(const char* aMimeType, nsIURI* aURI);
   virtual void TryNotifyContentObjectWrapper();
   virtual void StopPlugin();
--- a/layout/generic/nsPlaceholderFrame.cpp
+++ b/layout/generic/nsPlaceholderFrame.cpp
@@ -122,29 +122,37 @@ nsPlaceholderFrame::Reflow(nsPresContext
   aDesiredSize.height = 0;
 
   aStatus = NS_FRAME_COMPLETE;
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return NS_OK;
 }
 
 void
-nsPlaceholderFrame::Destroy()
+nsPlaceholderFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   nsIPresShell* shell = PresContext()->GetPresShell();
   nsIFrame* oof = mOutOfFlowFrame;
   if (oof) {
-    NS_ASSERTION(shell && oof->GetParent(), "Null presShell or parent!?");
-    // Unregister and destroy out-of-flow frame
+    // Unregister out-of-flow frame
     shell->FrameManager()->UnregisterPlaceholderFrame(this);
-    nsIAtom* listName = nsLayoutUtils::GetChildListNameFor(oof);
-    shell->FrameManager()->RemoveFrame(listName, oof);
+    mOutOfFlowFrame = nsnull;
+    // If aDestructRoot is not an ancestor of the out-of-flow frame,
+    // then call RemoveFrame on it here.
+    // Also destroy it here if it's a popup frame. (Bug 96291)
+    if (shell->FrameManager() &&
+        ((GetStateBits() & PLACEHOLDER_FOR_FLOAT) ||
+         !nsLayoutUtils::IsProperAncestorFrame(aDestructRoot, oof))) {
+      nsIAtom* listName = nsLayoutUtils::GetChildListNameFor(oof);
+      shell->FrameManager()->RemoveFrame(listName, oof);
+    }
+    // else oof will be destroyed by its parent
   }
 
-  nsFrame::Destroy();
+  nsFrame::DestroyFrom(aDestructRoot);
 }
 
 nsIAtom*
 nsPlaceholderFrame::GetType() const
 {
   return nsGkAtoms::placeholderFrame; 
 }
 
--- a/layout/generic/nsPlaceholderFrame.h
+++ b/layout/generic/nsPlaceholderFrame.h
@@ -125,17 +125,17 @@ public:
                                  InlineMinWidthData *aData);
   virtual void AddInlinePrefWidth(nsIRenderingContext *aRenderingContext,
                                   InlinePrefWidthData *aData);
   NS_IMETHOD Reflow(nsPresContext* aPresContext,
                     nsHTMLReflowMetrics& aDesiredSize,
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus& aStatus);
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   // nsIFrame overrides
 #if defined(DEBUG) || (defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF))
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists);
 #endif // DEBUG || (MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF)
   
--- a/layout/generic/nsSplittableFrame.cpp
+++ b/layout/generic/nsSplittableFrame.cpp
@@ -59,25 +59,25 @@ nsSplittableFrame::Init(nsIContent*     
     SetPrevInFlow(aPrevInFlow);
     aPrevInFlow->SetNextInFlow(this);
   }
 
   return rv;
 }
 
 void
-nsSplittableFrame::Destroy()
+nsSplittableFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // Disconnect from the flow list
   if (mPrevContinuation || mNextContinuation) {
     RemoveFromFlow(this);
   }
 
   // Let the base class destroy the frame
-  nsFrame::Destroy();
+  nsFrame::DestroyFrom(aDestructRoot);
 }
 
 nsSplittableType
 nsSplittableFrame::GetSplittableType() const
 {
   return NS_FRAME_SPLITTABLE;
 }
 
--- a/layout/generic/nsSplittableFrame.h
+++ b/layout/generic/nsSplittableFrame.h
@@ -52,17 +52,17 @@ public:
   NS_DECL_FRAMEARENA_HELPERS
 
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
   
   virtual nsSplittableType GetSplittableType() const;
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   /*
    * Frame continuations can be either fluid or not:
    * Fluid continuations ("in-flows") are the result of line breaking, 
    * column breaking, or page breaking.
    * Other (non-fluid) continuations can be the result of BiDi frame splitting.
    * A "flow" is a chain of fluid continuations.
    */
--- a/layout/generic/nsTextFrame.h
+++ b/layout/generic/nsTextFrame.h
@@ -79,17 +79,17 @@ public:
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists);
 
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
   
   NS_IMETHOD GetCursor(const nsPoint& aPoint,
                        nsIFrame::Cursor& aCursor);
   
   NS_IMETHOD CharacterDataChanged(CharacterDataChangeInfo* aInfo);
                                   
   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
   
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -3411,40 +3411,40 @@ nsTextFrame::Init(nsIContent*      aCont
   // Since our content has a frame now, this flag is no longer needed.
   aContent->UnsetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE);
   // We're not a continuing frame.
   // mContentOffset = 0; not necessary since we get zeroed out at init
   return nsFrame::Init(aContent, aParent, aPrevInFlow);
 }
 
 void
-nsTextFrame::Destroy()
+nsTextFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // We might want to clear NS_CREATE_FRAME_IF_NON_WHITESPACE or
   // NS_REFRAME_IF_WHITESPACE on mContent here, since our parent frame
   // type might be changing.  Not clear whether it's worth it.
   ClearTextRun();
   if (mNextContinuation) {
     mNextContinuation->SetPrevInFlow(nsnull);
   }
   // Let the base class destroy the frame
-  nsFrame::Destroy();
+  nsFrame::DestroyFrom(aDestructRoot);
 }
 
 class nsContinuingTextFrame : public nsTextFrame {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   friend nsIFrame* NS_NewContinuingTextFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   virtual nsIFrame* GetPrevContinuation() const {
     return mPrevContinuation;
   }
   NS_IMETHOD SetPrevContinuation(nsIFrame* aPrevContinuation) {
     NS_ASSERTION (!aPrevContinuation || GetType() == aPrevContinuation->GetType(),
                   "setting a prev continuation with incorrect type!");
     NS_ASSERTION (!nsSplittableFrame::IsInPrevContinuationChain(aPrevContinuation, this),
@@ -3546,17 +3546,17 @@ nsContinuingTextFrame::Init(nsIContent* 
     mState |= NS_FRAME_IS_BIDI;
   } // prev frame is bidi
 #endif // IBMBIDI
 
   return rv;
 }
 
 void
-nsContinuingTextFrame::Destroy()
+nsContinuingTextFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // The text associated with this frame will become associated with our
   // prev-continuation. If that means the text has changed style, then
   // we need to wipe out the text run for the text.
   // Note that mPrevContinuation can be null if we're destroying the whole
   // frame chain from the start to the end.
   // If this frame is mentioned in the userData for a textrun (say
   // because there's a direction change at the start of this frame), then
@@ -3569,17 +3569,17 @@ nsContinuingTextFrame::Destroy()
     // Clear the previous continuation's text run also, so that it can rebuild
     // the text run to include our text.
     if (mPrevContinuation) {
       (static_cast<nsTextFrame*>(mPrevContinuation))->ClearTextRun();
     }
   }
   nsSplittableFrame::RemoveFromFlow(this);
   // Let the base class destroy the frame
-  nsFrame::Destroy();
+  nsFrame::DestroyFrom(aDestructRoot);
 }
 
 nsIFrame*
 nsContinuingTextFrame::GetFirstInFlow() const
 {
   // Can't cast to |nsContinuingTextFrame*| because the first one isn't.
   nsIFrame *firstInFlow,
            *previous = const_cast<nsIFrame*>
--- a/layout/generic/nsVideoFrame.cpp
+++ b/layout/generic/nsVideoFrame.cpp
@@ -131,21 +131,21 @@ nsVideoFrame::CreateAnonymousContent(nsT
   NS_ENSURE_SUCCESS(rv, rv);
   if (!aElements.AppendElement(mVideoControls))
     return NS_ERROR_OUT_OF_MEMORY;
 
   return NS_OK;
 }
 
 void
-nsVideoFrame::Destroy()
+nsVideoFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   nsContentUtils::DestroyAnonymousContent(&mVideoControls);
   nsContentUtils::DestroyAnonymousContent(&mPosterImage);
-  nsContainerFrame::Destroy();
+  nsContainerFrame::DestroyFrom(aDestructRoot);
 }
 
 PRBool
 nsVideoFrame::IsLeaf() const
 {
   return PR_TRUE;
 }
 
--- a/layout/generic/nsVideoFrame.h
+++ b/layout/generic/nsVideoFrame.h
@@ -75,17 +75,17 @@ public:
   nsSize GetIntrinsicSize(nsIRenderingContext *aRenderingContext);
   virtual nsSize GetIntrinsicRatio();
   virtual nsSize ComputeSize(nsIRenderingContext *aRenderingContext,
                              nsSize aCBSize, nscoord aAvailableWidth,
                              nsSize aMargin, nsSize aBorder, nsSize aPadding,
                              PRBool aShrinkWrap);
   virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
   virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
   virtual PRBool IsLeaf() const;
 
   NS_IMETHOD Reflow(nsPresContext*          aPresContext,
                     nsHTMLReflowMetrics&     aDesiredSize,
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus&          aStatus);
 
 #ifdef ACCESSIBILITY
--- a/layout/generic/nsViewportFrame.cpp
+++ b/layout/generic/nsViewportFrame.cpp
@@ -59,20 +59,20 @@ NS_IMETHODIMP
 ViewportFrame::Init(nsIContent*      aContent,
                     nsIFrame*        aParent,
                     nsIFrame*        aPrevInFlow)
 {
   return Super::Init(aContent, aParent, aPrevInFlow);
 }
 
 void
-ViewportFrame::Destroy()
+ViewportFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
-  mFixedContainer.DestroyFrames(this);
-  nsContainerFrame::Destroy();
+  mFixedContainer.DestroyFrames(this, aDestructRoot);
+  nsContainerFrame::DestroyFrom(aDestructRoot);
 }
 
 NS_IMETHODIMP
 ViewportFrame::SetInitialChildList(nsIAtom*        aListName,
                                    nsFrameList&    aChildList)
 {
   nsresult rv = NS_OK;
 
--- a/layout/generic/nsViewportFrame.h
+++ b/layout/generic/nsViewportFrame.h
@@ -62,17 +62,17 @@ public:
   typedef nsContainerFrame Super;
 
   ViewportFrame(nsStyleContext* aContext)
     : nsContainerFrame(aContext)
     , mFixedContainer(nsGkAtoms::fixedList)
   {}
   virtual ~ViewportFrame() { } // useful for debugging
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        asPrevInFlow);
 
   NS_IMETHOD SetInitialChildList(nsIAtom*        aListName,
                                  nsFrameList&    aChildList);
 
--- a/layout/svg/base/src/nsSVGForeignObjectFrame.cpp
+++ b/layout/svg/base/src/nsSVGForeignObjectFrame.cpp
@@ -95,20 +95,20 @@ nsSVGForeignObjectFrame::Init(nsIContent
   AddStateBits(NS_STATE_SVG_PROPAGATE_TRANSFORM | 
                (aParent->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD));
   if (NS_SUCCEEDED(rv)) {
     nsSVGUtils::GetOuterSVGFrame(this)->RegisterForeignObject(this);
   }
   return rv;
 }
 
-void nsSVGForeignObjectFrame::Destroy()
+void nsSVGForeignObjectFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   nsSVGUtils::GetOuterSVGFrame(this)->UnregisterForeignObject(this);
-  nsSVGForeignObjectFrameBase::Destroy();
+  nsSVGForeignObjectFrameBase::DestroyFrom(aDestructRoot);
 }
 
 nsIAtom *
 nsSVGForeignObjectFrame::GetType() const
 {
   return nsGkAtoms::svgForeignObjectFrame;
 }
 
--- a/layout/svg/base/src/nsSVGForeignObjectFrame.h
+++ b/layout/svg/base/src/nsSVGForeignObjectFrame.h
@@ -62,17 +62,17 @@ protected:
 public:
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
   // nsIFrame:
   NS_IMETHOD  Init(nsIContent* aContent,
                    nsIFrame*   aParent,
                    nsIFrame*   aPrevInFlow);
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
   NS_IMETHOD  AttributeChanged(PRInt32         aNameSpaceID,
                                nsIAtom*        aAttribute,
                                PRInt32         aModType);
 
   virtual nsIFrame* GetContentInsertionFrame() {
     return GetFirstChild(nsnull)->GetContentInsertionFrame();
   }
 
--- a/layout/svg/base/src/nsSVGUseFrame.cpp
+++ b/layout/svg/base/src/nsSVGUseFrame.cpp
@@ -64,17 +64,17 @@ public:
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
 #endif
 
   NS_IMETHOD  AttributeChanged(PRInt32         aNameSpaceID,
                                nsIAtom*        aAttribute,
                                PRInt32         aModType);
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   /**
    * Get the "type" of the frame
    *
    * @see nsGkAtoms::svgUseFrame
    */
   virtual nsIAtom* GetType() const;
 
@@ -146,20 +146,20 @@ nsSVGUseFrame::AttributeChanged(PRInt32 
     return NS_OK;
   }
 
   return nsSVGUseFrameBase::AttributeChanged(aNameSpaceID,
                                              aAttribute, aModType);
 }
 
 void
-nsSVGUseFrame::Destroy()
+nsSVGUseFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   nsRefPtr<nsSVGUseElement> use = static_cast<nsSVGUseElement*>(mContent);
-  nsSVGUseFrameBase::Destroy();
+  nsSVGUseFrameBase::DestroyFrom(aDestructRoot);
   use->DestroyAnonymousContent();
 }
 
 PRBool
 nsSVGUseFrame::IsLeaf() const
 {
   return PR_TRUE;
 }
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -256,20 +256,20 @@ nsTableFrame::~nsTableFrame()
 
   if (nsnull!=mTableLayoutStrategy) {
     delete mTableLayoutStrategy;
     mTableLayoutStrategy = nsnull;
   }
 }
 
 void
-nsTableFrame::Destroy()
-{
-  mColGroups.DestroyFrames();
-  nsHTMLContainerFrame::Destroy();
+nsTableFrame::DestroyFrom(nsIFrame* aDestructRoot)
+{
+  mColGroups.DestroyFramesFrom(aDestructRoot);
+  nsHTMLContainerFrame::DestroyFrom(aDestructRoot);
 }
 
 // Make sure any views are positioned properly
 void
 nsTableFrame::RePositionViews(nsIFrame* aFrame)
 {
   nsContainerFrame::PositionFrameView(aFrame);
   nsContainerFrame::PositionChildViews(aFrame);
--- a/layout/tables/nsTableFrame.h
+++ b/layout/tables/nsTableFrame.h
@@ -188,18 +188,18 @@ public:
   nsPoint GetFirstSectionOrigin(const nsHTMLReflowState& aReflowState) const;
   /*
    * Notification that aAttribute has changed for content inside a table (cell, row, etc)
    */
   void AttributeChangedFor(nsIFrame*       aFrame,
                            nsIContent*     aContent, 
                            nsIAtom*        aAttribute); 
 
-  /** @see nsIFrame::Destroy */
-  virtual void Destroy();
+  /** @see nsIFrame::DestroyFrom */
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
   
   /** @see nsIFrame::DidSetStyleContext */
   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
 
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
                           nsFrameList&    aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
--- a/layout/tables/nsTableOuterFrame.cpp
+++ b/layout/tables/nsTableOuterFrame.cpp
@@ -206,20 +206,20 @@ NS_IMETHODIMP nsTableOuterFrame::GetAcce
 
 /* virtual */ PRBool
 nsTableOuterFrame::IsContainingBlock() const
 {
   return PR_FALSE;
 }
 
 void
-nsTableOuterFrame::Destroy()
+nsTableOuterFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
-  mCaptionFrames.DestroyFrames();
-  nsHTMLContainerFrame::Destroy();
+  mCaptionFrames.DestroyFramesFrom(aDestructRoot);
+  nsHTMLContainerFrame::DestroyFrom(aDestructRoot);
 }
 
 nsFrameList
 nsTableOuterFrame::GetChildList(nsIAtom* aListName) const
 {
   if (nsGkAtoms::captionList == aListName) {
     return mCaptionFrames;
   }
--- a/layout/tables/nsTableOuterFrame.h
+++ b/layout/tables/nsTableOuterFrame.h
@@ -95,17 +95,17 @@ public:
     * @param aPresShell the pres shell for this frame
     *
     * @return           the frame that was created
     */
   friend nsIFrame* NS_NewTableOuterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   
   // nsIFrame overrides - see there for a description
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
   
   virtual PRBool IsContainingBlock() const;
 
   NS_IMETHOD SetInitialChildList(nsIAtom*        aListName,
                                  nsFrameList&    aChildList);
  
   virtual nsFrameList GetChildList(nsIAtom* aListName) const;
 
--- a/layout/xul/base/src/nsBoxFrame.cpp
+++ b/layout/xul/base/src/nsBoxFrame.cpp
@@ -940,25 +940,25 @@ nsBoxFrame::DoLayout(nsBoxLayoutState& a
   }
 
   aState.SetLayoutFlags(oldFlags);
 
   return rv;
 }
 
 void
-nsBoxFrame::Destroy()
+nsBoxFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // unregister access key
   RegUnregAccessKey(PR_FALSE);
 
   // clean up the container box's layout manager and child boxes
   SetLayoutManager(nsnull);
 
-  nsContainerFrame::Destroy();
+  nsContainerFrame::DestroyFrom(aDestructRoot);
 } 
 
 #ifdef DEBUG_LAYOUT
 NS_IMETHODIMP
 nsBoxFrame::SetDebug(nsBoxLayoutState& aState, PRBool aDebug)
 {
   // see if our state matches the given debug state
   PRBool debugSet = mState & NS_STATE_CURRENTLY_IN_DEBUG;
--- a/layout/xul/base/src/nsBoxFrame.h
+++ b/layout/xul/base/src/nsBoxFrame.h
@@ -236,17 +236,17 @@ protected:
 
     virtual PRBool GetInitialEqualSize(PRBool& aEqualSize); 
     virtual void GetInitialOrientation(PRBool& aIsHorizontal);
     virtual void GetInitialDirection(PRBool& aIsNormal);
     virtual PRBool GetInitialHAlignment(Halignment& aHalign); 
     virtual PRBool GetInitialVAlignment(Valignment& aValign); 
     virtual PRBool GetInitialAutoStretch(PRBool& aStretch); 
   
-    virtual void Destroy();
+    virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
     nsSize mPrefSize;
     nsSize mMinSize;
     nsSize mMaxSize;
     nscoord mFlex;
     nscoord mAscent;
 
     nsCOMPtr<nsIBoxLayout> mLayoutManager;
--- a/layout/xul/base/src/nsDocElementBoxFrame.cpp
+++ b/layout/xul/base/src/nsDocElementBoxFrame.cpp
@@ -58,17 +58,17 @@
 #include "nsContentUtils.h"
 
 //#define DEBUG_REFLOW
 
 class nsDocElementBoxFrame : public nsBoxFrame,
                              public nsIAnonymousContentCreator
 {
 public:
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   friend nsIFrame* NS_NewBoxFrame(nsIPresShell* aPresShell,
                                   nsStyleContext* aContext);
 
   nsDocElementBoxFrame(nsIPresShell* aShell, nsStyleContext* aContext)
     :nsBoxFrame(aShell, aContext, PR_TRUE) {}
 
   NS_DECL_QUERYFRAME
@@ -99,21 +99,21 @@ nsIFrame*
 NS_NewDocElementBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsDocElementBoxFrame (aPresShell, aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsDocElementBoxFrame)
 
 void
-nsDocElementBoxFrame::Destroy()
+nsDocElementBoxFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   nsContentUtils::DestroyAnonymousContent(&mPopupgroupContent);
   nsContentUtils::DestroyAnonymousContent(&mTooltipContent);
-  nsBoxFrame::Destroy();
+  nsBoxFrame::DestroyFrom(aDestructRoot);
 }
 
 nsresult
 nsDocElementBoxFrame::CreateAnonymousContent(nsTArray<nsIContent*>& aElements)
 {
   nsIDocument* doc = mContent->GetDocument();
   if (!doc) {
     // The page is currently being torn down.  Why bother.
--- a/layout/xul/base/src/nsImageBoxFrame.cpp
+++ b/layout/xul/base/src/nsImageBoxFrame.cpp
@@ -199,26 +199,26 @@ nsImageBoxFrame::~nsImageBoxFrame()
 /* virtual */ void
 nsImageBoxFrame::MarkIntrinsicWidthsDirty()
 {
   SizeNeedsRecalc(mImageSize);
   nsLeafBoxFrame::MarkIntrinsicWidthsDirty();
 }
 
 void
-nsImageBoxFrame::Destroy()
+nsImageBoxFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // Release image loader first so that it's refcnt can go to zero
   if (mImageRequest)
     mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
 
   if (mListener)
     reinterpret_cast<nsImageBoxListener*>(mListener.get())->SetFrame(nsnull); // set the frame to null so we don't send messages to a dead object.
 
-  nsLeafBoxFrame::Destroy();
+  nsLeafBoxFrame::DestroyFrom(aDestructRoot);
 }
 
 
 NS_IMETHODIMP
 nsImageBoxFrame::Init(nsIContent*      aContent,
                       nsIFrame*        aParent,
                       nsIFrame*        aPrevInFlow)
 {
--- a/layout/xul/base/src/nsImageBoxFrame.h
+++ b/layout/xul/base/src/nsImageBoxFrame.h
@@ -87,17 +87,17 @@ public:
                    nsIFrame*        asPrevInFlow);
 
   NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
                               nsIAtom* aAttribute,
                               PRInt32 aModType);
 
   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   virtual nsIAtom* GetType() const;
 #ifdef DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
 
   /** 
    * Update mUseSrcAttr from appropriate content attributes or from
--- a/layout/xul/base/src/nsListBoxBodyFrame.cpp
+++ b/layout/xul/base/src/nsListBoxBodyFrame.cpp
@@ -230,33 +230,33 @@ nsListBoxBodyFrame::Init(nsIContent*    
   nsCOMPtr<nsIFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
   fm->GetHeight(mRowHeight);
 
   return rv;
 }
 
 void
-nsListBoxBodyFrame::Destroy()
+nsListBoxBodyFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // make sure we cancel any posted callbacks.
   if (mReflowCallbackPosted)
      PresContext()->PresShell()->CancelReflowCallback(this);
 
   // Revoke any pending position changed events
   for (PRUint32 i = 0; i < mPendingPositionChangeEvents.Length(); ++i) {
     mPendingPositionChangeEvents[i]->Revoke();
   }
 
   // Make sure we tell our listbox's box object we're being destroyed.
   if (mBoxObject) {
     mBoxObject->ClearCachedValues();
   }
 
-  nsBoxFrame::Destroy();
+  nsBoxFrame::DestroyFrom(aDestructRoot);
 }
 
 NS_IMETHODIMP
 nsListBoxBodyFrame::AttributeChanged(PRInt32 aNameSpaceID,
                                      nsIAtom* aAttribute, 
                                      PRInt32 aModType)
 {
   nsresult rv = NS_OK;
--- a/layout/xul/base/src/nsListBoxBodyFrame.h
+++ b/layout/xul/base/src/nsListBoxBodyFrame.h
@@ -80,17 +80,17 @@ public:
 
   friend nsIFrame* NS_NewListBoxBodyFrame(nsIPresShell* aPresShell,
                                           nsStyleContext* aContext);
   
   // nsIFrame
   NS_IMETHOD Init(nsIContent*     aContent,
                   nsIFrame*       aParent, 
                   nsIFrame*       aPrevInFlow);
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID, nsIAtom* aAttribute, PRInt32 aModType);
 
   // nsIScrollbarMediator
   NS_IMETHOD PositionChanged(nsIScrollbarFrame* aScrollbar, PRInt32 aOldIndex, PRInt32& aNewIndex);
   NS_IMETHOD ScrollbarButtonPressed(nsIScrollbarFrame* aScrollbar, PRInt32 aOldIndex, PRInt32 aNewIndex);
   NS_IMETHOD VisibilityChanged(PRBool aVisible);
 
--- a/layout/xul/base/src/nsMenuBarFrame.cpp
+++ b/layout/xul/base/src/nsMenuBarFrame.cpp
@@ -448,25 +448,25 @@ nsMenuBarFrame::RemoveKeyboardNavigator(
   if (!mIsActive) {
     nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
     if (pm)
       pm->SetActiveMenuBar(this, PR_FALSE);
   }
 }
 
 void
-nsMenuBarFrame::Destroy()
+nsMenuBarFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
   if (pm)
     pm->SetActiveMenuBar(this, PR_FALSE);
 
   mTarget->RemoveEventListener(NS_LITERAL_STRING("keypress"), (nsIDOMKeyListener*)mMenuBarListener, PR_FALSE); 
   mTarget->RemoveEventListener(NS_LITERAL_STRING("keydown"), (nsIDOMKeyListener*)mMenuBarListener, PR_FALSE);  
   mTarget->RemoveEventListener(NS_LITERAL_STRING("keyup"), (nsIDOMKeyListener*)mMenuBarListener, PR_FALSE);
 
   mTarget->RemoveEventListener(NS_LITERAL_STRING("mousedown"), (nsIDOMMouseListener*)mMenuBarListener, PR_FALSE);
   mTarget->RemoveEventListener(NS_LITERAL_STRING("blur"), (nsIDOMFocusListener*)mMenuBarListener, PR_TRUE);
 
   NS_IF_RELEASE(mMenuBarListener);
 
-  nsBoxFrame::Destroy();
+  nsBoxFrame::DestroyFrom(aDestructRoot);
 }
--- a/layout/xul/base/src/nsMenuBarFrame.h
+++ b/layout/xul/base/src/nsMenuBarFrame.h
@@ -82,17 +82,17 @@ public:
 
   void InstallKeyboardNavigator();
   void RemoveKeyboardNavigator();
 
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   virtual nsIAtom* GetType() const { return nsGkAtoms::menuBarFrame; }
 
 // Non-interface helpers
 
   void
   SetStayActive(PRBool aStayActive) { mStayActive = aStayActive; }
 
--- a/layout/xul/base/src/nsMenuFrame.cpp
+++ b/layout/xul/base/src/nsMenuFrame.cpp
@@ -364,17 +364,17 @@ nsMenuFrame::GetAdditionalChildListName(
 {
   if (NS_MENU_POPUP_LIST_INDEX == aIndex) {
     return nsGkAtoms::popupList;
   }
   return nsnull;
 }
 
 void
-nsMenuFrame::Destroy()
+nsMenuFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // Kill our timer if one is active. This is not strictly necessary as
   // the pointer to this frame will be cleared from the mediator, but
   // this is done for added safety.
   if (mOpenTimer) {
     mOpenTimer->Cancel();
   }
 
@@ -388,19 +388,19 @@ nsMenuFrame::Destroy()
 
   // are we our menu parent's current menu item?
   if (mMenuParent && mMenuParent->GetCurrentMenuItem() == this) {
     // yes; tell it that we're going away
     mMenuParent->CurrentMenuIsBeingDestroyed();
   }
 
   if (mPopupFrame)
-    mPopupFrame->Destroy();
+    mPopupFrame->DestroyFrom(aDestructRoot);
 
-  nsBoxFrame::Destroy();
+  nsBoxFrame::DestroyFrom(aDestructRoot);
 }
 
 NS_IMETHODIMP
 nsMenuFrame::BuildDisplayListForChildren(nsDisplayListBuilder*   aBuilder,
                                          const nsRect&           aDirtyRect,
                                          const nsDisplayListSet& aLists)
 {
   if (!aBuilder->IsForEventDelivery())
--- a/layout/xul/base/src/nsMenuFrame.h
+++ b/layout/xul/base/src/nsMenuFrame.h
@@ -130,17 +130,17 @@ public:
 
   // The following methods are all overridden so that the menupopup
   // can be stored in a separate list, so that it doesn't impact reflow of the
   // actual menu item at all.
   virtual nsFrameList GetChildList(nsIAtom* aListName) const;
   NS_IMETHOD SetInitialChildList(nsIAtom*        aListName,
                                  nsFrameList&    aChildList);
   virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   // Overridden to prevent events from going to children of the menu.
   NS_IMETHOD BuildDisplayListForChildren(nsDisplayListBuilder*   aBuilder,
                                          const nsRect&           aDirtyRect,
                                          const nsDisplayListSet& aLists);
                                          
   // this method can destroy the frame
   NS_IMETHOD HandleEvent(nsPresContext* aPresContext, 
--- a/layout/xul/base/src/nsMenuPopupFrame.cpp
+++ b/layout/xul/base/src/nsMenuPopupFrame.cpp
@@ -1561,29 +1561,29 @@ nsMenuPopupFrame::MoveToAttributePositio
   PRInt32 xpos = left.ToInteger(&err1);
   PRInt32 ypos = top.ToInteger(&err2);
 
   if (NS_SUCCEEDED(err1) && NS_SUCCEEDED(err2))
     MoveTo(xpos, ypos, PR_FALSE);
 }
 
 void
-nsMenuPopupFrame::Destroy()
+nsMenuPopupFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
   if (pm)
     pm->PopupDestroyed(this);
 
   nsIRootBox* rootBox =
     nsIRootBox::GetRootBox(PresContext()->GetPresShell());
   if (rootBox && rootBox->GetDefaultTooltip() == mContent) {
     rootBox->SetDefaultTooltip(nsnull);
   }
 
-  nsBoxFrame::Destroy();
+  nsBoxFrame::DestroyFrom(aDestructRoot);
 }
 
 
 void
 nsMenuPopupFrame::MoveTo(PRInt32 aLeft, PRInt32 aTop, PRBool aUpdateAttrs)
 {
   // reposition the popup at the specified coordinates. Don't clear the anchor
   // and position, because the popup can be reset to its anchor position by
--- a/layout/xul/base/src/nsMenuPopupFrame.h
+++ b/layout/xul/base/src/nsMenuPopupFrame.h
@@ -167,17 +167,17 @@ public:
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
 
   NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
                               nsIAtom* aAttribute,
                               PRInt32 aModType);
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   virtual void InvalidateInternal(const nsRect& aDamageRect,
                                   nscoord aX, nscoord aY, nsIFrame* aForChild,
                                   PRUint32 aFlags);
 
   // returns true if the popup is a panel with the noautohide attribute set to
   // true. These panels do not roll up automatically.
   PRBool IsNoAutoHide();
--- a/layout/xul/base/src/nsPopupSetFrame.cpp
+++ b/layout/xul/base/src/nsPopupSetFrame.cpp
@@ -51,24 +51,24 @@
 
 nsPopupFrameList::nsPopupFrameList(nsIContent* aPopupContent, nsPopupFrameList* aNext)
 :mNextPopup(aNext), 
  mPopupFrame(nsnull),
  mPopupContent(aPopupContent)
 {
 }
 
-nsPopupFrameList::~nsPopupFrameList()
+void nsPopupFrameList::Destroy(nsIFrame* aDestructRoot)
 {
   if (mPopupFrame) {
     nsIFrame* prevSib = mPopupFrame->GetPrevSibling();
     if (prevSib)
       prevSib->SetNextSibling(mPopupFrame->GetNextSibling());
     mPopupFrame->SetNextSibling(nsnull);
-    mPopupFrame->Destroy();
+    mPopupFrame->DestroyFrom((aDestructRoot) ? aDestructRoot : mPopupFrame);
   }
 }
 
 //
 // NS_NewPopupSetFrame
 //
 // Wrapper for creating a new menu popup container
 //
@@ -140,33 +140,33 @@ nsPopupSetFrame::SetInitialChildList(nsI
 {
   if (aListName == nsGkAtoms::popupList) {
     return AddPopupFrameList(aChildList);
   }
   return nsBoxFrame::SetInitialChildList(aListName, aChildList);
 }
 
 void
-nsPopupSetFrame::Destroy()
+nsPopupSetFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // remove each popup from the list as we go.
   while (mPopupList) {
     nsPopupFrameList* temp = mPopupList;
     mPopupList = mPopupList->mNextPopup;
-    delete temp; // destroys frame
+    temp->Destroy(aDestructRoot); // destroys frame
   }
 
   // Normally the root box is our grandparent, but in case of wrapping
   // it can be our great-grandparent.
   nsIRootBox *rootBox = nsIRootBox::GetRootBox(PresContext()->GetPresShell());
   if (rootBox) {
     rootBox->SetPopupSetFrame(nsnull);
   }
 
-  nsBoxFrame::Destroy();
+  nsBoxFrame::DestroyFrom(aDestructRoot);
 }
 
 NS_IMETHODIMP
 nsPopupSetFrame::DoLayout(nsBoxLayoutState& aState)
 {
   // lay us out
   nsresult rv = nsBoxFrame::DoLayout(aState);
 
@@ -247,17 +247,17 @@ nsPopupSetFrame::RemovePopupFrame(nsIFra
       else
         mPopupList = currEntry->mNextPopup;
       
       NS_ASSERTION((aPopup->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
                    aPopup->GetType() == nsGkAtoms::menuPopupFrame,
                    "found wrong type of frame in popupset's ::popupList");
       // Delete the entry.
       currEntry->mNextPopup = nsnull;
-      delete currEntry; // destroys the frame
+      currEntry->Destroy(); // destroys the frame
 #ifdef DEBUG
       found = PR_TRUE;
 #endif
 
       // Break out of the loop.
       break;
     }
 
--- a/layout/xul/base/src/nsPopupSetFrame.h
+++ b/layout/xul/base/src/nsPopupSetFrame.h
@@ -54,17 +54,17 @@ nsIFrame* NS_NewPopupSetFrame(nsIPresShe
 
 struct nsPopupFrameList {
   nsPopupFrameList* mNextPopup;  // The next popup in the list.
   nsMenuPopupFrame* mPopupFrame; // Our popup.
   nsIContent* mPopupContent;     // The content element for the <popup> itself.
 
 public:
   nsPopupFrameList(nsIContent* aPopupContent, nsPopupFrameList* aNext);
-  ~nsPopupFrameList();
+  void Destroy(nsIFrame* aDestructRoot = nsnull);
 };
 
 class nsPopupSetFrame : public nsBoxFrame
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   nsPopupSetFrame(nsIPresShell* aShell, nsStyleContext* aContext):
@@ -84,17 +84,17 @@ public:
                           nsFrameList&    aFrameList);
   NS_IMETHOD  SetInitialChildList(nsIAtom*        aListName,
                                   nsFrameList&    aChildList);
 
     // nsIBox
   NS_IMETHOD DoLayout(nsBoxLayoutState& aBoxLayoutState);
 
   // Used to destroy our popup frames.
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   virtual nsIAtom* GetType() const;
 
 #ifdef DEBUG
   NS_IMETHOD List(FILE* out, PRInt32 aIndent) const;
   NS_IMETHOD GetFrameName(nsAString& aResult) const
   {
       return MakeFrameName(NS_LITERAL_STRING("PopupSet"), aResult);
--- a/layout/xul/base/src/nsScrollBoxFrame.cpp
+++ b/layout/xul/base/src/nsScrollBoxFrame.cpp
@@ -49,17 +49,17 @@
 class nsAutoRepeatBoxFrame : public nsButtonBoxFrame
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   friend nsIFrame* NS_NewAutoRepeatBoxFrame(nsIPresShell* aPresShell,
                                             nsStyleContext* aContext);
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
                               nsIAtom* aAttribute,
                               PRInt32 aModType);
 
   NS_IMETHOD HandleEvent(nsPresContext* aPresContext, 
                          nsGUIEvent* aEvent,
                          nsEventStatus* aEventStatus);
@@ -185,22 +185,22 @@ nsAutoRepeatBoxFrame::AttributeChanged(P
 
 void
 nsAutoRepeatBoxFrame::Notify()
 {
   DoMouseClick(nsnull, mTrustedEvent);
 }
 
 void
-nsAutoRepeatBoxFrame::Destroy()
+nsAutoRepeatBoxFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // Ensure our repeat service isn't going... it's possible that a scrollbar can disappear out
   // from under you while you're in the process of scrolling.
   StopRepeat();
-  nsButtonBoxFrame::Destroy();
+  nsButtonBoxFrame::DestroyFrom(aDestructRoot);
 }
 
 PRBool
 nsAutoRepeatBoxFrame::IsActivatedOnHover()
 {
   return mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::repeat,
                                nsGkAtoms::hover, eCaseMatters);
 }
--- a/layout/xul/base/src/nsScrollbarButtonFrame.cpp
+++ b/layout/xul/base/src/nsScrollbarButtonFrame.cpp
@@ -310,15 +310,15 @@ nsScrollbarButtonFrame::GetParentWithTag
       }
    }
 
    result = nsnull;
    return NS_OK;
 }
 
 void
-nsScrollbarButtonFrame::Destroy()
+nsScrollbarButtonFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // Ensure our repeat service isn't going... it's possible that a scrollbar can disappear out
   // from under you while you're in the process of scrolling.
   StopRepeat();
-  nsButtonBoxFrame::Destroy();
+  nsButtonBoxFrame::DestroyFrom(aDestructRoot);
 }
--- a/layout/xul/base/src/nsScrollbarButtonFrame.h
+++ b/layout/xul/base/src/nsScrollbarButtonFrame.h
@@ -55,17 +55,17 @@ class nsScrollbarButtonFrame : public ns
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   nsScrollbarButtonFrame(nsIPresShell* aPresShell, nsStyleContext* aContext):
     nsButtonBoxFrame(aPresShell, aContext) {}
 
   // Overrides
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   friend nsIFrame* NS_NewScrollbarButtonFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
   NS_IMETHOD HandleEvent(nsPresContext* aPresContext, 
                          nsGUIEvent* aEvent,
                          nsEventStatus* aEventStatus);
 
   static nsresult GetChildWithTag(nsPresContext* aPresContext,
--- a/layout/xul/base/src/nsSliderFrame.cpp
+++ b/layout/xul/base/src/nsSliderFrame.cpp
@@ -1058,27 +1058,27 @@ nsSliderFrame::HandleRelease(nsPresConte
                                  nsEventStatus*  aEventStatus)
 {
   StopRepeat();
 
   return NS_OK;
 }
 
 void
-nsSliderFrame::Destroy()
+nsSliderFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // tell our mediator if we have one we are gone.
   if (mMediator) {
     mMediator->SetSlider(nsnull);
     mMediator = nsnull;
   }
   StopRepeat();
 
   // call base class Destroy()
-  nsBoxFrame::Destroy();
+  nsBoxFrame::DestroyFrom(aDestructRoot);
 }
 
 nsSize
 nsSliderFrame::GetPrefSize(nsBoxLayoutState& aState)
 {
   EnsureOrient();
   return nsBoxFrame::GetPrefSize(aState);
 }
--- a/layout/xul/base/src/nsSliderFrame.h
+++ b/layout/xul/base/src/nsSliderFrame.h
@@ -140,17 +140,17 @@ public:
 
   NS_IMETHOD  InsertFrames(nsIAtom*        aListName,
                            nsIFrame*       aPrevFrame,
                            nsFrameList&    aFrameList);
 
   NS_IMETHOD  RemoveFrame(nsIAtom*        aListName,
                           nsIFrame*       aOldFrame);
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   NS_IMETHOD BuildDisplayListForChildren(nsDisplayListBuilder*   aBuilder,
                                          const nsRect&           aDirtyRect,
                                          const nsDisplayListSet& aLists);
 
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists);
--- a/layout/xul/base/src/nsSplitterFrame.cpp
+++ b/layout/xul/base/src/nsSplitterFrame.cpp
@@ -252,25 +252,25 @@ NS_IMPL_FRAMEARENA_HELPERS(nsSplitterFra
 
 nsSplitterFrame::nsSplitterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 : nsBoxFrame(aPresShell, aContext),
   mInner(0)
 {
 }
 
 void
-nsSplitterFrame::Destroy()
+nsSplitterFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   if (mInner) {
     mInner->RemoveListener();
     mInner->Disconnect();
     mInner->Release();
     mInner = nsnull;
   }
-  nsBoxFrame::Destroy();
+  nsBoxFrame::DestroyFrom(aDestructRoot);
 }
 
 
 NS_IMETHODIMP
 nsSplitterFrame::GetCursor(const nsPoint&    aPoint,
                            nsIFrame::Cursor& aCursor)
 {
   return nsBoxFrame::GetCursor(aPoint, aCursor);
--- a/layout/xul/base/src/nsSplitterFrame.h
+++ b/layout/xul/base/src/nsSplitterFrame.h
@@ -50,17 +50,17 @@ class nsSplitterFrameInner;
 nsIFrame* NS_NewSplitterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
 class nsSplitterFrame : public nsBoxFrame
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   nsSplitterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
 #ifdef DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const {
     return MakeFrameName(NS_LITERAL_STRING("SplitterFrame"), aResult);
   }
 #endif
 
   // nsIFrame overrides
--- a/layout/xul/base/src/nsTextBoxFrame.cpp
+++ b/layout/xul/base/src/nsTextBoxFrame.cpp
@@ -168,21 +168,21 @@ nsTextBoxFrame::Init(nsIContent*      aC
 
     // register access key
     RegUnregAccessKey(PR_TRUE);
 
     return NS_OK;
 }
 
 void
-nsTextBoxFrame::Destroy()
+nsTextBoxFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
     // unregister access key
     RegUnregAccessKey(PR_FALSE);
-    nsTextBoxFrameSuper::Destroy();
+    nsTextBoxFrameSuper::DestroyFrom(aDestructRoot);
 }
 
 PRBool
 nsTextBoxFrame::AlwaysAppendAccessKey()
 {
   if (!gAccessKeyPrefInitialized) 
   {
     gAccessKeyPrefInitialized = PR_TRUE;
--- a/layout/xul/base/src/nsTextBoxFrame.h
+++ b/layout/xul/base/src/nsTextBoxFrame.h
@@ -59,17 +59,17 @@ public:
   enum CroppingStyle { CropNone, CropLeft, CropRight, CropCenter };
 
   friend nsIFrame* NS_NewTextBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
   NS_IMETHOD  Init(nsIContent*      aContent,
                    nsIFrame*        aParent,
                    nsIFrame*        asPrevInFlow);
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   NS_IMETHOD AttributeChanged(PRInt32         aNameSpaceID,
                               nsIAtom*        aAttribute,
                               PRInt32         aModType);
 
 #ifdef DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
--- a/layout/xul/base/src/nsXULLabelFrame.cpp
+++ b/layout/xul/base/src/nsXULLabelFrame.cpp
@@ -104,21 +104,21 @@ nsXULLabelFrame::Init(nsIContent*      a
   if (NS_FAILED(rv))
     return rv;
 
   // register access key
   return RegUnregAccessKey(PR_TRUE);
 }
 
 void
-nsXULLabelFrame::Destroy()
+nsXULLabelFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // unregister access key
   RegUnregAccessKey(PR_FALSE);
-  nsBlockFrame::Destroy();
+  nsBlockFrame::DestroyFrom(aDestructRoot);
 } 
 
 NS_IMETHODIMP
 nsXULLabelFrame::AttributeChanged(PRInt32 aNameSpaceID,
                                   nsIAtom* aAttribute,
                                   PRInt32 aModType)
 {
   nsresult rv = nsBlockFrame::AttributeChanged(aNameSpaceID, 
--- a/layout/xul/base/src/nsXULLabelFrame.h
+++ b/layout/xul/base/src/nsXULLabelFrame.h
@@ -54,17 +54,17 @@ public:
   friend nsIFrame* NS_NewXULLabelFrame(nsIPresShell* aPresShell,
                                        nsStyleContext *aContext);
   
   // nsIFrame
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
                               nsIAtom* aAttribute,
                               PRInt32 aModType);
 
   /**
    * Get the "type" of the frame
    *
--- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
@@ -300,17 +300,17 @@ nsTreeBodyFrame::CalcMaxRowWidth()
       mStringWidth = rowWidth;
   }
 
   mStringWidth += rowMargin.left + rowMargin.right;
   return mStringWidth;
 }
 
 void
-nsTreeBodyFrame::Destroy()
+nsTreeBodyFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   mScrollEvent.Revoke();
   // Make sure we cancel any posted callbacks. 
   if (mReflowCallbackPosted) {
     PresContext()->PresShell()->CancelReflowCallback(this);
     mReflowCallbackPosted = PR_FALSE;
   }
 
@@ -337,17 +337,17 @@ nsTreeBodyFrame::Destroy()
     nsCOMPtr<nsITreeSelection> sel;
     mView->GetSelection(getter_AddRefs(sel));
     if (sel)
       sel->SetTree(nsnull);
     mView->SetTree(nsnull);
     mView = nsnull;
   }
 
-  nsLeafBoxFrame::Destroy();
+  nsLeafBoxFrame::DestroyFrom(aDestructRoot);
 }
 
 void
 nsTreeBodyFrame::EnsureBoxObject()
 {
   if (!mTreeBoxObject) {
     nsIContent* parent = GetBaseElement();
     if (parent) {
--- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.h
+++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.h
@@ -149,17 +149,17 @@ public:
   NS_IMETHOD PositionChanged(nsIScrollbarFrame* aScrollbar, PRInt32 aOldIndex, PRInt32& aNewIndex);
   NS_IMETHOD ScrollbarButtonPressed(nsIScrollbarFrame* aScrollbar, PRInt32 aOldIndex, PRInt32 aNewIndex);
   NS_IMETHOD VisibilityChanged(PRBool aVisible) { Invalidate(); return NS_OK; }
 
   // Overridden from nsIFrame to cache our pres context.
   NS_IMETHOD Init(nsIContent*     aContent,
                   nsIFrame*       aParent,
                   nsIFrame*       aPrevInFlow);
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   NS_IMETHOD GetCursor(const nsPoint& aPoint,
                        nsIFrame::Cursor& aCursor);
 
   NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
                          nsGUIEvent* aEvent,
                          nsEventStatus* aEventStatus);
 
--- a/layout/xul/base/src/tree/src/nsTreeColFrame.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeColFrame.cpp
@@ -76,21 +76,21 @@ nsTreeColFrame::Init(nsIContent*      aC
                      nsIFrame*        aParent,
                      nsIFrame*        aPrevInFlow)
 {
   nsresult rv = nsBoxFrame::Init(aContent, aParent, aPrevInFlow);
   InvalidateColumns();
   return rv;
 }
 
-void                                                                
-nsTreeColFrame::Destroy()                          
+void
+nsTreeColFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   InvalidateColumns(PR_FALSE);
-  nsBoxFrame::Destroy();
+  nsBoxFrame::DestroyFrom(aDestructRoot);
 }
 
 class nsDisplayXULTreeColSplitterTarget : public nsDisplayItem {
 public:
   nsDisplayXULTreeColSplitterTarget(nsIFrame* aFrame) : nsDisplayItem(aFrame) {
     MOZ_COUNT_CTOR(nsDisplayXULTreeColSplitterTarget);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
--- a/layout/xul/base/src/tree/src/nsTreeColFrame.h
+++ b/layout/xul/base/src/tree/src/nsTreeColFrame.h
@@ -51,17 +51,17 @@ public:
   nsTreeColFrame(nsIPresShell* aPresShell,
                  nsStyleContext* aContext):
     nsBoxFrame(aPresShell, aContext) {}
 
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
 
-  virtual void Destroy();
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   NS_IMETHOD BuildDisplayListForChildren(nsDisplayListBuilder*   aBuilder,
                                          const nsRect&           aDirtyRect,
                                          const nsDisplayListSet& aLists);
 
   NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
                               nsIAtom* aAttribute,
                               PRInt32 aModType);