Bug 281387. Make nsIFrame::Append/InsertFrames use nsFrameList. r=bernd,roc, sr=dbaron
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 30 Jul 2009 13:23:32 -0400
changeset 30941 0a0b0c3f614bd114bd8d7ff6cb58d609c1d8a4b1
parent 30940 8cff4bd2121aa665fe597d221825f410501fb1fb
child 30942 358af1196dc2b298080cbe73efc9d5570153876e
push idunknown
push userunknown
push dateunknown
reviewersbernd, roc, dbaron
bugs281387
milestone1.9.2a1pre
Bug 281387. Make nsIFrame::Append/InsertFrames use nsFrameList. r=bernd,roc, sr=dbaron
layout/base/nsBidiPresUtils.cpp
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsFrameManager.cpp
layout/base/nsFrameManager.h
layout/forms/nsFieldSetFrame.cpp
layout/forms/nsHTMLButtonControlFrame.cpp
layout/forms/nsHTMLButtonControlFrame.h
layout/generic/nsAbsoluteContainingBlock.cpp
layout/generic/nsAbsoluteContainingBlock.h
layout/generic/nsBlockFrame.cpp
layout/generic/nsBlockFrame.h
layout/generic/nsColumnSetFrame.cpp
layout/generic/nsContainerFrame.cpp
layout/generic/nsContainerFrame.h
layout/generic/nsFrame.cpp
layout/generic/nsFrame.h
layout/generic/nsFrameList.h
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsGfxScrollFrame.h
layout/generic/nsHTMLFrame.cpp
layout/generic/nsIFrame.h
layout/generic/nsInlineFrame.cpp
layout/generic/nsInlineFrame.h
layout/generic/nsViewportFrame.cpp
layout/generic/nsViewportFrame.h
layout/mathml/nsMathMLContainerFrame.cpp
layout/mathml/nsMathMLContainerFrame.h
layout/mathml/nsMathMLForeignFrameWrapper.h
layout/mathml/nsMathMLmtableFrame.h
layout/svg/base/src/nsSVGContainerFrame.cpp
layout/svg/base/src/nsSVGContainerFrame.h
layout/svg/base/src/nsSVGTextContainerFrame.cpp
layout/svg/base/src/nsSVGTextContainerFrame.h
layout/tables/nsTableCellFrame.cpp
layout/tables/nsTableCellFrame.h
layout/tables/nsTableColGroupFrame.cpp
layout/tables/nsTableColGroupFrame.h
layout/tables/nsTableFrame.cpp
layout/tables/nsTableFrame.h
layout/tables/nsTableOuterFrame.cpp
layout/tables/nsTableOuterFrame.h
layout/tables/nsTableRowFrame.cpp
layout/tables/nsTableRowFrame.h
layout/tables/nsTableRowGroupFrame.cpp
layout/tables/nsTableRowGroupFrame.h
layout/xul/base/src/grid/nsGridLayout2.cpp
layout/xul/base/src/grid/nsGridLayout2.h
layout/xul/base/src/grid/nsGridRowLayout.cpp
layout/xul/base/src/grid/nsGridRowLayout.h
layout/xul/base/src/nsBoxFrame.cpp
layout/xul/base/src/nsBoxFrame.h
layout/xul/base/src/nsBoxLayout.cpp
layout/xul/base/src/nsBoxLayout.h
layout/xul/base/src/nsIBoxLayout.h
layout/xul/base/src/nsListBoxBodyFrame.cpp
layout/xul/base/src/nsListBoxBodyFrame.h
layout/xul/base/src/nsMenuFrame.cpp
layout/xul/base/src/nsMenuFrame.h
layout/xul/base/src/nsPopupSetFrame.cpp
layout/xul/base/src/nsPopupSetFrame.h
layout/xul/base/src/nsRootBoxFrame.cpp
layout/xul/base/src/nsSliderFrame.cpp
layout/xul/base/src/nsSliderFrame.h
--- a/layout/base/nsBidiPresUtils.cpp
+++ b/layout/base/nsBidiPresUtils.cpp
@@ -127,29 +127,33 @@ SplitInlineAncestors(nsIFrame*     aFram
     nsresult rv = presShell->FrameConstructor()->
       CreateContinuingFrame(presContext, parent, grandparent, &newParent, PR_FALSE);
     if (NS_FAILED(rv)) {
       return rv;
     }
     
     // The new parent adopts the new frame
     frame->SetNextSibling(nsnull);
-    rv = newParent->InsertFrames(nsGkAtoms::nextBidi, nsnull, newFrame);
-    if (NS_FAILED(rv)) {
-      return rv;
-    }
+    // XXXbz this thing should be rewritten on top of nsFrameList on a
+    // much higher level...
+    nsFrameList temp(newFrame);
 
     // Reparent views as necessary
-    rv = nsHTMLContainerFrame::ReparentFrameViewList(presContext, newFrame, parent, newParent);
+    rv = nsHTMLContainerFrame::ReparentFrameViewList(presContext, temp, parent, newParent);
     if (NS_FAILED(rv)) {
       return rv;
     }
     
+    rv = newParent->InsertFrames(nsGkAtoms::nextBidi, nsnull, temp);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
     // The list name nsGkAtoms::nextBidi would indicate we don't want reflow
-    rv = grandparent->InsertFrames(nsGkAtoms::nextBidi, parent, newParent);
+    nsFrameList temp2(newParent);
+    rv = grandparent->InsertFrames(nsGkAtoms::nextBidi, parent, temp2);
     if (NS_FAILED(rv)) {
       return rv;
     }
     
     frame = parent;
     newFrame = newParent;
     parent = grandparent;
   }
@@ -199,17 +203,19 @@ CreateBidiContinuation(nsIFrame*       a
   
   nsresult rv = presShell->FrameConstructor()->
     CreateContinuingFrame(presContext, aFrame, parent, aNewFrame, PR_FALSE);
   if (NS_FAILED(rv)) {
     return rv;
   }
   
   // The list name nsGkAtoms::nextBidi would indicate we don't want reflow
-  rv = parent->InsertFrames(nsGkAtoms::nextBidi, aFrame, *aNewFrame);
+  // XXXbz this needs higher-level framelist love
+  nsFrameList temp(*aNewFrame);
+  rv = parent->InsertFrames(nsGkAtoms::nextBidi, aFrame, temp);
   if (NS_FAILED(rv)) {
     return rv;
   }
   
   // Split inline ancestor frames
   rv = SplitInlineAncestors(aFrame);
   if (NS_FAILED(rv)) {
     return rv;
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1251,18 +1251,17 @@ nsFrameConstructorState::ProcessFrameIns
           // the previous frame
           break;
         }
         insertionPoint = f;
       }
     }
 
     rv = containingBlock->InsertFrames(aChildListName, insertionPoint,
-                                       firstNewFrame);
-    aFrameItems.Clear();
+                                       aFrameItems);
   }
 
   NS_POSTCONDITION(aFrameItems.IsEmpty(), "How did that happen?");
 
   // XXXbz And if NS_FAILED(rv), what?  I guess we need to clean up the list
   // and deal with all the placeholders... but what if the placeholders aren't
   // in the document yet?  Could that happen?
   NS_ASSERTION(NS_SUCCEEDED(rv), "Frames getting lost!");
@@ -2427,16 +2426,18 @@ nsresult
 nsCSSFrameConstructor::ConstructDocElementFrame(nsIContent*              aDocElement,
                                                 nsILayoutHistoryState*   aFrameState,
                                                 nsIFrame**               aNewFrame)
 {
   NS_PRECONDITION(mFixedContainingBlock,
                   "No viewport?  Someone forgot to call ConstructRootFrame!");
   NS_PRECONDITION(mFixedContainingBlock == mPresShell->FrameManager()->GetRootFrame(),
                   "Unexpected mFixedContainingBlock");
+  NS_PRECONDITION(!mDocElementContainingBlock,
+                  "Shouldn't have a doc element containing block here");
 
   *aNewFrame = nsnull;
 
   // Make sure to call PropagateScrollToViewport before
   // SetUpDocElementContainingBlock, since it sets up our scrollbar state
   // properly.
   nsIContent* propagatedScrollFrom = PropagateScrollToViewport();
 
@@ -2640,17 +2641,17 @@ nsCSSFrameConstructor::ConstructDocEleme
                  "Only XUL and SVG frames should reach here");
     ProcessChildren(state, aDocElement, styleContext, contentFrame, PR_TRUE,
                     childItems, PR_FALSE);
 
     // Set the initial child lists
     contentFrame->SetInitialChildList(nsnull, childItems);
   }
 
-  mDocElementContainingBlock->AppendFrames(nsnull, *aNewFrame);
+  SetInitialSingleChild(mDocElementContainingBlock, *aNewFrame);
 
   return NS_OK;
 }
 
 
 nsresult
 nsCSSFrameConstructor::ConstructRootFrame(nsIFrame** aNewFrame)
 {
@@ -2928,20 +2929,21 @@ nsCSSFrameConstructor::SetUpDocElementCo
     SetInitialSingleChild(rootFrame, pageFrame);
 
     // The eventual parent of the document element frame.
     // XXX should this be set for every new page (in ConstructPageFrame)?
     mDocElementContainingBlock = canvasFrame;
     mHasRootAbsPosContainingBlock = PR_TRUE;
   }
 
+  nsFrameList newFrameList(newFrame);
   if (viewportFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) {
-    SetInitialSingleChild(viewportFrame, newFrame);
+    viewportFrame->SetInitialChildList(nsnull, newFrameList);
   } else {
-    viewportFrame->AppendFrames(nsnull, newFrame);
+    viewportFrame->AppendFrames(nsnull, newFrameList);
   }
 
   return NS_OK;
 }
 
 nsresult
 nsCSSFrameConstructor::ConstructPageFrame(nsIPresShell*  aPresShell,
                                           nsPresContext* aPresContext,
@@ -3144,17 +3146,17 @@ nsCSSFrameConstructor::ConstructButtonFr
     nsFrameItems  anonymousChildItems;
     // if there are any anonymous children create frames for them.  Note that
     // we're doing this using a different parent frame from the one we pass to
     // ProcessChildren!
     CreateAnonymousFrames(aState, content, buttonFrame, anonymousChildItems);
     if (anonymousChildItems.NotEmpty()) {
       // the anonymous content is already parented to the area frame
       aState.mFrameManager->AppendFrames(blockFrame, nsnull,
-                                         anonymousChildItems.FirstChild());
+                                         anonymousChildItems);
     }
   }
 
   // our new button frame returned is the top frame. 
   *aNewFrame = buttonFrame; 
 
   return NS_OK;  
 }
@@ -4378,17 +4380,18 @@ nsCSSFrameConstructor::BeginBuildingScro
 
   return aScrolledChildStyle;
 }
 
 void
 nsCSSFrameConstructor::FinishBuildingScrollFrame(nsIFrame* aScrollFrame,
                                                  nsIFrame* aScrolledFrame)
 {
-  aScrollFrame->AppendFrames(nsnull, aScrolledFrame);
+  nsFrameList scrolled(aScrolledFrame);
+  aScrollFrame->AppendFrames(nsnull, scrolled);
 
   // force the scrolled frame to have a view. The view will be parented to
   // the correct anonymous inner view because the scrollframes override
   // nsIFrame::GetParentViewForChildFrame.
   nsHTMLContainerFrame::CreateViewForFrame(aScrolledFrame, PR_TRUE);
 
   // XXXbz what's the point of the code after this in this method?
   nsIView* view = aScrolledFrame->GetView();
@@ -5750,17 +5753,17 @@ nsCSSFrameConstructor::AppendFrames(nsFr
     
   if (aFrameList.IsEmpty()) {
     // It all got eaten by the special inline
     return NS_OK;
   }
   
   // Insert the frames after out aPrevSibling
   return aState.mFrameManager->InsertFrames(aParentFrame, nsnull, aPrevSibling,
-                                            aFrameList.FirstChild());
+                                            aFrameList);
 }
 
 #define UNSET_DISPLAY 255
 
 // This gets called to see if the frames corresponding to aSiblingDisplay and aDisplay
 // should be siblings in the frame tree. Although (1) rows and cols, (2) row groups 
 // and col groups, (3) row groups and captions, (4) legends and content inside fieldsets, (5) popups and other kids of the menu
 // are siblings from a content perspective, they are not considered siblings in the 
@@ -6412,19 +6415,18 @@ nsCSSFrameConstructor::ContentAppended(n
   // Notify the parent frame passing it the list of new frames
   if (NS_SUCCEEDED(result)) {
     // Append the flowed frames to the principal child list; captions
     // need special treatment
     if (captionItems.NotEmpty()) { // append the caption to the outer table
       NS_ASSERTION(nsGkAtoms::tableFrame == frameType, "how did that happen?");
       nsIFrame* outerTable = parentFrame->GetParent();
       if (outerTable) {
-        state.mFrameManager->AppendFrames(outerTable,
-                                          nsGkAtoms::captionList,
-                                          captionItems.FirstChild());
+        state.mFrameManager->AppendFrames(outerTable, nsGkAtoms::captionList,
+                                          captionItems);
       }
     }
 
     if (frameItems.NotEmpty()) { // append the in-flow kids
       AppendFrames(state, parentFrame, frameItems, prevSibling);
     }
   }
 
@@ -6812,46 +6814,46 @@ nsCSSFrameConstructor::ContentInserted(n
       
   if (NS_SUCCEEDED(rv) && frameItems.NotEmpty()) {
     NS_ASSERTION(captionItems.IsEmpty(), "leaking caption frames");
     // Notify the parent frame
     if (isAppend) {
       AppendFrames(state, parentFrame, frameItems, prevSibling);
     } else {
       state.mFrameManager->InsertFrames(parentFrame, nsnull, prevSibling,
-                                        frameItems.FirstChild());
+                                        frameItems);
     }
   }
   else {
     // we might have a caption treat it here
     if (NS_SUCCEEDED(rv) && captionItems.NotEmpty()) {
-      nsIFrame* newCaptionFrame = captionItems.FirstChild();
       nsIFrame* outerTableFrame;
-      if (GetCaptionAdjustedParent(parentFrame, newCaptionFrame, &outerTableFrame)) {
+      if (GetCaptionAdjustedParent(parentFrame, captionItems.FirstChild(),
+                                   &outerTableFrame)) {
         // If the parent of our current prevSibling is different from the frame
         // we'll actually use as the parent, then the calculated insertion
         // point is now invalid (bug 341382).
         if (prevSibling && prevSibling->GetParent() != outerTableFrame) {
           prevSibling = nsnull;
         }
         // If the parent is not a outer table frame we will try to add frames
         // to a named child list that the parent does not honour and the frames
         // will get lost
         NS_ASSERTION(nsGkAtoms::tableOuterFrame == outerTableFrame->GetType(),
                      "Pseudo frame construction failure, "
                      "a caption can be only a child of a outer table frame");
         if (isAppend) {
           state.mFrameManager->AppendFrames(outerTableFrame,
                                             nsGkAtoms::captionList,
-                                            newCaptionFrame);
+                                            captionItems);
         }
         else {
           state.mFrameManager->InsertFrames(outerTableFrame,
                                             nsGkAtoms::captionList,
-                                            prevSibling, newCaptionFrame);
+                                            prevSibling, captionItems);
         }
       }
     }
   }
 
   if (haveFirstLetterStyle) {
     // Recover the letter frames for the containing block when
     // it has first-letter style.
@@ -9700,18 +9702,17 @@ nsCSSFrameConstructor::WrapFramesInFirst
 
   if (aLineFrame) {
     // Give the inline frames to the lineFrame <b>after</b> reparenting them
     ReparentFrames(aState.mFrameManager, aLineFrame, firstLineChildren);
     if (aLineFrame->GetChildList(nsnull).IsEmpty() &&
         (aLineFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
       aLineFrame->SetInitialChildList(nsnull, firstLineChildren);
     } else {
-      aState.mFrameManager->AppendFrames(aLineFrame, nsnull,
-                                         firstLineChildren.FirstChild());
+      aState.mFrameManager->AppendFrames(aLineFrame, nsnull, firstLineChildren);
     }
   }
   else {
     rv = NS_ERROR_OUT_OF_MEMORY;
   }
 
   return rv;
 }
@@ -9757,19 +9758,20 @@ nsCSSFrameConstructor::InsertFirstLineFr
   nsFrameConstructorState& aState,
   nsIContent*              aContent,
   nsIFrame*                aBlockFrame,
   nsIFrame**               aParentFrame,
   nsIFrame*                aPrevSibling,
   nsFrameItems&            aFrameItems)
 {
   nsresult rv = NS_OK;
-  // XXXbz If you make this method actually do something, check to make sure
-  // that the caller is passing what you expect.  In particular, which content
-  // is aContent?
+  // XXXbz If you make this method actually do something, check to
+  // make sure that the caller is passing what you expect.  In
+  // particular, which content is aContent?  And audit the rest of
+  // this code too; it makes bogus assumptions and may not build.
 #if 0
   nsIFrame* parentFrame = *aParentFrame;
   nsIFrame* newFrame = aFrameItems.childList;
   PRBool isInline = IsInlineOutside(newFrame);
 
   if (!aPrevSibling) {
     // Insertion will become the first frame. Two cases: we either
     // already have a first-line frame or we don't.
@@ -10151,22 +10153,22 @@ nsCSSFrameConstructor::WrapFramesInFirst
   if (parentFrame) {
     if (parentFrame == aBlockFrame) {
       // Take textFrame out of the block's frame list and substitute the
       // letter frame(s) instead.
       aBlockFrames.DestroyFrame(textFrame, prevFrame);
       aBlockFrames.InsertFrames(nsnull, prevFrame, letterFrames);
     }
     else {
-      // Take the old textFrame out of the inline parents child list
+      // Take the old textFrame out of the inline parent's child list
       ::DeletingFrameSubtree(mPresShell->FrameManager(), textFrame);
       parentFrame->RemoveFrame(nsnull, textFrame);
 
       // Insert in the letter frame(s)
-      parentFrame->InsertFrames(nsnull, prevFrame, letterFrames.FirstChild());
+      parentFrame->InsertFrames(nsnull, prevFrame, letterFrames);
     }
   }
 
   return rv;
 }
 
 nsresult
 nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
@@ -10337,18 +10339,18 @@ nsCSSFrameConstructor::RemoveFloatingFir
   aFrameManager->RemoveFrame(aBlockFrame, nsGkAtoms::floatList,
                              floatFrame);
 
   // Remove placeholder frame
   ::DeletingFrameSubtree(aFrameManager, placeholderFrame);
   aFrameManager->RemoveFrame(parentFrame, nsnull, placeholderFrame);
 
   // Insert text frame in its place
-  aFrameManager->InsertFrames(parentFrame, nsnull,
-                              prevSibling, newTextFrame);
+  nsFrameList textList(newTextFrame);
+  aFrameManager->InsertFrames(parentFrame, nsnull, prevSibling, textList);
 
   return NS_OK;
 }
 
 nsresult
 nsCSSFrameConstructor::RemoveFirstLetterFrames(nsPresContext* aPresContext,
                                                nsIPresShell* aPresShell,
                                                nsFrameManager* aFrameManager,
@@ -10383,17 +10385,18 @@ nsCSSFrameConstructor::RemoveFirstLetter
       textFrame = NS_NewTextFrame(aPresShell, newSC);
       textFrame->Init(textContent, aFrame, nsnull);
 
       // Next rip out the kid and replace it with the text frame
       ::DeletingFrameSubtree(aFrameManager, kid);
       aFrameManager->RemoveFrame(aFrame, nsnull, kid);
 
       // Insert text frame in its place
-      aFrameManager->InsertFrames(aFrame, nsnull, prevSibling, textFrame);
+      nsFrameList textList(textFrame);
+      aFrameManager->InsertFrames(aFrame, nsnull, prevSibling, textList);
 
       *aStopLooking = PR_TRUE;
       aFrame->RemoveStateBits(NS_BLOCK_HAS_FIRST_LETTER_CHILD);
       break;
     }
     else if (IsInlineFrame(kid)) {
       // Look inside child inline frame for the letter frame
       RemoveFirstLetterFrames(aPresContext, aPresShell, aFrameManager, kid,
@@ -10464,17 +10467,17 @@ nsCSSFrameConstructor::RecoverLetterFram
   } while (aBlockFrame);
 
   if (parentFrame) {
     // Take the old textFrame out of the parents child list
     ::DeletingFrameSubtree(mPresShell->FrameManager(), textFrame);
     parentFrame->RemoveFrame(nsnull, textFrame);
 
     // Insert in the letter frame(s)
-    parentFrame->InsertFrames(nsnull, prevFrame, letterFrames.FirstChild());
+    parentFrame->InsertFrames(nsnull, prevFrame, letterFrames);
   }
   return rv;
 }
 
 //----------------------------------------------------------------------
 
 // listbox Widget Routines
 
@@ -10521,19 +10524,19 @@ nsCSSFrameConstructor::CreateListBoxCont
     ConstructFramesFromItemList(state, items, aParentFrame, frameItems);
 
     nsIFrame* newFrame = frameItems.FirstChild();
     *aNewFrame = newFrame;
 
     if (NS_SUCCEEDED(rv) && (nsnull != newFrame)) {
       // Notify the parent frame
       if (aIsAppend)
-        rv = ((nsListBoxBodyFrame*)aParentFrame)->ListBoxAppendFrames(newFrame);
+        rv = ((nsListBoxBodyFrame*)aParentFrame)->ListBoxAppendFrames(frameItems);
       else
-        rv = ((nsListBoxBodyFrame*)aParentFrame)->ListBoxInsertFrames(aPrevFrame, newFrame);
+        rv = ((nsListBoxBodyFrame*)aParentFrame)->ListBoxInsertFrames(aPrevFrame, frameItems);
     }
 
     EndUpdate();
   }
 
   return rv;
 #else
   return NS_ERROR_FAILURE;
@@ -10837,17 +10840,17 @@ nsCSSFrameConstructor::MoveFramesToEndOf
   // Reparent (cheaply) the child frames.  Have to grab the frame pointers
   // for MoveChildrenTo now, since aFramesToMove will get cleared when we add
   // the frames to aExistingEndFrame.  We already have newFirstChild.
   nsIFrame* existingFirstChild = aExistingEndFrame->GetFirstChild(nsnull);
   if (!existingFirstChild &&
       (aExistingEndFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
     aExistingEndFrame->SetInitialChildList(nsnull, aFramesToMove);
   } else {
-    aExistingEndFrame->InsertFrames(nsnull, nsnull, aFramesToMove.FirstChild());
+    aExistingEndFrame->InsertFrames(nsnull, nsnull, aFramesToMove);
   }
   nsFrameConstructorState* startState = aTargetState ? &aState : nsnull;
   MoveChildrenTo(aState.mFrameManager, aExistingEndFrame, newFirstChild,
                  existingFirstChild, aTargetState, startState);
 }
 
 void
 nsCSSFrameConstructor::BuildInlineChildItems(nsFrameConstructorState& aState,
--- a/layout/base/nsFrameManager.cpp
+++ b/layout/base/nsFrameManager.cpp
@@ -683,17 +683,17 @@ nsFrameManager::ClearUndisplayedContentM
 }
 
 //----------------------------------------------------------------------
 
 nsresult
 nsFrameManager::InsertFrames(nsIFrame*       aParentFrame,
                              nsIAtom*        aListName,
                              nsIFrame*       aPrevFrame,
-                             nsIFrame*       aFrameList)
+                             nsFrameList&    aFrameList)
 {
   NS_PRECONDITION(!aPrevFrame || (!aPrevFrame->GetNextContinuation()
                   || IS_TRUE_OVERFLOW_CONTAINER(aPrevFrame->GetNextContinuation()))
                   && !IS_TRUE_OVERFLOW_CONTAINER(aPrevFrame),
                   "aPrevFrame must be the last continuation in its chain!");
 
   return aParentFrame->InsertFrames(aListName, aPrevFrame, aFrameList);
 }
--- a/layout/base/nsFrameManager.h
+++ b/layout/base/nsFrameManager.h
@@ -145,25 +145,25 @@ public:
   NS_HIDDEN_(void) ClearUndisplayedContentIn(nsIContent* aContent,
                                              nsIContent* aParentContent);
   NS_HIDDEN_(void) ClearAllUndisplayedContentIn(nsIContent* aParentContent);
   NS_HIDDEN_(void) ClearUndisplayedContentMap();
 
   // Functions for manipulating the frame model
   NS_HIDDEN_(nsresult) AppendFrames(nsIFrame*       aParentFrame,
                                     nsIAtom*        aListName,
-                                    nsIFrame*       aFrameList)
+                                    nsFrameList&    aFrameList)
   {
     return aParentFrame->AppendFrames(aListName, aFrameList);
   }
 
   NS_HIDDEN_(nsresult) InsertFrames(nsIFrame*       aParentFrame,
                                     nsIAtom*        aListName,
                                     nsIFrame*       aPrevFrame,
-                                    nsIFrame*       aFrameList);
+                                    nsFrameList&    aFrameList);
 
   NS_HIDDEN_(nsresult) RemoveFrame(nsIFrame*       aParentFrame,
                                    nsIAtom*        aListName,
                                    nsIFrame*       aOldFrame);
 
   /*
    * Notification that a frame is about to be destroyed. This allows any
    * outstanding references to the frame to be cleaned up.
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -90,20 +90,20 @@ public:
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists);
 
   void PaintBorderBackground(nsIRenderingContext& aRenderingContext,
     nsPoint aPt, const nsRect& aDirtyRect);
 
   NS_IMETHOD AppendFrames(nsIAtom*       aListName,
-                          nsIFrame*      aFrameList);
+                          nsFrameList&   aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*       aListName,
                           nsIFrame*      aPrevFrame,
-                          nsIFrame*      aFrameList);
+                          nsFrameList&   aFrameList);
   NS_IMETHOD RemoveFrame(nsIAtom*       aListName,
                          nsIFrame*      aOldFrame);
 
   virtual nsIAtom* GetType() const;
   virtual PRBool IsContainingBlock() const;
 
 #ifdef ACCESSIBILITY  
   NS_IMETHOD  GetAccessible(nsIAccessible** aAccessible);
@@ -113,17 +113,17 @@ public:
   NS_IMETHOD GetFrameName(nsAString& aResult) const {
     return MakeFrameName(NS_LITERAL_STRING("FieldSet"), aResult);
   }
 #endif
 
 protected:
 
   virtual PRIntn GetSkipSides() const;
-  void ReParentFrameList(nsIFrame* aFrameList);
+  void ReParentFrameList(const nsFrameList& aFrameList);
 
   nsIFrame* mLegendFrame;
   nsIFrame* mContentFrame;
   nsRect    mLegendRect;
   nscoord   mLegendSpace;
 };
 
 nsIFrame*
@@ -608,44 +608,38 @@ nsFieldSetFrame::Reflow(nsPresContext*  
 PRIntn
 nsFieldSetFrame::GetSkipSides() const
 {
   return 0;
 }
 
 NS_IMETHODIMP
 nsFieldSetFrame::AppendFrames(nsIAtom*       aListName,
-                              nsIFrame*      aFrameList)
+                              nsFrameList&   aFrameList)
 {
-  if (aFrameList) {
-    // aFrameList is not allowed to contain "the legend" for this fieldset
-    ReParentFrameList(aFrameList);
-    return mContentFrame->AppendFrames(aListName, aFrameList);
-  }
-  return NS_OK;
+  // aFrameList is not allowed to contain "the legend" for this fieldset
+  ReParentFrameList(aFrameList);
+  return mContentFrame->AppendFrames(aListName, aFrameList);
 }
 
 NS_IMETHODIMP
 nsFieldSetFrame::InsertFrames(nsIAtom*       aListName,
                               nsIFrame*      aPrevFrame,
-                              nsIFrame*      aFrameList)
+                              nsFrameList&   aFrameList)
 {
   NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this ||
                aPrevFrame->GetParent() == mContentFrame,
                "inserting after sibling frame with different parent");
 
-  if (aFrameList) {
-    // aFrameList is not allowed to contain "the legend" for this fieldset
-    ReParentFrameList(aFrameList);
-    if (NS_UNLIKELY(aPrevFrame == mLegendFrame)) {
-      aPrevFrame = nsnull;
-    }
-    return mContentFrame->InsertFrames(aListName, aPrevFrame, aFrameList);
+  // aFrameList is not allowed to contain "the legend" for this fieldset
+  ReParentFrameList(aFrameList);
+  if (NS_UNLIKELY(aPrevFrame == mLegendFrame)) {
+    aPrevFrame = nsnull;
   }
-  return NS_OK;
+  return mContentFrame->InsertFrames(aListName, aPrevFrame, aFrameList);
 }
 
 NS_IMETHODIMP
 nsFieldSetFrame::RemoveFrame(nsIAtom*       aListName,
                              nsIFrame*      aOldFrame)
 {
   // For reference, see bug 70648, bug 276104 and bug 236071.
   NS_ASSERTION(aOldFrame != mLegendFrame, "Cannot remove mLegendFrame here");
@@ -661,19 +655,19 @@ NS_IMETHODIMP nsFieldSetFrame::GetAccess
     return accService->CreateHTMLGroupboxAccessible(static_cast<nsIFrame*>(this), aAccessible);
   }
 
   return NS_ERROR_FAILURE;
 }
 #endif
 
 void
-nsFieldSetFrame::ReParentFrameList(nsIFrame* aFrameList)
+nsFieldSetFrame::ReParentFrameList(const nsFrameList& aFrameList)
 {
   nsFrameManager* frameManager = PresContext()->FrameManager();
-  for (nsIFrame* frame = aFrameList; frame; frame = frame->GetNextSibling()) {
-    NS_ASSERTION(mLegendFrame || frame->GetType() != nsGkAtoms::legendFrame,
+  for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
+    NS_ASSERTION(mLegendFrame || e.get()->GetType() != nsGkAtoms::legendFrame,
                  "The fieldset's legend is not allowed in this list");
-    frame->SetParent(mContentFrame);
-    frameManager->ReParentStyleContext(frame);
+    e.get()->SetParent(mContentFrame);
+    frameManager->ReParentStyleContext(e.get());
   }
   mContentFrame->AddStateBits(GetStateBits() & NS_FRAME_HAS_CHILD_WITH_VIEW);
 }
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -401,26 +401,26 @@ void
 nsHTMLButtonControlFrame::SetAdditionalStyleContext(PRInt32 aIndex, 
                                                     nsStyleContext* aStyleContext)
 {
   mRenderer.SetStyleContext(aIndex, aStyleContext);
 }
 
 NS_IMETHODIMP 
 nsHTMLButtonControlFrame::AppendFrames(nsIAtom*        aListName,
-                                       nsIFrame*       aFrameList)
+                                       nsFrameList&    aFrameList)
 {
   NS_NOTREACHED("unsupported operation");
   return NS_ERROR_UNEXPECTED;
 }
 
 NS_IMETHODIMP
 nsHTMLButtonControlFrame::InsertFrames(nsIAtom*        aListName,
                                        nsIFrame*       aPrevFrame,
-                                       nsIFrame*       aFrameList)
+                                       nsFrameList&    aFrameList)
 {
   NS_NOTREACHED("unsupported operation");
   return NS_ERROR_UNEXPECTED;
 }
 
 NS_IMETHODIMP
 nsHTMLButtonControlFrame::RemoveFrame(nsIAtom*        aListName,
                                       nsIFrame*       aOldFrame)
--- a/layout/forms/nsHTMLButtonControlFrame.h
+++ b/layout/forms/nsHTMLButtonControlFrame.h
@@ -90,21 +90,21 @@ public:
                    nsIFrame*        aParent,
                    nsIFrame*        asPrevInFlow);
 
   virtual nsStyleContext* GetAdditionalStyleContext(PRInt32 aIndex) const;
   virtual void SetAdditionalStyleContext(PRInt32 aIndex, 
                                          nsStyleContext* aStyleContext);
  
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
 
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
 
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
 
 #ifdef ACCESSIBILITY
   NS_IMETHOD GetAccessible(nsIAccessible** aAccessible);
 #endif
 
--- a/layout/generic/nsAbsoluteContainingBlock.cpp
+++ b/layout/generic/nsAbsoluteContainingBlock.cpp
@@ -63,17 +63,17 @@ nsAbsoluteContainingBlock::SetInitialChi
 #endif
   mAbsoluteFrames.SetFrames(aChildList);
   return NS_OK;
 }
 
 nsresult
 nsAbsoluteContainingBlock::AppendFrames(nsIFrame*      aDelegatingFrame,
                                         nsIAtom*       aListName,
-                                        nsIFrame*      aFrameList)
+                                        nsFrameList&   aFrameList)
 {
   NS_ASSERTION(GetChildListName() == aListName, "unexpected child list");
 
   // Append the frames to our list of absolutely positioned frames
 #ifdef NS_DEBUG
   nsFrame::VerifyDirtyBitSet(aFrameList);
 #endif
   mAbsoluteFrames.AppendFrames(nsnull, aFrameList);
@@ -84,17 +84,17 @@ nsAbsoluteContainingBlock::AppendFrames(
     FrameNeedsReflow(aDelegatingFrame, nsIPresShell::eResize,
                      NS_FRAME_HAS_DIRTY_CHILDREN);
 }
 
 nsresult
 nsAbsoluteContainingBlock::InsertFrames(nsIFrame*      aDelegatingFrame,
                                         nsIAtom*       aListName,
                                         nsIFrame*      aPrevFrame,
-                                        nsIFrame*      aFrameList)
+                                        nsFrameList&   aFrameList)
 {
   NS_ASSERTION(GetChildListName() == aListName, "unexpected child list");
   NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == aDelegatingFrame,
                "inserting after sibling frame with different parent");
 
 #ifdef NS_DEBUG
   nsFrame::VerifyDirtyBitSet(aFrameList);
 #endif
--- a/layout/generic/nsAbsoluteContainingBlock.h
+++ b/layout/generic/nsAbsoluteContainingBlock.h
@@ -86,21 +86,21 @@ public:
 
   const nsFrameList& GetChildList() const { return mAbsoluteFrames; }
 
   nsresult SetInitialChildList(nsIFrame*       aDelegatingFrame,
                                nsIAtom*        aListName,
                                nsFrameList&    aChildList);
   nsresult AppendFrames(nsIFrame*      aDelegatingFrame,
                         nsIAtom*       aListName,
-                        nsIFrame*      aFrameList);
+                        nsFrameList&   aFrameList);
   nsresult InsertFrames(nsIFrame*      aDelegatingFrame,
                         nsIAtom*       aListName,
                         nsIFrame*      aPrevFrame,
-                        nsIFrame*      aFrameList);
+                        nsFrameList&   aFrameList);
   nsresult RemoveFrame(nsIFrame*      aDelegatingFrame,
                        nsIAtom*       aListName,
                        nsIFrame*      aOldFrame);
 
   // Called by the delegating frame after it has done its reflow first. This
   // function will reflow any absolutely positioned child frames that need to
   // be reflowed, e.g., because the absolutely positioned child frame has
   // 'auto' for an offset, or a percentage based width or height.
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -4411,16 +4411,18 @@ nsBlockFrame::HandleOverflowPlaceholders
 #ifdef DEBUG
       PRBool found =
 #endif
         oofs.mList.RemoveFrame(outOfFlow);
       NS_ASSERTION(found, "Must have the out of flow in some child list");
     }
     ReparentFrame(outOfFlow, parent, this);
 
+    // XXXbz should this be InsertFrame?  Or can |frame| really have
+    // following siblings here?
     aState.mOverflowPlaceholders.InsertFrames(nsnull, lastOverflowPlace, frame);
     // outOfFlow isn't inserted anywhere yet. Eventually the overflow
     // placeholders get put into the overflow lines, and at the same time we
     // insert the placeholders' out of flows into the overflow out-of-flows
     // list.
     lastOverflowPlace = frame;
 
     frame = frame->GetNextInFlow();
@@ -4494,18 +4496,17 @@ nsBlockFrame::DrainOverflowLines(nsBlock
       }
 
       // make the overflow out-of-flow frames mine too
       nsAutoOOFFrameList oofs(prevBlock);
       if (oofs.mList.NotEmpty()) {
         for (nsIFrame* f = oofs.mList.FirstChild(); f; f = f->GetNextSibling()) {
           ReparentFrame(f, prevBlock, this);
         }
-        mFloats.InsertFrames(nsnull, nsnull, oofs.mList.FirstChild());
-        oofs.mList.Clear();
+        mFloats.InsertFrames(nsnull, nsnull, oofs.mList);
       }
     }
     
     // The lines on the overflow list have already been marked dirty and their
     // previous margins marked dirty also.
   }
 
   // Don't need to reparent frames in our own overflow lines/oofs, because they're
@@ -4657,17 +4658,17 @@ nsBlockFrame::DrainOverflowLines(nsBlock
       if (!mLines.empty()) {
         keepPlaceholders.LastChild()->SetNextSibling(mLines.front()->mFirstChild);
       }
       mLines.push_front(newLine);
     }
 
     // Put the placeholders' out of flows into the float list
     keepOutOfFlows.SortByContentOrder();
-    mFloats.InsertFrames(nsnull, nsnull, keepOutOfFlows.FirstChild());
+    mFloats.InsertFrames(nsnull, nsnull, keepOutOfFlows);
   }
 
   return PR_TRUE;
 }
 
 nsLineList*
 nsBlockFrame::GetOverflowLines() const
 {
@@ -4784,19 +4785,19 @@ nsBlockFrame::LastChild()
   if (! mLines.empty()) {
     return mLines.back()->LastChild();
   }
   return nsnull;
 }
 
 NS_IMETHODIMP
 nsBlockFrame::AppendFrames(nsIAtom*  aListName,
-                           nsIFrame* aFrameList)
+                           nsFrameList& aFrameList)
 {
-  if (nsnull == aFrameList) {
+  if (aFrameList.IsEmpty()) {
     return NS_OK;
   }
   if (aListName) {
     if (nsGkAtoms::absoluteList == aListName) {
       return mAbsoluteContainer.AppendFrames(this, aListName, aFrameList);
     }
     else if (nsGkAtoms::floatList == aListName) {
       mFloats.AppendFrames(nsnull, aFrameList);
@@ -4822,28 +4823,31 @@ nsBlockFrame::AppendFrames(nsIAtom*  aLi
   nsFrame::ListTag(stdout, aFrameList);
   if (lastKid) {
     printf(" after ");
     nsFrame::ListTag(stdout, lastKid);
   }
   printf("\n");
 #endif
   nsresult rv = AddFrames(aFrameList, lastKid);
-  if (NS_SUCCEEDED(rv)) {
-    PresContext()->PresShell()->
-      FrameNeedsReflow(this, nsIPresShell::eTreeChange,
-                       NS_FRAME_HAS_DIRTY_CHILDREN); // XXX sufficient?
-  }
-  return rv;
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  aFrameList.Clear();
+
+  PresContext()->PresShell()->
+    FrameNeedsReflow(this, nsIPresShell::eTreeChange,
+                     NS_FRAME_HAS_DIRTY_CHILDREN); // XXX sufficient?
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsBlockFrame::InsertFrames(nsIAtom*  aListName,
                            nsIFrame* aPrevFrame,
-                           nsIFrame* aFrameList)
+                           nsFrameList& aFrameList)
 {
   NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
                "inserting after sibling frame with different parent");
 
   if (aListName) {
     if (nsGkAtoms::absoluteList == aListName) {
       return mAbsoluteContainer.InsertFrames(this, aListName, aPrevFrame,
                                              aFrameList);
@@ -4867,25 +4871,27 @@ nsBlockFrame::InsertFrames(nsIAtom*  aLi
   nsFrame::ListTag(stdout, aFrameList);
   if (aPrevFrame) {
     printf(" after ");
     nsFrame::ListTag(stdout, aPrevFrame);
   }
   printf("\n");
 #endif
   nsresult rv = AddFrames(aFrameList, aPrevFrame);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  aFrameList.Clear();
 #ifdef IBMBIDI
   if (aListName != nsGkAtoms::nextBidi)
 #endif // IBMBIDI
-  if (NS_SUCCEEDED(rv)) {
     PresContext()->PresShell()->
       FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                        NS_FRAME_HAS_DIRTY_CHILDREN); // XXX sufficient?
-  }
-  return rv;
+  return NS_OK;
 }
 
 static PRBool
 ShouldPutNextSiblingOnNewLine(nsIFrame* aLastFrame)
 {
   nsIAtom* type = aLastFrame->GetType();
   if (type == nsGkAtoms::brFrame)
     return PR_TRUE;
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -165,20 +165,20 @@ public:
 
   // nsIFrame
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
   NS_IMETHOD SetInitialChildList(nsIAtom*        aListName,
                                  nsFrameList&    aChildList);
   NS_IMETHOD  AppendFrames(nsIAtom*        aListName,
-                           nsIFrame*       aFrameList);
+                           nsFrameList&    aFrameList);
   NS_IMETHOD  InsertFrames(nsIAtom*        aListName,
                            nsIFrame*       aPrevFrame,
-                           nsIFrame*       aFrameList);
+                           nsFrameList&    aFrameList);
   NS_IMETHOD  RemoveFrame(nsIAtom*        aListName,
                           nsIFrame*       aOldFrame);
   virtual nsFrameList GetChildList(nsIAtom* aListName) const;
   virtual nsIFrame* GetLastChild(nsIAtom* aListName) const;
   virtual nscoord GetBaseline() const;
   virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
   virtual void Destroy();
   virtual nsSplittableType GetSplittableType() const;
--- a/layout/generic/nsColumnSetFrame.cpp
+++ b/layout/generic/nsColumnSetFrame.cpp
@@ -60,20 +60,20 @@ public:
                                  nsFrameList&    aChildList);
 
   NS_IMETHOD Reflow(nsPresContext* aPresContext,
                     nsHTMLReflowMetrics& aDesiredSize,
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus& aStatus);
                                
   NS_IMETHOD  AppendFrames(nsIAtom*        aListName,
-                           nsIFrame*       aFrameList);
+                           nsFrameList&    aFrameList);
   NS_IMETHOD  InsertFrames(nsIAtom*        aListName,
                            nsIFrame*       aPrevFrame,
-                           nsIFrame*       aFrameList);
+                           nsFrameList&    aFrameList);
   NS_IMETHOD  RemoveFrame(nsIAtom*        aListName,
                           nsIFrame*       aOldFrame);
 
   virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);  
   virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
 
   virtual nsIFrame* GetContentInsertionFrame() {
     nsIFrame* frame = GetFirstChild(nsnull);
@@ -1101,26 +1101,26 @@ nsColumnSetFrame::BuildDisplayList(nsDis
 PRIntn
 nsColumnSetFrame::GetSkipSides() const
 {
   return 0;
 }
 
 NS_IMETHODIMP
 nsColumnSetFrame::AppendFrames(nsIAtom*        aListName,
-                               nsIFrame*       aFrameList)
+                               nsFrameList&    aFrameList)
 {
   NS_NOTREACHED("AppendFrames not supported");
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 nsColumnSetFrame::InsertFrames(nsIAtom*        aListName,
                                nsIFrame*       aPrevFrame,
-                               nsIFrame*       aFrameList)
+                               nsFrameList&    aFrameList)
 {
   NS_NOTREACHED("InsertFrames not supported");
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 nsColumnSetFrame::RemoveFrame(nsIAtom*        aListName,
                               nsIFrame*       aOldFrame)
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -121,28 +121,28 @@ nsContainerFrame::SetInitialChildList(ns
     mFrames.SetFrames(aChildList);
     result = NS_OK;
   }
   return result;
 }
 
 NS_IMETHODIMP
 nsContainerFrame::AppendFrames(nsIAtom*  aListName,
-                               nsIFrame* aFrameList)
+                               nsFrameList& aFrameList)
 {
   if (nsnull != aListName) {
 #ifdef IBMBIDI
     if (aListName != nsGkAtoms::nextBidi)
 #endif
     {
       NS_ERROR("unexpected child list");
       return NS_ERROR_INVALID_ARG;
     }
   }
-  if (aFrameList) {
+  if (aFrameList.NotEmpty()) {
     mFrames.AppendFrames(this, aFrameList);
 
     // Ask the parent frame to reflow me.
 #ifdef IBMBIDI
     if (nsnull == aListName)
 #endif
     {
       PresContext()->PresShell()->
@@ -151,31 +151,31 @@ nsContainerFrame::AppendFrames(nsIAtom* 
     }
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsContainerFrame::InsertFrames(nsIAtom*  aListName,
                                nsIFrame* aPrevFrame,
-                               nsIFrame* aFrameList)
+                               nsFrameList& aFrameList)
 {
   NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
                "inserting after sibling frame with different parent");
 
   if (nsnull != aListName) {
 #ifdef IBMBIDI
     if (aListName != nsGkAtoms::nextBidi)
 #endif
     {
       NS_ERROR("unexpected child list");
       return NS_ERROR_INVALID_ARG;
     }
   }
-  if (aFrameList) {
+  if (aFrameList.NotEmpty()) {
     // Insert frames after aPrevFrame
     mFrames.InsertFrames(this, aPrevFrame, aFrameList);
 
 #ifdef IBMBIDI
     if (nsnull == aListName)
 #endif
     {
       PresContext()->PresShell()->
--- a/layout/generic/nsContainerFrame.h
+++ b/layout/generic/nsContainerFrame.h
@@ -75,20 +75,20 @@ class nsContainerFrame : public nsSplitt
 public:
   // nsIFrame overrides
   NS_IMETHOD Init(nsIContent* aContent,
                   nsIFrame*   aParent,
                   nsIFrame*   aPrevInFlow);
   NS_IMETHOD SetInitialChildList(nsIAtom*     aListName,
                                  nsFrameList& aChildList);
   NS_IMETHOD AppendFrames(nsIAtom*  aListName,
-                          nsIFrame* aFrameList);
+                          nsFrameList& aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*  aListName,
                           nsIFrame* aPrevFrame,
-                          nsIFrame* aFrameList);
+                          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 ChildIsDirty(nsIFrame* aChild);
 
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -410,26 +410,26 @@ NS_IMETHODIMP nsFrame::SetInitialChildLi
 #else
   NS_ASSERTION(aChildList.IsEmpty(), "not a container");
   return NS_OK;
 #endif
 }
 
 NS_IMETHODIMP
 nsFrame::AppendFrames(nsIAtom*        aListName,
-                      nsIFrame*       aFrameList)
+                      nsFrameList&    aFrameList)
 {
   NS_PRECONDITION(PR_FALSE, "not a container");
   return NS_ERROR_UNEXPECTED;
 }
 
 NS_IMETHODIMP
 nsFrame::InsertFrames(nsIAtom*        aListName,
                       nsIFrame*       aPrevFrame,
-                      nsIFrame*       aFrameList)
+                      nsFrameList&    aFrameList)
 {
   NS_PRECONDITION(PR_FALSE, "not a container");
   return NS_ERROR_UNEXPECTED;
 }
 
 NS_IMETHODIMP
 nsFrame::RemoveFrame(nsIAtom*        aListName,
                      nsIFrame*       aOldFrame)
--- a/layout/generic/nsFrame.h
+++ b/layout/generic/nsFrame.h
@@ -161,20 +161,20 @@ public:
 
   // nsIFrame
   NS_IMETHOD  Init(nsIContent*      aContent,
                    nsIFrame*        aParent,
                    nsIFrame*        asPrevInFlow);
   NS_IMETHOD  SetInitialChildList(nsIAtom*           aListName,
                                   nsFrameList&       aChildList);
   NS_IMETHOD  AppendFrames(nsIAtom*        aListName,
-                           nsIFrame*       aFrameList);
+                           nsFrameList&    aFrameList);
   NS_IMETHOD  InsertFrames(nsIAtom*        aListName,
                            nsIFrame*       aPrevFrame,
-                           nsIFrame*       aFrameList);
+                           nsFrameList&    aFrameList);
   NS_IMETHOD  RemoveFrame(nsIAtom*        aListName,
                           nsIFrame*       aOldFrame);
   virtual void Destroy();
   virtual nsStyleContext* GetAdditionalStyleContext(PRInt32 aIndex) const;
   virtual void SetAdditionalStyleContext(PRInt32 aIndex,
                                          nsStyleContext* aStyleContext);
   NS_IMETHOD  SetParent(const nsIFrame* aParent);
   virtual nscoord GetBaseline() const;
--- a/layout/generic/nsFrameList.h
+++ b/layout/generic/nsFrameList.h
@@ -320,30 +320,58 @@ public:
     Enumerator(const Enumerator& aOther) :
 #ifdef DEBUG
       mSlice(aOther.mSlice),
 #endif
       mFrame(aOther.mFrame),
       mEnd(aOther.mEnd)
     {}
 
-    PRBool AtEnd() const { return mFrame == mEnd; }
+    PRBool AtEnd() const {
+      // Can't just check mEnd, because some table code goes and destroys the
+      // tail of the frame list (including mEnd!) while iterating over the
+      // frame list.
+      return !mFrame || mFrame == mEnd;
+    }
 
     /* Next() needs to know about nsIFrame, and nsIFrame will need to
        know about nsFrameList methods, so in order to inline this put
        the implementation in nsIFrame.h */
     inline void Next();
 
-    nsIFrame* get() const { return mFrame; }
+    /**
+     * Get the current frame we're pointing to.  Do not call this on an
+     * iterator that is at end!
+     */
+    nsIFrame* get() const {
+      NS_PRECONDITION(!AtEnd(), "Enumerator is at end");
+      return mFrame;
+    }
+
+    /**
+     * Get an enumerator that is just like this one, but not limited in terms of
+     * the part of the list it will traverse.
+     */
+    Enumerator GetUnlimitedEnumerator() const {
+      return Enumerator(*this, nsnull);
+    }
 
 #ifdef DEBUG
     const nsFrameList& List() const { return mSlice.mList; }
 #endif
 
   protected:
+    Enumerator(const Enumerator& aOther, const nsIFrame* const aNewEnd):
+#ifdef DEBUG
+      mSlice(aOther.mSlice),
+#endif
+      mFrame(aOther.mFrame),
+      mEnd(aNewEnd)
+    {}
+
 #ifdef DEBUG
     /* Has to be an object, not a reference, since the slice could
        well be a temporary constructed from an nsFrameList */
     const Slice mSlice;
 #endif
     nsIFrame* mFrame; // our current frame.
     const nsIFrame* const mEnd; // The first frame we should NOT enumerate.
                                 // May be null.
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -169,28 +169,28 @@ nsHTMLScrollFrame::SetInitialChildList(n
   mInner.GetScrollableView()->AddScrollPositionListener(&mInner);
 
   return rv;
 }
 
 
 NS_IMETHODIMP
 nsHTMLScrollFrame::AppendFrames(nsIAtom*  aListName,
-                                nsIFrame* aFrameList)
+                                nsFrameList& aFrameList)
 {
   NS_ASSERTION(!aListName, "Only main list supported");
   mFrames.AppendFrames(nsnull, aFrameList);
   mInner.ReloadChildFrames();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLScrollFrame::InsertFrames(nsIAtom*  aListName,
                                 nsIFrame* aPrevFrame,
-                                nsIFrame* aFrameList)
+                                nsFrameList& aFrameList)
 {
   NS_ASSERTION(!aListName, "Only main list supported");
   NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
                "inserting after sibling frame with different parent");
   mFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
   mInner.ReloadChildFrames();
   return NS_OK;
 }
@@ -1056,27 +1056,27 @@ nsXULScrollFrame::SetInitialChildList(ns
   mInner.GetScrollableView()->AddScrollPositionListener(&mInner);
 
   return rv;
 }
 
 
 NS_IMETHODIMP
 nsXULScrollFrame::AppendFrames(nsIAtom*        aListName,
-                               nsIFrame*       aFrameList)
+                               nsFrameList&    aFrameList)
 {
   nsresult rv = nsBoxFrame::AppendFrames(aListName, aFrameList);
   mInner.ReloadChildFrames();
   return rv;
 }
 
 NS_IMETHODIMP
 nsXULScrollFrame::InsertFrames(nsIAtom*        aListName,
                                nsIFrame*       aPrevFrame,
-                               nsIFrame*       aFrameList)
+                               nsFrameList&    aFrameList)
 {
   nsresult rv = nsBoxFrame::InsertFrames(aListName, aPrevFrame, aFrameList);
   mInner.ReloadChildFrames();
   return rv;
 }
 
 NS_IMETHODIMP
 nsXULScrollFrame::RemoveFrame(nsIAtom*        aListName,
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -286,20 +286,20 @@ public:
   NS_IMETHOD Reflow(nsPresContext*          aPresContext,
                     nsHTMLReflowMetrics&     aDesiredSize,
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus&          aStatus);
 
   // Because there can be only one child frame, these two function return
   // NS_ERROR_FAILURE
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
 
   virtual void Destroy();
 
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
 
   virtual nsIView* GetParentViewForChildFrame(nsIFrame* aFrame) const {
     return mInner.GetParentViewForChildFrame(aFrame);
@@ -453,20 +453,20 @@ public:
   // XXXldb Is this actually used?
 #if 0
   virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
 #endif
 
   // Because there can be only one child frame, these two function return
   // NS_ERROR_FAILURE
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
 
   virtual void Destroy();
 
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
 
   virtual nsIView* GetParentViewForChildFrame(nsIFrame* aFrame) const {
     return mInner.GetParentViewForChildFrame(aFrame);
--- a/layout/generic/nsHTMLFrame.cpp
+++ b/layout/generic/nsHTMLFrame.cpp
@@ -94,20 +94,20 @@ public:
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
   virtual void Destroy();
 
   NS_IMETHOD SetInitialChildList(nsIAtom*        aListName,
                                  nsFrameList&    aChildList);
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
 
   virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
   virtual nsFrameList GetChildList(nsIAtom* aListName) const;
 
   virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
   virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
@@ -281,17 +281,17 @@ CanvasFrame::SetInitialChildList(nsIAtom
 
   NS_ASSERTION(aListName || aChildList.IsEmpty() || aChildList.OnlyChild(),
                "Primary child list can have at most one frame in it");
   return nsHTMLContainerFrame::SetInitialChildList(aListName, aChildList);
 }
 
 NS_IMETHODIMP
 CanvasFrame::AppendFrames(nsIAtom*        aListName,
-                          nsIFrame*       aFrameList)
+                          nsFrameList&    aFrameList)
 {
   nsresult  rv;
 
   if (nsGkAtoms::absoluteList == aListName)
     return mAbsoluteContainer.AppendFrames(this, aListName, aFrameList);
 
   NS_ASSERTION(!aListName, "unexpected child list name");
   NS_PRECONDITION(mFrames.IsEmpty(), "already have a child frame");
@@ -300,33 +300,35 @@ CanvasFrame::AppendFrames(nsIAtom*      
     rv = NS_ERROR_INVALID_ARG;
 
   } else if (!mFrames.IsEmpty()) {
     // We only allow a single child frame
     rv = NS_ERROR_FAILURE;
 
   } else {
     // Insert the new frames
+    NS_ASSERTION(aFrameList.FirstChild() == aFrameList.LastChild(),
+                 "Only one principal child frame allowed");
 #ifdef NS_DEBUG
     nsFrame::VerifyDirtyBitSet(aFrameList);
 #endif
-    mFrames.AppendFrame(nsnull, aFrameList);
+    mFrames.AppendFrames(nsnull, aFrameList);
 
     rv = PresContext()->PresShell()->
            FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                             NS_FRAME_HAS_DIRTY_CHILDREN);
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 CanvasFrame::InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
-                          nsIFrame*       aFrameList)
+                          nsFrameList&    aFrameList)
 {
   nsresult  rv;
 
   if (nsGkAtoms::absoluteList == aListName)
     return mAbsoluteContainer.InsertFrames(this, aListName, aPrevFrame, aFrameList);
 
   // Because we only support a single child frame inserting is the same
   // as appending
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -102,20 +102,20 @@ struct nsPeekOffsetStruct;
 struct nsPoint;
 struct nsRect;
 struct nsSize;
 struct nsMargin;
 
 typedef class nsIFrame nsIBox;
 
 // IID for the nsIFrame interface
-// 7b437d20-a34e-11dd-ad8b-0800200c9a66
+// 2871104e-2738-4ad7-b86a-ede63c71f1c2
 #define NS_IFRAME_IID \
-  { 0x7b437d20, 0xa34e, 0x11dd, \
-    { 0xad, 0x8b, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } }
+  { 0x2871104e, 0x2738, 0x4ad7,                       \
+    { 0xb8, 0x6a, 0xed, 0xe6, 0x3c, 0x71, 0xf1, 0xc2 } }
 
 /**
  * Indication of how the frame can be split. This is used when doing runaround
  * of floats, and when pulling up child frames from a next-in-flow.
  *
  * The choices are splittable, not splittable at all, and splittable in
  * a non-rectangular fashion. This last type only applies to block-level
  * elements, and indicates whether splitting can be used when doing runaround.
@@ -533,17 +533,17 @@ public:
    * 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.
    *
    * @param   aListName the name of the child list. A NULL pointer for the atom
    *            name means the unnamed principal child list
    * @param   aChildList list of child frames. Each of the frames has its
-   *            NS_FRAME_IS_DIRTY bit set
+   *            NS_FRAME_IS_DIRTY bit set.  Must not be empty.
    * @return  NS_ERROR_INVALID_ARG if there is no child list with the specified
    *            name,
    *          NS_ERROR_UNEXPECTED if the frame is an atomic frame or if the
    *            initial list of frames has already been set for that child list,
    *          NS_OK otherwise.  In this case, SetInitialChildList empties out
    *            aChildList in the process of moving the frames over to its own
    *            child list.
    * @see     #Init()
@@ -554,43 +554,47 @@ public:
   /**
    * This method is responsible for appending frames to the frame
    * list.  The implementation should append the frames to the specified
    * child list and then generate a reflow command.
    *
    * @param   aListName the name of the child list. A NULL pointer for the atom
    *            name means the unnamed principal child list
    * @param   aFrameList list of child frames to append. Each of the frames has
-   *            its NS_FRAME_IS_DIRTY bit set
+   *            its NS_FRAME_IS_DIRTY bit set.  Must not be empty.
    * @return  NS_ERROR_INVALID_ARG if there is no child list with the specified
    *            name,
    *          NS_ERROR_UNEXPECTED if the frame is an atomic frame,
-   *          NS_OK otherwise
+   *          NS_OK otherwise.  In this case, AppendFrames empties out
+   *            aChildList in the process of moving the frames over to its own
+   *            child list.
    */
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
-                          nsIFrame*       aFrameList) = 0;
+                          nsFrameList&    aFrameList) = 0;
 
   /**
    * This method is responsible for inserting frames into the frame
    * list.  The implementation should insert the new frames into the specified
    * child list and then generate a reflow command.
    *
    * @param   aListName the name of the child list. A NULL pointer for the atom
    *            name means the unnamed principal child list
    * @param   aPrevFrame the frame to insert frames <b>after</b>
    * @param   aFrameList list of child frames to insert <b>after</b> aPrevFrame.
    *            Each of the frames has its NS_FRAME_IS_DIRTY bit set
    * @return  NS_ERROR_INVALID_ARG if there is no child list with the specified
    *            name,
    *          NS_ERROR_UNEXPECTED if the frame is an atomic frame,
-   *          NS_OK otherwise
+   *          NS_OK otherwise.  In this case, InsertFrames empties out
+   *            aChildList in the process of moving the frames over to its own
+   *            child list.
    */
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
-                          nsIFrame*       aFrameList) = 0;
+                          nsFrameList&    aFrameList) = 0;
 
   /**
    * This method is responsible for removing a frame in the frame
    * list.  The implementation should do something with the removed frame
    * and then generate a reflow command. The implementation is responsible
    * for destroying aOldFrame (the caller mustn't destroy aOldFrame).
    *
    * @param   aListName the name of the child list. A NULL pointer for the atom
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -1093,33 +1093,33 @@ nsPositionedInlineFrame::SetInitialChild
     rv = nsInlineFrame::SetInitialChildList(aListName, aChildList);
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsPositionedInlineFrame::AppendFrames(nsIAtom*        aListName,
-                                      nsIFrame*       aFrameList)
+                                      nsFrameList&    aFrameList)
 {
   nsresult  rv;
   
   if (nsGkAtoms::absoluteList == aListName) {
     rv = mAbsoluteContainer.AppendFrames(this, aListName, aFrameList);
   } else {
     rv = nsInlineFrame::AppendFrames(aListName, aFrameList);
   }
 
   return rv;
 }
   
 NS_IMETHODIMP
 nsPositionedInlineFrame::InsertFrames(nsIAtom*        aListName,
                                       nsIFrame*       aPrevFrame,
-                                      nsIFrame*       aFrameList)
+                                      nsFrameList&    aFrameList)
 {
   nsresult  rv;
 
   if (nsGkAtoms::absoluteList == aListName) {
     rv = mAbsoluteContainer.InsertFrames(this, aListName, aPrevFrame,
                                          aFrameList);
   } else {
     rv = nsInlineFrame::InsertFrames(aListName, aPrevFrame, aFrameList);
--- a/layout/generic/nsInlineFrame.h
+++ b/layout/generic/nsInlineFrame.h
@@ -254,20 +254,20 @@ public:
 
   virtual ~nsPositionedInlineFrame() { } // useful for debugging
 
   virtual void Destroy();
 
   NS_IMETHOD SetInitialChildList(nsIAtom*        aListName,
                                  nsFrameList&    aChildList);
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
 
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists);
 
   virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
--- a/layout/generic/nsViewportFrame.cpp
+++ b/layout/generic/nsViewportFrame.cpp
@@ -107,17 +107,17 @@ ViewportFrame::BuildDisplayList(nsDispla
   // make the kid's BorderBackground our own. This ensures that the canvas
   // frame's background becomes our own background and therefore appears
   // below negative z-index elements.
   return BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
 }
 
 NS_IMETHODIMP
 ViewportFrame::AppendFrames(nsIAtom*        aListName,
-                            nsIFrame*       aFrameList)
+                            nsFrameList&    aFrameList)
 {
   nsresult rv = NS_OK;
 
   if (nsGkAtoms::fixedList == aListName) {
     rv = mFixedContainer.AppendFrames(this, aListName, aFrameList);
   }
   else {
     NS_ASSERTION(!aListName, "unexpected child list");
@@ -126,17 +126,17 @@ ViewportFrame::AppendFrames(nsIAtom*    
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 ViewportFrame::InsertFrames(nsIAtom*        aListName,
                             nsIFrame*       aPrevFrame,
-                            nsIFrame*       aFrameList)
+                            nsFrameList&    aFrameList)
 {
   nsresult rv = NS_OK;
 
   if (nsGkAtoms::fixedList == aListName) {
     rv = mFixedContainer.InsertFrames(this, aListName, aPrevFrame, aFrameList);
   }
   else {
     NS_ASSERTION(!aListName, "unexpected child list");
--- a/layout/generic/nsViewportFrame.h
+++ b/layout/generic/nsViewportFrame.h
@@ -70,21 +70,21 @@ public:
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        asPrevInFlow);
 
   NS_IMETHOD SetInitialChildList(nsIAtom*        aListName,
                                  nsFrameList&    aChildList);
 
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
 
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
 
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
 
   virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
 
   virtual nsFrameList GetChildList(nsIAtom* aListName) const;
 
--- a/layout/mathml/nsMathMLContainerFrame.cpp
+++ b/layout/mathml/nsMathMLContainerFrame.cpp
@@ -790,42 +790,36 @@ nsMathMLContainerFrame::ChildListChanged
       frame->AddStateBits(NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN);
     }
   }
   return ReLayoutChildren(frame);
 }
 
 NS_IMETHODIMP
 nsMathMLContainerFrame::AppendFrames(nsIAtom*        aListName,
-                                     nsIFrame*       aFrameList)
+                                     nsFrameList&    aFrameList)
 {
   if (aListName) {
     return NS_ERROR_INVALID_ARG;
   }
-  if (aFrameList) {
-    mFrames.AppendFrames(this, aFrameList);
-    return ChildListChanged(nsIDOMMutationEvent::ADDITION);
-  }
-  return NS_OK;
+  mFrames.AppendFrames(this, aFrameList);
+  return ChildListChanged(nsIDOMMutationEvent::ADDITION);
 }
 
 NS_IMETHODIMP
 nsMathMLContainerFrame::InsertFrames(nsIAtom*        aListName,
                                      nsIFrame*       aPrevFrame,
-                                     nsIFrame*       aFrameList)
+                                     nsFrameList&    aFrameList)
 {
   if (aListName) {
     return NS_ERROR_INVALID_ARG;
   }
-  if (aFrameList) {
-    // Insert frames after aPrevFrame
-    mFrames.InsertFrames(this, aPrevFrame, aFrameList);
-    return ChildListChanged(nsIDOMMutationEvent::ADDITION);
-  }
-  return NS_OK;
+  // Insert frames after aPrevFrame
+  mFrames.InsertFrames(this, aPrevFrame, aFrameList);
+  return ChildListChanged(nsIDOMMutationEvent::ADDITION);
 }
 
 NS_IMETHODIMP
 nsMathMLContainerFrame::RemoveFrame(nsIAtom*        aListName,
                                     nsIFrame*       aOldFrame)
 {
   if (aListName) {
     return NS_ERROR_INVALID_ARG;
--- a/layout/mathml/nsMathMLContainerFrame.h
+++ b/layout/mathml/nsMathMLContainerFrame.h
@@ -114,22 +114,22 @@ public:
       nsHTMLContainerFrame::IsFrameOfType(aFlags &
               ~(nsIFrame::eMathML | nsIFrame::eExcludesIgnorableWhitespace));
   }
 
   virtual PRIntn GetSkipSides() const { return 0; }
 
   NS_IMETHOD
   AppendFrames(nsIAtom*        aListName,
-               nsIFrame*       aFrameList);
+               nsFrameList&    aFrameList);
 
   NS_IMETHOD
   InsertFrames(nsIAtom*        aListName,
                nsIFrame*       aPrevFrame,
-               nsIFrame*       aFrameList);
+               nsFrameList&    aFrameList);
 
   NS_IMETHOD
   RemoveFrame(nsIAtom*        aListName,
               nsIFrame*       aOldFrame);
 
   /**
    * Both GetMinWidth and GetPrefWidth return whatever
    * GetIntrinsicWidth returns.
@@ -404,30 +404,30 @@ public:
     nsresult rv = nsBlockFrame::SetInitialChildList(aListName, aChildList);
     // re-resolve our subtree to set any mathml-expected data
     nsMathMLContainerFrame::RebuildAutomaticDataForChildren(this);
     return rv;
   }
 
   NS_IMETHOD
   AppendFrames(nsIAtom*        aListName,
-               nsIFrame*       aFrameList)
+               nsFrameList&    aFrameList)
   {
     NS_ASSERTION(!aListName || nsGkAtoms::nextBidi == aListName,
                  "unexpected frame list");
     nsresult rv = nsBlockFrame::AppendFrames(aListName, aFrameList);
     if (NS_LIKELY(!aListName))
       nsMathMLContainerFrame::ReLayoutChildren(this);
     return rv;
   }
 
   NS_IMETHOD
   InsertFrames(nsIAtom*        aListName,
                nsIFrame*       aPrevFrame,
-               nsIFrame*       aFrameList)
+               nsFrameList&    aFrameList)
   {
     NS_ASSERTION(!aListName || nsGkAtoms::nextBidi == aListName,
                  "unexpected frame list");
     nsresult rv = nsBlockFrame::InsertFrames(aListName, aPrevFrame, aFrameList);
     if (NS_LIKELY(!aListName))
       nsMathMLContainerFrame::ReLayoutChildren(this);
     return rv;
   }
@@ -472,30 +472,30 @@ public:
     nsresult rv = nsInlineFrame::SetInitialChildList(aListName, aChildList);
     // re-resolve our subtree to set any mathml-expected data
     nsMathMLContainerFrame::RebuildAutomaticDataForChildren(this);
     return rv;
   }
 
   NS_IMETHOD
   AppendFrames(nsIAtom*        aListName,
-               nsIFrame*       aFrameList)
+               nsFrameList&    aFrameList)
   {
     NS_ASSERTION(!aListName || nsGkAtoms::nextBidi == aListName,
                  "unexpected frame list");
     nsresult rv = nsInlineFrame::AppendFrames(aListName, aFrameList);
     if (NS_LIKELY(!aListName))
       nsMathMLContainerFrame::ReLayoutChildren(this);
     return rv;
   }
 
   NS_IMETHOD
   InsertFrames(nsIAtom*        aListName,
                nsIFrame*       aPrevFrame,
-               nsIFrame*       aFrameList)
+               nsFrameList&    aFrameList)
   {
     NS_ASSERTION(!aListName || nsGkAtoms::nextBidi == aListName,
                  "unexpected frame list");
     nsresult rv = nsInlineFrame::InsertFrames(aListName, aPrevFrame, aFrameList);
     if (NS_LIKELY(!aListName))
       nsMathMLContainerFrame::ReLayoutChildren(this);
     return rv;
   }
--- a/layout/mathml/nsMathMLForeignFrameWrapper.h
+++ b/layout/mathml/nsMathMLForeignFrameWrapper.h
@@ -84,26 +84,26 @@ public:
   Reflow(nsPresContext*          aPresContext,
          nsHTMLReflowMetrics&     aDesiredSize,
          const nsHTMLReflowState& aReflowState,
          nsReflowStatus&          aStatus);
 
   // we are just a wrapper and these methods shouldn't be called
   NS_IMETHOD
   AppendFrames(nsIAtom*        aListName,
-               nsIFrame*       aFrameList)
+               nsFrameList&    aFrameList)
   {
     NS_NOTREACHED("unsupported operation");
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   NS_IMETHOD
   InsertFrames(nsIAtom*        aListName,
                nsIFrame*       aPrevFrame,
-               nsIFrame*       aFrameList)
+               nsFrameList&    aFrameList)
   {
     NS_NOTREACHED("unsupported operation");
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   // Our life is bound to the life of our unique child.
   // When our child goes away, we ask our parent to delete us
   NS_IMETHOD
--- a/layout/mathml/nsMathMLmtableFrame.h
+++ b/layout/mathml/nsMathMLmtableFrame.h
@@ -109,27 +109,27 @@ public:
   // Overloaded nsTableFrame methods
 
   NS_IMETHOD
   SetInitialChildList(nsIAtom*  aListName,
                       nsFrameList& aChildList);
 
   NS_IMETHOD
   AppendFrames(nsIAtom*  aListName,
-               nsIFrame* aFrameList)
+               nsFrameList& aFrameList)
   {
     nsresult rv = nsTableFrame::AppendFrames(aListName, aFrameList);
     RestyleTable();
     return rv;
   }
 
   NS_IMETHOD
   InsertFrames(nsIAtom*  aListName,
                nsIFrame* aPrevFrame,
-               nsIFrame* aFrameList)
+               nsFrameList& aFrameList)
   {
     nsresult rv = nsTableFrame::InsertFrames(aListName, aPrevFrame, aFrameList);
     RestyleTable();
     return rv;
   }
 
   NS_IMETHOD
   RemoveFrame(nsIAtom*  aListName,
@@ -166,27 +166,27 @@ public:
 
   NS_IMETHOD
   AttributeChanged(PRInt32  aNameSpaceID,
                    nsIAtom* aAttribute,
                    PRInt32  aModType);
 
   NS_IMETHOD
   AppendFrames(nsIAtom*  aListName,
-               nsIFrame* aFrameList)
+               nsFrameList& aFrameList)
   {
     nsresult rv = nsTableRowFrame::AppendFrames(aListName, aFrameList);
     RestyleTable();
     return rv;
   }
 
   NS_IMETHOD
   InsertFrames(nsIAtom*  aListName,
                nsIFrame* aPrevFrame,
-               nsIFrame* aFrameList)
+               nsFrameList& aFrameList)
   {
     nsresult rv = nsTableRowFrame::InsertFrames(aListName, aPrevFrame, aFrameList);
     RestyleTable();
     return rv;
   }
 
   NS_IMETHOD
   RemoveFrame(nsIAtom*  aListName,
--- a/layout/svg/base/src/nsSVGContainerFrame.cpp
+++ b/layout/svg/base/src/nsSVGContainerFrame.cpp
@@ -51,25 +51,25 @@ nsIFrame*
 NS_NewSVGContainerFrame(nsIPresShell* aPresShell,
                         nsStyleContext* aContext)
 {
   return new (aPresShell) nsSVGContainerFrame(aContext);
 }
 
 NS_IMETHODIMP
 nsSVGContainerFrame::AppendFrames(nsIAtom* aListName,
-                                  nsIFrame* aFrameList)
+                                  nsFrameList& aFrameList)
 {
   return InsertFrames(aListName, mFrames.LastChild(), aFrameList);  
 }
 
 NS_IMETHODIMP
 nsSVGContainerFrame::InsertFrames(nsIAtom* aListName,
                                   nsIFrame* aPrevFrame,
-                                  nsIFrame* aFrameList)
+                                  nsFrameList& aFrameList)
 {
   NS_ASSERTION(!aListName, "unexpected child list");
   NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
                "inserting after sibling frame with different parent");
 
   mFrames.InsertFrames(this, aPrevFrame, aFrameList);
 
   return NS_OK;
@@ -105,36 +105,32 @@ nsSVGDisplayContainerFrame::Init(nsICont
   }
   nsresult rv = nsSVGContainerFrameBase::Init(aContent, aParent, aPrevInFlow);
   return rv;
 }
 
 NS_IMETHODIMP
 nsSVGDisplayContainerFrame::InsertFrames(nsIAtom* aListName,
                                          nsIFrame* aPrevFrame,
-                                         nsIFrame* aFrameList)
+                                         nsFrameList& aFrameList)
 {
-  // memorize last new frame
-  nsIFrame* lastNewFrame = nsnull;
-  {
-    nsFrameList tmpList(aFrameList);
-    lastNewFrame = tmpList.LastChild();
-  }
+  // memorize first old frame after insertion point
+  // XXXbz once again, this would work a lot better if the nsIFrame
+  // methods returned framelist iterators....
+  nsIFrame* firstOldFrame = aPrevFrame ?
+    aPrevFrame->GetNextSibling() : GetChildList(aListName).FirstChild();
+  nsIFrame* firstNewFrame = aFrameList.FirstChild();
   
   // Insert the new frames
   nsSVGContainerFrame::InsertFrames(aListName, aPrevFrame, aFrameList);
 
   // Call InitialUpdate on the new frames ONLY if our nsSVGOuterSVGFrame has had
   // its initial reflow (our NS_FRAME_FIRST_REFLOW bit is clear) - bug 399863.
   if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
-    nsIFrame* end = nsnull;
-    if (lastNewFrame)
-      end = lastNewFrame->GetNextSibling();
-
-    for (nsIFrame* kid = aFrameList; kid != end;
+    for (nsIFrame* kid = firstNewFrame; kid != firstOldFrame;
          kid = kid->GetNextSibling()) {
       nsISVGChildFrame* SVGFrame = do_QueryFrame(kid);
       if (SVGFrame) {
         SVGFrame->InitialUpdate(); 
       }
     }
   }
 
--- a/layout/svg/base/src/nsSVGContainerFrame.h
+++ b/layout/svg/base/src/nsSVGContainerFrame.h
@@ -58,20 +58,20 @@ public:
   
   NS_DECL_QUERYFRAME
 
   // Returns the transform to our gfxContext (to device pixels, not CSS px)
   virtual gfxMatrix GetCanvasTM() { return gfxMatrix(); }
 
   // nsIFrame:
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
 
   virtual PRBool IsFrameOfType(PRUint32 aFlags) const
   {
@@ -90,17 +90,17 @@ protected:
 public:
   NS_DECLARE_FRAME_ACCESSOR(nsSVGDisplayContainerFrame)
 
   NS_DECL_QUERYFRAME
 
   // nsIFrame:
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
 
   // nsISVGChildFrame interface:
   NS_IMETHOD PaintSVG(nsSVGRenderState* aContext,
--- a/layout/svg/base/src/nsSVGTextContainerFrame.cpp
+++ b/layout/svg/base/src/nsSVGTextContainerFrame.cpp
@@ -129,17 +129,17 @@ nsSVGTextContainerFrame::GetDy()
 }
 
 //----------------------------------------------------------------------
 // nsIFrame methods
 
 NS_IMETHODIMP
 nsSVGTextContainerFrame::InsertFrames(nsIAtom* aListName,
                                       nsIFrame* aPrevFrame,
-                                      nsIFrame* aFrameList)
+                                      nsFrameList& aFrameList)
 {
   nsresult rv = nsSVGDisplayContainerFrame::InsertFrames(aListName,
                                                          aPrevFrame,
                                                          aFrameList);
 
   NotifyGlyphMetricsChange();
   return rv;
 }
--- a/layout/svg/base/src/nsSVGTextContainerFrame.h
+++ b/layout/svg/base/src/nsSVGTextContainerFrame.h
@@ -59,17 +59,17 @@ public:
   
 public:
   NS_DECL_QUERYFRAME
   NS_DECLARE_FRAME_ACCESSOR(nsSVGTextContainerFrame)
 
   // nsIFrame
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD RemoveFrame(nsIAtom *aListName, nsIFrame *aOldFrame);
 
   NS_IMETHOD GetStartPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval);
   NS_IMETHOD GetEndPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval);
   NS_IMETHOD GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval);
   NS_IMETHOD GetRotationOfChar(PRUint32 charnum, float *_retval);
 
   /*
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -254,26 +254,26 @@ nsTableCellFrame::DidSetStyleContext(nsS
     nsRect damageArea(colIndex, rowIndex, GetColSpan(), GetRowSpan());
     tableFrame->SetBCDamageArea(damageArea);
   }
 }
 
      
 NS_IMETHODIMP
 nsTableCellFrame::AppendFrames(nsIAtom*        aListName,
-                               nsIFrame*       aFrameList)
+                               nsFrameList&    aFrameList)
 {
   NS_PRECONDITION(PR_FALSE, "unsupported operation");
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 nsTableCellFrame::InsertFrames(nsIAtom*        aListName,
                                nsIFrame*       aPrevFrame,
-                               nsIFrame*       aFrameList)
+                               nsFrameList&    aFrameList)
 {
   NS_PRECONDITION(PR_FALSE, "unsupported operation");
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 nsTableCellFrame::RemoveFrame(nsIAtom*        aListName,
                               nsIFrame*       aOldFrame)
--- a/layout/tables/nsTableCellFrame.h
+++ b/layout/tables/nsTableCellFrame.h
@@ -95,20 +95,20 @@ public:
 
   /** @see nsIFrame::DidSetStyleContext */
   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
   
   // table cells contain a block frame which does most of the work, and
   // so these functions should never be called. They assert and return
   // NS_ERROR_NOT_IMPLEMENTED
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
 
   virtual nsIFrame* GetContentInsertionFrame() {
     return GetFirstChild(nsnull)->GetContentInsertionFrame();
   }
 
   virtual nsMargin GetUsedMargin() const;
--- a/layout/tables/nsTableColGroupFrame.cpp
+++ b/layout/tables/nsTableColGroupFrame.cpp
@@ -92,88 +92,76 @@ void nsTableColGroupFrame::ResetColIndic
     }
     colGroupFrame = static_cast<nsTableColGroupFrame*>
                                (colGroupFrame->GetNextSibling());
   }
 }
 
 
 nsresult
-nsTableColGroupFrame::AddColsToTable(PRInt32          aFirstColIndex,
-                                     PRBool           aResetSubsequentColIndices,
-                                     nsIFrame*        aFirstFrame,
-                                     nsIFrame*        aLastFrame)
+nsTableColGroupFrame::AddColsToTable(PRInt32                   aFirstColIndex,
+                                     PRBool                    aResetSubsequentColIndices,
+                                     const nsFrameList::Slice& aCols)
 {
   nsresult rv = NS_OK;
   nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
-  if (!tableFrame || !aFirstFrame)
+  if (!tableFrame)
     return NS_ERROR_NULL_POINTER;
 
   // set the col indices of the col frames and and add col info to the table
   PRInt32 colIndex = aFirstColIndex;
-  nsIFrame* kidFrame = aFirstFrame;
-  PRBool foundLastFrame = PR_FALSE;
-  while (kidFrame) {
-    if (nsGkAtoms::tableColFrame == kidFrame->GetType()) {
-      ((nsTableColFrame*)kidFrame)->SetColIndex(colIndex);
-      if (!foundLastFrame) {
-        mColCount++;
-        tableFrame->InsertCol((nsTableColFrame &)*kidFrame, colIndex);
-      }
-      colIndex++;
-    }
-    if (kidFrame == aLastFrame) {
-      foundLastFrame = PR_TRUE;
-    }
-    kidFrame = kidFrame->GetNextSibling(); 
+  nsFrameList::Enumerator e(aCols);
+  for (; !e.AtEnd(); e.Next()) {
+    ((nsTableColFrame*)e.get())->SetColIndex(colIndex);
+    mColCount++;
+    tableFrame->InsertCol((nsTableColFrame &)*e.get(), colIndex);
+    colIndex++;
   }
+
+  for (nsFrameList::Enumerator eTail = e.GetUnlimitedEnumerator();
+       !eTail.AtEnd();
+       eTail.Next()) {
+    ((nsTableColFrame*)eTail.get())->SetColIndex(colIndex);
+    colIndex++;
+  }
+
   // We have already set the colindex for all the colframes in this
   // colgroup that come after the first inserted colframe, but there could
   // be other colgroups following this one and their colframes need
   // correct colindices too.
   if (aResetSubsequentColIndices && GetNextSibling()) {
     ResetColIndices(GetNextSibling(), colIndex);
   }
 
   return rv;
 }
 
 
-PRBool
-nsTableColGroupFrame::GetLastRealColGroup(nsTableFrame* aTableFrame, 
-                                          nsIFrame**    aLastColGroup)
+nsTableColGroupFrame*
+nsTableColGroupFrame::GetLastRealColGroup(nsTableFrame* aTableFrame)
 {
-  *aLastColGroup = nsnull;
   nsFrameList colGroups = aTableFrame->GetColGroups();
 
   nsIFrame* nextToLastColGroup = nsnull;
-  nsIFrame* lastColGroup       = colGroups.FirstChild();
-  while(lastColGroup) {
-    nsIFrame* next = lastColGroup->GetNextSibling();
-    if (next) {
-      nextToLastColGroup = lastColGroup;
-      lastColGroup = next;
-    }
-    else {
-      break;
-    }
+  nsFrameList::FrameLinkEnumerator link(colGroups);
+  for ( ; !link.AtEnd(); link.Next()) {
+    nextToLastColGroup = link.PrevFrame();
   }
 
-  if (!lastColGroup) return PR_TRUE; // there are no col group frames
+  if (!link.PrevFrame()) {
+    return nsnull; // there are no col group frames
+  }
  
   nsTableColGroupType lastColGroupType =
-    ((nsTableColGroupFrame *)lastColGroup)->GetColType();
+    static_cast<nsTableColGroupFrame*>(link.PrevFrame())->GetColType();
   if (eColGroupAnonymousCell == lastColGroupType) {
-    *aLastColGroup = nextToLastColGroup;
-    return PR_FALSE;
+    return static_cast<nsTableColGroupFrame*>(nextToLastColGroup);
   }
-  else {
-    *aLastColGroup = lastColGroup;
-    return PR_TRUE;
-  }
+ 
+  return static_cast<nsTableColGroupFrame*>(link.PrevFrame());
 }
 
 // don't set mColCount here, it is done in AddColsToTable
 NS_IMETHODIMP
 nsTableColGroupFrame::SetInitialChildList(nsIAtom*        aListName,
                                           nsFrameList&    aChildList)
 {
   if (!mFrames.IsEmpty()) {
@@ -218,49 +206,47 @@ nsTableColGroupFrame::DidSetStyleContext
                       tableFrame->GetRowCount());
     tableFrame->SetBCDamageArea(damageArea);
   }
   return;
 }
 
 NS_IMETHODIMP
 nsTableColGroupFrame::AppendFrames(nsIAtom*        aListName,
-                                   nsIFrame*       aFrameList)
+                                   nsFrameList&    aFrameList)
 {
   NS_ASSERTION(!aListName, "unexpected child list");
 
   nsTableColFrame* col = GetFirstColumn();
   nsTableColFrame* nextCol;
   while (col && col->GetColType() == eColAnonymousColGroup) {
     // this colgroup spans one or more columns but now that there is a
     // real column below, spanned anonymous columns should be removed,
     // since the HTML spec says to ignore the span of a colgroup if it
     // has content columns in it.
     nextCol = col->GetNextCol();
     RemoveFrame(nsnull, col);
     col = nextCol;
   }
 
-  mFrames.AppendFrames(this, aFrameList);
-  InsertColsReflow(GetStartColumnIndex() + mColCount, aFrameList);
+  const nsFrameList::Slice& newFrames =
+    mFrames.AppendFrames(this, aFrameList);
+  InsertColsReflow(GetStartColumnIndex() + mColCount, newFrames);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTableColGroupFrame::InsertFrames(nsIAtom*        aListName,
                                    nsIFrame*       aPrevFrame,
-                                   nsIFrame*       aFrameList)
+                                   nsFrameList&    aFrameList)
 {
   NS_ASSERTION(!aListName, "unexpected child list");
   NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
                "inserting after sibling frame with different parent");
 
-  nsFrameList frames(aFrameList); // convience for getting last frame
-  nsIFrame* lastFrame = frames.LastChild();
-
   nsTableColFrame* col = GetFirstColumn();
   nsTableColFrame* nextCol;
   while (col && col->GetColType() == eColAnonymousColGroup) {
     // this colgroup spans one or more columns but now that there is a
     // real column below, spanned anonymous columns should be removed,
     // since the HTML spec says to ignore the span of a colgroup if it
     // has content columns in it.
     nextCol = col->GetNextCol();
@@ -276,32 +262,32 @@ nsTableColGroupFrame::InsertFrames(nsIAt
   }
 
   NS_ASSERTION(!aPrevFrame || aPrevFrame == aPrevFrame->GetLastContinuation(),
                "Prev frame should be last in continuation chain");
   NS_ASSERTION(!aPrevFrame || !GetNextColumn(aPrevFrame) ||
                GetNextColumn(aPrevFrame)->GetColType() != eColAnonymousCol,
                "Shouldn't be inserting before a spanned colframe");
 
-  mFrames.InsertFrames(this, aPrevFrame, aFrameList);
+  const nsFrameList::Slice& newFrames =
+    mFrames.InsertFrames(this, aPrevFrame, aFrameList);
   nsIFrame* prevFrame = nsTableFrame::GetFrameAtOrBefore(this, aPrevFrame,
                                                          nsGkAtoms::tableColFrame);
 
   PRInt32 colIndex = (prevFrame) ? ((nsTableColFrame*)prevFrame)->GetColIndex() + 1 : GetStartColumnIndex();
-  InsertColsReflow(colIndex, aFrameList, lastFrame);
+  InsertColsReflow(colIndex, newFrames);
 
   return NS_OK;
 }
 
 void
-nsTableColGroupFrame::InsertColsReflow(PRInt32         aColIndex,
-                                       nsIFrame*       aFirstFrame,
-                                       nsIFrame*       aLastFrame)
+nsTableColGroupFrame::InsertColsReflow(PRInt32                   aColIndex,
+                                       const nsFrameList::Slice& aCols)
 {
-  AddColsToTable(aColIndex, PR_TRUE, aFirstFrame, aLastFrame);
+  AddColsToTable(aColIndex, PR_TRUE, aCols);
 
   PresContext()->PresShell()->FrameNeedsReflow(this,
                                                nsIPresShell::eTreeChange,
                                                NS_FRAME_HAS_DIRTY_CHILDREN);
 }
 
 void
 nsTableColGroupFrame::RemoveChild(nsTableColFrame& aChild,
--- a/layout/tables/nsTableColGroupFrame.h
+++ b/layout/tables/nsTableColGroupFrame.h
@@ -98,32 +98,30 @@ public:
   void SetColType(nsTableColGroupType aType);
   
   /** Real in this context are colgroups that come from an element
     * with table-column-group display or wrap around columns that
     * come from an element with table-column display. Colgroups
     * that are the result of wrapping cells in an anonymous
     * column and colgroup are not considered real here.
     * @param aTableFrame - the table parent of the colgroups
-    * @param aLastColgroup - the last real colgroup
-    * @return  is false if there is a non real colgroup at the end
+    * @return the last real colgroup
     */
-  static PRBool GetLastRealColGroup(nsTableFrame* aTableFrame, 
-                                    nsIFrame**    aLastColGroup);
+  static nsTableColGroupFrame* GetLastRealColGroup(nsTableFrame* aTableFrame);
 
   /** @see nsIFrame::DidSetStyleContext */
   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
 
   /** @see nsIFrame::AppendFrames, InsertFrames, RemoveFrame
     */
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
 
   /** remove the column aChild from the column group, if requested renumber
     * the subsequent columns in this column group and all following column
     * groups. see also ResetColIndices for this
     * @param aChild       - the column frame that needs to be removed
     * @param aResetSubsequentColIndices - if true the columns that follow
@@ -156,28 +154,26 @@ public:
 
   /** Add column frames to the table storages: colframe cache and cellmap
     * this doesn't change the mFrames of the colgroup frame.
     * @param aFirstColIndex - the index at which aFirstFrame should be inserted
     *                         into the colframe cache.
     * @param aResetSubsequentColIndices - the indices of the col frames
     *                                     after the insertion might need
     *                                     an update
-    * @param aFirstFrame - first frame that needs to be added to the table,
-    *                      the frame should have a correctly set sibling
-    * @param aLastFrame  - last frame that needs to be added. It can be either
-    *                      null or should be in the sibling chain of
-    *                      aFirstFrame
+    * @param aCols - an iterator that can be used to iterate over the col
+    *                frames to be added.  Once this is done, the frames on the
+    *                sbling chain of its .get() at that point will still need
+    *                their col indices updated.
     * @result            - if there is no table frame or the table frame is not
     *                      the first in flow it will return an error
     */
-  nsresult AddColsToTable(PRInt32          aFirstColIndex,
-                          PRBool           aResetSubsequentColIndices,
-                          nsIFrame*        aFirstFrame,
-                          nsIFrame*        aLastFrame = nsnull);
+  nsresult AddColsToTable(PRInt32                   aFirstColIndex,
+                          PRBool                    aResetSubsequentColIndices,
+                          const nsFrameList::Slice& aCols);
 
 #ifdef DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
   void Dump(PRInt32 aIndent);
 #endif
 
   /** returns the number of columns represented by this group.
     * if there are col children, count them (taking into account the span of each)
@@ -232,19 +228,18 @@ public:
    * Set full border widths before collapsing with cell borders
    * @param aForSide - side to set; only accepts top and bottom
    */
   void SetContinuousBCBorderWidth(PRUint8     aForSide,
                                   BCPixelSize aPixelValue);
 protected:
   nsTableColGroupFrame(nsStyleContext* aContext);
 
-  void InsertColsReflow(PRInt32         aColIndex,
-                        nsIFrame*       aFirstFrame,
-                        nsIFrame*       aLastFrame = nsnull);
+  void InsertColsReflow(PRInt32                   aColIndex,
+                        const nsFrameList::Slice& aCols);
 
   /** implement abstract method on nsHTMLContainerFrame */
   virtual PRIntn GetSkipSides() const;
 
   // data members
   PRInt32 mColCount;
   // the starting column index this col group represents. Must be >= 0. 
   PRInt32 mStartColIndex;
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -349,18 +349,18 @@ nsTableFrame::SetInitialChildList(nsIAto
     }
   }
 
   // If we have a prev-in-flow, then we're a table that has been split and
   // so don't treat this like an append
   if (!GetPrevInFlow()) {
     // process col groups first so that real cols get constructed before
     // anonymous ones due to cells in rows.
-    InsertColGroups(0, mColGroups.FirstChild());
-    AppendRowGroups(mFrames.FirstChild());
+    InsertColGroups(0, mColGroups);
+    InsertRowGroups(mFrames);
     // calc collapsing borders 
     if (IsBorderCollapse()) {
       nsRect damageArea(0, 0, GetColCount(), GetRowCount());
       SetBCDamageArea(damageArea);
     }
   }
 
   return NS_OK;
@@ -522,88 +522,82 @@ void nsTableFrame::AdjustRowIndices(PRIn
   OrderRowGroups(rowGroups);
 
   for (PRUint32 rgX = 0; rgX < rowGroups.Length(); rgX++) {
     rowGroups[rgX]->AdjustRowIndices(aRowIndex, aAdjustment);
   }
 }
 
 
-void nsTableFrame::ResetRowIndices(nsIFrame* aFirstRowGroupFrame,
-                                   nsIFrame* aLastRowGroupFrame)
+void nsTableFrame::ResetRowIndices(const nsFrameList::Slice& aRowGroupsToExclude)
 {
   // Iterate over the row groups and adjust the row indices of all rows
   // omit the rowgroups that will be inserted later
+  // XXXbz this code seems to assume that the row groups handed out by
+  // aRowGroupsToExclude are already in OrderRowGroups() order.
+  // There's no reason that would be true!
   RowGroupArray rowGroups;
   OrderRowGroups(rowGroups);
 
   PRInt32 rowIndex = 0;
   nsTableRowGroupFrame* newRgFrame = nsnull;
-  nsIFrame* omitRgFrame = aFirstRowGroupFrame;
-  if (omitRgFrame) {
-    newRgFrame = GetRowGroupFrame(omitRgFrame);
-    if (omitRgFrame == aLastRowGroupFrame)
-      omitRgFrame = nsnull;
+  nsFrameList::Enumerator excludeRowGroupsEnumerator(aRowGroupsToExclude);
+  if (!excludeRowGroupsEnumerator.AtEnd()) {
+    newRgFrame = GetRowGroupFrame(excludeRowGroupsEnumerator.get());
+    excludeRowGroupsEnumerator.Next();
   }
 
   for (PRUint32 rgX = 0; rgX < rowGroups.Length(); rgX++) {
     nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
     if (rgFrame == newRgFrame) {
-      // omit the new rowgroup
-      if (omitRgFrame) {
-        omitRgFrame = omitRgFrame->GetNextSibling();
-        if (omitRgFrame) {
-          newRgFrame  = GetRowGroupFrame(omitRgFrame);
-          if (omitRgFrame == aLastRowGroupFrame)
-            omitRgFrame = nsnull;
-        }
+      // omit the new rowgroup and move our iterator along
+      if (!excludeRowGroupsEnumerator.AtEnd()) {
+        newRgFrame = GetRowGroupFrame(excludeRowGroupsEnumerator.get());
+        excludeRowGroupsEnumerator.Next();
       }
     }
     else {
-      nsIFrame* rowFrame = rgFrame->GetFirstChild(nsnull);
-      for ( ; rowFrame; rowFrame = rowFrame->GetNextSibling()) {
-        if (NS_STYLE_DISPLAY_TABLE_ROW==rowFrame->GetStyleDisplay()->mDisplay) {
-          ((nsTableRowFrame *)rowFrame)->SetRowIndex(rowIndex);
+      const nsFrameList& rowFrames = rgFrame->GetChildList(nsnull);
+      for (nsFrameList::Enumerator rows(rowFrames); !rows.AtEnd(); rows.Next()) {
+        if (NS_STYLE_DISPLAY_TABLE_ROW==rows.get()->GetStyleDisplay()->mDisplay) {
+          ((nsTableRowFrame *)rows.get())->SetRowIndex(rowIndex);
           rowIndex++;
         }
       }
     }
   }
 }
-void nsTableFrame::InsertColGroups(PRInt32         aStartColIndex,
-                                   nsIFrame*       aFirstFrame,
-                                   nsIFrame*       aLastFrame)
+void nsTableFrame::InsertColGroups(PRInt32                   aStartColIndex,
+                                   const nsFrameList::Slice& aColGroups)
 {
   PRInt32 colIndex = aStartColIndex;
-  nsTableColGroupFrame* firstColGroupToReset = nsnull;
-  nsIFrame* kidFrame = aFirstFrame;
-  PRBool didLastFrame = PR_FALSE;
-  while (kidFrame) {
-    if (nsGkAtoms::tableColGroupFrame == kidFrame->GetType()) {
-      if (didLastFrame) {
-        firstColGroupToReset = (nsTableColGroupFrame*)kidFrame;
-        break;
-      }
-      else {
-        nsTableColGroupFrame* cgFrame = (nsTableColGroupFrame*)kidFrame;
-        cgFrame->SetStartColumnIndex(colIndex);
-        nsIFrame* firstCol = kidFrame->GetFirstChild(nsnull);
-        cgFrame->AddColsToTable(colIndex, PR_FALSE, firstCol);
-        PRInt32 numCols = cgFrame->GetColCount();
-        colIndex += numCols;
-      }
-    }
-    if (kidFrame == aLastFrame) {
-      didLastFrame = PR_TRUE;
-    }
-    kidFrame = kidFrame->GetNextSibling();
-  }
-
-  if (firstColGroupToReset) {
-    nsTableColGroupFrame::ResetColIndices(firstColGroupToReset, colIndex);
+  nsFrameList::Enumerator colGroups(aColGroups);
+  for (; !colGroups.AtEnd(); colGroups.Next()) {
+    nsTableColGroupFrame* cgFrame =
+      static_cast<nsTableColGroupFrame*>(colGroups.get());
+    cgFrame->SetStartColumnIndex(colIndex);
+    // XXXbz this sucks.  AddColsToTable will actually remove colgroups from
+    // the list we're traversing!  Need to fix things here.  :( I guess this is
+    // why the old code used pointer-to-last-frame as opposed to
+    // pointer-to-frame-after-last....
+
+    // How about dealing with this by storing a const reference to the
+    // mNextSibling of the framelist's last frame, instead of storing a pointer
+    // to the first-after-next frame?  Will involve making nsFrameList friend
+    // of nsIFrame, but it's time for that anyway.
+    cgFrame->AddColsToTable(colIndex, PR_FALSE,
+                              colGroups.get()->GetChildList(nsnull));
+    PRInt32 numCols = cgFrame->GetColCount();
+    colIndex += numCols;
+  }
+
+  nsFrameList::Enumerator remainingColgroups = colGroups.GetUnlimitedEnumerator();
+  if (!remainingColgroups.AtEnd()) {
+    nsTableColGroupFrame::ResetColIndices(
+      static_cast<nsTableColGroupFrame*>(remainingColgroups.get()), colIndex);
   }
 }
 
 void nsTableFrame::InsertCol(nsTableColFrame& aColFrame,
                              PRInt32          aColIndex)
 {
   mColFrames.InsertElementAt(aColIndex, &aColFrame);
   nsTableColType insertedColType = aColFrame.GetColType();
@@ -759,31 +753,29 @@ nsTableFrame::AppendAnonymousColFrames(n
     nsIFrame* colFrame = NS_NewTableColFrame(shell, styleContext);
     ((nsTableColFrame *) colFrame)->SetColType(aColType);
     colFrame->Init(iContent, aColGroupFrame, nsnull);
 
     newColFrames.AddChild(colFrame);
   }
   nsFrameList& cols = aColGroupFrame->GetWritableChildList();
   nsIFrame* oldLastCol = cols.LastChild();
-  nsIFrame* firstNewCol = newColFrames.FirstChild();
-  nsIFrame* lastNewCol = newColFrames.lastChild;
-  cols.InsertFrames(nsnull, oldLastCol, newColFrames);
+  const nsFrameList::Slice& newCols =
+    cols.InsertFrames(nsnull, oldLastCol, newColFrames);
   if (aAddToTable) {
     // get the starting col index in the cache
     PRInt32 startColIndex;
     if (oldLastCol) {
       startColIndex =
         static_cast<nsTableColFrame*>(oldLastCol)->GetColIndex() + 1;
     } else {
       startColIndex = aColGroupFrame->GetStartColumnIndex();
     }
 
-    aColGroupFrame->AddColsToTable(startColIndex, PR_TRUE, 
-                                   firstNewCol, lastNewCol);
+    aColGroupFrame->AddColsToTable(startColIndex, PR_TRUE, newCols);
   }
 }
 
 void
 nsTableFrame::MatchCellMapToColCache(nsTableCellMap* aCellMap)
 {
   PRInt32 numColsInMap   = GetColCount();
   PRInt32 numColsInCache = mColFrames.Length();
@@ -1018,27 +1010,16 @@ void nsTableFrame::RemoveRows(nsTableRow
   }
   AdjustRowIndices(firstRowIndex, -aNumRowsToRemove);
 #ifdef DEBUG_TABLE_CELLMAP
   printf("=== removeRowsAfter\n");
   Dump(PR_TRUE, PR_TRUE, PR_TRUE);
 #endif
 }
 
-void nsTableFrame::AppendRowGroups(nsIFrame* aFirstRowGroupFrame)
-{
-  if (aFirstRowGroupFrame) {
-    nsTableCellMap* cellMap = GetCellMap();
-    if (cellMap) {
-      nsFrameList newList(aFirstRowGroupFrame);
-      InsertRowGroups(aFirstRowGroupFrame, newList.LastChild());
-    }
-  }
-}
-
 nsTableRowGroupFrame*
 nsTableFrame::GetRowGroupFrame(nsIFrame* aFrame,
                                nsIAtom*  aFrameTypeIn)
 {
   nsIFrame* rgFrame = nsnull;
   nsIAtom* frameType = aFrameTypeIn;
   if (!aFrameTypeIn) {
     frameType = aFrame->GetType();
@@ -1081,84 +1062,73 @@ nsTableFrame::CollectRows(nsIFrame*     
       }
       childFrame = childFrame->GetNextSibling();
     }
   }
   return numRows;
 }
 
 void
-nsTableFrame::InsertRowGroups(nsIFrame* aFirstRowGroupFrame,
-                              nsIFrame* aLastRowGroupFrame)
+nsTableFrame::InsertRowGroups(const nsFrameList::Slice& aRowGroups)
 {
 #ifdef DEBUG_TABLE_CELLMAP
   printf("=== insertRowGroupsBefore\n");
   Dump(PR_TRUE, PR_FALSE, PR_TRUE);
 #endif
   nsTableCellMap* cellMap = GetCellMap();
   if (cellMap) {
     RowGroupArray orderedRowGroups;
     OrderRowGroups(orderedRowGroups);
 
     nsAutoTArray<nsTableRowFrame*, 8> rows;
     // Loop over the rowgroups and check if some of them are new, if they are
     // insert cellmaps in the order that is predefined by OrderRowGroups,
+    // XXXbz this code is O(N*M) where N is number of new rowgroups
+    // and M is number of rowgroups we have!
     PRUint32 rgIndex;
     for (rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
-      nsIFrame* kidFrame = aFirstRowGroupFrame;
-      while (kidFrame) {
-        nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(kidFrame);
+      for (nsFrameList::Enumerator rowgroups(aRowGroups); !rowgroups.AtEnd();
+           rowgroups.Next()) {
+        nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(rowgroups.get());
 
         if (orderedRowGroups[rgIndex] == rgFrame) {
           nsTableRowGroupFrame* priorRG =
             (0 == rgIndex) ? nsnull : orderedRowGroups[rgIndex - 1]; 
           // create and add the cell map for the row group
           cellMap->InsertGroupCellMap(*rgFrame, priorRG);
         
           break;
         }
-        else {
-          if (kidFrame == aLastRowGroupFrame) {
-            break;
-          }
-          kidFrame = kidFrame->GetNextSibling();
-        }
       }
     }
     cellMap->Synchronize(this);
-    ResetRowIndices(aFirstRowGroupFrame, aLastRowGroupFrame);
+    ResetRowIndices(aRowGroups);
 
     //now that the cellmaps are reordered too insert the rows
     for (rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
-      nsIFrame* kidFrame = aFirstRowGroupFrame;
-      while (kidFrame) {
-        nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(kidFrame);
+      for (nsFrameList::Enumerator rowgroups(aRowGroups); !rowgroups.AtEnd();
+           rowgroups.Next()) {
+        nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(rowgroups.get());
 
         if (orderedRowGroups[rgIndex] == rgFrame) {
           nsTableRowGroupFrame* priorRG =
             (0 == rgIndex) ? nsnull : orderedRowGroups[rgIndex - 1]; 
           // collect the new row frames in an array and add them to the table
-          PRInt32 numRows = CollectRows(kidFrame, rows);
+          PRInt32 numRows = CollectRows(rowgroups.get(), rows);
           if (numRows > 0) {
             PRInt32 rowIndex = 0;
             if (priorRG) {
               PRInt32 priorNumRows = priorRG->GetRowCount();
               rowIndex = priorRG->GetStartRowIndex() + priorNumRows;
             }
             InsertRows(*rgFrame, rows, rowIndex, PR_TRUE);
             rows.Clear();
           }
           break;
         }
-        else {
-          if (kidFrame == aLastRowGroupFrame) {
-            break;
-          }
-          kidFrame = kidFrame->GetNextSibling();
-        }
       }
     }    
     
   }
 #ifdef DEBUG_TABLE_CELLMAP
   printf("=== insertRowGroupsAfter\n");
   Dump(PR_TRUE, PR_TRUE, PR_TRUE);
 #endif
@@ -2015,20 +1985,19 @@ nsTableFrame::PushChildren(const FrameAr
     // Insert the frames after any repeated header and footer frames
     nsIFrame* firstBodyFrame = nextInFlow->GetFirstBodyRowGroupFrame();
     nsIFrame* prevSibling = nsnull;
     if (firstBodyFrame) {
       prevSibling = nextInFlow->mFrames.GetPrevSiblingFor(firstBodyFrame);
     }
     // When pushing and pulling frames we need to check for whether any
     // views need to be reparented.
-    for (nsIFrame* f = frames.FirstChild(); f; f = f->GetNextSibling()) {
-      nsHTMLContainerFrame::ReparentFrameView(PresContext(), f, this, nextInFlow);
-    }
-    nextInFlow->mFrames.InsertFrames(GetNextInFlow(), prevSibling, frames.FirstChild());
+    ReparentFrameViewList(PresContext(), frames, this, nextInFlow);
+    nextInFlow->mFrames.InsertFrames(nextInFlow, prevSibling,
+                                     frames);
   }
   else if (frames.NotEmpty()) {
     // Add the frames to our overflow list
     SetOverflowFrames(PresContext(), frames);
   }
 }
 
 // collapsing row groups, rows, col groups and cols are accounted for after both passes of
@@ -2133,135 +2102,122 @@ nsTableFrame::DidSetStyleContext(nsStyle
      }
   }
 }
 
 
 
 NS_IMETHODIMP
 nsTableFrame::AppendFrames(nsIAtom*        aListName,
-                           nsIFrame*       aFrameList)
+                           nsFrameList&    aFrameList)
 {
   NS_ASSERTION(!aListName || aListName == nsGkAtoms::colGroupList,
                "unexpected child list");
 
   // Because we actually have two child lists, one for col group frames and one
   // for everything else, we need to look at each frame individually
   // XXX The frame construction code should be separating out child frames
   // based on the type, bug 343048.
-  nsIFrame* f = aFrameList;
-  while (f) {
-    // Get the next frame and disconnect this frame from its sibling
-    nsIFrame* next = f->GetNextSibling();
-    f->SetNextSibling(nsnull);
+  while (!aFrameList.IsEmpty()) {
+    nsIFrame* f = aFrameList.FirstChild();
+    aFrameList.RemoveFrame(f);
 
     // See what kind of frame we have
     const nsStyleDisplay* display = f->GetStyleDisplay();
 
     if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay) {
-      nsTableColGroupFrame* lastColGroup;
-      PRBool doAppend = nsTableColGroupFrame::GetLastRealColGroup(this, (nsIFrame**) &lastColGroup);
+      nsTableColGroupFrame* lastColGroup =
+        nsTableColGroupFrame::GetLastRealColGroup(this);
       PRInt32 startColIndex = (lastColGroup) 
         ? lastColGroup->GetStartColumnIndex() + lastColGroup->GetColCount() : 0;
-      if (doAppend) {
-        // Append the new col group frame
-        mColGroups.AppendFrame(nsnull, f);
-      }
-      else {
-        // there is a colgroup after the last real one
-          mColGroups.InsertFrame(nsnull, lastColGroup, f);
-      }
+      mColGroups.InsertFrame(nsnull, lastColGroup, f);
       // Insert the colgroup and its cols into the table
-      InsertColGroups(startColIndex, f, f);
+      InsertColGroups(startColIndex,
+                      nsFrameList::Slice(mColGroups, f, f->GetNextSibling()));
     } else if (IsRowGroup(display->mDisplay)) {
       // Append the new row group frame to the sibling chain
       mFrames.AppendFrame(nsnull, f);
 
       // insert the row group and its rows into the table
-      InsertRowGroups(f, f);
+      InsertRowGroups(nsFrameList::Slice(mFrames, f, nsnull));
     } else {
       // Nothing special to do, just add the frame to our child list
+      NS_NOTREACHED("How did we get here?  Frame construction screwed up");
       mFrames.AppendFrame(nsnull, f);
     }
-
-    // Move to the next frame
-    f = next;
   }
 
 #ifdef DEBUG_TABLE_CELLMAP
   printf("=== TableFrame::AppendFrames\n");
   Dump(PR_TRUE, PR_TRUE, PR_TRUE);
 #endif
   PresContext()->PresShell()->FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                                                NS_FRAME_HAS_DIRTY_CHILDREN);
   SetGeometryDirty();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTableFrame::InsertFrames(nsIAtom*        aListName,
                            nsIFrame*       aPrevFrame,
-                           nsIFrame*       aFrameList)
+                           nsFrameList&    aFrameList)
 {
   // Asssume there's only one frame being inserted. The problem is that
   // row group frames and col group frames go in separate child lists and
   // so if there's more than one type of frames this gets messy...
   // XXX The frame construction code should be separating out child frames
   // based on the type, bug 343048.
  
   NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
                "inserting after sibling frame with different parent");
 
   if ((aPrevFrame && !aPrevFrame->GetNextSibling()) ||
-      (!aPrevFrame && !GetFirstChild(aListName))) {
+      (!aPrevFrame && GetChildList(aListName).IsEmpty())) {
     // Treat this like an append; still a workaround for bug 343048.
     return AppendFrames(aListName, aFrameList);
   }
 
   // See what kind of frame we have
-  const nsStyleDisplay* display = aFrameList->GetStyleDisplay();
+  const nsStyleDisplay* display = aFrameList.FirstChild()->GetStyleDisplay();
 #ifdef DEBUG
   // verify that all sibling have the same type, if they do not, expect cellmap issues
-  nsIFrame* nextFrame = aFrameList->GetNextSibling();
-  while (nextFrame) {
-    const nsStyleDisplay* nextDisplay = nextFrame->GetStyleDisplay();
+  for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
+    const nsStyleDisplay* nextDisplay = e.get()->GetStyleDisplay();
     NS_ASSERTION((display->mDisplay == NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP) ==
         (nextDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP),
       "heterogenous childlist");  
-    nextFrame = nextFrame->GetNextSibling();    
   }
 #endif  
   if (aPrevFrame) {
     const nsStyleDisplay* prevDisplay = aPrevFrame->GetStyleDisplay();
     // Make sure they belong on the same frame list
     if ((display->mDisplay == NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP) !=
         (prevDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP)) {
       // the previous frame is not valid, see comment at ::AppendFrames
       // XXXbz Using content indices here means XBL will get screwed
       // over...  Oh, well.
-      nsIFrame* pseudoFrame = aFrameList;
+      nsIFrame* pseudoFrame = aFrameList.FirstChild();
       nsIContent* parentContent = GetContent();
       nsIContent* content;
       aPrevFrame = nsnull;
       while (pseudoFrame  && (parentContent ==
                               (content = pseudoFrame->GetContent()))) {
         pseudoFrame = pseudoFrame->GetFirstChild(nsnull);
       }
       nsCOMPtr<nsIContent> container = content->GetParent();
       if (NS_LIKELY(container)) { // XXX need this null-check, see bug 411823.
         PRInt32 newIndex = container->IndexOf(content);
         nsIFrame* kidFrame;
         PRBool isColGroup = (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP ==
                              display->mDisplay);
         nsTableColGroupFrame* lastColGroup;
         if (isColGroup) {
           kidFrame = mColGroups.FirstChild();
-          nsTableColGroupFrame::GetLastRealColGroup(this,
-                                                   (nsIFrame**) &lastColGroup);
+          lastColGroup = nsTableColGroupFrame::GetLastRealColGroup(this);
         }
         else {
           kidFrame = mFrames.FirstChild();
         }
         // Important: need to start at a value smaller than all valid indices
         PRInt32 lastIndex = -1;
         while (kidFrame) {
           if (isColGroup) {
@@ -2283,41 +2239,40 @@ nsTableFrame::InsertFrames(nsIAtom*     
           kidFrame = kidFrame->GetNextSibling();
         }
       }
     }
   }
   if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay) {
     NS_ASSERTION(!aListName || aListName == nsGkAtoms::colGroupList,
                  "unexpected child list");
-    // Insert the column group frame
-    nsFrameList frames(aFrameList); // convience for getting last frame
-    nsIFrame* lastFrame = frames.LastChild();
-    mColGroups.InsertFrames(nsnull, aPrevFrame, aFrameList);
+    // Insert the column group frames
+    const nsFrameList::Slice& newColgroups =
+      mColGroups.InsertFrames(nsnull, aPrevFrame, aFrameList);
     // find the starting col index for the first new col group
     PRInt32 startColIndex = 0;
     if (aPrevFrame) {
       nsTableColGroupFrame* prevColGroup = 
         (nsTableColGroupFrame*)GetFrameAtOrBefore(this, aPrevFrame,
                                                   nsGkAtoms::tableColGroupFrame);
       if (prevColGroup) {
         startColIndex = prevColGroup->GetStartColumnIndex() + prevColGroup->GetColCount();
       }
     }
-    InsertColGroups(startColIndex, aFrameList, lastFrame);
+    InsertColGroups(startColIndex, newColgroups);
   } else if (IsRowGroup(display->mDisplay)) {
     NS_ASSERTION(!aListName, "unexpected child list");
-    nsFrameList newList(aFrameList);
-    nsIFrame* lastSibling = newList.LastChild();
     // Insert the frames in the sibling chain
-    mFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
-
-    InsertRowGroups(aFrameList, lastSibling);
+    const nsFrameList::Slice& newRowGroups =
+      mFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
+
+    InsertRowGroups(newRowGroups);
   } else {
     NS_ASSERTION(!aListName, "unexpected child list");
+    NS_NOTREACHED("How did we even get here?");
     // Just insert the frame and don't worry about reflowing it
     mFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
     return NS_OK;
   }
 
   PresContext()->PresShell()->FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                                                NS_FRAME_HAS_DIRTY_CHILDREN);
   SetGeometryDirty();
@@ -2372,17 +2327,18 @@ nsTableFrame::RemoveFrame(nsIAtom*      
       }
 
        // remove the row group frame from the sibling chain
       mFrames.DestroyFrame(aOldFrame);
      
       // XXXldb [reflow branch merging 20060830] do we still need this?
       if (cellMap) {
         cellMap->Synchronize(this);
-        ResetRowIndices();
+        // Create an empty slice
+        ResetRowIndices(nsFrameList::Slice(mFrames, nsnull, nsnull));
         nsRect damageArea;
         cellMap->RebuildConsideringCells(nsnull, nsnull, 0, 0, PR_FALSE, damageArea);
       }
 
       MatchCellMapToColCache(cellMap);
     } else {
       // Just remove the frame
       mFrames.DestroyFrame(aOldFrame);
--- a/layout/tables/nsTableFrame.h
+++ b/layout/tables/nsTableFrame.h
@@ -195,20 +195,20 @@ public:
 
   /** @see nsIFrame::Destroy */
   virtual void Destroy();
   
   /** @see nsIFrame::DidSetStyleContext */
   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
 
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
 
   virtual nsMargin GetUsedBorder() const;
   virtual nsMargin GetUsedPadding() const;
 
   // Get the offset from the border box to the area where the row groups fit
   nsMargin GetChildAreaOffset(const nsHTMLReflowState* aReflowState) const;
@@ -494,32 +494,22 @@ public:
                      PRInt32                     aRowIndex,
                      PRBool                      aConsiderSpans);
 
   virtual void RemoveRows(nsTableRowFrame& aFirstRowFrame,
                           PRInt32          aNumRowsToRemove,
                           PRBool           aConsiderSpans);
 
   /** Insert multiple rowgroups into the table cellmap handling
-    * @param aFirstRowGroupFrame - first row group to be inserted all siblings
-    *                              will be appended too.
+    * @param aRowGroups - iterator that iterates over the rowgroups to insert
     */
-  void AppendRowGroups(nsIFrame* aFirstRowGroupFrame);
+  void InsertRowGroups(const nsFrameList::Slice& aRowGroups);
 
-  /** Insert multiple rowgroups into the table cellmap handling
-    * @param aFirstRowGroupFrame - first row group to be inserted
-    * @param aLastRowGroupFrame  - when inserting the siblings of 
-    *                              aFirstRowGroupFrame stop at this row group
-    */
-  void InsertRowGroups(nsIFrame*       aFirstRowGroupFrame,
-                       nsIFrame*       aLastRowGroupFrame);
-
-  void InsertColGroups(PRInt32         aColIndex,
-                       nsIFrame*       aFirstFrame,
-                       nsIFrame*       aLastFrame = nsnull);
+  void InsertColGroups(PRInt32                   aStartColIndex,
+                       const nsFrameList::Slice& aColgroups);
 
   virtual void RemoveCol(nsTableColGroupFrame* aColGroupFrame,
                          PRInt32               aColIndex,
                          PRBool                aRemoveFromCache,
                          PRBool                aRemoveFromCellMap);
 
   NS_IMETHOD GetIndexByRowAndColumn(PRInt32 aRow, PRInt32 aColumn, PRInt32 *aIndex);
   NS_IMETHOD GetRowAndColumnByIndex(PRInt32 aIndex, PRInt32 *aRow, PRInt32 *aColumn);
@@ -740,23 +730,20 @@ public:
     * @param aAdjustment - shift the row index by this amount
     */
   void AdjustRowIndices(PRInt32 aRowIndex,
                         PRInt32 aAdjustment);
 
   /** Reset the rowindices of all rows as they might have changed due to 
     * rowgroup reordering, exclude new row group frames that show in the
     * reordering but are not yet inserted into the cellmap
-    * @param aFirstRowGroupFrame - first row group to be excluded
-    * @param aLastRowGroupFrame  - last sibling of aFirstRowGroupFrame that
-    *                              should be excluded when reseting the row
-    *                              indices.
+    * @param aRowGroupsToExclude - an iterator that will produce the row groups
+    *                              to exclude.
     */
-  void ResetRowIndices(nsIFrame* aFirstRowGroupFrame = nsnull,
-                       nsIFrame* aLastRowGroupFrame = nsnull);
+  void ResetRowIndices(const nsFrameList::Slice& aRowGroupsToExclude);
 
   nsTArray<nsTableColFrame*>& GetColCache();
 
   /** Return aFrame's child if aFrame is an nsScrollFrame, otherwise return aFrame
     */
   static nsTableRowGroupFrame* GetRowGroupFrame(nsIFrame* aFrame,
                                                 nsIAtom*  aFrameTypeIn = nsnull);
 
--- a/layout/tables/nsTableOuterFrame.cpp
+++ b/layout/tables/nsTableOuterFrame.cpp
@@ -261,25 +261,25 @@ nsTableOuterFrame::SetInitialChildList(n
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTableOuterFrame::AppendFrames(nsIAtom*        aListName,
-                                nsIFrame*       aFrameList)
+                                nsFrameList&    aFrameList)
 {
   nsresult rv;
 
   // We only have two child frames: the inner table and a caption frame.
   // The inner frame is provided when we're initialized, and it cannot change
   if (nsGkAtoms::captionList == aListName) {
-    NS_ASSERTION(!aFrameList ||
-                 aFrameList->GetType() == nsGkAtoms::tableCaptionFrame,
+    NS_ASSERTION(aFrameList.IsEmpty() ||
+                 aFrameList.FirstChild()->GetType() == nsGkAtoms::tableCaptionFrame,
                  "appending non-caption frame to captionList");
     mCaptionFrames.AppendFrames(this, aFrameList);
     mCaptionFrame = mCaptionFrames.FirstChild();
     rv = NS_OK;
 
     // Reflow the new caption frame. It's already marked dirty, so
     // just tell the pres shell.
     PresContext()->PresShell()->
@@ -292,23 +292,23 @@ nsTableOuterFrame::AppendFrames(nsIAtom*
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsTableOuterFrame::InsertFrames(nsIAtom*        aListName,
                                 nsIFrame*       aPrevFrame,
-                                nsIFrame*       aFrameList)
+                                nsFrameList&    aFrameList)
 {
   if (nsGkAtoms::captionList == aListName) {
     NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
                  "inserting after sibling frame with different parent");
-    NS_ASSERTION(!aFrameList ||
-                 aFrameList->GetType() == nsGkAtoms::tableCaptionFrame,
+    NS_ASSERTION(aFrameList.IsEmpty() ||
+                 aFrameList.FirstChild()->GetType() == nsGkAtoms::tableCaptionFrame,
                  "inserting non-caption frame into captionList");
     mCaptionFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
     mCaptionFrame = mCaptionFrames.FirstChild();
 
     // Reflow the new caption frame. It's already marked dirty, so
     // just tell the pres shell.
     PresContext()->PresShell()->
       FrameNeedsReflow(this, nsIPresShell::eTreeChange,
--- a/layout/tables/nsTableOuterFrame.h
+++ b/layout/tables/nsTableOuterFrame.h
@@ -105,21 +105,21 @@ public:
   NS_IMETHOD SetInitialChildList(nsIAtom*        aListName,
                                  nsFrameList&    aChildList);
  
   virtual nsFrameList GetChildList(nsIAtom* aListName) const;
 
   virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
 
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
 
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
 
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
 
   virtual nsIFrame* GetContentInsertionFrame() {
     return GetFirstChild(nsnull)->GetContentInsertionFrame();
   }
 
--- a/layout/tables/nsTableRowFrame.cpp
+++ b/layout/tables/nsTableRowFrame.cpp
@@ -194,28 +194,29 @@ nsTableRowFrame::DidSetStyleContext(nsSt
     nsRect damageArea(0, GetRowIndex(), tableFrame->GetColCount(), 1);
     tableFrame->SetBCDamageArea(damageArea);
   }
   return;
 }
 
 NS_IMETHODIMP
 nsTableRowFrame::AppendFrames(nsIAtom*        aListName,
-                              nsIFrame*       aFrameList)
+                              nsFrameList&    aFrameList)
 {
   NS_ASSERTION(!aListName, "unexpected child list");
 
   // Append the frames
-  mFrames.AppendFrames(nsnull, aFrameList);
+  // XXXbz why do we append here first, then append to table, while
+  // for InsertFrames we do it in the other order?  Bug 507419 covers this.
+  const nsFrameList::Slice& newCells = mFrames.AppendFrames(nsnull, aFrameList);
 
   // Add the new cell frames to the table
   nsTableFrame *tableFrame =  nsTableFrame::GetTableFrame(this);
-  for (nsIFrame* childFrame = aFrameList; childFrame;
-       childFrame = childFrame->GetNextSibling()) {
-    nsTableCellFrame *cellFrame = do_QueryFrame(childFrame);
+  for (nsFrameList::Enumerator e(newCells) ; !e.AtEnd(); e.Next()) {
+    nsTableCellFrame *cellFrame = do_QueryFrame(e.get());
     NS_ASSERTION(cellFrame, "Unexpected frame");
     if (cellFrame) {
       // Add the cell to the cell map
       tableFrame->AppendCell(*cellFrame, GetRowIndex());
     }
   }
 
   PresContext()->PresShell()->FrameNeedsReflow(this, nsIPresShell::eTreeChange,
@@ -224,32 +225,33 @@ nsTableRowFrame::AppendFrames(nsIAtom*  
 
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
 nsTableRowFrame::InsertFrames(nsIAtom*        aListName,
                               nsIFrame*       aPrevFrame,
-                              nsIFrame*       aFrameList)
+                              nsFrameList&    aFrameList)
 {
   NS_ASSERTION(!aListName, "unexpected child list");
   NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
                "inserting after sibling frame with different parent");
 
   // Get the table frame
   nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
   
   // gather the new frames (only those which are cells) into an array
+  // XXXbz there shouldn't be any other ones here... can we just put
+  // them all in the array and not do all this QI nonsense?
   nsIAtom* cellFrameType = (tableFrame->IsBorderCollapse()) ? nsGkAtoms::bcTableCellFrame : nsGkAtoms::tableCellFrame;
   nsTableCellFrame* prevCellFrame = (nsTableCellFrame *)nsTableFrame::GetFrameAtOrBefore(this, aPrevFrame, cellFrameType);
   nsTArray<nsTableCellFrame*> cellChildren;
-  for (nsIFrame* childFrame = aFrameList; childFrame;
-       childFrame = childFrame->GetNextSibling()) {
-    nsTableCellFrame *cellFrame = do_QueryFrame(childFrame);
+  for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
+    nsTableCellFrame *cellFrame = do_QueryFrame(e.get());
     NS_ASSERTION(cellFrame, "Unexpected frame");
     if (cellFrame) {
       cellChildren.AppendElement(cellFrame);
     }
   }
   // insert the cells into the cell map
   PRInt32 colIndex = -1;
   if (prevCellFrame) {
--- a/layout/tables/nsTableRowFrame.h
+++ b/layout/tables/nsTableRowFrame.h
@@ -75,20 +75,20 @@ public:
 
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
   /** @see nsIFrame::DidSetStyleContext */
   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
   
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
 
   /** instantiate a new instance of nsTableRowFrame.
     * @param aPresShell the pres shell for this frame
     *
     * @return           the frame that was created
     */
--- a/layout/tables/nsTableRowGroupFrame.cpp
+++ b/layout/tables/nsTableRowGroupFrame.cpp
@@ -1385,30 +1385,31 @@ nsTableRowGroupFrame::DidSetStyleContext
                       GetRowCount());
     tableFrame->SetBCDamageArea(damageArea);
   }
   return;
 }
 
 NS_IMETHODIMP
 nsTableRowGroupFrame::AppendFrames(nsIAtom*        aListName,
-                                   nsIFrame*       aFrameList)
+                                   nsFrameList&    aFrameList)
 {
   NS_ASSERTION(!aListName, "unexpected child list");
 
   ClearRowCursor();
 
   // collect the new row frames in an array
+  // XXXbz why are we doing the QI stuff?  There shouldn't be any non-rows here.
   nsAutoTArray<nsTableRowFrame*, 8> rows;
-  for (nsIFrame* childFrame = aFrameList; childFrame;
-       childFrame = childFrame->GetNextSibling()) {
-    nsTableRowFrame *rowFrame = do_QueryFrame(childFrame);
+  for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
+    nsTableRowFrame *rowFrame = do_QueryFrame(e.get());
+    NS_ASSERTION(rowFrame, "Unexpected frame; frame constructor screwed up");
     if (rowFrame) {
       NS_ASSERTION(NS_STYLE_DISPLAY_TABLE_ROW ==
-                     childFrame->GetStyleDisplay()->mDisplay,
+                     e.get()->GetStyleDisplay()->mDisplay,
                    "wrong display type on rowframe");      
       rows.AppendElement(rowFrame);
     }
   }
 
   PRInt32 rowIndex = GetRowCount();
   // Append the frames to the sibling chain
   mFrames.AppendFrames(nsnull, aFrameList);
@@ -1425,37 +1426,38 @@ nsTableRowGroupFrame::AppendFrames(nsIAt
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTableRowGroupFrame::InsertFrames(nsIAtom*        aListName,
                                    nsIFrame*       aPrevFrame,
-                                   nsIFrame*       aFrameList)
+                                   nsFrameList&    aFrameList)
 {
   NS_ASSERTION(!aListName, "unexpected child list");
   NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
                "inserting after sibling frame with different parent");
 
   ClearRowCursor();
 
   nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
   if (!tableFrame)
     return NS_ERROR_NULL_POINTER;
 
   // collect the new row frames in an array
+  // XXXbz why are we doing the QI stuff?  There shouldn't be any non-rows here.
   nsTArray<nsTableRowFrame*> rows;
   PRBool gotFirstRow = PR_FALSE;
-  for (nsIFrame* childFrame = aFrameList; childFrame;
-       childFrame = childFrame->GetNextSibling()) {
-    nsTableRowFrame *rowFrame = do_QueryFrame(childFrame);
+  for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
+    nsTableRowFrame *rowFrame = do_QueryFrame(e.get());
+    NS_ASSERTION(rowFrame, "Unexpected frame; frame constructor screwed up");
     if (rowFrame) {
       NS_ASSERTION(NS_STYLE_DISPLAY_TABLE_ROW ==
-                     childFrame->GetStyleDisplay()->mDisplay,
+                     e.get()->GetStyleDisplay()->mDisplay,
                    "wrong display type on rowframe");      
       rows.AppendElement(rowFrame);
       if (!gotFirstRow) {
         rowFrame->SetFirstInserted(PR_TRUE);
         gotFirstRow = PR_TRUE;
         tableFrame->SetRowInserted(PR_TRUE);
       }
     }
--- a/layout/tables/nsTableRowGroupFrame.h
+++ b/layout/tables/nsTableRowGroupFrame.h
@@ -106,21 +106,21 @@ public:
     * @return           the frame that was created
     */
   friend nsIFrame* NS_NewTableRowGroupFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   virtual ~nsTableRowGroupFrame();
   /** @see nsIFrame::DidSetStyleContext */
   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
   
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
 
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
 
   virtual nsMargin GetUsedMargin() const;
   virtual nsMargin GetUsedBorder() const;
   virtual nsMargin GetUsedPadding() const;
 
--- a/layout/xul/base/src/grid/nsGridLayout2.cpp
+++ b/layout/xul/base/src/grid/nsGridLayout2.cpp
@@ -255,24 +255,25 @@ nsMargin
 nsGridLayout2::GetTotalMargin(nsIBox* aBox, PRBool aIsHorizontal)
 {
   nsMargin margin(0,0,0,0);
   return margin;
 }
 
 void
 nsGridLayout2::ChildrenInserted(nsIBox* aBox, nsBoxLayoutState& aState,
-                                nsIBox* aPrevBox, nsIBox* aChildList)
+                                nsIBox* aPrevBox,
+                                const nsFrameList::Slice& aNewChildren)
 {
   mGrid.NeedsRebuild(aState);
 }
 
 void
 nsGridLayout2::ChildrenAppended(nsIBox* aBox, nsBoxLayoutState& aState,
-                                nsIBox* aChildList)
+                                const nsFrameList::Slice& aNewChildren)
 {
   mGrid.NeedsRebuild(aState);
 }
 
 void
 nsGridLayout2::ChildrenRemoved(nsIBox* aBox, nsBoxLayoutState& aState,
                                nsIBox* aChildList)
 {
--- a/layout/xul/base/src/grid/nsGridLayout2.h
+++ b/layout/xul/base/src/grid/nsGridLayout2.h
@@ -75,19 +75,20 @@ public:
   virtual nsSize GetMaxSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState);
   virtual nsSize GetPrefSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState);
   virtual void CountRowsColumns(nsIBox* aBox, PRInt32& aRowCount, PRInt32& aComputedColumnCount) { aRowCount++; }
   virtual void DirtyRows(nsIBox* aBox, nsBoxLayoutState& aState) { }
   virtual PRInt32 BuildRows(nsIBox* aBox, nsGridRow* aRows);
   virtual nsMargin GetTotalMargin(nsIBox* aBox, PRBool aIsHorizontal);
   virtual Type GetType() { return eGrid; }
   virtual void ChildrenInserted(nsIBox* aBox, nsBoxLayoutState& aState,
-                              nsIBox* aPrevBox, nsIBox* aChildList);
+                                nsIBox* aPrevBox,
+                                const nsFrameList::Slice& aNewChildren);
   virtual void ChildrenAppended(nsIBox* aBox, nsBoxLayoutState& aState,
-                              nsIBox* aChildList);
+                                const nsFrameList::Slice& aNewChildren);
   virtual void ChildrenRemoved(nsIBox* aBox, nsBoxLayoutState& aState,
                              nsIBox* aChildList);
   virtual void ChildrenSet(nsIBox* aBox, nsBoxLayoutState& aState,
                          nsIBox* aChildList);
 protected:
 
   nsGridLayout2(nsIPresShell* aShell);
   nsGrid mGrid;
--- a/layout/xul/base/src/grid/nsGridRowLayout.cpp
+++ b/layout/xul/base/src/grid/nsGridRowLayout.cpp
@@ -49,23 +49,26 @@
 #include "nsStackLayout.h"
 #include "nsGrid.h"
 
 nsGridRowLayout::nsGridRowLayout():nsSprocketLayout()
 {
 }
 
 void
-nsGridRowLayout::ChildrenInserted(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aPrevBox, nsIBox* aChildList)
+nsGridRowLayout::ChildrenInserted(nsIBox* aBox, nsBoxLayoutState& aState,
+                                  nsIBox* aPrevBox,
+                                  const nsFrameList::Slice& aNewChildren)
 {
   ChildAddedOrRemoved(aBox, aState);
 }
 
 void
-nsGridRowLayout::ChildrenAppended(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aChildList)
+nsGridRowLayout::ChildrenAppended(nsIBox* aBox, nsBoxLayoutState& aState,
+                                  const nsFrameList::Slice& aNewChildren)
 {
   ChildAddedOrRemoved(aBox, aState);
 }
 
 void
 nsGridRowLayout::ChildrenRemoved(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aChildList)
 {
   ChildAddedOrRemoved(aBox, aState);
--- a/layout/xul/base/src/grid/nsGridRowLayout.h
+++ b/layout/xul/base/src/grid/nsGridRowLayout.h
@@ -65,18 +65,21 @@ class nsGridRowLayout : public nsSprocke
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
   virtual nsGridRowGroupLayout* CastToRowGroupLayout() { return nsnull; }
   virtual nsGridLayout2* CastToGridLayout() { return nsnull; }
   virtual nsGrid* GetGrid(nsIBox* aBox, PRInt32* aIndex, nsGridRowLayout* aRequestor=nsnull);
   virtual void GetParentGridPart(nsIBox* aBox, nsIBox** aParentBox, nsIGridPart** aParentGridRow);
-  virtual void ChildrenInserted(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aPrevBox, nsIBox* aChildList);
-  virtual void ChildrenAppended(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aChildList);
+  virtual void ChildrenInserted(nsIBox* aBox, nsBoxLayoutState& aState,
+                                nsIBox* aPrevBox,
+                                const nsFrameList::Slice& aNewChildren);
+  virtual void ChildrenAppended(nsIBox* aBox, nsBoxLayoutState& aState,
+                                const nsFrameList::Slice& aNewChildren);
   virtual void ChildrenRemoved(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aChildList);
   virtual void ChildrenSet(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aChildList);
   virtual nsMargin GetTotalMargin(nsIBox* aBox, PRBool aIsHorizontal);
 
 protected:
   virtual void ChildAddedOrRemoved(nsIBox* aBox, nsBoxLayoutState& aState)=0;
 
   nsGridRowLayout();
--- a/layout/xul/base/src/nsBoxFrame.cpp
+++ b/layout/xul/base/src/nsBoxFrame.cpp
@@ -1031,58 +1031,59 @@ nsBoxFrame::RemoveFrame(nsIAtom*        
     FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                      NS_FRAME_HAS_DIRTY_CHILDREN);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsBoxFrame::InsertFrames(nsIAtom*        aListName,
                          nsIFrame*       aPrevFrame,
-                         nsIFrame*       aFrameList)
+                         nsFrameList&    aFrameList)
 {
    NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
                 "inserting after sibling frame with different parent");
    NS_ASSERTION(!aPrevFrame || mFrames.ContainsFrame(aPrevFrame),
                 "inserting after sibling frame not in our child list");
    NS_PRECONDITION(!aListName, "We don't support out-of-flow kids");
    nsBoxLayoutState state(PresContext());
 
    // insert the child frames
-   mFrames.InsertFrames(this, aPrevFrame, aFrameList);
+   const nsFrameList::Slice& newFrames =
+     mFrames.InsertFrames(this, aPrevFrame, aFrameList);
 
    // notify the layout manager
    if (mLayoutManager)
-     mLayoutManager->ChildrenInserted(this, state, aPrevFrame, aFrameList);
+     mLayoutManager->ChildrenInserted(this, state, aPrevFrame, newFrames);
 
 #ifdef DEBUG_LAYOUT
    // if we are in debug make sure our children are in debug as well.
    if (mState & NS_STATE_CURRENTLY_IN_DEBUG)
        SetDebugOnChildList(state, mFrames.FirstChild(), PR_TRUE);
 #endif
 
    PresContext()->PresShell()->
      FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                       NS_FRAME_HAS_DIRTY_CHILDREN);
    return NS_OK;
 }
 
 
 NS_IMETHODIMP
 nsBoxFrame::AppendFrames(nsIAtom*        aListName,
-                         nsIFrame*       aFrameList)
+                         nsFrameList&    aFrameList)
 {
    NS_PRECONDITION(!aListName, "We don't support out-of-flow kids");
    nsBoxLayoutState state(PresContext());
 
    // append the new frames
-   mFrames.AppendFrames(this, aFrameList);
+   const nsFrameList::Slice& newFrames = mFrames.AppendFrames(this, aFrameList);
 
    // notify the layout manager
    if (mLayoutManager)
-     mLayoutManager->ChildrenAppended(this, state, aFrameList);
+     mLayoutManager->ChildrenAppended(this, state, newFrames);
 
 #ifdef DEBUG_LAYOUT
    // if we are in debug make sure our children are in debug as well.
    if (mState & NS_STATE_CURRENTLY_IN_DEBUG)
        SetDebugOnChildList(state, mFrames.FirstChild(), PR_TRUE);
 #endif
 
    // XXXbz why is this NS_FRAME_FIRST_REFLOW check here?
--- a/layout/xul/base/src/nsBoxFrame.h
+++ b/layout/xul/base/src/nsBoxFrame.h
@@ -124,21 +124,21 @@ public:
   virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
 
   NS_IMETHOD Reflow(nsPresContext*          aPresContext,
                     nsHTMLReflowMetrics&     aDesiredSize,
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus&          aStatus);
 
   NS_IMETHOD  AppendFrames(nsIAtom*        aListName,
-                           nsIFrame*       aFrameList);
+                           nsFrameList&    aFrameList);
 
   NS_IMETHOD  InsertFrames(nsIAtom*        aListName,
                            nsIFrame*       aPrevFrame,
-                           nsIFrame*       aFrameList);
+                           nsFrameList&    aFrameList);
 
   NS_IMETHOD  RemoveFrame(nsIAtom*        aListName,
                           nsIFrame*       aOldFrame);
 
   virtual nsIFrame* GetContentInsertionFrame();
 
   NS_IMETHOD  SetInitialChildList(nsIAtom*        aListName,
                                   nsFrameList&    aChildList);
--- a/layout/xul/base/src/nsBoxLayout.cpp
+++ b/layout/xul/base/src/nsBoxLayout.cpp
@@ -141,22 +141,25 @@ nsBoxLayout::AddSmallestSize(nsSize& aSi
   if (aSize2.width < aSize.width)
      aSize.width = aSize2.width;
 
   if (aSize2.height < aSize.height)
      aSize.height = aSize2.height;
 }
 
 void
-nsBoxLayout::ChildrenInserted(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aPrevBox, nsIBox* aChildList)
+nsBoxLayout::ChildrenInserted(nsIBox* aBox, nsBoxLayoutState& aState,
+                              nsIBox* aPrevBox,
+                              const nsFrameList::Slice& aNewChildren)
 {
 }
 
 void
-nsBoxLayout::ChildrenAppended(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aChildList)
+nsBoxLayout::ChildrenAppended(nsIBox* aBox, nsBoxLayoutState& aState,
+                              const nsFrameList::Slice& aNewChildren)
 {
 }
 
 void
 nsBoxLayout::ChildrenRemoved(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aChildList)
 {
 }
 
--- a/layout/xul/base/src/nsBoxLayout.h
+++ b/layout/xul/base/src/nsBoxLayout.h
@@ -50,18 +50,21 @@ public:
   NS_DECL_ISUPPORTS
 
   NS_IMETHOD Layout(nsIBox* aBox, nsBoxLayoutState& aState);
 
   virtual nsSize GetPrefSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState);
   virtual nsSize GetMinSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState);
   virtual nsSize GetMaxSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState);
   virtual nscoord GetAscent(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState);
-  virtual void ChildrenInserted(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aPrevBox, nsIBox* aChildList);
-  virtual void ChildrenAppended(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aChildList);
+  virtual void ChildrenInserted(nsIBox* aBox, nsBoxLayoutState& aState,
+                                nsIBox* aPrevBox,
+                                const nsFrameList::Slice& aNewChildren);
+  virtual void ChildrenAppended(nsIBox* aBox, nsBoxLayoutState& aState,
+                                const nsFrameList::Slice& aNewChildren);
   virtual void ChildrenRemoved(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aChildList);
   virtual void ChildrenSet(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aChildList);
   virtual void IntrinsicWidthsDirty(nsIBox* aBox, nsBoxLayoutState& aState);
 
   virtual void GetParentLayout(nsIBox* aBox, nsIBoxLayout** aParent);
   virtual void AddBorderAndPadding(nsIBox* aBox, nsSize& aSize);
   virtual void AddMargin(nsIBox* aChild, nsSize& aSize);
   virtual void AddMargin(nsSize& aSize, const nsMargin& aMargin);
--- a/layout/xul/base/src/nsIBoxLayout.h
+++ b/layout/xul/base/src/nsIBoxLayout.h
@@ -42,36 +42,41 @@
 #include "nsIFrame.h"
 
 class nsPresContext;
 class nsBoxLayout;
 class nsBoxLayoutState;
 class nsIRenderingContext;
 struct nsRect;
 
-// c9bf9fe7-a2f4-4f38-bbed-11a05633d676
+// 6a529924-c73d-4fae-af7a-0e8084e701d5
 #define NS_IBOX_LAYOUT_IID \
-{ 0xc9bf9fe7, 0xa2f4, 0x4f38, \
-  { 0xbb, 0xed, 0x11, 0xa0, 0x56, 0x33, 0xd6, 0x76 } }
+{ 0x6a529924, 0xc73d, 0x4fae, \
+ { 0xaf, 0x7a, 0x0e, 0x80, 0x84, 0xe7, 0x01, 0xd5 } }
 
 class nsIBoxLayout : public nsISupports {
 
 public:
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IBOX_LAYOUT_IID)
 
   NS_IMETHOD Layout(nsIBox* aBox, nsBoxLayoutState& aState)=0;
 
   virtual nsSize GetPrefSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState)=0;
   virtual nsSize GetMinSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState)=0;
   virtual nsSize GetMaxSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState)=0;
   virtual nscoord GetAscent(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState)=0;
 
-  virtual void ChildrenInserted(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aPrevBox, nsIBox* aChildList)=0;
-  virtual void ChildrenAppended(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aChildList)=0;
+  // FIXME: Bug 507416.  The Children* notifications don't actually
+  // use all those arguments.  Can we just simplify the signatures?
+  virtual void ChildrenInserted(nsIBox* aBox, nsBoxLayoutState& aState,
+                                nsIBox* aPrevBox,
+                                const nsFrameList::Slice& aNewChildren)=0;
+  virtual void ChildrenAppended(nsIBox* aBox, nsBoxLayoutState& aState,
+                                const nsFrameList::Slice& aNewChildren)=0;
   virtual void ChildrenRemoved(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aChildList)=0;
   virtual void ChildrenSet(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aChildList)=0;
   virtual void IntrinsicWidthsDirty(nsIBox* aBox, nsBoxLayoutState& aState)=0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIBoxLayout, NS_IBOX_LAYOUT_IID)
 
 #endif
--- a/layout/xul/base/src/nsListBoxBodyFrame.cpp
+++ b/layout/xul/base/src/nsListBoxBodyFrame.cpp
@@ -1305,38 +1305,40 @@ nsListBoxBodyFrame::ContinueReflow(nscoo
     }
     return PR_FALSE;
   }
   else
     return PR_TRUE;
 }
 
 NS_IMETHODIMP
-nsListBoxBodyFrame::ListBoxAppendFrames(nsIFrame* aFrameList)
+nsListBoxBodyFrame::ListBoxAppendFrames(nsFrameList& aFrameList)
 {
   // append them after
   nsBoxLayoutState state(PresContext());
-  mFrames.AppendFrames(nsnull, aFrameList);
+  const nsFrameList::Slice& newFrames = mFrames.AppendFrames(nsnull, aFrameList);
   if (mLayoutManager)
-    mLayoutManager->ChildrenAppended(this, state, aFrameList);
+    mLayoutManager->ChildrenAppended(this, state, newFrames);
   PresContext()->PresShell()->
     FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                      NS_FRAME_HAS_DIRTY_CHILDREN);
   
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsListBoxBodyFrame::ListBoxInsertFrames(nsIFrame* aPrevFrame, nsIFrame* aFrameList)
+nsListBoxBodyFrame::ListBoxInsertFrames(nsIFrame* aPrevFrame,
+                                        nsFrameList& aFrameList)
 {
   // insert the frames to our info list
   nsBoxLayoutState state(PresContext());
-  mFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
+  const nsFrameList::Slice& newFrames =
+    mFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
   if (mLayoutManager)
-    mLayoutManager->ChildrenInserted(this, state, aPrevFrame, aFrameList);
+    mLayoutManager->ChildrenInserted(this, state, aPrevFrame, newFrames);
   PresContext()->PresShell()->
     FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                      NS_FRAME_HAS_DIRTY_CHILDREN);
 
   return NS_OK;
 }
 
 // 
--- a/layout/xul/base/src/nsListBoxBodyFrame.h
+++ b/layout/xul/base/src/nsListBoxBodyFrame.h
@@ -131,18 +131,18 @@ public:
 
   // lazy row creation and destruction
   void CreateRows();
   void DestroyRows(PRInt32& aRowsToLose);
   void ReverseDestroyRows(PRInt32& aRowsToLose);
   nsIBox* GetFirstItemBox(PRInt32 aOffset, PRBool* aCreated);
   nsIBox* GetNextItemBox(nsIBox* aBox, PRInt32 aOffset, PRBool* aCreated);
   PRBool ContinueReflow(nscoord height);
-  NS_IMETHOD ListBoxAppendFrames(nsIFrame* aFrameList);
-  NS_IMETHOD ListBoxInsertFrames(nsIFrame* aPrevFrame, nsIFrame* aFrameList);
+  NS_IMETHOD ListBoxAppendFrames(nsFrameList& aFrameList);
+  NS_IMETHOD ListBoxInsertFrames(nsIFrame* aPrevFrame, nsFrameList& aFrameList);
   void OnContentInserted(nsPresContext* aPresContext, nsIContent* aContent);
   void OnContentRemoved(nsPresContext* aPresContext,  nsIFrame* aChildFrame, PRInt32 aIndex);
 
   void GetListItemContentAt(PRInt32 aIndex, nsIContent** aContent);
   void GetListItemNextSibling(nsIContent* aListItem, nsIContent** aContent, PRInt32& aSiblingIndex);
 
   void PostReflowCallback();
 
--- a/layout/xul/base/src/nsMenuFrame.cpp
+++ b/layout/xul/base/src/nsMenuFrame.cpp
@@ -329,25 +329,16 @@ nsFrameList
 nsMenuFrame::GetChildList(nsIAtom* aListName) const
 {
   if (nsGkAtoms::popupList == aListName) {
     return mPopupFrame;
   }
   return nsBoxFrame::GetChildList(aListName);
 }
 
-nsIFrame*
-nsMenuFrame::SetPopupFrame(nsIFrame* aChildList)
-{
-  // Check for a menupopup and move it to mPopupFrame
-  nsFrameList frames(aChildList);
-  SetPopupFrame(frames);
-  return frames.FirstChild();
-}
-
 void
 nsMenuFrame::SetPopupFrame(nsFrameList& aFrameList)
 {
   for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
     if (e.get()->GetType() == nsGkAtoms::menuPopupFrame) {
       // Remove this frame from the list and set it as mPopupFrame
       mPopupFrame = (nsMenuPopupFrame *)e.get();
       aFrameList.RemoveFrame(e.get());
@@ -1209,69 +1200,61 @@ nsMenuFrame::RemoveFrame(nsIAtom*       
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsMenuFrame::InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
-                          nsIFrame*       aFrameList)
+                          nsFrameList&    aFrameList)
 {
   if (!mPopupFrame && (!aListName || aListName == nsGkAtoms::popupList)) {
-    aFrameList = SetPopupFrame(aFrameList);
+    SetPopupFrame(aFrameList);
     if (mPopupFrame) {
-
 #ifdef DEBUG_LAYOUT
       nsBoxLayoutState state(PresContext());
       SetDebug(state, aFrameList, mState & NS_STATE_CURRENTLY_IN_DEBUG);
 #endif
 
       PresContext()->PresShell()->
         FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                          NS_FRAME_HAS_DIRTY_CHILDREN);
-
-      return NS_OK;
     }
   }
 
-  if (!aFrameList)
+  if (aFrameList.IsEmpty())
     return NS_OK;
 
   if (NS_UNLIKELY(aPrevFrame == mPopupFrame)) {
     aPrevFrame = nsnull;
   }
 
   return nsBoxFrame::InsertFrames(aListName, aPrevFrame, aFrameList);
 }
 
 NS_IMETHODIMP
 nsMenuFrame::AppendFrames(nsIAtom*        aListName,
-                          nsIFrame*       aFrameList)
+                          nsFrameList&    aFrameList)
 {
-  if (!aFrameList)
-    return NS_OK;
-
   if (!mPopupFrame && (!aListName || aListName == nsGkAtoms::popupList)) {
-    aFrameList = SetPopupFrame(aFrameList);
+    SetPopupFrame(aFrameList);
     if (mPopupFrame) {
 
 #ifdef DEBUG_LAYOUT
       nsBoxLayoutState state(PresContext());
       SetDebug(state, aFrameList, mState & NS_STATE_CURRENTLY_IN_DEBUG);
 #endif
       PresContext()->PresShell()->
         FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                          NS_FRAME_HAS_DIRTY_CHILDREN);
-
-      return NS_OK;
     }
   }
 
-  if (!aFrameList)
+  if (aFrameList.IsEmpty())
     return NS_OK;
 
   return nsBoxFrame::AppendFrames(aListName, aFrameList); 
 }
 
 PRBool
 nsMenuFrame::SizeToPopup(nsBoxLayoutState& aState, nsSize& aSize)
 {
--- a/layout/xul/base/src/nsMenuFrame.h
+++ b/layout/xul/base/src/nsMenuFrame.h
@@ -142,21 +142,21 @@ public:
                                          const nsDisplayListSet& aLists);
                                          
   // this method can destroy the frame
   NS_IMETHOD HandleEvent(nsPresContext* aPresContext, 
                          nsGUIEvent*     aEvent,
                          nsEventStatus*  aEventStatus);
 
   NS_IMETHOD  AppendFrames(nsIAtom*        aListName,
-                           nsIFrame*       aFrameList);
+                           nsFrameList&    aFrameList);
 
   NS_IMETHOD  InsertFrames(nsIAtom*        aListName,
                            nsIFrame*       aPrevFrame,
-                           nsIFrame*       aFrameList);
+                           nsFrameList&    aFrameList);
 
   NS_IMETHOD  RemoveFrame(nsIAtom*        aListName,
                           nsIFrame*       aOldFrame);
 
   virtual nsIAtom* GetType() const { return nsGkAtoms::menuFrame; }
 
   NS_IMETHOD SelectMenu(PRBool aActivateFlag);
 
@@ -224,21 +224,18 @@ public:
 #endif
 
   static PRBool IsSizedToPopup(nsIContent* aContent, PRBool aRequireAlways);
 
 protected:
   friend class nsMenuTimerMediator;
   friend class nsASyncMenuInitialization;
 
-  // initialize mPopupFrame to the first popup frame within aChildList. Returns
-  // aChildList with the popup frame removed.
-  nsIFrame* SetPopupFrame(nsIFrame* aChildList);
-
-  // As above, but using an nsFrameList; modifies the passed-in list.
+  // initialize mPopupFrame to the first popup frame within
+  // aChildList. Removes the popup, if any, from aChildList.
   void SetPopupFrame(nsFrameList& aChildList);
 
   // set mMenuParent to the nearest enclosing menu bar or menupopup frame of
   // aParent (or aParent itself). This is called when initializing the frame,
   // so aParent should be the expected parent of this frame.
   void InitMenuParent(nsIFrame* aParent);
 
   // Update the menu's type (normal, checkbox, radio).
--- a/layout/xul/base/src/nsPopupSetFrame.cpp
+++ b/layout/xul/base/src/nsPopupSetFrame.cpp
@@ -87,21 +87,20 @@ nsPopupSetFrame::Init(nsIContent*      a
 nsIAtom*
 nsPopupSetFrame::GetType() const
 {
   return nsGkAtoms::popupSetFrame;
 }
 
 NS_IMETHODIMP
 nsPopupSetFrame::AppendFrames(nsIAtom*        aListName,
-                              nsIFrame*       aFrameList)
+                              nsFrameList&    aFrameList)
 {
   if (aListName == nsGkAtoms::popupList) {
-    nsFrameList temp(aFrameList);
-    return AddPopupFrameList(temp);
+    return AddPopupFrameList(aFrameList);
   }
   return nsBoxFrame::AppendFrames(aListName, aFrameList);
 }
 
 NS_IMETHODIMP
 nsPopupSetFrame::RemoveFrame(nsIAtom*        aListName,
                              nsIFrame*       aOldFrame)
 {
@@ -109,21 +108,20 @@ nsPopupSetFrame::RemoveFrame(nsIAtom*   
     return RemovePopupFrame(aOldFrame);
   }
   return nsBoxFrame::RemoveFrame(aListName, aOldFrame);
 }
 
 NS_IMETHODIMP
 nsPopupSetFrame::InsertFrames(nsIAtom*        aListName,
                               nsIFrame*       aPrevFrame,
-                              nsIFrame*       aFrameList)
+                              nsFrameList&    aFrameList)
 {
   if (aListName == nsGkAtoms::popupList) {
-    nsFrameList temp(aFrameList);
-    return AddPopupFrameList(temp);
+    return AddPopupFrameList(aFrameList);
   }
   return nsBoxFrame::InsertFrames(aListName, aPrevFrame, aFrameList);
 }
 
 NS_IMETHODIMP
 nsPopupSetFrame::SetInitialChildList(nsIAtom*        aListName,
                                      nsFrameList&    aChildList)
 {
--- a/layout/xul/base/src/nsPopupSetFrame.h
+++ b/layout/xul/base/src/nsPopupSetFrame.h
@@ -68,22 +68,22 @@ public:
     nsBoxFrame(aShell, aContext) {}
 
   ~nsPopupSetFrame() {}
   
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD  SetInitialChildList(nsIAtom*        aListName,
                                   nsFrameList&    aChildList);
 
     // nsIBox
   NS_IMETHOD DoLayout(nsBoxLayoutState& aBoxLayoutState);
 
   // Used to destroy our popup frames.
   virtual void Destroy();
--- a/layout/xul/base/src/nsRootBoxFrame.cpp
+++ b/layout/xul/base/src/nsRootBoxFrame.cpp
@@ -85,20 +85,20 @@ public:
   virtual nsPopupSetFrame* GetPopupSetFrame();
   virtual void SetPopupSetFrame(nsPopupSetFrame* aPopupSet);
   virtual nsIContent* GetDefaultTooltip();
   virtual void SetDefaultTooltip(nsIContent* aTooltip);
   virtual nsresult AddTooltipSupport(nsIContent* aNode);
   virtual nsresult RemoveTooltipSupport(nsIContent* aNode);
 
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
-                          nsIFrame*       aFrameList);
+                          nsFrameList&    aFrameList);
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
 
   NS_IMETHOD Reflow(nsPresContext*          aPresContext,
                     nsHTMLReflowMetrics&     aDesiredSize,
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus&          aStatus);
   NS_IMETHOD HandleEvent(nsPresContext* aPresContext, 
@@ -149,17 +149,17 @@ nsRootBoxFrame::nsRootBoxFrame(nsIPresSh
 
   nsCOMPtr<nsIBoxLayout> layout;
   NS_NewStackLayout(aShell, layout);
   SetLayoutManager(layout);
 }
 
 NS_IMETHODIMP
 nsRootBoxFrame::AppendFrames(nsIAtom*        aListName,
-                             nsIFrame*       aFrameList)
+                             nsFrameList&    aFrameList)
 {
   nsresult  rv;
 
   NS_ASSERTION(!aListName, "unexpected child list name");
   NS_PRECONDITION(mFrames.IsEmpty(), "already have a child frame");
   if (aListName) {
     // We only support unnamed principal child list
     rv = NS_ERROR_INVALID_ARG;
@@ -173,17 +173,17 @@ nsRootBoxFrame::AppendFrames(nsIAtom*   
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsRootBoxFrame::InsertFrames(nsIAtom*        aListName,
                              nsIFrame*       aPrevFrame,
-                             nsIFrame*       aFrameList)
+                             nsFrameList&    aFrameList)
 {
   nsresult  rv;
 
   // Because we only support a single child frame inserting is the same
   // as appending
   NS_PRECONDITION(!aPrevFrame, "unexpected previous sibling frame");
   if (aPrevFrame) {
     rv = NS_ERROR_UNEXPECTED;
--- a/layout/xul/base/src/nsSliderFrame.cpp
+++ b/layout/xul/base/src/nsSliderFrame.cpp
@@ -135,29 +135,29 @@ nsSliderFrame::RemoveFrame(nsIAtom*     
     RemoveListener();
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsSliderFrame::InsertFrames(nsIAtom*        aListName,
                             nsIFrame*       aPrevFrame,
-                            nsIFrame*       aFrameList)
+                            nsFrameList&    aFrameList)
 {
   PRBool wasEmpty = mFrames.IsEmpty();
   nsresult rv = nsBoxFrame::InsertFrames(aListName, aPrevFrame, aFrameList);
   if (wasEmpty)
     AddListener();
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsSliderFrame::AppendFrames(nsIAtom*        aListName,
-                            nsIFrame*       aFrameList)
+                            nsFrameList&    aFrameList)
 {
   // if we have no children and on was added then make sure we add the
   // listener
   PRBool wasEmpty = mFrames.IsEmpty();
   nsresult rv = nsBoxFrame::AppendFrames(aListName, aFrameList);
   if (wasEmpty)
     AddListener();
 
--- a/layout/xul/base/src/nsSliderFrame.h
+++ b/layout/xul/base/src/nsSliderFrame.h
@@ -129,21 +129,21 @@ public:
   // nsIBox
   virtual nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState);
   virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState);
   virtual nsSize GetMaxSize(nsBoxLayoutState& aBoxLayoutState);
   NS_IMETHOD DoLayout(nsBoxLayoutState& aBoxLayoutState);
 
   // nsIFrame overrides
   NS_IMETHOD  AppendFrames(nsIAtom*        aListName,
-                           nsIFrame*       aFrameList);
+                           nsFrameList&    aFrameList);
 
   NS_IMETHOD  InsertFrames(nsIAtom*        aListName,
                            nsIFrame*       aPrevFrame,
-                           nsIFrame*       aFrameList);
+                           nsFrameList&    aFrameList);
 
   NS_IMETHOD  RemoveFrame(nsIAtom*        aListName,
                           nsIFrame*       aOldFrame);
 
   virtual void Destroy();
 
   NS_IMETHOD BuildDisplayListForChildren(nsDisplayListBuilder*   aBuilder,
                                          const nsRect&           aDirtyRect,