Backing out changesets 75919d3eb3d0 and 14ce7619e9c1 due to test failures
authorRobert O'Callahan <robert@ocallahan.org>
Sun, 07 Sep 2008 00:35:20 +1200
changeset 18888 75c0f6a369410cc4ea6f3e1446cb650b73cc4e03
parent 18887 14ce7619e9c186286e15419bb7800b3fd5c3e34f
child 18889 08bf39f0754a98d12273697dec47df2045198cc7
push idunknown
push userunknown
push dateunknown
milestone1.9.1b1pre
Backing out changesets 75919d3eb3d0 and 14ce7619e9c1 due to test failures
layout/base/crashtests/crashtests.list
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSFrameConstructor.h
layout/generic/nsAbsoluteContainingBlock.cpp
layout/generic/nsAbsoluteContainingBlock.h
layout/generic/nsBlockFrame.cpp
layout/generic/nsContainerFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsHTMLFrame.cpp
layout/generic/nsHTMLParts.h
layout/generic/nsHTMLReflowState.cpp
layout/generic/nsInlineFrame.cpp
layout/generic/nsPageContentFrame.cpp
layout/generic/nsPageContentFrame.h
layout/generic/nsViewportFrame.cpp
layout/reftests/bugs/reftest.list
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -1,14 +1,13 @@
 load 56746-1.html
 load 143862-1.html
 load 143862-2.html
 load 243159-1.html
 load 243159-2.xhtml
-load 243519-1.html
 load 306940-1.html
 load 310267-1.xml
 load 310638-1.svg
 load 310638-2.html
 load 313086-1.xml
 load 321058-1.xul
 load 321058-2.xul
 load 321077-1.xul
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1801,19 +1801,19 @@ nsCSSFrameConstructor::nsCSSFrameConstru
   , mRootElementStyleFrame(nsnull)
   , mFixedContainingBlock(nsnull)
   , mDocElementContainingBlock(nsnull)
   , mGfxScrollFrame(nsnull)
   , mPageSequenceFrame(nsnull)
   , mUpdateCount(0)
   , mQuotesDirty(PR_FALSE)
   , mCountersDirty(PR_FALSE)
+  , mInitialContainingBlockIsAbsPosContainer(PR_FALSE)
   , mIsDestroyingFrameTree(PR_FALSE)
   , mRebuildAllStyleData(PR_FALSE)
-  , mHasRootAbsPosContainingBlock(PR_FALSE)
 {
   if (!gGotXBLFormPrefs) {
     gGotXBLFormPrefs = PR_TRUE;
 
     gUseXBLForms =
       nsContentUtils::GetBoolPref("nglayout.debug.enable_xbl_forms");
   }
 
@@ -3967,16 +3967,42 @@ nsCSSFrameConstructor::GetDisplay(nsIFra
   }
   return aFrame->GetStyleContext()->GetStyleDisplay();
 }
 
 /***********************************************
  * END TABLE SECTION
  ***********************************************/
 
+nsresult
+nsCSSFrameConstructor::ConstructDocElementTableFrame(nsIContent*     aDocElement,
+                                                     nsIFrame*       aParentFrame,
+                                                     nsIFrame**      aNewTableFrame,
+                                                     nsFrameConstructorState& aState)
+{
+  nsFrameItems    frameItems;
+
+  // XXXbz this is wrong.  We should at least be setting the fixed container in
+  // the framestate here.  Better yet, we should pass through aState
+  // unmodified.  Can't do that, though, because then a fixed or absolute
+  // positioned root table with auto offsets would look for a block to compute
+  // its hypothetical box and crash.  So we just disable fixed positioning
+  // altogether in documents where the root is a table.  Oh, well.
+  nsFrameConstructorState state(mPresShell, nsnull, nsnull, nsnull,
+                                aState.mFrameState);
+  ConstructFrame(state, aDocElement, aParentFrame, frameItems);
+  *aNewTableFrame = frameItems.childList;
+  if (!*aNewTableFrame) {
+    NS_WARNING("cannot get table contentFrame");
+    // XXXbz maybe better to return the error from ConstructFrame?
+    return NS_ERROR_FAILURE;
+  }
+  return NS_OK;
+}
+
 static PRBool CheckOverflow(nsPresContext* aPresContext,
                             const nsStyleDisplay* aDisplay)
 {
   if (aDisplay->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE)
     return PR_FALSE;
 
   if (aDisplay->mOverflowX == NS_STYLE_OVERFLOW_CLIP)
     aPresContext->SetViewportOverflowOverride(NS_STYLE_OVERFLOW_HIDDEN,
@@ -4062,16 +4088,39 @@ nsCSSFrameConstructor::PropagateScrollTo
  * New one
  */
 nsresult
 nsCSSFrameConstructor::ConstructDocElementFrame(nsFrameConstructorState& aState,
                                                 nsIContent*              aDocElement,
                                                 nsIFrame*                aParentFrame,
                                                 nsIFrame**               aNewFrame)
 {
+    // how the root frame hierarchy should look
+
+    /*
+
+---------------No Scrollbars------
+
+
+     AreaFrame or BoxFrame (InitialContainingBlock)
+  
+
+
+---------------Gfx Scrollbars ------
+
+
+     ScrollFrame
+
+         ^
+         |
+         |
+     AreaFrame or BoxFrame (InitialContainingBlock)
+          
+*/    
+
   *aNewFrame = nsnull;
 
   if (!mTempFrameTreeState)
     aState.mPresShell->CaptureHistoryState(getter_AddRefs(mTempFrameTreeState));
 
   // ----- reattach gfx scrollbars ------
   // Gfx scrollframes were created in the root frame but the primary frame map may have been destroyed if a 
   // new style sheet was loaded so lets reattach the frames to their content.
@@ -4135,219 +4184,157 @@ nsCSSFrameConstructor::ConstructDocEleme
     PropagateScrollToViewport() == aDocElement;
 
   NS_ASSERTION(!display->IsScrollableOverflow() || 
                aState.mPresContext->IsPaginated() ||
                propagatedScrollToViewport,
                "Scrollbars should have been propagated to the viewport");
 #endif
 
-  nsFrameConstructorSaveState absoluteSaveState;
-  if (mHasRootAbsPosContainingBlock) {
-    // Push the absolute containing block now so we can absolutely position
-    // the root element
-    aState.PushAbsoluteContainingBlock(mDocElementContainingBlock, absoluteSaveState);
-  }
-
+  nsIFrame* contentFrame = nsnull;
+  PRBool isBlockFrame = PR_FALSE;
   nsresult rv;
 
   // The rules from CSS 2.1, section 9.2.4, have already been applied
   // by the style system, so we can assume that display->mDisplay is
   // either NONE, BLOCK, or TABLE.
 
   PRBool docElemIsTable = (display->mDisplay == NS_STYLE_DISPLAY_TABLE) &&
                           !IsSpecialContent(aDocElement, aDocElement->Tag(),
                                             aDocElement->GetNameSpaceID(),
                                             styleContext);
 
-  // contentFrame is the primary frame for the root element. *aNewFrame
-  // is the frame that will be the child of the initial containing block.
-  // These are usually the same frame but they can be different, in
-  // particular if the root frame is positioned, in which case
-  // contentFrame is the out-of-flow frame and *aNewFrame is the
-  // placeholder.
-  nsIFrame* contentFrame;
-  PRBool processChildren = PR_FALSE;
   if (docElemIsTable) {
-    nsIFrame* innerTableFrame;
-    nsFrameItems frameItems;
     // if the document is a table then just populate it.
-    rv = ConstructTableFrame(aState, aDocElement,
-                             aParentFrame, styleContext,
-                             kNameSpaceID_None, PR_FALSE, frameItems, contentFrame,
-                             innerTableFrame);
-    if (NS_FAILED(rv))
+    rv = ConstructDocElementTableFrame(aDocElement, aParentFrame, &contentFrame,
+                                       aState);
+    if (NS_FAILED(rv)) {
       return rv;
-    if (!contentFrame || !frameItems.childList)
-      return NS_ERROR_FAILURE;
-    *aNewFrame = frameItems.childList;
-    NS_ASSERTION(!frameItems.childList->GetNextSibling(),
-                 "multiple root element frames");
+    }
+    styleContext = contentFrame->GetStyleContext();
   } else {
     // otherwise build a box or a block
 #ifdef MOZ_XUL
     if (aDocElement->IsNodeOfType(nsINode::eXUL)) {
       contentFrame = NS_NewDocElementBoxFrame(mPresShell, styleContext);
-      if (NS_UNLIKELY(!contentFrame)) {
-        return NS_ERROR_OUT_OF_MEMORY;
-      }
-      InitAndRestoreFrame(aState, aDocElement, aParentFrame, nsnull, contentFrame);
-      *aNewFrame = contentFrame;
-      processChildren = PR_TRUE;
     }
     else
 #endif 
 #ifdef MOZ_SVG
     if (aDocElement->GetNameSpaceID() == kNameSpaceID_SVG) {
       if (aDocElement->Tag() == nsGkAtoms::svg && NS_SVGEnabled()) {
         contentFrame = NS_NewSVGOuterSVGFrame(mPresShell, aDocElement, styleContext);
-        if (NS_UNLIKELY(!contentFrame)) {
-          return NS_ERROR_OUT_OF_MEMORY;
-        }
-        InitAndRestoreFrame(aState, aDocElement,
-                            aState.GetGeometricParent(display, aParentFrame),
-                            nsnull, contentFrame);
-
-        // AddChild takes care of transforming the frame tree for fixed-pos
-        // or abs-pos situations
-        nsFrameItems frameItems;
-        rv = aState.AddChild(contentFrame, frameItems, aDocElement,
-                             styleContext, aParentFrame);
-        if (NS_FAILED(rv) || !frameItems.childList) {
-          return rv;
-        }
-        *aNewFrame = frameItems.childList;
-        processChildren = PR_TRUE;
-
-        // See if we need to create a view, e.g. the frame is absolutely positioned
-        nsHTMLContainerFrame::CreateViewForFrame(contentFrame, aParentFrame, PR_FALSE);
       } else {
         return NS_ERROR_FAILURE;
       }
     }
     else 
 #endif
     {
-      contentFrame = NS_NewBlockFrame(mPresShell, styleContext,
-        NS_BLOCK_SPACE_MGR|NS_BLOCK_MARGIN_ROOT);
-      if (!contentFrame)
-        return NS_ERROR_OUT_OF_MEMORY;
-      nsFrameItems frameItems;
-      rv = ConstructBlock(aState, display, aDocElement,
-                          aState.GetGeometricParent(display, aParentFrame),
-                          aParentFrame, styleContext, &contentFrame,
-                          frameItems, display->IsPositioned());
-      if (NS_FAILED(rv) || !frameItems.childList)
-        return rv;
-      *aNewFrame = frameItems.childList;
-      NS_ASSERTION(!frameItems.childList->GetNextSibling(),
-                   "multiple root element frames");
-    }
+      contentFrame = NS_NewDocumentElementFrame(mPresShell, styleContext);
+      isBlockFrame = PR_TRUE;
+    }
+    
+    if (NS_UNLIKELY(!contentFrame)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+
+    // initialize the child
+    InitAndRestoreFrame(aState, aDocElement, aParentFrame, nsnull, contentFrame);
   }
 
   // set the primary frame
   aState.mFrameManager->SetPrimaryFrameFor(aDocElement, contentFrame);
 
+  *aNewFrame = contentFrame;
+
   mInitialContainingBlock = contentFrame;
+  mInitialContainingBlockIsAbsPosContainer = PR_FALSE;
 
   // Figure out which frame has the main style for the document element,
   // assigning it to mRootElementStyleFrame.
   // Backgrounds should be propagated from that frame to the viewport.
   PRBool isChild;
   contentFrame->GetParentStyleContextFrame(aState.mPresContext,
           &mRootElementStyleFrame, &isChild);
   if (!isChild) {
     mRootElementStyleFrame = mInitialContainingBlock;
   }
 
-  if (processChildren) {
-    // Still need to process the child content
-    nsFrameItems childItems;
+  // if it was a table then we don't need to process our children.
+  if (!docElemIsTable) {
+    // Process the child content
+    nsFrameConstructorSaveState absoluteSaveState;
+    nsFrameConstructorSaveState floatSaveState;
+    nsFrameItems                childItems;
+
+    if (isBlockFrame) {
+      PRBool haveFirstLetterStyle, haveFirstLineStyle;
+      ShouldHaveSpecialBlockStyle(aDocElement, styleContext,
+                                  &haveFirstLetterStyle, &haveFirstLineStyle);
+      mInitialContainingBlockIsAbsPosContainer = PR_TRUE;
+      aState.PushAbsoluteContainingBlock(contentFrame, absoluteSaveState);
+      aState.PushFloatContainingBlock(contentFrame, floatSaveState,
+                                      haveFirstLetterStyle,
+                                      haveFirstLineStyle);
+    }
 
     // Create any anonymous frames the doc element frame requires
     // This must happen before ProcessChildren to ensure that popups are
     // never constructed before the popupset.
     CreateAnonymousFrames(nsnull, aState, aDocElement, contentFrame,
                           PR_FALSE, childItems, PR_TRUE);
-    NS_ASSERTION(!nsLayoutUtils::GetAsBlock(contentFrame),
-                 "Only XUL and SVG frames should reach here");
     ProcessChildren(aState, aDocElement, contentFrame, PR_TRUE, childItems,
-                    PR_FALSE);
+                    isBlockFrame);
 
     // Set the initial child lists
     contentFrame->SetInitialChildList(nsnull, childItems.childList);
   }
 
   return NS_OK;
 }
 
 
 nsresult
 nsCSSFrameConstructor::ConstructRootFrame(nsIContent*     aDocElement,
                                           nsIFrame**      aNewFrame)
 {
   AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
   NS_PRECONDITION(aNewFrame, "null out param");
   
+  // how the root frame hierarchy should look
+
     /*
-       how the root frame hierarchy should look
-
-  Galley presentation, non-XUL, with scrolling (i.e. not a frameset):
-  
-      ViewportFrame [fixed-cb]
-        nsHTMLScrollFrame
-          CanvasFrame [abs-cb]
-            root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
-                                nsTableOuterFrame, nsPlaceholderFrame)
-
-  Galley presentation, non-XUL, without scrolling (i.e. a frameset):
-  
-      ViewportFrame [fixed-cb]
-        CanvasFrame [abs-cb]
-          root element frame (nsBlockFrame)
-
-  Galley presentation, XUL
-  
-      ViewportFrame [fixed-cb]
-        nsRootBoxFrame
-          root element frame (nsDocElementBoxFrame)
-
-  Print presentation, non-XUL
-
-      ViewportFrame
-        nsSimplePageSequenceFrame
-          nsPageFrame [fixed-cb]
-            nsPageContentFrame
-              CanvasFrame [abs-cb]
-                root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
-                                    nsTableOuterFrame, nsPlaceholderFrame)
-
-  Print-preview presentation, non-XUL
-
-      ViewportFrame
-        nsHTMLScrollFrame
-          nsSimplePageSequenceFrame
-            nsPageFrame [fixed-cb]
-              nsPageContentFrame
-                CanvasFrame [abs-cb]
-                  root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
-                                      nsTableOuterFrame, nsPlaceholderFrame)
-
-  Print/print preview of XUL is not supported.
-  [fixed-cb]: the default containing block for fixed-pos content
-  [abs-cb]: the default containing block for abs-pos content
- 
-  Meaning of nsCSSFrameConstructor fields:
-    mInitialContainingBlock is "root element frame".
-    mDocElementContainingBlock is the parent of mInitialContainingBlock
-      (i.e. CanvasFrame or nsRootBoxFrame)
-    mFixedContainingBlock is the [fixed-cb]
-    mGfxScrollFrame is the nsHTMLScrollFrame mentioned above, or null if there isn't one
-    mPageSequenceFrame is the nsSimplePageSequenceFrame, or null if there isn't one
-*/
+
+---------------No Scrollbars------
+
+
+
+     ViewPortFrame (FixedContainingBlock) <---- RootView
+
+         ^
+         |
+     RootFrame(DocElementContainingBlock)
+  
+
+
+---------------Gfx Scrollbars ------
+
+
+     ViewPortFrame (FixedContainingBlock) <---- RootView
+
+         ^
+         |
+     ScrollFrame
+
+         ^
+         |
+     RootFrame(DocElementContainingBlock)
+          
+*/    
 
   // Set up our style rule observer.
   {
     mPresShell->StyleSet()->SetBindingManager(mDocument->BindingManager());
   }
 
   // --------- BUILD VIEWPORT -----------
   nsIFrame*                 viewportFrame = nsnull;
@@ -4402,17 +4389,16 @@ nsCSSFrameConstructor::ConstructRootFram
     {
       // pass a temporary stylecontext, the correct one will be set later
       rootFrame = NS_NewRootBoxFrame(mPresShell, viewportPseudoStyle);
     } else
 #endif
     {
       // pass a temporary stylecontext, the correct one will be set later
       rootFrame = NS_NewCanvasFrame(mPresShell, viewportPseudoStyle);
-      mHasRootAbsPosContainingBlock = PR_TRUE;
     }
 
     rootPseudo = nsCSSAnonBoxes::canvas;
     mDocElementContainingBlock = rootFrame;
   } else {
     // Create a page sequence frame
     rootFrame = NS_NewSimplePageSequenceFrame(mPresShell, viewportPseudoStyle);
     mPageSequenceFrame = rootFrame;
@@ -4531,41 +4517,40 @@ nsCSSFrameConstructor::ConstructRootFram
   
   if (isScrollable) {
     FinishBuildingScrollFrame(parentFrame, rootFrame);
   }
   
   if (isPaginated) { // paginated
     // Create the first page
     // Set the initial child lists
-    nsIFrame *pageFrame, *canvasFrame;
+    nsIFrame *pageFrame, *pageContentFrame;
     ConstructPageFrame(mPresShell, presContext, rootFrame, nsnull,
-                       pageFrame, canvasFrame);
+                       pageFrame, pageContentFrame);
     rootFrame->SetInitialChildList(nsnull, 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;
+    mDocElementContainingBlock = pageContentFrame;
   }
 
   viewportFrame->SetInitialChildList(nsnull, newFrame);
   
   *aNewFrame = viewportFrame;
 
   return NS_OK;
 }
 
 nsresult
-nsCSSFrameConstructor::ConstructPageFrame(nsIPresShell*  aPresShell,
+nsCSSFrameConstructor::ConstructPageFrame(nsIPresShell*   aPresShell,
                                           nsPresContext* aPresContext,
-                                          nsIFrame*      aParentFrame,
-                                          nsIFrame*      aPrevPageFrame,
-                                          nsIFrame*&     aPageFrame,
-                                          nsIFrame*&     aCanvasFrame)
+                                          nsIFrame*       aParentFrame,
+                                          nsIFrame*       aPrevPageFrame,
+                                          nsIFrame*&      aPageFrame,
+                                          nsIFrame*&      aPageContentFrame)
 {
   nsStyleContext* parentStyleContext = aParentFrame->GetStyleContext();
   nsStyleSet *styleSet = aPresShell->StyleSet();
 
   nsRefPtr<nsStyleContext> pagePseudoStyle;
   pagePseudoStyle = styleSet->ResolvePseudoStyleFor(nsnull,
                                                     nsCSSAnonBoxes::page,
                                                     parentStyleContext);
@@ -4578,47 +4563,31 @@ nsCSSFrameConstructor::ConstructPageFram
   // the pages easier and faster.
   aPageFrame->Init(nsnull, aParentFrame, aPrevPageFrame);
 
   nsRefPtr<nsStyleContext> pageContentPseudoStyle;
   pageContentPseudoStyle = styleSet->ResolvePseudoStyleFor(nsnull,
                                                            nsCSSAnonBoxes::pageContent,
                                                            pagePseudoStyle);
 
-  nsIFrame* pageContentFrame = NS_NewPageContentFrame(aPresShell, pageContentPseudoStyle);
-  if (NS_UNLIKELY(!pageContentFrame))
+  aPageContentFrame = NS_NewPageContentFrame(aPresShell, pageContentPseudoStyle);
+  if (NS_UNLIKELY(!aPageContentFrame))
     return NS_ERROR_OUT_OF_MEMORY;
 
   // Initialize the page content frame and force it to have a view. Also make it the
   // containing block for fixed elements which are repeated on every page.
   nsIFrame* prevPageContentFrame = nsnull;
   if (aPrevPageFrame) {
     prevPageContentFrame = aPrevPageFrame->GetFirstChild(nsnull);
     NS_ASSERTION(prevPageContentFrame, "missing page content frame");
   }
-  pageContentFrame->Init(nsnull, aPageFrame, prevPageContentFrame);
-  aPageFrame->SetInitialChildList(nsnull, pageContentFrame);
-  mFixedContainingBlock = pageContentFrame;
-
-  nsRefPtr<nsStyleContext> canvasPseudoStyle;
-  canvasPseudoStyle = styleSet->ResolvePseudoStyleFor(nsnull,
-                                                      nsCSSAnonBoxes::canvas,
-                                                      pageContentPseudoStyle);
-
-  aCanvasFrame = NS_NewCanvasFrame(aPresShell, canvasPseudoStyle);
-  if (NS_UNLIKELY(!aCanvasFrame))
-    return NS_ERROR_OUT_OF_MEMORY;
-
-  nsIFrame* prevCanvasFrame = nsnull;
-  if (prevPageContentFrame) {
-    prevCanvasFrame = prevPageContentFrame->GetFirstChild(nsnull);
-    NS_ASSERTION(prevCanvasFrame, "missing canvas frame");
-  }
-  aCanvasFrame->Init(nsnull, pageContentFrame, prevCanvasFrame);
-  pageContentFrame->SetInitialChildList(nsnull, aCanvasFrame);
+  aPageContentFrame->Init(nsnull, aPageFrame, prevPageContentFrame);
+  mFixedContainingBlock = aPageContentFrame;
+
+  aPageFrame->SetInitialChildList(nsnull, aPageContentFrame);
 
   return NS_OK;
 }
 
 /* static */
 nsresult
 nsCSSFrameConstructor::CreatePlaceholderFrameFor(nsIPresShell*    aPresShell, 
                                                  nsIContent*      aContent,
@@ -6707,34 +6676,27 @@ nsCSSFrameConstructor::InitAndRestoreFra
 
   return rv;
 }
 
 already_AddRefed<nsStyleContext>
 nsCSSFrameConstructor::ResolveStyleContext(nsIFrame*         aParentFrame,
                                            nsIContent*       aContent)
 {
-  nsStyleContext* parentStyleContext = nsnull;
+  nsStyleContext* parentStyleContext;
   if (aContent->GetParent()) {
     aParentFrame = nsFrame::CorrectStyleParentFrame(aParentFrame, nsnull);
   
-    if (aParentFrame) {
-      // Resolve the style context based on the content object and the parent
-      // style context
-      parentStyleContext = aParentFrame->GetStyleContext();
-    } else {
-      // Perhaps aParentFrame is a canvasFrame and we're replicating
-      // fixed-pos frames.
-      // XXX should we create a way to tell ConstructFrame which style
-      // context to use, and pass it the style context for the
-      // previous page's fixed-pos frame?
-    }
+    // Resolve the style context based on the content object and the parent
+    // style context
+    parentStyleContext = aParentFrame->GetStyleContext();
   } else {
     // This has got to be a call from ConstructDocElementTableFrame.
-    // Not sure how best to assert that here.
+    // Not sure how best to asserrt that here.
+    parentStyleContext = nsnull;
   }
 
   nsStyleSet *styleSet = mPresShell->StyleSet();
 
   if (aContent->IsNodeOfType(nsINode::eELEMENT)) {
     return styleSet->ResolveStyleFor(aContent, parentStyleContext);
   } else {
 
@@ -7537,76 +7499,55 @@ nsCSSFrameConstructor::ReconstructDocEle
 
   nsresult rv = NS_OK;
 
   // XXXbz is that null-check needed?  Why?
   if (mDocument && mPresShell) {
     nsIContent *rootContent = mDocument->GetRootContent();
     
     if (rootContent) {
+      // Before removing the frames associated with the content object, ask them to save their
+      // state onto a temporary state object.
+      CaptureStateForFramesOf(rootContent, mTempFrameTreeState);
+
       nsFrameConstructorState state(mPresShell, mFixedContainingBlock,
                                     nsnull, nsnull, mTempFrameTreeState);
 
-      // Before removing the frames associated with the content object, ask them to save their
-      // state onto a temporary state object.
-      CaptureStateFor(state.mFrameManager->GetRootFrame(), mTempFrameTreeState);
-
       // Get the frame that corresponds to the document element
       nsIFrame* docElementFrame =
         state.mFrameManager->GetPrimaryFrameFor(rootContent, -1);
-
-      if (docElementFrame) {
-        // Destroy out-of-flow frames that might not be in the frame subtree
-        // rooted at docElementFrame
-        ::DeletingFrameSubtree(state.mFrameManager, docElementFrame);
-      }
-
+        
       // Remove any existing fixed items: they are always on the
       // FixedContainingBlock.  Note that this has to be done before we call
       // ClearPlaceholderFrameMap(), since RemoveFixedItems uses the
       // placeholder frame map.
-      rv = RemoveFixedItems(state, docElementFrame);
-
+      rv = RemoveFixedItems(state);
       if (NS_SUCCEEDED(rv)) {
-        nsPlaceholderFrame* placeholderFrame = nsnull;
-        if (docElementFrame &&
-            (docElementFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
-          // Get the placeholder frame now, before we tear down the
-          // placeholder frame map
-          placeholderFrame =
-            state.mFrameManager->GetPlaceholderFrameFor(docElementFrame);
-          NS_ASSERTION(placeholderFrame, "No placeholder for out-of-flow?");
-        }
-
         // Clear the hash tables that map from content to frame and out-of-flow
         // frame to placeholder frame
         state.mFrameManager->ClearPrimaryFrameMap();
         state.mFrameManager->ClearPlaceholderFrameMap();
         state.mFrameManager->ClearUndisplayedContentMap();
 
         if (docElementFrame) {
           // Take the docElementFrame, and remove it from its parent.
+        
           // XXXbz So why can't we reuse ContentRemoved?
 
+          NS_ASSERTION(docElementFrame->GetParent() == mDocElementContainingBlock,
+                       "Unexpected doc element parent frame");
+
           // Notify self that we will destroy the entire frame tree, this blocks
           // RemoveMappingsForFrameSubtree() which would otherwise lead to a
           // crash since we cleared the placeholder map above (bug 398982).
           PRBool wasDestroyingFrameTree = mIsDestroyingFrameTree;
           WillDestroyFrameTree();
-
-          rv = state.mFrameManager->RemoveFrame(docElementFrame->GetParent(),
-                    GetChildListNameFor(docElementFrame), docElementFrame);
-          
-          if (placeholderFrame) {
-            // Remove the placeholder frame first (XXX second for now) (so
-            // that it doesn't retain a dangling pointer to memory)
-            rv |= state.mFrameManager->RemoveFrame(placeholderFrame->GetParent(),
-                                            nsnull, placeholderFrame);
-          }
-
+          // Remove the old document element hieararchy
+          rv = state.mFrameManager->RemoveFrame(mDocElementContainingBlock,
+                                                nsnull, docElementFrame);
           mIsDestroyingFrameTree = wasDestroyingFrameTree;
           if (NS_FAILED(rv)) {
             return rv;
           }
         }
         
         mInitialContainingBlock = nsnull;
         mRootElementStyleFrame = nsnull;
@@ -7693,18 +7634,19 @@ nsCSSFrameConstructor::GetAbsoluteContai
     }
   }
 
   // If we found an absolutely positioned containing block, then use the
   // first-continuation.
   if (containingBlock)
     return AdjustAbsoluteContainingBlock(containingBlock);
 
-  // If we didn't find it, then use the document element containing block
-  return mHasRootAbsPosContainingBlock ? mDocElementContainingBlock : nsnull;
+  // If we didn't find it, then use the initial containing block if it
+  // supports abs pos kids.
+  return mInitialContainingBlockIsAbsPosContainer ? mInitialContainingBlock : nsnull;
 }
 
 nsIFrame*
 nsCSSFrameConstructor::GetFloatContainingBlock(nsIFrame* aFrame)
 {
   NS_PRECONDITION(mInitialContainingBlock, "no initial containing block");
   
   // Starting with aFrame, look for a frame that is a float containing block.
@@ -10279,19 +10221,19 @@ nsCSSFrameConstructor::CreateContinuingF
 
     if (newFrame) {
       newFrame->Init(content, aParentFrame, aFrame);
       // XXXbz should we be passing in a non-null aContentParentFrame?
       nsHTMLContainerFrame::CreateViewForFrame(newFrame, nsnull, PR_FALSE);
     }
 
   } else if (nsGkAtoms::pageFrame == frameType) {
-    nsIFrame* canvasFrame;
+    nsIFrame* pageContentFrame;
     rv = ConstructPageFrame(shell, aPresContext, aParentFrame, aFrame,
-                            newFrame, canvasFrame);
+                            newFrame, pageContentFrame);
   } else if (nsGkAtoms::tableOuterFrame == frameType) {
     rv = CreateContinuingOuterTableFrame(shell, aPresContext, aFrame, aParentFrame,
                                          content, styleContext, &newFrame);
 
   } else if (nsGkAtoms::tableFrame == frameType) {
     rv = CreateContinuingTableFrame(shell, aPresContext, aFrame, aParentFrame,
                                     content, styleContext, &newFrame);
 
@@ -10470,27 +10412,27 @@ nsCSSFrameConstructor::CreateContinuingF
     newFrame->SetNextContinuation(nextContinuation);
   }
   return NS_OK;
 }
 
 nsresult
 nsCSSFrameConstructor::ReplicateFixedFrames(nsPageContentFrame* aParentFrame)
 {
-  // Now deal with fixed-pos things....  They should appear on all pages,
-  // so we want to move over the placeholders when processing the child
-  // of the pageContentFrame.
+  // Now deal with fixed-pos things....  They should appear on all pages, and
+  // the placeholders must be kids of a block, so we want to move over the
+  // placeholders when processing the child of the pageContentFrame.
 
   nsIFrame* prevPageContentFrame = aParentFrame->GetPrevInFlow();
   if (!prevPageContentFrame) {
     return NS_OK;
   }
-  nsIFrame* canvasFrame = aParentFrame->GetFirstChild(nsnull);
-  nsIFrame* prevCanvasFrame = prevPageContentFrame->GetFirstChild(nsnull);
-  if (!canvasFrame || !prevCanvasFrame) {
+  nsIFrame* docRootFrame = aParentFrame->GetFirstChild(nsnull);
+  nsIFrame* prevDocRootFrame = prevPageContentFrame->GetFirstChild(nsnull);
+  if (!docRootFrame || !prevDocRootFrame) {
     // document's root element frame missing
     return NS_ERROR_UNEXPECTED;
   }
 
   nsFrameItems fixedPlaceholders;
   nsIFrame* firstFixed = prevPageContentFrame->GetFirstChild(nsGkAtoms::fixedList);
   if (!firstFixed) {
     return NS_OK;
@@ -10508,29 +10450,29 @@ nsCSSFrameConstructor::ReplicateFixedFra
   // Iterate across fixed frames and replicate each whose placeholder is a
   // descendant of aFrame. (We don't want to explicitly copy placeholders that
   // are within fixed frames, because that would cause duplicates on the new
   // page - bug 389619)
   for (nsIFrame* fixed = firstFixed; fixed; fixed = fixed->GetNextSibling()) {
     nsIFrame* prevPlaceholder = nsnull;
     mPresShell->GetPlaceholderFrameFor(fixed, &prevPlaceholder);
     if (prevPlaceholder &&
-        nsLayoutUtils::IsProperAncestorFrame(prevCanvasFrame, prevPlaceholder)) {
+        nsLayoutUtils::IsProperAncestorFrame(prevDocRootFrame, prevPlaceholder)) {
       nsresult rv = ConstructFrame(state, fixed->GetContent(),
-                                   canvasFrame, fixedPlaceholders);
+                                   docRootFrame, fixedPlaceholders);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
   // Add the placeholders to our primary child list.
-  // XXXbz this is a little screwed up, since the fixed frames will have 
-  // broken auto-positioning. Oh, well.
-  NS_ASSERTION(!canvasFrame->GetFirstChild(nsnull),
+  // XXXbz this is a little screwed up, since the fixed frames will have the
+  // wrong parent block and hence auto-positioning will be broken.  Oh, well.
+  NS_ASSERTION(!docRootFrame->GetFirstChild(nsnull),
                "leaking frames; doc root continuation must be empty");
-  canvasFrame->SetInitialChildList(nsnull, fixedPlaceholders.childList);
+  docRootFrame->SetInitialChildList(nsnull, fixedPlaceholders.childList);
   return NS_OK;
 }
 
 static PRBool
 IsBindingAncestor(nsIContent* aContent, nsIContent* aBindingRoot)
 {
   while (PR_TRUE) {
     // Native-anonymous content doesn't contain insertion points, so
@@ -12851,32 +12793,24 @@ nsCSSFrameConstructor::ReframeContaining
       }
     }
   }
 
   // If we get here, we're screwed!
   return ReconstructDocElementHierarchyInternal();
 }
 
-nsresult
-nsCSSFrameConstructor::RemoveFixedItems(const nsFrameConstructorState& aState,
-                                        nsIFrame *aRootElementFrame)
+nsresult nsCSSFrameConstructor::RemoveFixedItems(const nsFrameConstructorState& aState)
 {
   nsresult rv=NS_OK;
 
   if (mFixedContainingBlock) {
     nsIFrame *fixedChild = nsnull;
     do {
       fixedChild = mFixedContainingBlock->GetFirstChild(nsGkAtoms::fixedList);
-      if (fixedChild == aRootElementFrame) {
-        // Skip the root element frame, if it happens to be fixed-positioned
-        // It will be explicitly removed later in
-        // ReconstructDocElementHierarchyInternal
-        fixedChild = fixedChild->GetNextSibling();
-      }
       if (fixedChild) {
         // Remove the placeholder so it doesn't end up sitting about pointing
         // to the removed fixed frame.
         nsPlaceholderFrame *placeholderFrame =
           aState.mFrameManager->GetPlaceholderFrameFor(fixedChild);
         NS_ASSERTION(placeholderFrame, "no placeholder for fixed-pos frame");
         NS_ASSERTION(placeholderFrame->GetType() ==
                      nsGkAtoms::placeholderFrame,
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -265,17 +265,17 @@ private:
   nsresult ReinsertContent(nsIContent*    aContainer,
                            nsIContent*    aChild);
 
   nsresult ConstructPageFrame(nsIPresShell*  aPresShell, 
                               nsPresContext* aPresContext,
                               nsIFrame*      aParentFrame,
                               nsIFrame*      aPrevPageFrame,
                               nsIFrame*&     aPageFrame,
-                              nsIFrame*&     aCanvasFrame);
+                              nsIFrame*&     aPageContentFrame);
 
   void DoContentStateChanged(nsIContent*     aContent,
                              PRInt32         aStateMask);
 
   /* aMinHint is the minimal change that should be made to the element */
   void RestyleElement(nsIContent*     aContent,
                       nsIFrame*       aPrimaryFrame,
                       nsChangeHint    aMinHint);
@@ -1044,18 +1044,17 @@ private:
 
   nsresult InsertFirstLineFrames(nsFrameConstructorState& aState,
                                  nsIContent*              aContent,
                                  nsIFrame*                aBlockFrame,
                                  nsIFrame**               aParentFrame,
                                  nsIFrame*                aPrevSibling,
                                  nsFrameItems&            aFrameItems);
 
-  nsresult RemoveFixedItems(const nsFrameConstructorState& aState,
-                            nsIFrame*                      aRootElementFrame);
+  nsresult RemoveFixedItems(const nsFrameConstructorState& aState);
 
   // Find the right frame to use for aContent when looking for sibling
   // frames for aTargetContent.  If aPrevSibling is true, this
   // will look for last continuations, etc, as necessary.  This calls
   // IsValidSibling as needed; if that returns false it returns null.
   //
   // @param aTargetContentDisplay the CSS display enum for aTargetContent if
   // already known, UNSET_DISPLAY otherwise.
@@ -1160,19 +1159,16 @@ private:
     nsCOMPtr<nsIPresShell> mPresShell;
     nsLazyFrameConstructionCallback* mCallback;
     void* mArg;
   };
 
   nsIDocument*        mDocument;  // Weak ref
   nsIPresShell*       mPresShell; // Weak ref
 
-  // See the comment at the start of ConstructRootFrame for more details
-  // about the following frames.
-  
   // This is not the real CSS 2.1 "initial containing block"! It is just
   // the outermost frame for the root element.
   nsIFrame*           mInitialContainingBlock;
   // This is the frame for the root element that has no pseudo-element style.
   nsIFrame*           mRootElementStyleFrame;
   // This is the containing block for fixed-pos frames --- the viewport
   nsIFrame*           mFixedContainingBlock;
   // This is the containing block that contains the root element ---
@@ -1180,20 +1176,19 @@ private:
   nsIFrame*           mDocElementContainingBlock;
   nsIFrame*           mGfxScrollFrame;
   nsIFrame*           mPageSequenceFrame;
   nsQuoteList         mQuoteList;
   nsCounterManager    mCounterManager;
   PRUint16            mUpdateCount;
   PRPackedBool        mQuotesDirty : 1;
   PRPackedBool        mCountersDirty : 1;
+  PRPackedBool        mInitialContainingBlockIsAbsPosContainer : 1;
   PRPackedBool        mIsDestroyingFrameTree : 1;
   PRPackedBool        mRebuildAllStyleData : 1;
-  // This is true if mDocElementContainingBlock supports absolute positioning
-  PRPackedBool        mHasRootAbsPosContainingBlock : 1;
 
   nsRevocableEventPtr<RestyleEvent> mRestyleEvent;
 
   nsCOMPtr<nsILayoutHistoryState> mTempFrameTreeState;
 
   nsDataHashtable<nsISupportsHashKey, RestyleData> mPendingRestyles;
 
   static nsIXBLService * gXBLService;
--- a/layout/generic/nsAbsoluteContainingBlock.cpp
+++ b/layout/generic/nsAbsoluteContainingBlock.cpp
@@ -47,16 +47,27 @@
 #include "nsHTMLContainerFrame.h"
 #include "nsHTMLParts.h"
 #include "nsPresContext.h"
 
 #ifdef DEBUG
 #include "nsBlockFrame.h"
 #endif
 
+
+nsresult
+nsAbsoluteContainingBlock::FirstChild(const nsIFrame* aDelegatingFrame,
+                                      nsIAtom*        aListName,
+                                      nsIFrame**      aFirstChild) const
+{
+  NS_PRECONDITION(GetChildListName() == aListName, "unexpected child list name");
+  *aFirstChild = mAbsoluteFrames.FirstChild();
+  return NS_OK;
+}
+
 nsresult
 nsAbsoluteContainingBlock::SetInitialChildList(nsIFrame*       aDelegatingFrame,
                                                nsIAtom*        aListName,
                                                nsIFrame*       aChildList)
 {
   NS_PRECONDITION(GetChildListName() == aListName, "unexpected child list name");
 #ifdef NS_DEBUG
   nsFrame::VerifyDirtyBitSet(aChildList);
--- a/layout/generic/nsAbsoluteContainingBlock.h
+++ b/layout/generic/nsAbsoluteContainingBlock.h
@@ -79,17 +79,20 @@ public:
                  mChildListName == nsGkAtoms::fixedList,
                  "should either represent position:fixed or absolute content");
   }
 
 #ifdef DEBUG
   nsIAtom* GetChildListName() const { return mChildListName; }
 #endif
 
-  nsIFrame* GetFirstChild() const { return mAbsoluteFrames.FirstChild(); }
+  nsresult FirstChild(const nsIFrame* aDelegatingFrame,
+                      nsIAtom*        aListName,
+                      nsIFrame**      aFirstChild) const;
+  nsIFrame* GetFirstChild() { return mAbsoluteFrames.FirstChild(); }
 
   nsresult SetInitialChildList(nsIFrame*       aDelegatingFrame,
                                nsIAtom*        aListName,
                                nsIFrame*       aChildList);
   nsresult AppendFrames(nsIFrame*      aDelegatingFrame,
                         nsIAtom*       aListName,
                         nsIFrame*      aFrameList);
   nsresult InsertFrames(nsIFrame*      aDelegatingFrame,
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -515,17 +515,19 @@ nsBlockFrame::GetBaseline() const
 
 /////////////////////////////////////////////////////////////////////////////
 // Child frame enumeration
 
 nsIFrame*
 nsBlockFrame::GetFirstChild(nsIAtom* aListName) const
 {
   if (nsGkAtoms::absoluteList == aListName) {
-    return mAbsoluteContainer.GetFirstChild();
+    nsIFrame* result = nsnull;
+    mAbsoluteContainer.FirstChild(this, aListName, &result);
+    return result;
   }
   else if (nsnull == aListName) {
     return (mLines.empty()) ? nsnull : mLines.front()->mFirstChild;
   }
   else if (aListName == nsGkAtoms::overflowList) {
     nsLineList* overflowLines = GetOverflowLines();
     return overflowLines ? overflowLines->front()->mFirstChild : nsnull;
   }
@@ -796,35 +798,37 @@ CalculateContainingBlockSizeForAbsolutes
 
   nsSize cbSize(aFrameSize);
     // Containing block is relative to the padding edge
   const nsMargin& border =
     aReflowState.mComputedBorderPadding - aReflowState.mComputedPadding;
   cbSize.width -= border.LeftRight();
   cbSize.height -= border.TopBottom();
 
-  if (frame->GetParent()->GetContent() == frame->GetContent() &&
-      frame->GetParent()->GetType() != nsGkAtoms::canvasFrame) {
-    // We are a wrapped frame for the content (and the wrapper is not the
-    // canvas frame, whose size is not meaningful here).
-    // Use the container's dimensions, if they have been precomputed.
+  if (frame->GetParent()->GetContent() == frame->GetContent()) {
+    // We are a wrapped frame for the content. Use the container's
+    // dimensions, if they have been precomputed.
     // XXX This is a hack! We really should be waiting until the outermost
     // frame is fully reflowed and using the resulting dimensions, even
     // if they're intrinsic.
     // In fact we should be attaching absolute children to the outermost
     // frame and not always sticking them in block frames.
 
     // First, find the reflow state for the outermost frame for this
     // content.
     const nsHTMLReflowState* aLastRS = &aReflowState;
     const nsHTMLReflowState* lastButOneRS = &aReflowState;
+    PRBool isCanvasBlock = PR_FALSE;
     while (aLastRS->parentReflowState &&
            aLastRS->parentReflowState->frame->GetContent() == frame->GetContent()) {
       lastButOneRS = aLastRS;
       aLastRS = aLastRS->parentReflowState;
+      if (aLastRS->frame->GetType() == nsGkAtoms::canvasFrame) {
+        isCanvasBlock = PR_TRUE;
+      }
     }
     if (aLastRS != &aReflowState) {
       // Scrollbars need to be specifically excluded, if present, because they are outside the
       // padding-edge. We need better APIs for getting the various boxes from a frame.
       nsIScrollableFrame* scrollFrame;
       CallQueryInterface(aLastRS->frame, &scrollFrame);
       nsMargin scrollbars(0,0,0,0);
       if (scrollFrame) {
@@ -835,21 +839,33 @@ CalculateContainingBlockSizeForAbsolutes
           scrollbars.top = scrollbars.bottom = 0;
         }
         if (!lastButOneRS->mFlags.mAssumingVScrollbar) {
           scrollbars.left = scrollbars.right = 0;
         }
       }
       // We found a reflow state for the outermost wrapping frame, so use
       // its computed metrics if available
-      if (aLastRS->ComputedWidth() != NS_UNCONSTRAINEDSIZE) {
+      // XXX grotesque hack for Firefox 2 compatibility until we can
+      // properly fix abs-pos containers! If this is the block for
+      // the root element, don't adjust the width here, just use the block's
+      // width. We have to do this because the abs-pos frame will be
+      // positioned relative to the block, not the canvas frame, and the
+      // block might have borders and margin which will throw things off
+      // if we use the canvas frame width.
+      // Positioning abs-pos frames relative to the canvas is bug 425432.
+      if (aLastRS->ComputedWidth() != NS_UNCONSTRAINEDSIZE && !isCanvasBlock) {
         cbSize.width = PR_MAX(0,
           aLastRS->ComputedWidth() + aLastRS->mComputedPadding.LeftRight() - scrollbars.LeftRight());
       }
       if (aLastRS->ComputedHeight() != NS_UNCONSTRAINEDSIZE) {
+        // XXX This can be terribly wrong if we're the root element's block,
+        // because our margin and borders will be included in the height
+        // here but the abs-pos element(s) are positioned relative to
+        // our content rect...
         cbSize.height = PR_MAX(0,
           aLastRS->ComputedHeight() + aLastRS->mComputedPadding.TopBottom() - scrollbars.TopBottom());
       }
     }
   }
 
   return cbSize;
 }
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -1579,19 +1579,16 @@ nsContainerFrame::List(FILE* out, PRInt3
             NS_LossyConvertUTF16toASCII(atomString).get());
   }
 
   // Output the children
   nsIAtom* listName = nsnull;
   PRInt32 listIndex = 0;
   PRBool outputOneList = PR_FALSE;
   do {
-    if (!outputOneList) {
-      fputs("\n", out);
-    }
     nsIFrame* kid = GetFirstChild(listName);
     if (nsnull != kid) {
       if (outputOneList) {
         IndentBy(out, aIndent);
       }
       outputOneList = PR_TRUE;
       nsAutoString tmp;
       if (nsnull != listName) {
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -5554,29 +5554,22 @@ nsFrame::CorrectStyleParentFrame(nsIFram
          // ancestor.
          aChildPseudo != nsGkAtoms::placeholderFrame)) {
       return parent;
     }
 
     parent = parent->GetParent();
   } while (parent);
 
-  if (aProspectiveParent->GetStyleContext()->GetPseudoType() ==
-      nsCSSAnonBoxes::viewportScroll) {
-    // aProspectiveParent is the scrollframe for a viewport
-    // and the kids are the anonymous scrollbars
-    return aProspectiveParent;
-  }
-
-  // We can get here if the root element is absolutely positioned.
-  // We can't test for this very accurately, but it can only happen
-  // when the prospective parent is a canvas frame.
-  NS_ASSERTION(aProspectiveParent->GetType() == nsGkAtoms::canvasFrame,
+  // We can get here if aProspectiveParent is the scrollframe for a viewport
+  // and the kids are the anonymous scrollbars.
+  NS_ASSERTION(aProspectiveParent->GetStyleContext()->GetPseudoType() ==
+                 nsCSSAnonBoxes::viewportScroll,
                "Should have found a parent before this");
-  return nsnull;
+  return aProspectiveParent;
 }
 
 nsresult
 nsFrame::DoGetParentStyleContextFrame(nsPresContext* aPresContext,
                                       nsIFrame**      aProviderFrame,
                                       PRBool*         aIsChild)
 {
   *aIsChild = PR_FALSE;
--- a/layout/generic/nsHTMLFrame.cpp
+++ b/layout/generic/nsHTMLFrame.cpp
@@ -49,82 +49,68 @@
 #include "nsGUIEvent.h"
 #include "nsStyleConsts.h"
 #include "nsGkAtoms.h"
 #include "nsIEventStateManager.h"
 #include "nsIDeviceContext.h"
 #include "nsIPresShell.h"
 #include "nsIScrollPositionListener.h"
 #include "nsDisplayList.h"
-#include "nsAbsoluteContainingBlock.h"
 
 // for focus
 #include "nsIDOMWindowInternal.h"
 #include "nsIFocusController.h"
 #include "nsIScrollableFrame.h"
 #include "nsIScrollableView.h"
 #include "nsIDocShell.h"
 #include "nsICanvasFrame.h"
 
 #ifdef DEBUG_rods
 //#define DEBUG_CANVAS_FOCUS
 #endif
 
-#define CANVAS_ABS_POS_CHILD_LIST NS_CONTAINER_LIST_COUNT_INCL_OC
-
 // Interface IDs
 
 /**
  * Root frame class.
  *
  * The root frame is the parent frame for the document element's frame.
  * It only supports having a single child frame which must be an area
  * frame
  */
 class CanvasFrame : public nsHTMLContainerFrame, 
                     public nsIScrollPositionListener, 
                     public nsICanvasFrame {
 public:
   CanvasFrame(nsStyleContext* aContext)
-  : nsHTMLContainerFrame(aContext), mDoPaintFocus(PR_FALSE),
-    mAbsoluteContainer(nsGkAtoms::absoluteList) {}
+  : nsHTMLContainerFrame(aContext), mDoPaintFocus(PR_FALSE) {}
 
    // nsISupports
   NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
 
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
   virtual void Destroy();
 
-  NS_IMETHOD SetInitialChildList(nsIAtom*        aListName,
-                                 nsIFrame*       aChildList);
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
                           nsIFrame*       aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
                           nsIFrame*       aFrameList);
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
 
-  virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
-  virtual nsIFrame* GetFirstChild(nsIAtom* aListName) const;
-
   virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
   virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
   NS_IMETHOD Reflow(nsPresContext*          aPresContext,
                     nsHTMLReflowMetrics&     aDesiredSize,
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus&          aStatus);
   virtual PRBool IsContainingBlock() const { return PR_TRUE; }
-  virtual PRBool IsFrameOfType(PRUint32 aFlags) const
-  {
-    return nsHTMLContainerFrame::IsFrameOfType(aFlags &
-             ~(nsIFrame::eCanContainOverflowContainers));
-  }
 
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists);
 
   void PaintFocus(nsIRenderingContext& aRenderingContext, nsPoint aPt);
 
   // nsIScrollPositionListener
@@ -137,47 +123,31 @@ public:
 
   /**
    * Get the "type" of the frame
    *
    * @see nsGkAtoms::canvasFrame
    */
   virtual nsIAtom* GetType() const;
 
-  virtual nsresult StealFrame(nsPresContext* aPresContext,
-                              nsIFrame*      aChild,
-                              PRBool         aForceNormal)
-  {
-    NS_ASSERTION(!aForceNormal, "No-one should be passing this in here");
-
-    // CanvasFrame keeps overflow container continuations of its child
-    // frame in main child list
-    nsresult rv = nsContainerFrame::StealFrame(aPresContext, aChild, PR_TRUE);
-    if (NS_FAILED(rv)) {
-      rv = nsContainerFrame::StealFrame(aPresContext, aChild);
-    }
-    return rv;
-  }
-
 #ifdef DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
   NS_IMETHOD GetContentForEvent(nsPresContext* aPresContext,
                                 nsEvent* aEvent,
                                 nsIContent** aContent);
 
   nsRect CanvasArea() const;
 
 protected:
   virtual PRIntn GetSkipSides() const;
 
   // Data members
-  PRPackedBool              mDoPaintFocus;
-  nsCOMPtr<nsIViewManager>  mViewManager;
-  nsAbsoluteContainingBlock mAbsoluteContainer;
+  PRPackedBool             mDoPaintFocus;
+  nsCOMPtr<nsIViewManager> mViewManager;
 
 private:
   NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; }
   NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; }
 };
 
 
 //----------------------------------------------------------------------
@@ -223,18 +193,16 @@ CanvasFrame::Init(nsIContent*      aCont
   }
 
   return rv;
 }
 
 void
 CanvasFrame::Destroy()
 {
-  mAbsoluteContainer.DestroyFrames(this);
-
   nsIScrollableView* scrollingView = nsnull;
   mViewManager->GetRootScrollableView(&scrollingView);
   if (scrollingView) {
     scrollingView->RemoveScrollPositionListener(this);
   }
 
   nsHTMLContainerFrame::Destroy();
 }
@@ -273,42 +241,30 @@ CanvasFrame::ScrollPositionDidChange(nsI
   return NS_OK;
 }
 
 NS_IMETHODIMP
 CanvasFrame::SetHasFocus(PRBool aHasFocus)
 {
   if (mDoPaintFocus != aHasFocus) {
     mDoPaintFocus = aHasFocus;
-    mViewManager->UpdateAllViews(NS_VMREFRESH_NO_SYNC);
+    nsIViewManager* vm = PresContext()->PresShell()->GetViewManager();
+    if (vm) {
+      vm->UpdateAllViews(NS_VMREFRESH_NO_SYNC);
+    }
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
-CanvasFrame::SetInitialChildList(nsIAtom*        aListName,
-                                 nsIFrame*       aChildList)
-{
-  if (nsGkAtoms::absoluteList == aListName)
-    return mAbsoluteContainer.SetInitialChildList(this, aListName, aChildList);
-
-  NS_ASSERTION(aListName || !aChildList || !aChildList->GetNextSibling(),
-               "Primary child list can have at most one frame in it");
-  return nsHTMLContainerFrame::SetInitialChildList(aListName, aChildList);
-}
-
-NS_IMETHODIMP
 CanvasFrame::AppendFrames(nsIAtom*        aListName,
                           nsIFrame*       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");
   if (aListName) {
     // We only support unnamed principal child list
     rv = NS_ERROR_INVALID_ARG;
 
   } else if (!mFrames.IsEmpty()) {
     // We only allow a single child frame
@@ -331,19 +287,16 @@ CanvasFrame::AppendFrames(nsIAtom*      
 
 NS_IMETHODIMP
 CanvasFrame::InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
                           nsIFrame*       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
   NS_PRECONDITION(!aPrevFrame, "unexpected previous sibling frame");
   if (aPrevFrame) {
     rv = NS_ERROR_UNEXPECTED;
   } else {
     rv = AppendFrames(aListName, aFrameList);
   }
@@ -352,19 +305,16 @@ CanvasFrame::InsertFrames(nsIAtom*      
 }
 
 NS_IMETHODIMP
 CanvasFrame::RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame)
 {
   nsresult  rv;
 
-  if (nsGkAtoms::absoluteList == aListName)
-    return mAbsoluteContainer.RemoveFrame(this, aListName, aOldFrame);
-
   NS_ASSERTION(!aListName, "unexpected child list name");
   if (aListName) {
     // We only support the unnamed principal child list
     rv = NS_ERROR_INVALID_ARG;
   
   } else if (aOldFrame == mFrames.FirstChild()) {
     // It's our one and only child frame
     // Damage the area occupied by the deleted frame
@@ -380,34 +330,16 @@ CanvasFrame::RemoveFrame(nsIAtom*       
                             NS_FRAME_HAS_DIRTY_CHILDREN);
   } else {
     rv = NS_ERROR_FAILURE;
   }
 
   return rv;
 }
 
-nsIAtom*
-CanvasFrame::GetAdditionalChildListName(PRInt32 aIndex) const
-{
-  if (CANVAS_ABS_POS_CHILD_LIST == aIndex)
-    return nsGkAtoms::absoluteList;
-
-  return nsHTMLContainerFrame::GetAdditionalChildListName(aIndex);
-}
-
-nsIFrame*
-CanvasFrame::GetFirstChild(nsIAtom* aListName) const
-{
-  if (nsGkAtoms::absoluteList == aListName)
-    return mAbsoluteContainer.GetFirstChild();
-
-  return nsHTMLContainerFrame::GetFirstChild(aListName);
-}
-
 nsRect CanvasFrame::CanvasArea() const
 {
   nsRect result(GetOverflowRect());
 
   nsIScrollableFrame *scrollableFrame;
   CallQueryInterface(GetParent(), &scrollableFrame);
   if (scrollableFrame) {
     nsIScrollableView* scrollableView = scrollableFrame->GetScrollableView();
@@ -482,38 +414,31 @@ public:
 };
 
 NS_IMETHODIMP
 CanvasFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists)
 {
   nsresult rv;
-
-  if (GetPrevInFlow()) {
-    DisplayOverflowContainers(aBuilder, aDirtyRect, aLists);
-  }
-
-  aBuilder->MarkFramesForDisplayList(this, mAbsoluteContainer.GetFirstChild(), aDirtyRect);
-  
   // Force a background to be shown. We may have a background propagated to us,
   // in which case GetStyleBackground wouldn't have the right background
   // and the code in nsFrame::DisplayBorderBackgroundOutline might not give us
   // a background.
   // We don't have any border or outline, and our background draws over
   // the overflow area, so just add nsDisplayCanvasBackground instead of
   // calling DisplayBorderBackgroundOutline.
   if (IsVisibleForPainting(aBuilder)) { 
     rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
            nsDisplayCanvasBackground(this));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  nsIFrame* kid;
-  for (kid = GetFirstChild(nsnull); kid; kid = kid->GetNextSibling()) {
+  nsIFrame* kid = GetFirstChild(nsnull);
+  if (kid) {
     // Put our child into its own pseudo-stack.
     rv = BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists,
                                   DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
 #ifdef DEBUG_CANVAS_FOCUS
   nsCOMPtr<nsIContent> focusContent;
@@ -598,150 +523,88 @@ CanvasFrame::GetPrefWidth(nsIRenderingCo
   if (mFrames.IsEmpty())
     result = 0;
   else
     result = mFrames.FirstChild()->GetPrefWidth(aRenderingContext);
   return result;
 }
 
 NS_IMETHODIMP
-CanvasFrame::Reflow(nsPresContext*           aPresContext,
+CanvasFrame::Reflow(nsPresContext*          aPresContext,
                     nsHTMLReflowMetrics&     aDesiredSize,
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus&          aStatus)
 {
   DO_GLOBAL_REFLOW_COUNT("CanvasFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
   NS_FRAME_TRACE_REFLOW_IN("CanvasFrame::Reflow");
 
   // Initialize OUT parameter
   aStatus = NS_FRAME_COMPLETE;
 
-  CanvasFrame* prevCanvasFrame = static_cast<CanvasFrame*>
-                                               (GetPrevInFlow());
-  if (prevCanvasFrame) {
-    nsIFrame* overflow = prevCanvasFrame->GetOverflowFrames(aPresContext, PR_TRUE);
-    if (overflow) {
-      NS_ASSERTION(!overflow->GetNextSibling(),
-                   "must have doc root as canvas frame's only child");
-      nsHTMLContainerFrame::ReparentFrameView(aPresContext, overflow, prevCanvasFrame, this);
-      // Prepend overflow to the our child list. There may already be
-      // children placeholders for fixed-pos elements, which don't get
-      // reflowed but must not be lost until the canvas frame is destroyed.
-      mFrames.InsertFrames(this, nsnull, overflow);
-    }
-  }
-
-  // Reflow our one and only normal child frame. It's either the root
-  // element's frame or a placeholder for that frame, if the root element
-  // is abs-pos or fixed-pos. We may have additional children which
-  // are placeholders for continuations of fixed-pos content, but those
-  // don't need to be reflowed. The normal child is always comes before
-  // the fixed-pos placeholders, because we insert it at the start
-  // of the child list, above.
+  // Reflow our one and only child frame
   nsHTMLReflowMetrics kidDesiredSize;
   if (mFrames.IsEmpty()) {
     // We have no child frame, so return an empty size
     aDesiredSize.width = aDesiredSize.height = 0;
   } else {
     nsIFrame* kidFrame = mFrames.FirstChild();
     PRBool kidDirty = (kidFrame->GetStateBits() & NS_FRAME_IS_DIRTY) != 0;
 
+    // We must specify an unconstrained available height, because constrained
+    // is only for when we're paginated...
     nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame,
                                      nsSize(aReflowState.availableWidth,
-                                            aReflowState.availableHeight));
+                                            NS_UNCONSTRAINEDSIZE));
 
     if (aReflowState.mFlags.mVResize &&
         (kidFrame->GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_HEIGHT)) {
       // Tell our kid it's being vertically resized too.  Bit of a
       // hack for framesets.
       kidReflowState.mFlags.mVResize = PR_TRUE;
     }
-
-    nsPoint kidPt(kidReflowState.mComputedMargin.left,
-                  kidReflowState.mComputedMargin.top);
-    // Apply CSS relative positioning
-    const nsStyleDisplay* styleDisp = kidFrame->GetStyleDisplay();
-    if (NS_STYLE_POSITION_RELATIVE == styleDisp->mPosition) {
-      kidPt += nsPoint(kidReflowState.mComputedOffsets.left,
-                       kidReflowState.mComputedOffsets.top);
-    }
-
+    
     // Reflow the frame
     ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState,
-                kidPt.x, kidPt.y, 0, aStatus);
+                kidReflowState.mComputedMargin.left, kidReflowState.mComputedMargin.top,
+                0, aStatus);
 
     // Complete the reflow and position and size the child frame
     FinishReflowChild(kidFrame, aPresContext, &kidReflowState, kidDesiredSize,
-                      kidPt.x, kidPt.y, 0);
-
-    if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
-      nsIFrame* nextFrame = kidFrame->GetNextInFlow();
-      NS_ASSERTION(nextFrame || aStatus & NS_FRAME_REFLOW_NEXTINFLOW,
-        "If it's incomplete and has no nif yet, it must flag a nif reflow.");
-      if (!nextFrame) {
-        nsresult rv = nsHTMLContainerFrame::CreateNextInFlow(aPresContext,
-                                              this, kidFrame, nextFrame);
-        NS_ENSURE_SUCCESS(rv, rv);
-        kidFrame->SetNextSibling(nextFrame->GetNextSibling());
-        nextFrame->SetNextSibling(nsnull);
-        SetOverflowFrames(aPresContext, nextFrame);
-        // Root overflow containers will be normal children of
-        // the canvas frame, but that's ok because there
-        // aren't any other frames we need to isolate them from
-        // during reflow.
-      }
-      if (NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus)) {
-        nextFrame->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
-      }
-    }
+                      kidReflowState.mComputedMargin.left,
+                      kidReflowState.mComputedMargin.top, 0);
 
     // If the child frame was just inserted, then we're responsible for making sure
     // it repaints
     if (kidDirty) {
       // But we have a new child, which will affect our background, so
       // invalidate our whole rect.
       // Note: Even though we request to be sized to our child's size, our
       // scroll frame ensures that we are always the size of the viewport.
       // Also note: GetPosition() on a CanvasFrame is always going to return
       // (0, 0). We only want to invalidate GetRect() since GetOverflowRect()
       // could also include overflow to our top and left (out of the viewport)
       // which doesn't need to be painted.
       nsIFrame* viewport = PresContext()->GetPresShell()->GetRootFrame();
       viewport->Invalidate(nsRect(nsPoint(0, 0), viewport->GetSize()));
     }
-    
+
     // Return our desired size (which doesn't matter)
-    aDesiredSize.width = aReflowState.ComputedWidth();
-    aDesiredSize.height = aReflowState.ComputedHeight();
+    aDesiredSize.width = aReflowState.availableWidth;
+    aDesiredSize.height = kidDesiredSize.height +
+                          kidReflowState.mComputedMargin.TopBottom();
 
     aDesiredSize.mOverflowArea.UnionRect(
       nsRect(0, 0, aDesiredSize.width, aDesiredSize.height),
-      kidDesiredSize.mOverflowArea + kidPt);
-
-    if (mAbsoluteContainer.HasAbsoluteFrames()) {
-      PRBool widthChanged = aDesiredSize.width != mRect.width;
-      PRBool heightChanged = aDesiredSize.height != mRect.height;
-      nsRect absPosBounds;
-      mAbsoluteContainer.Reflow(this, aPresContext, aReflowState, aStatus,
-                                aDesiredSize.width, aDesiredSize.height,
-                                PR_TRUE, widthChanged, heightChanged,
-                                &absPosBounds);
-      aDesiredSize.mOverflowArea.UnionRect(aDesiredSize.mOverflowArea, absPosBounds);
-    }
+      kidDesiredSize.mOverflowArea +
+        nsPoint(kidReflowState.mComputedMargin.left,
+                kidReflowState.mComputedMargin.top));
+    FinishAndStoreOverflow(&aDesiredSize);
   }
 
-  if (prevCanvasFrame) {
-    ReflowOverflowContainerChildren(aPresContext, aReflowState,
-                                    aDesiredSize.mOverflowArea, 0,
-                                    aStatus);
-  }
-
-  FinishAndStoreOverflow(&aDesiredSize);
-
   NS_FRAME_TRACE_REFLOW_OUT("CanvasFrame::Reflow", aStatus);
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return NS_OK;
 }
 
 PRIntn
 CanvasFrame::GetSkipSides() const
 {
--- a/layout/generic/nsHTMLParts.h
+++ b/layout/generic/nsHTMLParts.h
@@ -108,34 +108,41 @@ nsIFrame*
 NS_NewAreaFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, PRUint32 aFlags);
 
 // These AreaFrame's shrink wrap around their contents
 inline nsIFrame*
 NS_NewTableCellInnerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) {
   return NS_NewBlockFrame(aPresShell, aContext);
 }
 
-// This type of BlockFrame is a margin root, but does not shrink wrap
+// This type of AreaFrame is the document root, a margin root, and the
+// initial containing block for absolutely positioned elements
+inline nsIFrame*
+NS_NewDocumentElementFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) {
+  return NS_NewAreaFrame(aPresShell, aContext, NS_BLOCK_SPACE_MGR|NS_BLOCK_MARGIN_ROOT);
+}
+
+// This type of AreaFrame is a margin root, but does not shrink wrap
 inline nsIFrame*
 NS_NewAbsoluteItemWrapperFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) {
-  return NS_NewBlockFrame(aPresShell, aContext, NS_BLOCK_SPACE_MGR|NS_BLOCK_MARGIN_ROOT);
+  return NS_NewAreaFrame(aPresShell, aContext, NS_BLOCK_SPACE_MGR|NS_BLOCK_MARGIN_ROOT);
 }
 
-// This type of BlockFrame shrink wraps
+// This type of AreaFrame shrink wraps
 inline nsIFrame*
 NS_NewFloatingItemWrapperFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) {
-  return NS_NewBlockFrame(aPresShell, aContext,
+  return NS_NewAreaFrame(aPresShell, aContext,
     NS_BLOCK_SPACE_MGR|NS_BLOCK_MARGIN_ROOT);
 }
 
-// This type of BlockFrame doesn't use its own space manager and
+// This type of AreaFrame doesn't use its own space manager and
 // doesn't shrink wrap.
 inline nsIFrame*
 NS_NewRelativeItemWrapperFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, PRUint32 aFlags) {
-  return NS_NewBlockFrame(aPresShell, aContext, aFlags);
+  return NS_NewAreaFrame(aPresShell, aContext, aFlags);
 }
 
 nsIFrame*
 NS_NewBRFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
 nsIFrame*
 NS_NewCommentFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
--- a/layout/generic/nsHTMLReflowState.cpp
+++ b/layout/generic/nsHTMLReflowState.cpp
@@ -1526,17 +1526,35 @@ nsHTMLReflowState::ComputeContainingBloc
       aContainingBlockHeight = aContainingBlockRS->frame->GetRect().height -
         computedBorder.TopBottom();
       NS_ASSERTION(aContainingBlockHeight >= 0,
                    "Negative containing block height!");
     } else {
       // If the ancestor is block-level, the containing block is formed by the
       // padding edge of the ancestor
       aContainingBlockWidth += aContainingBlockRS->mComputedPadding.LeftRight();
-      aContainingBlockHeight += aContainingBlockRS->mComputedPadding.TopBottom();
+
+      // If the containing block is the initial containing block and it has a
+      // height that depends on its content, then use the viewport height instead.
+      // This gives us a reasonable value against which to compute percentage
+      // based heights and to do bottom relative positioning
+      if ((NS_AUTOHEIGHT == aContainingBlockHeight) &&
+          nsLayoutUtils::IsInitialContainingBlock(aContainingBlockRS->frame)) {
+
+        // Use the viewport height as the containing block height
+        const nsHTMLReflowState* rs = aContainingBlockRS->parentReflowState;
+        while (rs) {
+          aContainingBlockHeight = rs->mComputedHeight;
+          rs = rs->parentReflowState;
+        }
+
+      } else {
+        aContainingBlockHeight +=
+          aContainingBlockRS->mComputedPadding.TopBottom();
+      }
     }
   } else {
     // an element in quirks mode gets a containing block based on looking for a
     // parent with a non-auto height if the element has a percent height
     if (NS_AUTOHEIGHT == aContainingBlockHeight) {
       if (eCompatibility_NavQuirks == aPresContext->CompatibilityMode() &&
           mStylePosition->mHeight.GetUnit() == eStyleUnit_Percent) {
         aContainingBlockHeight = CalcQuirkContainingBlockHeight(aContainingBlockRS);
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -1068,18 +1068,21 @@ nsPositionedInlineFrame::GetAdditionalCh
     return nsGkAtoms::absoluteList;
   }
   return nsnull;
 }
 
 nsIFrame*
 nsPositionedInlineFrame::GetFirstChild(nsIAtom* aListName) const
 {
-  if (nsGkAtoms::absoluteList == aListName)
-    return mAbsoluteContainer.GetFirstChild();
+  if (nsGkAtoms::absoluteList == aListName) {
+    nsIFrame* result = nsnull;
+    mAbsoluteContainer.FirstChild(this, aListName, &result);
+    return result;
+  }
 
   return nsInlineFrame::GetFirstChild(aListName);
 }
 
 nsIAtom*
 nsPositionedInlineFrame::GetType() const
 {
   return nsGkAtoms::positionedInlineFrame;
--- a/layout/generic/nsPageContentFrame.cpp
+++ b/layout/generic/nsPageContentFrame.cpp
@@ -64,48 +64,137 @@ nsPageContentFrame::ComputeSize(nsIRende
 {
   NS_ASSERTION(mPD, "Pages are supposed to have page data");
   nscoord height = (!mPD || mPD->mReflowSize.height == NS_UNCONSTRAINEDSIZE)
                    ? NS_UNCONSTRAINEDSIZE
                    : (mPD->mReflowSize.height - mPD->mReflowMargin.TopBottom());
   return nsSize(aAvailableWidth, height);
 }
 
+/**
+ * Returns true if aFrame is a placeholder for one of our fixed frames.
+ */
+inline PRBool
+nsPageContentFrame::IsFixedPlaceholder(nsIFrame* aFrame)
+{
+  if (!aFrame || nsGkAtoms::placeholderFrame != aFrame->GetType())
+    return PR_FALSE;
+
+  return static_cast<nsPlaceholderFrame*>(aFrame)->GetOutOfFlowFrame()
+           ->GetParent() == this;
+}
+
+/**
+ * Steals replicated fixed placeholder frames from aDocRoot so they don't
+ * get in the way of reflow.
+ */
+inline nsFrameList
+nsPageContentFrame::StealFixedPlaceholders(nsIFrame* aDocRoot)
+{
+  nsPresContext* presContext = PresContext();
+  nsFrameList list;
+  if (GetPrevInFlow()) {
+    for (nsIFrame* f = aDocRoot->GetFirstChild(nsnull);
+        IsFixedPlaceholder(f); f = aDocRoot->GetFirstChild(nsnull)) {
+      nsresult rv = static_cast<nsContainerFrame*>(aDocRoot)
+                      ->StealFrame(presContext, f);
+      NS_ENSURE_SUCCESS(rv, list);
+      list.AppendFrame(nsnull, f);
+    }
+  }
+  return list;
+}
+
+/**
+ * Restores stolen replicated fixed placeholder frames to aDocRoot.
+ */
+static inline nsresult
+ReplaceFixedPlaceholders(nsIFrame*    aDocRoot,
+                         nsFrameList& aPlaceholderList)
+{
+  nsresult rv = NS_OK;
+  if (aPlaceholderList.NotEmpty()) {
+    rv = static_cast<nsContainerFrame*>(aDocRoot)
+           ->AddFrames(aPlaceholderList.FirstChild(), nsnull);
+  }
+  return rv;
+}
+
 NS_IMETHODIMP
 nsPageContentFrame::Reflow(nsPresContext*           aPresContext,
                            nsHTMLReflowMetrics&     aDesiredSize,
                            const nsHTMLReflowState& aReflowState,
                            nsReflowStatus&          aStatus)
 {
   DO_GLOBAL_REFLOW_COUNT("nsPageContentFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
   aStatus = NS_FRAME_COMPLETE;  // initialize out parameter
   nsresult rv = NS_OK;
 
-  if (GetPrevInFlow() && (GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
+  // A PageContentFrame must always have one child: the doc root element's frame.
+  // We only need to get overflow frames if we don't already have that child;
+  // Also we need to avoid repeating the call to ReplicateFixedFrames.
+  nsPageContentFrame* prevPageContentFrame = static_cast<nsPageContentFrame*>
+                                               (GetPrevInFlow());
+  if (mFrames.IsEmpty() && prevPageContentFrame) {
+    // Pull the doc root frame's continuation and copy fixed frames.
+    nsIFrame* overflow = prevPageContentFrame->GetOverflowFrames(aPresContext, PR_TRUE);
+    NS_ASSERTION(overflow && !overflow->GetNextSibling(),
+                 "must have doc root as pageContentFrame's only child");
+    nsHTMLContainerFrame::ReparentFrameView(aPresContext, overflow, prevPageContentFrame, this);
+    // Prepend overflow to the page content frame. There may already be
+    // children placeholders which don't get reflowed but must not be
+    // lost until the page content frame is destroyed.
+    mFrames.InsertFrames(this, nsnull, overflow);
     nsresult rv = aPresContext->PresShell()->FrameConstructor()
                     ->ReplicateFixedFrames(this);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  // A PageContentFrame must always have one child: the canvas frame.
   // Resize our frame allowing it only to be as big as we are
   // XXX Pay attention to the page's border and padding...
   if (mFrames.NotEmpty()) {
     nsIFrame* frame = mFrames.FirstChild();
     nsSize  maxSize(aReflowState.availableWidth, aReflowState.availableHeight);
     nsHTMLReflowState kidReflowState(aPresContext, aReflowState, frame, maxSize);
-    kidReflowState.SetComputedHeight(aReflowState.availableHeight);
 
     mPD->mPageContentSize  = aReflowState.availableWidth;
 
+    // Get replicated fixed frames' placeholders out of the way
+    nsFrameList stolenPlaceholders = StealFixedPlaceholders(frame);
+
     // Reflow the page content area
     rv = ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, 0, 0, 0, aStatus);
     NS_ENSURE_SUCCESS(rv, rv);
 
+    // Put removed fixed placeholders back
+    rv = ReplaceFixedPlaceholders(frame, stolenPlaceholders);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
+      nsIFrame* nextFrame = frame->GetNextInFlow();
+      NS_ASSERTION(nextFrame || aStatus & NS_FRAME_REFLOW_NEXTINFLOW,
+        "If it's incomplete and has no nif yet, it must flag a nif reflow.");
+      if (!nextFrame) {
+        nsresult rv = nsHTMLContainerFrame::CreateNextInFlow(aPresContext,
+                                              this, frame, nextFrame);
+        NS_ENSURE_SUCCESS(rv, rv);
+        frame->SetNextSibling(nextFrame->GetNextSibling());
+        nextFrame->SetNextSibling(nsnull);
+        SetOverflowFrames(aPresContext, nextFrame);
+        // Root overflow containers will be normal children of
+        // the pageContentFrame, but that's ok because there
+        // aren't any other frames we need to isolate them from
+        // during reflow.
+      }
+      if (NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus)) {
+        nextFrame->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
+      }
+    }
+
     // The document element's background should cover the entire canvas, so
     // take into account the combined area and any space taken up by
     // absolutely positioned elements
     nsMargin padding(0,0,0,0);
 
     // XXXbz this screws up percentage padding (sets padding to zero
     // in the percentage padding case)
     kidReflowState.mStylePadding->GetPadding(padding);
--- a/layout/generic/nsPageContentFrame.h
+++ b/layout/generic/nsPageContentFrame.h
@@ -78,12 +78,16 @@ public:
   // Debugging
   NS_IMETHOD  GetFrameName(nsAString& aResult) const;
 #endif
 
 protected:
   nsPageContentFrame(nsStyleContext* aContext) : ViewportFrame(aContext) {}
 
   nsSharedPageData*         mPD;
+
+private:
+  PRBool IsFixedPlaceholder(nsIFrame* aFrame);
+  nsFrameList StealFixedPlaceholders(nsIFrame* aDocRoot);
 };
 
 #endif /* nsPageContentFrame_h___ */
 
--- a/layout/generic/nsViewportFrame.cpp
+++ b/layout/generic/nsViewportFrame.cpp
@@ -174,18 +174,21 @@ ViewportFrame::GetAdditionalChildListNam
   }
 
   return nsnull;
 }
 
 nsIFrame*
 ViewportFrame::GetFirstChild(nsIAtom* aListName) const
 {
-  if (nsGkAtoms::fixedList == aListName)
-    return mFixedContainer.GetFirstChild();
+  if (nsGkAtoms::fixedList == aListName) {
+    nsIFrame* result = nsnull;
+    mFixedContainer.FirstChild(this, aListName, &result);
+    return result;
+  }
 
   return nsContainerFrame::GetFirstChild(aListName);
 }
 
 /* virtual */ nscoord
 ViewportFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
 {
   nscoord result;
@@ -301,17 +304,18 @@ ViewportFrame::Reflow(nsPresContext*    
                           : kidHeight;
 
   // Make a copy of the reflow state and change the computed width and height
   // to reflect the available space for the fixed items
   nsHTMLReflowState reflowState(aReflowState);
   nsPoint offset = AdjustReflowStateForScrollbars(&reflowState);
   
 #ifdef DEBUG
-  nsIFrame* f = mFixedContainer.GetFirstChild();
+  nsIFrame* f;
+  mFixedContainer.FirstChild(this, nsGkAtoms::fixedList, &f);
   NS_ASSERTION(!f || (offset.x == 0 && offset.y == 0),
                "We don't handle correct positioning of fixed frames with "
                "scrollbars in odd positions");
 #endif
 
   // Just reflow all the fixed-pos frames.
   rv = mFixedContainer.Reflow(this, aPresContext, reflowState, aStatus,
                               reflowState.ComputedWidth(),
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -120,17 +120,16 @@ fails == 25888-3r.html 25888-3r-ref.html
 == 163504-1b.html 163504-1-ref.html
 == 163504-2a.html 163504-2-ref.html
 == 163504-2b.html 163504-2-ref.html
 == 169749-1.html 169749-1-ref.html
 == 172073-1.html 172073-1-ref.html
 == 180085-1.html 180085-1-ref.html
 == 180085-2.html 180085-2-ref.html
 == 185388-1.html 185388-1-ref.html
-!= 200774-1.html about:blank # really a crashtest
 == 201215-1.html 201215-1-ref.html
 == 201293-1a.html 201293-1-ref.html
 == 201293-1b.html 201293-1-ref.html
 == 201293-1c.html 201293-1-ref.html
 == 201293-1d.html 201293-1-ref.html
 == 206516-1.html 206516-1-ref.html
 == 210094-1a.html 210094-1-ref.html
 == 210094-1b.html 210094-1-ref.html
@@ -162,37 +161,16 @@ fails == 25888-3r.html 25888-3r-ref.html
 == 234686-19.html 234686-ref.html
 == 234964-1.html 234964-1-ref.html
 == 234964-2.html 234964-2-ref.html
 == 235593-1.html 235593-1-ref.html
 == 236539-1.html 236539-1-ref.html
 == 240470-1.html 240470-1-ref.html
 == 243266-1.html 243266-1-ref.html
 == 243302-1.html 243302-1-ref.html
-== 243519-1.html 243519-1-ref.html
-== 243519-2.html 243519-2-ref.html
-== 243519-3.html 243519-3-ref.html
-== 243519-4a.html 243519-4-ref.html
-== 243519-4b.html 243519-4-ref.html
-== 243519-4c.html 243519-4-ref.html
-== 243519-4d.html 243519-4-ref.html
-== 243519-4e.html 243519-4-ref.html
-== 243519-4f.html 243519-4-ref.html
-== 243519-5a.html 243519-5-ref.html
-== 243519-5b.html 243519-5-ref.html
-== 243519-5c.html 243519-5-ref.html
-== 243519-5d.html 243519-5-ref.html
-== 243519-6.html 243519-6-ref.html
-== 243519-7.html 243519-7-ref.html
-== 243519-8.svg 243519-8-ref.svg
-== 243519-9a.html 243519-9-ref.html
-== 243519-9b.html 243519-9-ref.html
-== 243519-9c.html 243519-9-ref.html
-== 243519-9d.html 243519-9-ref.html
-== 243519-9e.html 243519-9-ref.html
 == 244135-1.html 244135-1-ref.html
 == 244135-2.html 244135-2-ref.html
 == 244932-1.html 244932-1-ref.html
 == 249982-1.html 249982-1-ref.html
 == 253701-1.html 253701-1-ref.html
 == 255820-1.html 255820-1-ref.html
 == 262151-1.html 262151-1-ref.html
 #== 263683-1.html 263683-1-ref.html