Back out bug 10209 and bug 656875 (its regression fix) from Aurora because the work on this bug has not been finished yet
authorEhsan Akhgari <ehsan@mozilla.com>
Wed, 01 Jun 2011 16:18:15 -0400
changeset 71924 a10dd1a539dbce87b47b343fa32e25e2bc61562a
parent 71923 b9f09ba568b45413ec0a81906522a265aa197012
child 71945 613c2f8b57e8bbb8dd41aaabe55ec3dc948bec6c
child 71948 f589ea8489ca25cba2c23845000bd3906f5ca860
push idunknown
push userunknown
push dateunknown
bugs10209, 656875
milestone7.0a1
Back out bug 10209 and bug 656875 (its regression fix) from Aurora because the work on this bug has not been finished yet
content/base/src/nsGkAtomList.h
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSRendering.cpp
layout/base/nsFrameManager.cpp
layout/base/nsFrameManager.h
layout/doc/frame_reflow_debug.html
layout/generic/nsAbsoluteContainingBlock.cpp
layout/generic/nsBlockFrame.cpp
layout/generic/nsBlockFrame.h
layout/generic/nsCanvasFrame.cpp
layout/generic/nsCanvasFrame.h
layout/generic/nsContainerFrame.cpp
layout/generic/nsContainerFrame.h
layout/generic/nsFrame.cpp
layout/generic/nsFrame.h
layout/generic/nsHTMLParts.h
layout/generic/nsHTMLReflowState.cpp
layout/generic/nsIFrame.h
layout/generic/nsInlineFrame.cpp
layout/generic/nsInlineFrame.h
layout/generic/nsLineLayout.cpp
layout/generic/nsPageContentFrame.cpp
layout/generic/nsQueryFrame.h
layout/generic/nsViewportFrame.cpp
layout/generic/nsViewportFrame.h
layout/reftests/bugs/656875.html
layout/reftests/bugs/reftest.list
layout/tables/nsTableFrame.cpp
layout/tables/nsTableOuterFrame.cpp
layout/xul/base/src/nsMenuFrame.cpp
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1741,16 +1741,17 @@ GK_ATOM(menuBarFrame,"MenuBarFrame")
 GK_ATOM(menuFrame,"MenuFrame")
 GK_ATOM(menuPopupFrame,"MenuPopupFrame")
 GK_ATOM(objectFrame, "ObjectFrame")
 GK_ATOM(pageFrame, "PageFrame")
 GK_ATOM(pageBreakFrame, "PageBreakFrame")
 GK_ATOM(pageContentFrame, "PageContentFrame")
 GK_ATOM(placeholderFrame, "PlaceholderFrame")
 GK_ATOM(popupSetFrame, "PopupSetFrame")
+GK_ATOM(positionedInlineFrame, "PositionedInlineFrame")
 GK_ATOM(canvasFrame, "CanvasFrame")
 GK_ATOM(rootFrame, "RootFrame")
 GK_ATOM(scrollFrame, "ScrollFrame")
 GK_ATOM(scrollbarFrame, "ScrollbarFrame")
 GK_ATOM(sequenceFrame, "SequenceFrame")
 GK_ATOM(sliderFrame, "sliderFrame")
 GK_ATOM(tableCaptionFrame, "TableCaptionFrame")
 GK_ATOM(tableCellFrame, "TableCellFrame")
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1015,20 +1015,16 @@ nsFrameConstructorState::PushAbsoluteCon
   mAbsoluteItems = 
     nsAbsoluteItems(AdjustAbsoluteContainingBlock(aNewAbsoluteContainingBlock));
 
   /* See if we're wiring the fixed-pos and abs-pos lists together.  This happens iff
    * we're a transformed element.
    */
   mFixedPosIsAbsPos = (aNewAbsoluteContainingBlock &&
                        aNewAbsoluteContainingBlock->GetStyleDisplay()->HasTransform());
-
-  if (aNewAbsoluteContainingBlock) {
-    aNewAbsoluteContainingBlock->MarkAsAbsoluteContainingBlock();
-  }
 }
 
 void
 nsFrameConstructorState::PushFloatContainingBlock(nsIFrame* aNewFloatContainingBlock,
                                                   nsFrameConstructorSaveState& aSaveState)
 {
   NS_PRECONDITION(!aNewFloatContainingBlock ||
                   aNewFloatContainingBlock->IsFloatContainingBlock(),
@@ -1214,24 +1210,17 @@ nsFrameConstructorState::ProcessFrameIns
   
   // Insert the frames hanging out in aItems.  We can use SetInitialChildList()
   // if the containing block hasn't been reflowed yet (so NS_FRAME_FIRST_REFLOW
   // is set) and doesn't have any frames in the aChildListName child list yet.
   const nsFrameList& childList = containingBlock->GetChildList(aChildListName);
   nsresult rv = NS_OK;
   if (childList.IsEmpty() &&
       (containingBlock->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
-    // If we're injecting absolutely positioned frames, inject them on the
-    // absolute containing block
-    if (aChildListName == containingBlock->GetAbsoluteListName()) {
-      rv = containingBlock->GetAbsoluteContainingBlock()->
-           SetInitialChildList(containingBlock, aChildListName, aFrameItems);
-    } else {
-      rv = containingBlock->SetInitialChildList(aChildListName, aFrameItems);
-    }
+    rv = containingBlock->SetInitialChildList(aChildListName, aFrameItems);
   } else {
     // Note that whether the frame construction context is doing an append or
     // not is not helpful here, since it could be appending to some frame in
     // the middle of the document, which means we're not necessarily
     // appending to the children of the containing block.
     //
     // We need to make sure the 'append to the end of document' case is fast.
     // So first test the last child of the containing block
@@ -1239,33 +1228,33 @@ nsFrameConstructorState::ProcessFrameIns
 
     // CompareTreePosition uses placeholder hierarchy for out of flow frames,
     // so this will make out-of-flows respect the ordering of placeholders,
     // which is great because it takes care of anonymous content.
     nsIFrame* firstNewFrame = aFrameItems.FirstChild();  
     if (!lastChild ||
         nsLayoutUtils::CompareTreePosition(lastChild, firstNewFrame, containingBlock) < 0) {
       // no lastChild, or lastChild comes before the new children, so just append
-      rv = mFrameManager->AppendFrames(containingBlock, aChildListName, aFrameItems);
+      rv = containingBlock->AppendFrames(aChildListName, aFrameItems);
     } else {
       // try the other children
       nsIFrame* insertionPoint = nsnull;
       for (nsIFrame* f = childList.FirstChild(); f != lastChild;
            f = f->GetNextSibling()) {
         PRInt32 compare =
           nsLayoutUtils::CompareTreePosition(f, firstNewFrame, containingBlock);
         if (compare > 0) {
           // f comes after the new children, so stop here and insert after
           // the previous frame
           break;
         }
         insertionPoint = f;
       }
-      rv = mFrameManager->InsertFrames(containingBlock, aChildListName,
-                                       insertionPoint, aFrameItems);
+      rv = containingBlock->InsertFrames(aChildListName, insertionPoint,
+                                         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?
@@ -2548,18 +2537,16 @@ nsCSSFrameConstructor::ConstructRootFram
 
   nsContainerFrame::SyncFrameViewProperties(mPresShell->GetPresContext(), viewportFrame,
                                             viewportPseudoStyle, rootView);
   nsContainerFrame::SyncWindowProperties(mPresShell->GetPresContext(), viewportFrame,
                                          rootView);
 
   // The viewport is the containing block for 'fixed' elements
   mFixedContainingBlock = viewportFrame;
-  // Make it an absolute container for fixed-pos elements
-  mFixedContainingBlock->MarkAsAbsoluteContainingBlock();
 
   *aNewFrame = viewportFrame;
   return NS_OK;
 }
 
 nsresult
 nsCSSFrameConstructor::SetUpDocElementContainingBlock(nsIContent* aDocElement)
 {
@@ -2834,18 +2821,16 @@ nsCSSFrameConstructor::ConstructPageFram
   nsIFrame* prevPageContentFrame = nsnull;
   if (aPrevPageFrame) {
     prevPageContentFrame = aPrevPageFrame->GetFirstChild(nsnull);
     NS_ASSERTION(prevPageContentFrame, "missing page content frame");
   }
   pageContentFrame->Init(nsnull, aPageFrame, prevPageContentFrame);
   SetInitialSingleChild(aPageFrame, pageContentFrame);
   mFixedContainingBlock = pageContentFrame;
-  // Make it an absolute container for fixed-pos elements
-  mFixedContainingBlock->MarkAsAbsoluteContainingBlock();
 
   nsRefPtr<nsStyleContext> canvasPseudoStyle;
   canvasPseudoStyle = styleSet->ResolveAnonymousBoxStyle(nsCSSAnonBoxes::canvas,
                                                          pageContentPseudoStyle);
 
   aCanvasFrame = NS_NewCanvasFrame(aPresShell, canvasPseudoStyle);
   if (NS_UNLIKELY(!aCanvasFrame))
     return NS_ERROR_OUT_OF_MEMORY;
@@ -5523,17 +5508,17 @@ nsCSSFrameConstructor::GetAbsoluteContai
       // Find the outermost wrapped block under this frame
       for (nsIFrame* wrappedFrame = aFrame; wrappedFrame != frame->GetParent();
            wrappedFrame = wrappedFrame->GetParent()) {
         nsIAtom* frameType = wrappedFrame->GetType();
         if (nsGkAtoms::blockFrame == frameType ||
 #ifdef MOZ_XUL
             nsGkAtoms::XULLabelFrame == frameType ||
 #endif
-            (nsGkAtoms::inlineFrame == frameType && wrappedFrame->IsAbsoluteContainer())) {
+            nsGkAtoms::positionedInlineFrame == frameType) {
           containingBlock = wrappedFrame;
         } else if (nsGkAtoms::fieldSetFrame == frameType) {
           // If the positioned frame is a fieldset, use the area frame inside it.
           // We don't use GetContentInsertionFrame for fieldsets yet.
           containingBlock = GetFieldSetBlockFrame(wrappedFrame);
         }
       }
 
@@ -8479,16 +8464,23 @@ nsCSSFrameConstructor::CreateContinuingF
     }
 #endif  
   } else if (nsGkAtoms::columnSetFrame == frameType) {
     newFrame = NS_NewColumnSetFrame(shell, styleContext, 0);
 
     if (newFrame) {
       newFrame->Init(content, aParentFrame, aFrame);
     }
+  
+  } else if (nsGkAtoms::positionedInlineFrame == frameType) {
+    newFrame = NS_NewPositionedInlineFrame(shell, styleContext);
+
+    if (newFrame) {
+      newFrame->Init(content, aParentFrame, aFrame);
+    }
 
   } else if (nsGkAtoms::pageFrame == frameType) {
     nsIFrame* canvasFrame;
     rv = ConstructPageFrame(shell, aPresContext, aParentFrame, aFrame,
                             newFrame, canvasFrame);
   } else if (nsGkAtoms::tableOuterFrame == frameType) {
     rv = CreateContinuingOuterTableFrame(shell, aPresContext, aFrame, aParentFrame,
                                          content, styleContext, &newFrame);
@@ -10709,26 +10701,30 @@ nsCSSFrameConstructor::ConstructInline(n
   nsStyleContext* const styleContext = aItem.mStyleContext;
 
   nsIFrame *newFrame;
 
   PRBool positioned =
     NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay &&
     (NS_STYLE_POSITION_RELATIVE == aDisplay->mPosition ||
      aDisplay->HasTransform());
-  newFrame = NS_NewInlineFrame(mPresShell, styleContext);
+  if (positioned) {
+    newFrame = NS_NewPositionedInlineFrame(mPresShell, styleContext);
+  } else {
+    newFrame = NS_NewInlineFrame(mPresShell, styleContext);
+  }
 
   // Initialize the frame
   InitAndRestoreFrame(aState, content, aParentFrame, nsnull, newFrame);
 
   nsFrameConstructorSaveState absoluteSaveState;  // definition cannot be inside next block
                                                   // because the object's destructor is significant
                                                   // this is part of the fix for bug 42372
 
-  if (positioned) {
+  if (positioned) {                            
     // Relatively positioned frames becomes a container for child
     // frames that are positioned
     aState.PushAbsoluteContainingBlock(newFrame, absoluteSaveState);
   }
 
   // Process the child content
   nsFrameItems childItems;
   nsresult rv = ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame,
@@ -10817,25 +10813,27 @@ nsCSSFrameConstructor::CreateIBSiblings(
 
     MoveChildrenTo(aState.mPresContext, aInitialInline, blockFrame, blockKids);
 
     SetFrameIsSpecial(lastNewInline, blockFrame);
     aSiblings.AddChild(blockFrame);
 
     // Now grab the initial inlines in aChildItems and put them into an inline
     // frame
-    nsIFrame* inlineFrame = NS_NewInlineFrame(mPresShell, styleContext);
+    nsIFrame* inlineFrame;
+    if (aIsPositioned) {
+      inlineFrame = NS_NewPositionedInlineFrame(mPresShell, styleContext);
+    }
+    else {
+      inlineFrame = NS_NewInlineFrame(mPresShell, styleContext);
+    }
 
     InitAndRestoreFrame(aState, content, parentFrame, nsnull, inlineFrame,
                         PR_FALSE);
 
-    if (aIsPositioned) {
-      inlineFrame->MarkAsAbsoluteContainingBlock();
-    }
-
     if (aChildItems.NotEmpty()) {
       nsFrameList::FrameLinkEnumerator firstBlock(aChildItems);
       FindFirstBlock(firstBlock);
       nsFrameList inlineKids = aChildItems.ExtractHead(firstBlock);
 
       MoveChildrenTo(aState.mPresContext, aInitialInline, inlineFrame,
                      inlineKids);
     }
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -2540,17 +2540,18 @@ PrepareBackgroundLayer(nsPresContext* aP
   }
 
   // Compute background origin area relative to aBorderArea now as we may need
   // it to compute the effective image size for a CSS gradient.
   nsRect bgPositioningArea(0, 0, 0, 0);
 
   nsIAtom* frameType = aForFrame->GetType();
   nsIFrame* geometryFrame = aForFrame;
-  if (frameType == nsGkAtoms::inlineFrame) {
+  if (frameType == nsGkAtoms::inlineFrame ||
+      frameType == nsGkAtoms::positionedInlineFrame) {
     // XXXjwalden Strictly speaking this is not quite faithful to how
     // background-break is supposed to interact with background-origin values,
     // but it's a non-trivial amount of work to make it fully conformant, and
     // until the specification is more finalized (and assuming background-break
     // even makes the cut) it doesn't make sense to hammer out exact behavior.
     switch (aBackground.mBackgroundInlinePolicy) {
     case NS_STYLE_BG_INLINE_POLICY_EACH_BOX:
       bgPositioningArea = nsRect(nsPoint(0,0), aBorderArea.Size());
--- a/layout/base/nsFrameManager.cpp
+++ b/layout/base/nsFrameManager.cpp
@@ -88,17 +88,16 @@
 #include "nsUnicharUtils.h"
 #include "nsPrintfCString.h"
 #include "nsLayoutErrors.h"
 #include "nsLayoutUtils.h"
 #include "nsAutoPtr.h"
 #include "imgIRequest.h"
 #include "nsTransitionManager.h"
 #include "RestyleTracker.h"
-#include "nsAbsoluteContainingBlock.h"
 
 #include "nsFrameManager.h"
 #include "nsRuleProcessorData.h"
 
 #ifdef ACCESSIBILITY
 #include "nsAccessibilityService.h"
 #endif
 
@@ -467,48 +466,29 @@ nsFrameManager::ClearAllUndisplayedConte
       if (child->GetParent() != aParentContent) {
         ClearUndisplayedContentIn(child, child->GetParent());
       }
     }
   }
 }
 
 //----------------------------------------------------------------------
-nsresult
-nsFrameManager::AppendFrames(nsIFrame*       aParentFrame,
-                             nsIAtom*        aListName,
-                             nsFrameList&    aFrameList)
-{
-  if (aParentFrame->IsAbsoluteContainer() &&
-      aListName == aParentFrame->GetAbsoluteListName()) {
-    return aParentFrame->GetAbsoluteContainingBlock()->
-           AppendFrames(aParentFrame, aListName, aFrameList);
-  } else {
-    return aParentFrame->AppendFrames(aListName, aFrameList);
-  }
-}
 
 nsresult
 nsFrameManager::InsertFrames(nsIFrame*       aParentFrame,
                              nsIAtom*        aListName,
                              nsIFrame*       aPrevFrame,
                              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!");
 
-  if (aParentFrame->IsAbsoluteContainer() &&
-      aListName == aParentFrame->GetAbsoluteListName()) {
-    return aParentFrame->GetAbsoluteContainingBlock()->
-           InsertFrames(aParentFrame, aListName, aPrevFrame, aFrameList);
-  } else {
-    return aParentFrame->InsertFrames(aListName, aPrevFrame, aFrameList);
-  }
+  return aParentFrame->InsertFrames(aListName, aPrevFrame, aFrameList);
 }
 
 nsresult
 nsFrameManager::RemoveFrame(nsIAtom*        aListName,
                             nsIFrame*       aOldFrame)
 {
   PRBool wasDestroyingFrames = mIsDestroyingFrames;
   mIsDestroyingFrames = PR_TRUE;
@@ -523,25 +503,17 @@ nsFrameManager::RemoveFrame(nsIAtom*    
 
   NS_ASSERTION(!aOldFrame->GetPrevContinuation() ||
                // exception for nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames
                aOldFrame->GetType() == nsGkAtoms::textFrame,
                "Must remove first continuation.");
   NS_ASSERTION(!(aOldFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW &&
                  GetPlaceholderFrameFor(aOldFrame)),
                "Must call RemoveFrame on placeholder for out-of-flows.");
-  nsresult rv = NS_OK;
-  nsIFrame* parentFrame = aOldFrame->GetParent();
-  if (parentFrame->IsAbsoluteContainer() &&
-      aListName == parentFrame->GetAbsoluteListName()) {
-    parentFrame->GetAbsoluteContainingBlock()->
-      RemoveFrame(parentFrame, aListName, aOldFrame);
-  } else {
-    rv = parentFrame->RemoveFrame(aListName, aOldFrame);
-  }
+  nsresult rv = aOldFrame->GetParent()->RemoveFrame(aListName, aOldFrame);
 
   mIsDestroyingFrames = wasDestroyingFrames;
 
   return rv;
 }
 
 //----------------------------------------------------------------------
 
--- a/layout/base/nsFrameManager.h
+++ b/layout/base/nsFrameManager.h
@@ -119,17 +119,20 @@ public:
                                             nsStyleContext* aStyleContext);
   NS_HIDDEN_(void) ClearUndisplayedContentIn(nsIContent* aContent,
                                              nsIContent* aParentContent);
   NS_HIDDEN_(void) ClearAllUndisplayedContentIn(nsIContent* aParentContent);
 
   // Functions for manipulating the frame model
   NS_HIDDEN_(nsresult) AppendFrames(nsIFrame*       aParentFrame,
                                     nsIAtom*        aListName,
-                                    nsFrameList&    aFrameList);
+                                    nsFrameList&    aFrameList)
+  {
+    return aParentFrame->AppendFrames(aListName, aFrameList);
+  }
 
   NS_HIDDEN_(nsresult) InsertFrames(nsIFrame*       aParentFrame,
                                     nsIAtom*        aListName,
                                     nsIFrame*       aPrevFrame,
                                     nsFrameList&    aFrameList);
 
   NS_HIDDEN_(nsresult) RemoveFrame(nsIAtom*        aListName,
                                    nsIFrame*       aOldFrame);
--- a/layout/doc/frame_reflow_debug.html
+++ b/layout/doc/frame_reflow_debug.html
@@ -168,16 +168,17 @@ The entries in the reflow log can be con
  <tr><td>img</td><td>image</td></tr>
  <tr><td>inline</td><td>inline</td></tr>
  <tr><td>letter</td><td>letter</td></tr>
  <tr><td>line</td><td>line</td></tr>
  <tr><td>select</td><td>select</td></tr>
  <tr><td>obj</td><td>object</td></tr>
  <tr><td>page</td><td>page</td></tr>
  <tr><td>place</td><td>placeholder</td></tr>
+ <tr><td>posInline</td><td>positionedInline</td></tr>
  <tr><td>canvas</td><td>canvas</td></tr>
  <tr><td>root</td><td>root</td></tr>
  <tr><td>scroll</td><td>scroll</td></tr>
  <tr><td>caption</td><td>tableCaption</td></tr>
  <tr><td>cell</td><td>tableCell</td></tr>
  <tr><td>bcCell</td><td>bcTableCell</td></tr>
  <tr><td>col</td><td>tableCol</td></tr>
  <tr><td>colG</td><td>tableColGroup</td></tr>
--- a/layout/generic/nsAbsoluteContainingBlock.cpp
+++ b/layout/generic/nsAbsoluteContainingBlock.cpp
@@ -422,17 +422,17 @@ nsAbsoluteContainingBlock::ReflowAbsolut
                                    aContainingBlockHeight);
 
   // Send the WillReflow() notification and position the frame
   aKidFrame->WillReflow(aPresContext);
 
   PRBool constrainHeight = (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE)
     && aConstrainHeight
        // Don't split if told not to (e.g. for fixed frames)
-    && (aDelegatingFrame->GetType() != nsGkAtoms::inlineFrame)
+    && (aDelegatingFrame->GetType() != nsGkAtoms::positionedInlineFrame)
        //XXX we don't handle splitting frames for inline absolute containing blocks yet
     && (aKidFrame->GetRect().y <= aReflowState.availableHeight);
        // Don't split things below the fold. (Ideally we shouldn't *have*
        // anything totally below the fold, but we can't position frames
        // across next-in-flow breaks yet.
   if (constrainHeight) {
     kidReflowState.availableHeight = aReflowState.availableHeight - border.top
                                      - kidReflowState.mComputedMargin.top;
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -303,17 +303,17 @@ NS_IMPL_FRAMEARENA_HELPERS(nsBlockFrame)
 
 nsBlockFrame::~nsBlockFrame()
 {
 }
 
 void
 nsBlockFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
-  DestroyAbsoluteFrames(aDestructRoot);
+  mAbsoluteContainer.DestroyFrames(this, aDestructRoot);
   // Outside bullets are not in our child-list so check for them here
   // and delete them when present.
   if (mBullet && HaveOutsideBullet()) {
     mBullet->DestroyFrom(aDestructRoot);
     mBullet = nsnull;
   }
 
   mFloats.DestroyFramesFrom(aDestructRoot);
@@ -580,17 +580,20 @@ nsBlockFrame::GetCaretBaseline() const
 }
 
 /////////////////////////////////////////////////////////////////////////////
 // Child frame enumeration
 
 nsFrameList
 nsBlockFrame::GetChildList(nsIAtom* aListName) const
 {
-  if (nsnull == aListName) {
+  if (nsGkAtoms::absoluteList == aListName) {
+    return mAbsoluteContainer.GetChildList();
+  }
+  else if (nsnull == aListName) {
     return mFrames;
   }
   else if (aListName == nsGkAtoms::overflowList) {
     // XXXbz once we start using nsFrameList for our overflow list, we
     // could switch GetChildList to returning a |const nsFrameList&|.
     nsLineList* overflowLines = GetOverflowLines();
     return overflowLines ? nsFrameList(overflowLines->front()->mFirstChild,
                                        overflowLines->back()->LastChild())
@@ -612,32 +615,35 @@ nsBlockFrame::GetChildList(nsIAtom* aLis
                                : nsFrameList::EmptyList();
   }
   return nsContainerFrame::GetChildList(aListName);
 }
 
 #define NS_BLOCK_FRAME_OVERFLOW_OOF_LIST_INDEX  (NS_CONTAINER_LIST_COUNT_INCL_OC + 0)
 #define NS_BLOCK_FRAME_FLOAT_LIST_INDEX         (NS_CONTAINER_LIST_COUNT_INCL_OC + 1)
 #define NS_BLOCK_FRAME_BULLET_LIST_INDEX        (NS_CONTAINER_LIST_COUNT_INCL_OC + 2)
-#define NS_BLOCK_FRAME_PUSHED_FLOATS_LIST_INDEX (NS_CONTAINER_LIST_COUNT_INCL_OC + 3)
+#define NS_BLOCK_FRAME_ABSOLUTE_LIST_INDEX      (NS_CONTAINER_LIST_COUNT_INCL_OC + 3)
+#define NS_BLOCK_FRAME_PUSHED_FLOATS_LIST_INDEX (NS_CONTAINER_LIST_COUNT_INCL_OC + 4)
 // If adding/removing lists, don't forget to update the count in nsBlockFrame.h
 
 nsIAtom*
 nsBlockFrame::GetAdditionalChildListName(PRInt32 aIndex) const
 {
   if (aIndex < NS_CONTAINER_LIST_COUNT_INCL_OC)
     return nsContainerFrame::GetAdditionalChildListName(aIndex);
 
   switch (aIndex) {
   case NS_BLOCK_FRAME_FLOAT_LIST_INDEX:
     return nsGkAtoms::floatList;
   case NS_BLOCK_FRAME_BULLET_LIST_INDEX:
     return nsGkAtoms::bulletList;
   case NS_BLOCK_FRAME_OVERFLOW_OOF_LIST_INDEX:
     return nsGkAtoms::overflowOutOfFlowList;
+  case NS_BLOCK_FRAME_ABSOLUTE_LIST_INDEX:
+    return nsGkAtoms::absoluteList;
   case NS_BLOCK_FRAME_PUSHED_FLOATS_LIST_INDEX:
     return nsGkAtoms::pushedFloatsList;
   default:
     return nsnull;
   }
 }
 
 /* virtual */ PRBool
@@ -1165,31 +1171,30 @@ nsBlockFrame::Reflow(nsPresContext*     
   // condition 1.
   // XXX checking oldSize is bogus, there are various reasons we might have
   // reflowed but our size might not have been changed to what we
   // asked for (e.g., we ended up being pushed to a new page)
   // When WillReflowAgainForClearance is true, we will reflow again without
   // resetting the size. Because of this, we must not reflow our abs-pos children
   // in that situation --- what we think is our "new size"
   // will not be our real new size. This also happens to be more efficient.
-  if (HasAbsolutelyPositionedChildren()) {
-    nsAbsoluteContainingBlock* absoluteContainer = GetAbsoluteContainingBlock();
+  if (mAbsoluteContainer.HasAbsoluteFrames()) {
     PRBool haveInterrupt = aPresContext->HasPendingInterrupt();
     if (reflowState->WillReflowAgainForClearance() ||
         haveInterrupt) {
       // Make sure that when we reflow again we'll actually reflow all the abs
       // pos frames that might conceivably depend on our size (or all of them,
       // if we're dirty right now and interrupted; in that case we also need
       // to mark them all with NS_FRAME_IS_DIRTY).  Sadly, we can't do much
       // better than that, because we don't really know what our size will be,
       // and it might in fact not change on the followup reflow!
       if (haveInterrupt && (GetStateBits() & NS_FRAME_IS_DIRTY)) {
-        absoluteContainer->MarkAllFramesDirty();
+        mAbsoluteContainer.MarkAllFramesDirty();
       } else {
-        absoluteContainer->MarkSizeDependentFramesDirty();
+        mAbsoluteContainer.MarkSizeDependentFramesDirty();
       }
     } else {
       nsSize containingBlockSize =
         CalculateContainingBlockSizeForAbsolutes(*reflowState,
                                                  nsSize(aMetrics.width,
                                                         aMetrics.height));
 
       // Mark frames that depend on changes we just made to this frame as dirty:
@@ -1203,22 +1208,22 @@ nsBlockFrame::Reflow(nsPresContext*     
       // If isRoot and we have auto height, then we are the initial
       // containing block and the containing block height is the
       // viewport height, which can't change during incremental
       // reflow.
       PRBool cbHeightChanged =
         !(isRoot && NS_UNCONSTRAINEDSIZE == reflowState->ComputedHeight()) &&
         aMetrics.height != oldSize.height;
 
-      absoluteContainer->Reflow(this, aPresContext, *reflowState,
-                                state.mReflowStatus,
-                                containingBlockSize.width,
-                                containingBlockSize.height, PR_TRUE,
-                                cbWidthChanged, cbHeightChanged,
-                                &aMetrics.mOverflowAreas);
+      rv = mAbsoluteContainer.Reflow(this, aPresContext, *reflowState,
+                                     state.mReflowStatus,
+                                     containingBlockSize.width,
+                                     containingBlockSize.height, PR_TRUE,
+                                     cbWidthChanged, cbHeightChanged,
+                                     &aMetrics.mOverflowAreas);
 
       //XXXfr Why isn't this rv (and others in this file) checked/returned?
     }
   }
 
   // Determine if we need to repaint our border, background or outline
   CheckInvalidateSizeChange(aMetrics);
 
@@ -4698,17 +4703,20 @@ nsBlockFrame::RemovePushedFloats()
 NS_IMETHODIMP
 nsBlockFrame::AppendFrames(nsIAtom*  aListName,
                            nsFrameList& aFrameList)
 {
   if (aFrameList.IsEmpty()) {
     return NS_OK;
   }
   if (aListName) {
-    if (nsGkAtoms::floatList == aListName) {
+    if (nsGkAtoms::absoluteList == aListName) {
+      return mAbsoluteContainer.AppendFrames(this, aListName, aFrameList);
+    }
+    else if (nsGkAtoms::floatList == aListName) {
       mFloats.AppendFrames(nsnull, aFrameList);
       return NS_OK;
     }
     else {
       NS_ERROR("unexpected child list");
       return NS_ERROR_INVALID_ARG;
     }
   }
@@ -4743,17 +4751,21 @@ NS_IMETHODIMP
 nsBlockFrame::InsertFrames(nsIAtom*  aListName,
                            nsIFrame* aPrevFrame,
                            nsFrameList& aFrameList)
 {
   NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
                "inserting after sibling frame with different parent");
 
   if (aListName) {
-    if (nsGkAtoms::floatList == aListName) {
+    if (nsGkAtoms::absoluteList == aListName) {
+      return mAbsoluteContainer.InsertFrames(this, aListName, aPrevFrame,
+                                             aFrameList);
+    }
+    else if (nsGkAtoms::floatList == aListName) {
       mFloats.InsertFrames(this, aPrevFrame, aFrameList);
       return NS_OK;
     }
 #ifdef IBMBIDI
     else if (nsGkAtoms::nextBidi == aListName) {}
 #endif // IBMBIDI
     else {
       NS_ERROR("unexpected child list");
@@ -5004,16 +5016,20 @@ nsBlockFrame::RemoveFrame(nsIAtom*  aLis
 
   if (nsnull == aListName) {
     PRBool hasFloats = BlockHasAnyFloats(aOldFrame);
     rv = DoRemoveFrame(aOldFrame, REMOVE_FIXED_CONTINUATIONS);
     if (hasFloats) {
       MarkSameFloatManagerLinesDirty(this);
     }
   }
+  else if (nsGkAtoms::absoluteList == aListName) {
+    mAbsoluteContainer.RemoveFrame(this, aListName, aOldFrame);
+    return NS_OK;
+  }
   else if (nsGkAtoms::floatList == aListName) {
     // Make sure to mark affected lines dirty for the float frame
     // we are removing; this way is a bit messy, but so is the rest of the code.
     // See bug 390762.
     NS_ASSERTION(!aOldFrame->GetPrevContinuation(),
                  "RemoveFrame should not be called on pushed floats.");
     for (nsIFrame* f = aOldFrame;
          f && !(f->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER);
@@ -5046,19 +5062,19 @@ nsBlockFrame::DoRemoveOutOfFlowFrame(nsI
 {
   // The containing block is always the parent of aFrame.
   nsBlockFrame* block = (nsBlockFrame*)aFrame->GetParent();
 
   // Remove aFrame from the appropriate list.
   const nsStyleDisplay* display = aFrame->GetStyleDisplay();
   if (display->IsAbsolutelyPositioned()) {
     // This also deletes the next-in-flows
-    block->GetAbsoluteContainingBlock()->RemoveFrame(block,
-                                                     nsGkAtoms::absoluteList,
-                                                     aFrame);
+    block->mAbsoluteContainer.RemoveFrame(block,
+                                          nsGkAtoms::absoluteList,
+                                          aFrame);
   }
   else {
     // First remove aFrame's next-in-flows
     nsIFrame* nif = aFrame->GetNextInFlow();
     if (nif) {
       static_cast<nsContainerFrame*>(nif->GetParent())
         ->DeleteNextInFlowChild(aFrame->PresContext(), nif, PR_FALSE);
     }
@@ -6247,16 +6263,18 @@ nsBlockFrame::BuildDisplayList(nsDisplay
     DisplayOverflowContainers(aBuilder, aDirtyRect, aLists);
     for (nsIFrame* f = mFloats.FirstChild(); f; f = f->GetNextSibling()) {
       if (f->GetStateBits() & NS_FRAME_IS_PUSHED_FLOAT)
          BuildDisplayListForChild(aBuilder, f, aDirtyRect, aLists);
     }
   }
 
   aBuilder->MarkFramesForDisplayList(this, mFloats, aDirtyRect);
+  aBuilder->MarkFramesForDisplayList(this, mAbsoluteContainer.GetChildList(),
+                                     aDirtyRect);
 
   // Prepare for text-overflow processing.
   nsAutoPtr<TextOverflow> textOverflow(
     TextOverflow::WillProcessLines(aBuilder, aLists, this));
 
   // Don't use the line cursor if we might have a descendant placeholder ...
   // it might skip lines that contain placeholders but don't themselves
   // intersect with the dirty area.
@@ -6510,17 +6528,20 @@ nsBlockFrame::Init(nsIContent*      aCon
 }
 
 NS_IMETHODIMP
 nsBlockFrame::SetInitialChildList(nsIAtom*        aListName,
                                   nsFrameList&    aChildList)
 {
   nsresult rv = NS_OK;
 
-  if (nsGkAtoms::floatList == aListName) {
+  if (nsGkAtoms::absoluteList == aListName) {
+    mAbsoluteContainer.SetInitialChildList(this, aListName, aChildList);
+  }
+  else if (nsGkAtoms::floatList == aListName) {
     mFloats.SetFrames(aChildList);
   }
   else {
     nsPresContext* presContext = PresContext();
 
 #ifdef DEBUG
     // The only times a block that is an anonymous box is allowed to have a
     // first-letter frame are when it's the block inside a non-anonymous cell,
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -79,17 +79,17 @@ class nsBlockInFlowLineIterator;
 class nsBulletFrame;
 class nsLineBox;
 class nsFirstLineFrame;
 class nsIntervalSet;
 /**
  * Child list name indices
  * @see #GetAdditionalChildListName()
  */
-#define NS_BLOCK_LIST_COUNT  (NS_CONTAINER_LIST_COUNT_INCL_OC + 4)
+#define NS_BLOCK_LIST_COUNT  (NS_CONTAINER_LIST_COUNT_INCL_OC + 5)
 
 /**
  * Some invariants:
  * -- The overflow out-of-flows list contains the out-of-
  * flow frames whose placeholders are in the overflow list.
  * -- A given piece of content has at most one placeholder
  * frame in a block's normal child list.
  * -- While a block is being reflowed, and from then until
@@ -336,16 +336,17 @@ public:
    */
   static nsBlockFrame* GetNearestAncestorBlock(nsIFrame* aCandidate);
   
 protected:
   nsBlockFrame(nsStyleContext* aContext)
     : nsHTMLContainerFrame(aContext)
     , mMinWidth(NS_INTRINSIC_WIDTH_UNKNOWN)
     , mPrefWidth(NS_INTRINSIC_WIDTH_UNKNOWN)
+    , mAbsoluteContainer(nsGkAtoms::absoluteList)
   {
 #ifdef DEBUG
   InitDebugFlags();
 #endif
   }
   virtual ~nsBlockFrame();
 
 #ifdef DEBUG
@@ -771,16 +772,20 @@ protected:
 
   // XXX_fix_me: subclass one more time!
   // For list-item frames, this is the bullet frame.
   nsBulletFrame* mBullet;
 
   friend class nsBlockReflowState;
   friend class nsBlockInFlowLineIterator;
 
+private:
+  nsAbsoluteContainingBlock mAbsoluteContainer;
+
+
 #ifdef DEBUG
 public:
   static PRBool gLamePaintMetrics;
   static PRBool gLameReflowMetrics;
   static PRBool gNoisy;
   static PRBool gNoisyDamageRepair;
   static PRBool gNoisyIntrinsic;
   static PRBool gNoisyReflow;
--- a/layout/generic/nsCanvasFrame.cpp
+++ b/layout/generic/nsCanvasFrame.cpp
@@ -47,45 +47,49 @@
 #include "nsRenderingContext.h"
 #include "nsGUIEvent.h"
 #include "nsStyleConsts.h"
 #include "nsGkAtoms.h"
 #include "nsEventStateManager.h"
 #include "nsIPresShell.h"
 #include "nsIScrollPositionListener.h"
 #include "nsDisplayList.h"
+#include "nsAbsoluteContainingBlock.h"
 #include "nsCSSFrameConstructor.h"
 #include "nsFrameManager.h"
 
 // for focus
 #include "nsIDOMWindowInternal.h"
 #include "nsIScrollableFrame.h"
 #include "nsIDocShell.h"
 
 #ifdef DEBUG_rods
 //#define DEBUG_CANVAS_FOCUS
 #endif
 
+#define CANVAS_ABS_POS_CHILD_LIST NS_CONTAINER_LIST_COUNT_INCL_OC
+
 
 nsIFrame*
 NS_NewCanvasFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsCanvasFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsCanvasFrame)
 
 NS_QUERYFRAME_HEAD(nsCanvasFrame)
   NS_QUERYFRAME_ENTRY(nsCanvasFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsHTMLContainerFrame)
 
 void
 nsCanvasFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
-  DestroyAbsoluteFrames(aDestructRoot);
+  mAbsoluteContainer.DestroyFrames(this, aDestructRoot);
+
   nsIScrollableFrame* sf =
     PresContext()->GetPresShell()->GetRootScrollFrameAsScrollable();
   if (sf) {
     sf->RemoveScrollPositionListener(this);
   }
 
   nsHTMLContainerFrame::DestroyFrom(aDestructRoot);
 }
@@ -117,25 +121,31 @@ nsCanvasFrame::SetHasFocus(PRBool aHasFo
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCanvasFrame::SetInitialChildList(nsIAtom*        aListName,
                                    nsFrameList&    aChildList)
 {
+  if (nsGkAtoms::absoluteList == aListName)
+    return mAbsoluteContainer.SetInitialChildList(this, aListName, aChildList);
+
   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
 nsCanvasFrame::AppendFrames(nsIAtom*        aListName,
                             nsFrameList&    aFrameList)
 {
+  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
     return NS_ERROR_INVALID_ARG;
   }
 
   if (!mFrames.IsEmpty()) {
@@ -158,29 +168,37 @@ nsCanvasFrame::AppendFrames(nsIAtom*    
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCanvasFrame::InsertFrames(nsIAtom*        aListName,
                             nsIFrame*       aPrevFrame,
                             nsFrameList&    aFrameList)
 {
+  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)
     return NS_ERROR_UNEXPECTED;
 
   return AppendFrames(aListName, aFrameList);
 }
 
 NS_IMETHODIMP
 nsCanvasFrame::RemoveFrame(nsIAtom*        aListName,
                            nsIFrame*       aOldFrame)
 {
+  if (nsGkAtoms::absoluteList == aListName) {
+    mAbsoluteContainer.RemoveFrame(this, aListName, aOldFrame);
+    return NS_OK;
+  }
+
   NS_ASSERTION(!aListName, "unexpected child list name");
   if (aListName) {
     // We only support the unnamed principal child list
     return NS_ERROR_INVALID_ARG;
   }
 
   if (aOldFrame != mFrames.FirstChild())
     return NS_ERROR_FAILURE;
@@ -195,16 +213,34 @@ nsCanvasFrame::RemoveFrame(nsIAtom*     
   mFrames.DestroyFrame(aOldFrame);
 
   PresContext()->PresShell()->
     FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                      NS_FRAME_HAS_DIRTY_CHILDREN);
   return NS_OK;
 }
 
+nsIAtom*
+nsCanvasFrame::GetAdditionalChildListName(PRInt32 aIndex) const
+{
+  if (CANVAS_ABS_POS_CHILD_LIST == aIndex)
+    return nsGkAtoms::absoluteList;
+
+  return nsHTMLContainerFrame::GetAdditionalChildListName(aIndex);
+}
+
+nsFrameList
+nsCanvasFrame::GetChildList(nsIAtom* aListName) const
+{
+  if (nsGkAtoms::absoluteList == aListName)
+    return mAbsoluteContainer.GetChildList();
+
+  return nsHTMLContainerFrame::GetChildList(aListName);
+}
+
 nsRect nsCanvasFrame::CanvasArea() const
 {
   // Not clear which overflow rect we want here, but it probably doesn't
   // matter.
   nsRect result(GetVisualOverflowRect());
 
   nsIScrollableFrame *scrollableFrame = do_QueryFrame(GetParent());
   if (scrollableFrame) {
@@ -273,16 +309,19 @@ nsCanvasFrame::BuildDisplayList(nsDispla
                                 const nsDisplayListSet& aLists)
 {
   nsresult rv;
 
   if (GetPrevInFlow()) {
     DisplayOverflowContainers(aBuilder, aDirtyRect, aLists);
   }
 
+  aBuilder->MarkFramesForDisplayList(this, mAbsoluteContainer.GetChildList(),
+                                     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)) { 
@@ -509,16 +548,25 @@ nsCanvasFrame::Reflow(nsPresContext*    
     } else {
       aDesiredSize.height = aReflowState.ComputedHeight();
     }
 
     aDesiredSize.SetOverflowAreasToDesiredBounds();
     aDesiredSize.mOverflowAreas.UnionWith(
       kidDesiredSize.mOverflowAreas + kidPt);
 
+    if (mAbsoluteContainer.HasAbsoluteFrames()) {
+      PRBool widthChanged = aDesiredSize.width != mRect.width;
+      PRBool heightChanged = aDesiredSize.height != mRect.height;
+      mAbsoluteContainer.Reflow(this, aPresContext, aReflowState, aStatus,
+                                aDesiredSize.width, aDesiredSize.height,
+                                PR_TRUE, widthChanged, heightChanged,
+                                &aDesiredSize.mOverflowAreas);
+    }
+
     // Handle invalidating fixed-attachment backgrounds propagated to the
     // canvas when the canvas size (and therefore the background positioning
     // area's size) changes.  Such backgrounds are not invalidated in the
     // normal manner because the size of the original frame for that background
     // may not have changed.
     //
     // This isn't the right fix for this issue, taken more generally.  In
     // particular, this doesn't handle fixed-attachment backgrounds that are *not*
@@ -549,17 +597,17 @@ nsCanvasFrame::Reflow(nsPresContext*    
   }
 
   if (prevCanvasFrame) {
     ReflowOverflowContainerChildren(aPresContext, aReflowState,
                                     aDesiredSize.mOverflowAreas, 0,
                                     aStatus);
   }
 
-  FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus);
+  FinishAndStoreOverflow(&aDesiredSize);
 
   NS_FRAME_TRACE_REFLOW_OUT("nsCanvasFrame::Reflow", aStatus);
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return NS_OK;
 }
 
 PRIntn
 nsCanvasFrame::GetSkipSides() const
--- a/layout/generic/nsCanvasFrame.h
+++ b/layout/generic/nsCanvasFrame.h
@@ -37,16 +37,17 @@
 
 /* rendering object that goes directly inside the document's scrollbars */
 
 #ifndef nsCanvasFrame_h___
 #define nsCanvasFrame_h___
 
 #include "nsHTMLContainerFrame.h"
 #include "nsIScrollPositionListener.h"
+#include "nsAbsoluteContainingBlock.h"
 #include "nsDisplayList.h"
 #include "nsGkAtoms.h"
 
 class nsPresContext;
 class nsRenderingContext;
 class nsEvent;
 
 /**
@@ -58,17 +59,18 @@ class nsEvent;
  */
 class nsCanvasFrame : public nsHTMLContainerFrame,
                       public nsIScrollPositionListener
 {
 public:
   nsCanvasFrame(nsStyleContext* aContext)
   : nsHTMLContainerFrame(aContext),
     mDoPaintFocus(PR_FALSE),
-    mAddedScrollPositionListener(PR_FALSE) {}
+    mAddedScrollPositionListener(PR_FALSE),
+    mAbsoluteContainer(nsGkAtoms::absoluteList) {}
 
   NS_DECL_QUERYFRAME_TARGET(nsCanvasFrame)
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
 
   virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
@@ -77,16 +79,19 @@ public:
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
                           nsFrameList&    aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
                           nsFrameList&    aFrameList);
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
 
+  virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
+  virtual nsFrameList GetChildList(nsIAtom* aListName) const;
+
   virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext);
   virtual nscoord GetPrefWidth(nsRenderingContext *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
@@ -142,16 +147,17 @@ public:
   nsRect CanvasArea() const;
 
 protected:
   virtual PRIntn GetSkipSides() const;
 
   // Data members
   PRPackedBool              mDoPaintFocus;
   PRPackedBool              mAddedScrollPositionListener;
+  nsAbsoluteContainingBlock mAbsoluteContainer;
 };
 
 /**
  * Override nsDisplayBackground methods so that we pass aBGClipRect to
  * PaintBackground, covering the whole overflow area.
  * We can also paint an "extra background color" behind the normal
  * background.
  */
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -314,37 +314,37 @@ nsContainerFrame::GetChildList(nsIAtom* 
   }
 
   if (nsGkAtoms::excessOverflowContainersList == aListName) {
     nsFrameList* list = GetPropTableFrames(PresContext(),
                                            ExcessOverflowContainersProperty());
     return list ? *list : nsFrameList::EmptyList();
   }
 
-  return nsSplittableFrame::GetChildList(aListName);
+  return nsFrameList::EmptyList();
 }
 
-#define NS_CONTAINER_FRAME_OVERFLOW_LIST_INDEX                   1
-#define NS_CONTAINER_FRAME_OVERFLOW_CONTAINERS_LIST_INDEX        2
-#define NS_CONTAINER_FRAME_EXCESS_OVERFLOW_CONTAINERS_LIST_INDEX 3
+#define NS_CONTAINER_FRAME_OVERFLOW_LIST_INDEX                   0
+#define NS_CONTAINER_FRAME_OVERFLOW_CONTAINERS_LIST_INDEX        1
+#define NS_CONTAINER_FRAME_EXCESS_OVERFLOW_CONTAINERS_LIST_INDEX 2
 // If adding/removing lists, don't forget to update count in .h file
 
 
 nsIAtom*
 nsContainerFrame::GetAdditionalChildListName(PRInt32 aIndex) const
 {
   if (NS_CONTAINER_FRAME_OVERFLOW_LIST_INDEX == aIndex)
     return nsGkAtoms::overflowList;
   else if (IsFrameOfType(nsIFrame::eCanContainOverflowContainers)) {
     if (NS_CONTAINER_FRAME_OVERFLOW_CONTAINERS_LIST_INDEX == aIndex)
       return nsGkAtoms::overflowContainersList;
     else if (NS_CONTAINER_FRAME_EXCESS_OVERFLOW_CONTAINERS_LIST_INDEX == aIndex)
       return nsGkAtoms::excessOverflowContainersList;
   }
-  return nsSplittableFrame::GetAdditionalChildListName(aIndex);
+  return nsnull;
 }
 
 /////////////////////////////////////////////////////////////////////////////
 // Painting/Events
 
 NS_IMETHODIMP
 nsContainerFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                    const nsRect&           aDirtyRect,
--- a/layout/generic/nsContainerFrame.h
+++ b/layout/generic/nsContainerFrame.h
@@ -45,17 +45,19 @@
 #include "nsFrameList.h"
 #include "nsLayoutUtils.h"
 #include "nsAutoPtr.h"
 
 /**
  * Child list name indices
  * @see #GetAdditionalChildListName()
  */
-#define NS_CONTAINER_LIST_COUNT_INCL_OC 4
+#define NS_CONTAINER_LIST_COUNT_SANS_OC 1
+  // for frames that don't use overflow containers
+#define NS_CONTAINER_LIST_COUNT_INCL_OC 3
   // for frames that support overflow containers
 
 // Option flags for ReflowChild() and FinishReflowChild()
 // member functions
 #define NS_FRAME_NO_MOVE_VIEW         0x0001
 #define NS_FRAME_NO_MOVE_FRAME        (0x0002 | NS_FRAME_NO_MOVE_VIEW)
 #define NS_FRAME_NO_SIZE_VIEW         0x0004
 #define NS_FRAME_NO_VISIBILITY        0x0008
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -117,17 +117,16 @@
 #include "nsIObjectLoadingContent.h"
 #include "nsExpirationTracker.h"
 #include "nsSVGIntegrationUtils.h"
 #include "nsSVGEffects.h"
 #include "nsChangeHint.h"
 
 #include "gfxContext.h"
 #include "CSSCalc.h"
-#include "nsAbsoluteContainingBlock.h"
 
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
 using namespace mozilla::layers;
 
 static NS_DEFINE_CID(kLookAndFeelCID,  NS_LOOKANDFEEL_CID);
 
@@ -250,44 +249,16 @@ nsFrame::RootFrameList(nsPresContext* aP
     nsIFrame* frame = shell->FrameManager()->GetRootFrame();
     if(frame) {
       frame->List(out, aIndent);
     }
   }
 }
 #endif
 
-static void
-DestroyAbsoluteContainingBlock(void* aPropertyValue)
-{
-  delete static_cast<nsAbsoluteContainingBlock*>(aPropertyValue);
-}
-
-NS_DECLARE_FRAME_PROPERTY(AbsoluteContainingBlockProperty, DestroyAbsoluteContainingBlock)
-
-PRBool
-nsIFrame::HasAbsolutelyPositionedChildren() const {
-  return IsAbsoluteContainer() && GetAbsoluteContainingBlock()->HasAbsoluteFrames();
-}
-
-nsAbsoluteContainingBlock*
-nsIFrame::GetAbsoluteContainingBlock() const {
-  NS_ASSERTION(IsAbsoluteContainer(), "The frame is not marked as an abspos container correctly");
-  nsAbsoluteContainingBlock* absCB = static_cast<nsAbsoluteContainingBlock*>
-    (Properties().Get(AbsoluteContainingBlockProperty()));
-  NS_ASSERTION(absCB, "The frame is marked as an abspos container but doesn't have the property");
-  return absCB;
-}
-
-void
-nsIFrame::MarkAsAbsoluteContainingBlock() {
-  AddStateBits(NS_FRAME_HAS_ABSPOS_CHILDREN);
-  Properties().Set(AbsoluteContainingBlockProperty(), new nsAbsoluteContainingBlock(GetAbsoluteListName()));
-}
-
 void
 NS_MergeReflowStatusInto(nsReflowStatus* aPrimary, nsReflowStatus aSecondary)
 {
   *aPrimary |= aSecondary &
     (NS_FRAME_NOT_COMPLETE | NS_FRAME_OVERFLOW_INCOMPLETE |
      NS_FRAME_TRUNCATED | NS_FRAME_REFLOW_NEXTINFLOW);
   if (*aPrimary & NS_FRAME_NOT_COMPLETE) {
     *aPrimary &= ~NS_FRAME_OVERFLOW_INCOMPLETE;
@@ -948,33 +919,23 @@ nsFrame::GetBaseline() const
 }
 
 // Child frame enumeration
 
 nsIAtom*
 nsFrame::GetAdditionalChildListName(PRInt32 aIndex) const
 {
   NS_PRECONDITION(aIndex >= 0, "invalid index number");
-  // An index of 0 should always be an absolute list, we should ignore anything
-  // else if child frame types have ignored them.
-  if (aIndex == 0) {
-    return GetAbsoluteListName();
-  }
   return nsnull;
 }
 
 nsFrameList
 nsFrame::GetChildList(nsIAtom* aListName) const
 {
-  if (IsAbsoluteContainer() &&
-      aListName == GetAbsoluteListName()) {
-    return GetAbsoluteContainingBlock()->GetChildList();
-  } else {
-    return nsFrameList::EmptyList();
-  }
+  return nsFrameList::EmptyList();
 }
 
 static nsIFrame*
 GetActiveSelectionFrame(nsPresContext* aPresContext, nsIFrame* aFrame)
 {
   nsIContent* capturingContent = nsIPresShell::GetCapturingContent();
   if (capturingContent) {
     nsIFrame* activeFrame = aPresContext->GetPrimaryFrameFor(capturingContent);
@@ -1484,19 +1445,16 @@ nsIFrame::BuildDisplayListForStackingCon
   }
 
   PRBool usingSVGEffects = nsSVGIntegrationUtils::UsingEffectsForFrame(this);
   if (usingSVGEffects) {
     dirtyRect =
       nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, dirtyRect);
   }
 
-  // Mark the display list items for absolutely positioned children
-  MarkAbsoluteFramesForDisplayList(aBuilder, dirtyRect);
-
   nsDisplayListCollection set;
   nsresult rv;
   {    
     nsDisplayListBuilder::AutoIsRootSetter rootSetter(aBuilder, PR_TRUE);
     nsDisplayListBuilder::AutoInTransformSetter
       inTransformSetter(aBuilder, inTransform);
     rv = BuildDisplayList(aBuilder, dirtyRect, set);
   }
@@ -1619,17 +1577,17 @@ nsIFrame::BuildDisplayListForChild(nsDis
                                    PRUint32                aFlags) {
   // If painting is restricted to just the background of the top level frame,
   // then we have nothing to do here.
   if (aBuilder->IsBackgroundOnly())
     return NS_OK;
 
   if (aChild->GetStateBits() & NS_FRAME_TOO_DEEP_IN_FRAME_TREE)
     return NS_OK;
-
+  
   const nsStyleDisplay* disp = aChild->GetStyleDisplay();
   // PR_TRUE if this is a real or pseudo stacking context
   PRBool pseudoStackingContext =
     (aFlags & DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT) != 0;
   // XXX we REALLY need a "are you an inline-block sort of thing?" here!!!
   if ((aFlags & DISPLAY_CHILD_INLINE) &&
       (disp->mDisplay != NS_STYLE_DISPLAY_INLINE ||
        aChild->IsContainingBlock() ||
@@ -1665,25 +1623,19 @@ nsIFrame::BuildDisplayListForChild(nsDis
       dirty = *savedDirty;
     } else {
       // The out-of-flow frame did not intersect the dirty area. We may still
       // need to traverse into it, since it may contain placeholders we need
       // to enter to reach other out-of-flow frames that are visible.
       dirty.SetEmpty();
     }
     pseudoStackingContext = PR_TRUE;
-  }
-
-  // Mark the display list items for absolutely positioned children
-  aChild->MarkAbsoluteFramesForDisplayList(aBuilder, dirty);
-
-  if (childType != nsGkAtoms::placeholderFrame &&
-      aBuilder->GetSelectedFramesOnly() &&
-      aChild->IsLeaf() &&
-      !(aChild->GetStateBits() & NS_FRAME_SELECTED_CONTENT)) {
+  } else if (aBuilder->GetSelectedFramesOnly() &&
+             aChild->IsLeaf() &&
+             !(aChild->GetStateBits() & NS_FRAME_SELECTED_CONTENT)) {
     return NS_OK;
   }
 
   if (aBuilder->GetIncludeAllOutOfFlows() &&
       (aChild->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
     dirty = aChild->GetVisualOverflowRect();
   } else if (!(aChild->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)) {
     // No need to descend into aChild to catch placeholders for visible
@@ -1837,25 +1789,16 @@ nsIFrame::BuildDisplayListForChild(nsDis
   // This doesn't affect correctness because the positioned descendants list
   // is sorted by z-order and content in BuildDisplayListForStackingContext,
   // but it means that sort routine needs to do less work.
   aLists.PositionedDescendants()->AppendToTop(&extraPositionedDescendants);
   return NS_OK;
 }
 
 void
-nsIFrame::MarkAbsoluteFramesForDisplayList(nsDisplayListBuilder* aBuilder,
-                                           const nsRect& aDirtyRect)
-{
-  if (IsAbsoluteContainer()) {
-    aBuilder->MarkFramesForDisplayList(this, GetAbsoluteContainingBlock()->GetChildList(), aDirtyRect);
-  }
-}
-
-void
 nsIFrame::WrapReplacedContentForBorderRadius(nsDisplayListBuilder* aBuilder,
                                              nsDisplayList* aFromList,
                                              const nsDisplayListSet& aToLists)
 {
   nscoord radii[8];
   if (GetContentBoxBorderRadii(radii)) {
     // If we have a border-radius, we have to clip our content to that
     // radius.
@@ -3595,17 +3538,16 @@ nsFrame::WillReflow(nsPresContext* aPres
 
 NS_IMETHODIMP
 nsFrame::DidReflow(nsPresContext*           aPresContext,
                    const nsHTMLReflowState*  aReflowState,
                    nsDidReflowStatus         aStatus)
 {
   NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
                      ("nsFrame::DidReflow: aStatus=%d", aStatus));
-
   if (NS_FRAME_REFLOW_FINISHED == aStatus) {
     mState &= ~(NS_FRAME_IN_REFLOW | NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY |
                 NS_FRAME_HAS_DIRTY_CHILDREN);
   }
 
   // Notify the percent height observer if there is a percent height.
   // The observer may be able to initiate another reflow with a computed
   // height. This happens in the case where a table cell has no computed
@@ -3616,65 +3558,16 @@ nsFrame::DidReflow(nsPresContext*       
     if (height.HasPercent()) {
       aReflowState->mPercentHeightObserver->NotifyPercentHeight(*aReflowState);
     }
   }
 
   return NS_OK;
 }
 
-void
-nsFrame::FinishReflowWithAbsoluteFrames(nsPresContext*           aPresContext,
-                                        nsHTMLReflowMetrics&     aDesiredSize,
-                                        const nsHTMLReflowState& aReflowState,
-                                        nsReflowStatus&          aStatus)
-{
-  ReflowAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus);
-
-  FinishAndStoreOverflow(&aDesiredSize);
-}
-
-void
-nsFrame::DestroyAbsoluteFrames(nsIFrame* aDestructRoot)
-{
-  if (IsAbsoluteContainer()) {
-    GetAbsoluteContainingBlock()->DestroyFrames(this, aDestructRoot);
-  }
-}
-
-void
-nsFrame::ReflowAbsoluteFrames(nsPresContext*           aPresContext,
-                              nsHTMLReflowMetrics&     aDesiredSize,
-                              const nsHTMLReflowState& aReflowState,
-                              nsReflowStatus&          aStatus)
-{
-  if (HasAbsolutelyPositionedChildren()) {
-    nsAbsoluteContainingBlock* absoluteContainer = GetAbsoluteContainingBlock();
-
-    // Let the absolutely positioned container reflow any absolutely positioned
-    // child frames that need to be reflowed
-
-    // The containing block for the abs pos kids is formed by our padding edge.
-    nsMargin computedBorder =
-      aReflowState.mComputedBorderPadding - aReflowState.mComputedPadding;
-    nscoord containingBlockWidth =
-      aDesiredSize.width - computedBorder.LeftRight();
-    nscoord containingBlockHeight =
-      aDesiredSize.height - computedBorder.TopBottom();
-
-    nsContainerFrame* container = do_QueryFrame(this);
-    NS_ASSERTION(container, "Abs-pos children only supported on container frames for now");
-
-    absoluteContainer->Reflow(container, aPresContext, aReflowState, aStatus,
-                              containingBlockWidth, containingBlockHeight,
-                              PR_TRUE, PR_TRUE, PR_TRUE, // XXX could be optimized
-                              &aDesiredSize.mOverflowAreas);
-  }
-}
-
 /* virtual */ PRBool
 nsFrame::CanContinueTextRun() const
 {
   // By default, a frame will *not* allow a text run to be continued
   // through it.
   return PR_FALSE;
 }
 
@@ -6265,17 +6158,18 @@ nsIFrame::SetOverflowAreas(const nsOverf
     *overflow = aOverflowAreas;
   }
 }
 
 inline PRBool
 IsInlineFrame(nsIFrame *aFrame)
 {
   nsIAtom *type = aFrame->GetType();
-  return type == nsGkAtoms::inlineFrame;
+  return type == nsGkAtoms::inlineFrame ||
+         type == nsGkAtoms::positionedInlineFrame;
 }
 
 void 
 nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
                                  nsSize aNewSize)
 {
   nsRect bounds(nsPoint(0, 0), aNewSize);
 
@@ -7980,16 +7874,17 @@ void DR_State::InitFrameTypeTable()
   AddFrameTypeInfo(nsGkAtoms::imageFrame,            "img",       "image");
   AddFrameTypeInfo(nsGkAtoms::inlineFrame,           "inline",    "inline");
   AddFrameTypeInfo(nsGkAtoms::letterFrame,           "letter",    "letter");
   AddFrameTypeInfo(nsGkAtoms::lineFrame,             "line",      "line");
   AddFrameTypeInfo(nsGkAtoms::listControlFrame,      "select",    "select");
   AddFrameTypeInfo(nsGkAtoms::objectFrame,           "obj",       "object");
   AddFrameTypeInfo(nsGkAtoms::pageFrame,             "page",      "page");
   AddFrameTypeInfo(nsGkAtoms::placeholderFrame,      "place",     "placeholder");
+  AddFrameTypeInfo(nsGkAtoms::positionedInlineFrame, "posInline", "positionedInline");
   AddFrameTypeInfo(nsGkAtoms::canvasFrame,           "canvas",    "canvas");
   AddFrameTypeInfo(nsGkAtoms::rootFrame,             "root",      "root");
   AddFrameTypeInfo(nsGkAtoms::scrollFrame,           "scroll",    "scroll");
   AddFrameTypeInfo(nsGkAtoms::tableCaptionFrame,     "caption",   "tableCaption");
   AddFrameTypeInfo(nsGkAtoms::tableCellFrame,        "cell",      "tableCell");
   AddFrameTypeInfo(nsGkAtoms::bcTableCellFrame,      "bcCell",    "bcTableCell");
   AddFrameTypeInfo(nsGkAtoms::tableColFrame,         "col",       "tableCol");
   AddFrameTypeInfo(nsGkAtoms::tableColGroupFrame,    "colG",      "tableColGroup");
--- a/layout/generic/nsFrame.h
+++ b/layout/generic/nsFrame.h
@@ -323,25 +323,16 @@ public:
   NS_IMETHOD  WillReflow(nsPresContext* aPresContext);
   NS_IMETHOD  Reflow(nsPresContext*          aPresContext,
                      nsHTMLReflowMetrics&     aDesiredSize,
                      const nsHTMLReflowState& aReflowState,
                      nsReflowStatus&          aStatus);
   NS_IMETHOD  DidReflow(nsPresContext*           aPresContext,
                         const nsHTMLReflowState*  aReflowState,
                         nsDidReflowStatus         aStatus);
-  void ReflowAbsoluteFrames(nsPresContext*           aPresContext,
-                            nsHTMLReflowMetrics&     aDesiredSize,
-                            const nsHTMLReflowState& aReflowState,
-                            nsReflowStatus&          aStatus);
-  void FinishReflowWithAbsoluteFrames(nsPresContext*           aPresContext,
-                                      nsHTMLReflowMetrics&     aDesiredSize,
-                                      const nsHTMLReflowState& aReflowState,
-                                      nsReflowStatus&          aStatus);
-  void DestroyAbsoluteFrames(nsIFrame* aDestructRoot);
   virtual PRBool CanContinueTextRun() const;
 
   // Selection Methods
   // XXX Doc me... (in nsIFrame.h puhleeze)
   // XXX If these are selection specific, then the name should imply selection
   // rather than generic event processing, e.g., SelectionHandlePress...
   NS_IMETHOD HandlePress(nsPresContext* aPresContext,
                          nsGUIEvent *    aEvent,
--- a/layout/generic/nsHTMLParts.h
+++ b/layout/generic/nsHTMLParts.h
@@ -134,16 +134,18 @@ nsIFrame*
 NS_NewViewportFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame*
 NS_NewCanvasFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame*
 NS_NewImageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame*
 NS_NewInlineFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame*
+NS_NewPositionedInlineFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
+nsIFrame*
 NS_NewObjectFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame*
 NS_NewTextFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame*
 NS_NewContinuingTextFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame*
 NS_NewEmptyFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 inline nsIFrame*
--- a/layout/generic/nsHTMLReflowState.cpp
+++ b/layout/generic/nsHTMLReflowState.cpp
@@ -1568,17 +1568,17 @@ nsHTMLReflowState::ComputeContainingBloc
   aContainingBlockWidth = aContainingBlockRS->mComputedWidth;
   aContainingBlockHeight = aContainingBlockRS->mComputedHeight;
   
   if (NS_FRAME_GET_TYPE(mFrameType) == NS_CSS_FRAME_TYPE_ABSOLUTE) {
     // See if the ancestor is block-level or inline-level
     if (NS_FRAME_GET_TYPE(aContainingBlockRS->mFrameType) == NS_CSS_FRAME_TYPE_INLINE) {
       // Base our size on the actual size of the frame.  In cases when this is
       // completely bogus (eg initial reflow), this code shouldn't even be
-      // called, since the code in nsInlineFrame::Reflow will pass in
+      // called, since the code in nsPositionedInlineFrame::Reflow will pass in
       // the containing block dimensions to our constructor.
       // XXXbz we should be taking the in-flows into account too, but
       // that's very hard.
       nsMargin computedBorder = aContainingBlockRS->mComputedBorderPadding -
         aContainingBlockRS->mComputedPadding;
       aContainingBlockWidth = aContainingBlockRS->frame->GetRect().width -
         computedBorder.LeftRight();;
       NS_ASSERTION(aContainingBlockWidth >= 0,
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -98,17 +98,16 @@ class nsAccessible;
 #endif
 class nsDisplayListBuilder;
 class nsDisplayListSet;
 class nsDisplayList;
 class gfxSkipChars;
 class gfxSkipCharsIterator;
 class gfxContext;
 class nsLineList_iterator;
-class nsAbsoluteContainingBlock;
 
 struct nsPeekOffsetStruct;
 struct nsPoint;
 struct nsRect;
 struct nsSize;
 struct nsMargin;
 struct CharacterDataChangeInfo;
 
@@ -281,19 +280,16 @@ typedef PRUint64 nsFrameState;
 #define NS_FRAME_HAS_CLIP                           NS_FRAME_STATE_BIT(35)
 
 // Frame is a display root and the retained layer tree needs to be updated
 // at the next paint via display list construction.
 // Only meaningful for display roots, so we don't really need a global state
 // bit; we could free up this bit with a little extra complexity.
 #define NS_FRAME_UPDATE_LAYER_TREE                  NS_FRAME_STATE_BIT(36)
 
-// Frame can accept absolutely positioned children.
-#define NS_FRAME_HAS_ABSPOS_CHILDREN                NS_FRAME_STATE_BIT(37)
-
 // The lower 20 bits and upper 32 bits of the frame state are reserved
 // by this API.
 #define NS_FRAME_RESERVED                           ~NS_FRAME_IMPL_RESERVED
 
 // Box layout bits
 #define NS_STATE_IS_HORIZONTAL                      NS_FRAME_STATE_BIT(22)
 #define NS_STATE_IS_DIRECTION_NORMAL                NS_FRAME_STATE_BIT(31)
 
@@ -583,18 +579,16 @@ public:
    *
    * 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.  Must not be empty.
-   *            This method cannot handle the child list returned by
-   *            GetAbsoluteListName().
    * @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()
@@ -2702,39 +2696,27 @@ NS_PTR_TO_INT32(frame->Properties().Get(
     for (int i = 0, l = list->Length(); i < l; i++) {
       nsCOMPtr<nsIPresShell> shell = do_QueryReferent(list->ElementAt(i));
       
       if (shell) {
         shell->IncrementPaintCount();
       }
     }
   }  
-
-  /**
-   * Accessors for the absolute containing block.
-   */
-  PRBool IsAbsoluteContainer() const { return !!(mState & NS_FRAME_HAS_ABSPOS_CHILDREN); }
-  PRBool HasAbsolutelyPositionedChildren() const;
-  nsAbsoluteContainingBlock* GetAbsoluteContainingBlock() const;
-  virtual void MarkAsAbsoluteContainingBlock();
-  // Child frame types override this function to select their own child list name
-  virtual nsIAtom* GetAbsoluteListName() const { return nsGkAtoms::absoluteList; }
-
+  
 protected:
   // Members
   nsRect           mRect;
   nsIContent*      mContent;
   nsStyleContext*  mStyleContext;
   nsIFrame*        mParent;
 private:
   nsIFrame*        mNextSibling;  // doubly-linked list of frames
   nsIFrame*        mPrevSibling;  // Do not touch outside SetNextSibling!
 
-  void MarkAbsoluteFramesForDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect);
-
   static void DestroyPaintedPresShellList(void* propertyValue) {
     nsTArray<nsWeakPtr>* list = static_cast<nsTArray<nsWeakPtr>*>(propertyValue);
     list->Clear();
     delete list;
   }
 
   // Stores weak references to all the PresShells that were painted during
   // the last paint event so that we can increment their paint count during
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -42,16 +42,17 @@
 #include "nsBlockFrame.h"
 #include "nsPlaceholderFrame.h"
 #include "nsGkAtoms.h"
 #include "nsHTMLParts.h"
 #include "nsStyleContext.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsRenderingContext.h"
+#include "nsAbsoluteContainingBlock.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsAutoPtr.h"
 #include "nsFrameManager.h"
 #ifdef ACCESSIBILITY
 #include "nsIServiceManager.h"
 #include "nsAccessibilityService.h"
 #endif
 #include "nsDisplayList.h"
@@ -408,19 +409,17 @@ nsInlineFrame::Reflow(nsPresContext*    
   if (mFrames.IsEmpty()) {
     // Try to pull over one frame before starting so that we know
     // whether we have an anonymous block or not.
     PRBool complete;
     (void) PullOneFrame(aPresContext, irs, &complete);
   }
 
   rv = ReflowFrames(aPresContext, aReflowState, irs, aMetrics, aStatus);
-
-  ReflowAbsoluteFrames(aPresContext, aMetrics, aReflowState, aStatus);
-
+  
   // Note: the line layout code will properly compute our
   // overflow-rect state for us.
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
   return rv;
 }
 
 /* virtual */ PRBool
@@ -918,23 +917,16 @@ nsInlineFrame::GetBaseline() const
   nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
   if (fm) {
     ascent = fm->MaxAscent();
   }
   return NS_MIN(mRect.height, ascent + GetUsedBorderAndPadding().top);
 }
 
-void
-nsInlineFrame::DestroyFrom(nsIFrame* aDestructRoot)
-{
-  DestroyAbsoluteFrames(aDestructRoot);
-  nsInlineFrameSuper::DestroyFrom(aDestructRoot);
-}
-
 #ifdef ACCESSIBILITY
 already_AddRefed<nsAccessible>
 nsInlineFrame::CreateAccessible()
 {
   // Broken image accessibles are created here, because layout
   // replaces the image or image control frame with an inline frame
   nsIAtom *tagAtom = mContent->Tag();
   if ((tagAtom == nsGkAtoms::img || tagAtom == nsGkAtoms::input || 
@@ -1104,18 +1096,16 @@ nsFirstLineFrame::Reflow(nsPresContext* 
   }
 
   NS_ASSERTION(!aReflowState.mLineLayout->GetInFirstLine(),
                "Nested first-line frames? BOGUS");
   aReflowState.mLineLayout->SetInFirstLine(PR_TRUE);
   rv = ReflowFrames(aPresContext, aReflowState, irs, aMetrics, aStatus);
   aReflowState.mLineLayout->SetInFirstLine(PR_FALSE);
 
-  ReflowAbsoluteFrames(aPresContext, aMetrics, aReflowState, aStatus);
-
   // Note: the line layout code will properly compute our overflow state for us
 
   return rv;
 }
 
 /* virtual */ void
 nsFirstLineFrame::PullOverflowsFromPrevInFlow()
 {
@@ -1126,8 +1116,167 @@ nsFirstLineFrame::PullOverflowsFromPrevI
       // Assume that our prev-in-flow has the same line container that we do.
       const nsFrameList::Slice& newFrames =
         mFrames.InsertFrames(this, nsnull, *prevOverflowFrames);
       ReparentChildListStyle(PresContext(), newFrames, this);
     }
   }
 }
 
+//////////////////////////////////////////////////////////////////////
+
+nsIFrame*
+NS_NewPositionedInlineFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
+{
+  return new (aPresShell) nsPositionedInlineFrame(aContext);
+}
+
+NS_IMPL_FRAMEARENA_HELPERS(nsPositionedInlineFrame)
+
+void
+nsPositionedInlineFrame::DestroyFrom(nsIFrame* aDestructRoot)
+{
+  mAbsoluteContainer.DestroyFrames(this, aDestructRoot);
+  nsInlineFrame::DestroyFrom(aDestructRoot);
+}
+
+NS_IMETHODIMP
+nsPositionedInlineFrame::SetInitialChildList(nsIAtom*        aListName,
+                                             nsFrameList&    aChildList)
+{
+  nsresult  rv;
+
+  if (nsGkAtoms::absoluteList == aListName) {
+    rv = mAbsoluteContainer.SetInitialChildList(this, aListName, aChildList);
+  } else {
+    rv = nsInlineFrame::SetInitialChildList(aListName, aChildList);
+  }
+
+  return rv;
+}
+
+NS_IMETHODIMP
+nsPositionedInlineFrame::AppendFrames(nsIAtom*        aListName,
+                                      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,
+                                      nsFrameList&    aFrameList)
+{
+  nsresult  rv;
+
+  if (nsGkAtoms::absoluteList == aListName) {
+    rv = mAbsoluteContainer.InsertFrames(this, aListName, aPrevFrame,
+                                         aFrameList);
+  } else {
+    rv = nsInlineFrame::InsertFrames(aListName, aPrevFrame, aFrameList);
+  }
+
+  return rv;
+}
+  
+NS_IMETHODIMP
+nsPositionedInlineFrame::RemoveFrame(nsIAtom*        aListName,
+                                     nsIFrame*       aOldFrame)
+{
+  nsresult  rv;
+
+  if (nsGkAtoms::absoluteList == aListName) {
+    mAbsoluteContainer.RemoveFrame(this, aListName, aOldFrame);
+    rv = NS_OK;
+  } else {
+    rv = nsInlineFrame::RemoveFrame(aListName, aOldFrame);
+  }
+
+  return rv;
+}
+
+NS_IMETHODIMP
+nsPositionedInlineFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
+                                          const nsRect&           aDirtyRect,
+                                          const nsDisplayListSet& aLists)
+{
+  aBuilder->MarkFramesForDisplayList(this, mAbsoluteContainer.GetChildList(),
+				     aDirtyRect);
+  return nsHTMLContainerFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
+}
+
+nsIAtom*
+nsPositionedInlineFrame::GetAdditionalChildListName(PRInt32 aIndex) const
+{
+  if (0 == aIndex) {
+    return nsGkAtoms::absoluteList;
+  }
+  return nsnull;
+}
+
+nsFrameList
+nsPositionedInlineFrame::GetChildList(nsIAtom* aListName) const
+{
+  if (nsGkAtoms::absoluteList == aListName)
+    return mAbsoluteContainer.GetChildList();
+
+  return nsInlineFrame::GetChildList(aListName);
+}
+
+nsIAtom*
+nsPositionedInlineFrame::GetType() const
+{
+  return nsGkAtoms::positionedInlineFrame;
+}
+
+NS_IMETHODIMP
+nsPositionedInlineFrame::Reflow(nsPresContext*          aPresContext,
+                                nsHTMLReflowMetrics&     aDesiredSize,
+                                const nsHTMLReflowState& aReflowState,
+                                nsReflowStatus&          aStatus)
+{
+  nsresult  rv = NS_OK;
+
+  // Don't bother optimizing for fast incremental reflow of absolute
+  // children of an inline
+
+  // Let the inline frame do its reflow first
+  rv = nsInlineFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
+
+  // Let the absolutely positioned container reflow any absolutely positioned
+  // child frames that need to be reflowed
+  // We want to do this under either of two conditions:
+  //  1. If we didn't do the incremental reflow above.
+  //  2. If our size changed.
+  // Even though it's the padding edge that's the containing block, we
+  // can use our rect (the border edge) since if the border style
+  // changed, the reflow would have been targeted at us so we'd satisfy
+  // condition 1.
+  if (NS_SUCCEEDED(rv) &&
+      mAbsoluteContainer.HasAbsoluteFrames()) {
+    // The containing block for the abs pos kids is formed by our padding edge.
+    nsMargin computedBorder =
+      aReflowState.mComputedBorderPadding - aReflowState.mComputedPadding;
+    nscoord containingBlockWidth =
+      aDesiredSize.width - computedBorder.LeftRight();
+    nscoord containingBlockHeight =
+      aDesiredSize.height - computedBorder.TopBottom();
+
+    // Factor the absolutely positioned child bounds into the overflow area
+    // Don't include this frame's bounds, nor its inline descendants' bounds,
+    // and don't store the overflow property.
+    // That will all be done by nsLineLayout::RelativePositionFrames.
+    rv = mAbsoluteContainer.Reflow(this, aPresContext, aReflowState, aStatus,
+                                   containingBlockWidth, containingBlockHeight,
+                                   PR_TRUE, PR_TRUE, PR_TRUE, // XXX could be optimized
+                                   &aDesiredSize.mOverflowAreas);
+  }
+
+  return rv;
+}
--- a/layout/generic/nsInlineFrame.h
+++ b/layout/generic/nsInlineFrame.h
@@ -36,16 +36,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 /* rendering object for CSS display:inline objects */
 
 #ifndef nsInlineFrame_h___
 #define nsInlineFrame_h___
 
 #include "nsHTMLContainerFrame.h"
+#include "nsAbsoluteContainingBlock.h"
 #include "nsLineLayout.h"
 
 class nsAnonymousBlockFrame;
 
 #define nsInlineFrameSuper nsHTMLContainerFrame
 
 /**  In Bidi left (or right) margin/padding/border should be applied to left
  *  (or right) most frame (or a continuation frame).
@@ -91,18 +92,16 @@ public:
   {
     return nsInlineFrameSuper::IsFrameOfType(aFlags &
       ~(nsIFrame::eBidiInlineContainer | nsIFrame::eLineParticipant));
   }
 
   virtual PRBool IsEmpty();
   virtual PRBool IsSelfEmpty();
 
-  virtual void DestroyFrom(nsIFrame* aDestructRoot);
-
   virtual PRBool PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset,
                                      PRBool aRespectClusters = PR_TRUE);
   
   // nsIHTMLReflow overrides
   virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext,
                                  InlineMinWidthData *aData);
   virtual void AddInlinePrefWidth(nsRenderingContext *aRenderingContext,
                                   InlinePrefWidthData *aData);
@@ -223,9 +222,58 @@ public:
 protected:
   nsFirstLineFrame(nsStyleContext* aContext) : nsInlineFrame(aContext) {}
 
   virtual nsIFrame* PullOneFrame(nsPresContext* aPresContext,
                                  InlineReflowState& rs,
                                  PRBool* aIsComplete);
 };
 
+//----------------------------------------------------------------------
+
+// Derived class created for relatively positioned inline-level elements
+// that acts as a containing block for child absolutely positioned
+// elements
+
+class nsPositionedInlineFrame : public nsInlineFrame
+{
+public:
+  NS_DECL_FRAMEARENA_HELPERS
+
+  nsPositionedInlineFrame(nsStyleContext* aContext)
+    : nsInlineFrame(aContext)
+    , mAbsoluteContainer(nsGkAtoms::absoluteList)
+  {}
+
+  virtual ~nsPositionedInlineFrame() { } // useful for debugging
+
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
+
+  NS_IMETHOD SetInitialChildList(nsIAtom*        aListName,
+                                 nsFrameList&    aChildList);
+  NS_IMETHOD AppendFrames(nsIAtom*        aListName,
+                          nsFrameList&    aFrameList);
+  NS_IMETHOD InsertFrames(nsIAtom*        aListName,
+                          nsIFrame*       aPrevFrame,
+                          nsFrameList&    aFrameList);
+  NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
+                         nsIFrame*       aOldFrame);
+
+  NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
+                              const nsRect&           aDirtyRect,
+                              const nsDisplayListSet& aLists);
+
+  virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
+
+  virtual nsFrameList GetChildList(nsIAtom* aListName) const;
+
+  NS_IMETHOD Reflow(nsPresContext*          aPresContext,
+                    nsHTMLReflowMetrics&     aDesiredSize,
+                    const nsHTMLReflowState& aReflowState,
+                    nsReflowStatus&          aStatus);
+  
+  virtual nsIAtom* GetType() const;
+
+protected:
+  nsAbsoluteContainingBlock mAbsoluteContainer;
+};
+
 #endif /* nsInlineFrame_h___ */
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -657,17 +657,18 @@ IsPercentageAware(const nsIFrame* aFrame
 
   nsIAtom *fType = aFrame->GetType();
   if (fType == nsGkAtoms::textFrame) {
     // None of these things can ever be true for text frames.
     return PR_FALSE;
   }
 
   // Some of these things don't apply to non-replaced inline frames
-  // (that is, fType == nsGkAtoms::inlineFrame), but we won't bother making
+  // (that is, fType == nsGkAtoms::inlineFrame || fType ==
+  // nsGkAtoms::positionedInlineFrame), but we won't bother making
   // things unnecessarily complicated, since they'll probably be set
   // quite rarely.
 
   const nsStyleMargin* margin = aFrame->GetStyleMargin();
   if (HasPercentageUnitSide(margin->mMargin)) {
     return PR_TRUE;
   }
 
--- a/layout/generic/nsPageContentFrame.cpp
+++ b/layout/generic/nsPageContentFrame.cpp
@@ -132,20 +132,23 @@ nsPageContentFrame::Reflow(nsPresContext
     }
 
     // Place and size the child
     FinishReflowChild(frame, aPresContext, &kidReflowState, aDesiredSize, 0, 0, 0);
 
     NS_ASSERTION(aPresContext->IsDynamic() || !NS_FRAME_IS_FULLY_COMPLETE(aStatus) ||
                   !frame->GetNextInFlow(), "bad child flow list");
   }
-
-  // Reflow our fixed frames
+  // Reflow our fixed frames 
   nsReflowStatus fixedStatus = NS_FRAME_COMPLETE;
-  ReflowAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, fixedStatus);
+  mFixedContainer.Reflow(this, aPresContext, aReflowState, fixedStatus,
+                         aReflowState.availableWidth,
+                         aReflowState.availableHeight,
+                         PR_FALSE, PR_TRUE, PR_TRUE, // XXX could be optimized
+                         nsnull /* ignore overflow */);
   NS_ASSERTION(NS_FRAME_IS_COMPLETE(fixedStatus), "fixed frames can be truncated, but not incomplete");
 
   // Return our desired size
   aDesiredSize.width = aReflowState.availableWidth;
   if (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) {
     aDesiredSize.height = aReflowState.availableHeight;
   }
 
--- a/layout/generic/nsQueryFrame.h
+++ b/layout/generic/nsQueryFrame.h
@@ -179,16 +179,17 @@ public:
     nsMenuFrame_id,
     nsMenuPopupFrame_id,
     nsObjectFrame_id,
     nsPageBreakFrame_id,
     nsPageContentFrame_id,
     nsPageFrame_id,
     nsPlaceholderFrame_id,
     nsPopupSetFrame_id,
+    nsPositionedInlineFrame_id,
     nsProgressFrame_id,
     nsProgressMeterFrame_id,
     nsResizerFrame_id,
     nsRootBoxFrame_id,
     nsScrollbarButtonFrame_id,
     nsScrollbarFrame_id,
     nsSelectsAreaFrame_id,
     nsSimplePageSequenceFrame_id,
--- a/layout/generic/nsViewportFrame.cpp
+++ b/layout/generic/nsViewportFrame.cpp
@@ -42,17 +42,16 @@
 
 #include "nsCOMPtr.h"
 #include "nsViewportFrame.h"
 #include "nsHTMLParts.h"
 #include "nsGkAtoms.h"
 #include "nsIScrollableFrame.h"
 #include "nsDisplayList.h"
 #include "FrameLayerBuilder.h"
-#include "nsAbsoluteContainingBlock.h"
 
 using namespace mozilla;
 
 nsIFrame*
 NS_NewViewportFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) ViewportFrame(aContext);
 }
@@ -65,95 +64,164 @@ ViewportFrame::Init(nsIContent*      aCo
                     nsIFrame*        aPrevInFlow)
 {
   return Super::Init(aContent, aParent, aPrevInFlow);
 }
 
 void
 ViewportFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
-  DestroyAbsoluteFrames(aDestructRoot);
+  mFixedContainer.DestroyFrames(this, aDestructRoot);
   nsContainerFrame::DestroyFrom(aDestructRoot);
 }
 
 NS_IMETHODIMP
 ViewportFrame::SetInitialChildList(nsIAtom*        aListName,
                                    nsFrameList&    aChildList)
 {
+  nsresult rv = NS_OK;
+
   // See which child list to add the frames to
 #ifdef NS_DEBUG
   nsFrame::VerifyDirtyBitSet(aChildList);
 #endif
-  return nsContainerFrame::SetInitialChildList(aListName, aChildList);
+  if (nsGkAtoms::fixedList == aListName) {
+    rv = mFixedContainer.SetInitialChildList(this, aListName, aChildList);
+  } 
+  else {
+    rv = nsContainerFrame::SetInitialChildList(aListName, aChildList);
+  }
+
+  return rv;
 }
 
 NS_IMETHODIMP
 ViewportFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists)
 {
+  // We don't need any special painting or event handling. We just need to
+  // mark our visible out-of-flow frames (i.e., the fixed position frames) so
+  // that display list construction is guaranteed to recurse into their
+  // ancestors.
+  aBuilder->MarkFramesForDisplayList(this, mFixedContainer.GetChildList(),
+                                     aDirtyRect);
+
   nsIFrame* kid = mFrames.FirstChild();
   if (!kid)
     return NS_OK;
 
   // 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,
                             nsFrameList&    aFrameList)
 {
-  NS_ASSERTION(!aListName, "unexpected child list");
-  NS_ASSERTION(GetChildList(nsnull).IsEmpty(), "Shouldn't have any kids!");
-  return nsContainerFrame::AppendFrames(aListName, aFrameList);
+  nsresult rv = NS_OK;
+
+  if (nsGkAtoms::fixedList == aListName) {
+    rv = mFixedContainer.AppendFrames(this, aListName, aFrameList);
+  }
+  else {
+    NS_ASSERTION(!aListName, "unexpected child list");
+    NS_ASSERTION(GetChildList(nsnull).IsEmpty(), "Shouldn't have any kids!");
+    rv = nsContainerFrame::AppendFrames(aListName, aFrameList);
+  }
+
+  return rv;
 }
 
 NS_IMETHODIMP
 ViewportFrame::InsertFrames(nsIAtom*        aListName,
                             nsIFrame*       aPrevFrame,
                             nsFrameList&    aFrameList)
 {
-  NS_ASSERTION(!aListName, "unexpected child list");
-  NS_ASSERTION(GetChildList(nsnull).IsEmpty(), "Shouldn't have any kids!");
-  return nsContainerFrame::InsertFrames(aListName, aPrevFrame, aFrameList);
+  nsresult rv = NS_OK;
+
+  if (nsGkAtoms::fixedList == aListName) {
+    rv = mFixedContainer.InsertFrames(this, aListName, aPrevFrame, aFrameList);
+  }
+  else {
+    NS_ASSERTION(!aListName, "unexpected child list");
+    NS_ASSERTION(GetChildList(nsnull).IsEmpty(), "Shouldn't have any kids!");
+    rv = nsContainerFrame::InsertFrames(aListName, aPrevFrame, aFrameList);
+  }
+
+  return rv;
 }
 
 NS_IMETHODIMP
 ViewportFrame::RemoveFrame(nsIAtom*        aListName,
                            nsIFrame*       aOldFrame)
 {
-  NS_ASSERTION(!aListName, "unexpected child list");
-  return nsContainerFrame::RemoveFrame(aListName, aOldFrame);
+  nsresult rv = NS_OK;
+
+  if (nsGkAtoms::fixedList == aListName) {
+    mFixedContainer.RemoveFrame(this, aListName, aOldFrame);
+    rv = NS_OK;
+  }
+  else {
+    NS_ASSERTION(!aListName, "unexpected child list");
+    rv = nsContainerFrame::RemoveFrame(aListName, aOldFrame);
+  }
+
+  return rv;
+}
+
+nsIAtom*
+ViewportFrame::GetAdditionalChildListName(PRInt32 aIndex) const
+{
+  NS_PRECONDITION(aIndex >= 0, "illegal index");
+
+  if (0 == aIndex) {
+    return nsGkAtoms::fixedList;
+  }
+
+  return nsnull;
+}
+
+nsFrameList
+ViewportFrame::GetChildList(nsIAtom* aListName) const
+{
+  if (nsGkAtoms::fixedList == aListName)
+    return mFixedContainer.GetChildList();
+
+  return nsContainerFrame::GetChildList(aListName);
 }
 
 /* virtual */ nscoord
 ViewportFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
 {
   nscoord result;
   DISPLAY_MIN_WIDTH(this, result);
   if (mFrames.IsEmpty())
     result = 0;
   else
     result = mFrames.FirstChild()->GetMinWidth(aRenderingContext);
+    
+  // XXXldb Deal with mFixedContainer (matters for SizeToContent)!
 
   return result;
 }
 
 /* virtual */ nscoord
 ViewportFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
 {
   nscoord result;
   DISPLAY_PREF_WIDTH(this, result);
   if (mFrames.IsEmpty())
     result = 0;
   else
     result = mFrames.FirstChild()->GetPrefWidth(aRenderingContext);
+    
+  // XXXldb Deal with mFixedContainer (matters for SizeToContent)!
 
   return result;
 }
 
 nsPoint
 ViewportFrame::AdjustReflowStateForScrollbars(nsHTMLReflowState* aReflowState) const
 {
   // Calculate how much room is available for fixed frames. That means
@@ -241,34 +309,30 @@ ViewportFrame::Reflow(nsPresContext*    
   aDesiredSize.height = aReflowState.ComputedHeight() != NS_UNCONSTRAINEDSIZE
                           ? aReflowState.ComputedHeight()
                           : 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
-  if (IsAbsoluteContainer()) {
-    NS_ASSERTION(GetAbsoluteContainingBlock()->GetChildList().IsEmpty() ||
-                 (offset.x == 0 && offset.y == 0),
-                 "We don't handle correct positioning of fixed frames with "
-                 "scrollbars in odd positions");
-  }
+  NS_ASSERTION(mFixedContainer.GetChildList().IsEmpty() ||
+               (offset.x == 0 && offset.y == 0),
+               "We don't handle correct positioning of fixed frames with "
+               "scrollbars in odd positions");
 #endif
 
-  if (IsAbsoluteContainer()) {
-    // Just reflow all the fixed-pos frames.
-    rv = GetAbsoluteContainingBlock()->Reflow(this, aPresContext, reflowState, aStatus,
-                                              reflowState.ComputedWidth(),
-                                              reflowState.ComputedHeight(),
-                                              PR_FALSE, PR_TRUE, PR_TRUE, // XXX could be optimized
-                                              nsnull /* ignore overflow */);
-  }
+  // Just reflow all the fixed-pos frames.
+  rv = mFixedContainer.Reflow(this, aPresContext, reflowState, aStatus,
+                              reflowState.ComputedWidth(),
+                              reflowState.ComputedHeight(),
+                              PR_FALSE, PR_TRUE, PR_TRUE, // XXX could be optimized
+                              nsnull /* ignore overflow */);
 
   // If we were dirty then do a repaint
   if (GetStateBits() & NS_FRAME_IS_DIRTY) {
     nsRect damageRect(0, 0, aDesiredSize.width, aDesiredSize.height);
     Invalidate(damageRect);
   }
 
   // XXX Should we do something to clip our children to this?
--- a/layout/generic/nsViewportFrame.h
+++ b/layout/generic/nsViewportFrame.h
@@ -40,32 +40,35 @@
  * the document's scrollbars and contains fixed-positioned elements
  */
 
 #ifndef nsViewportFrame_h___
 #define nsViewportFrame_h___
 
 #include "nsContainerFrame.h"
 #include "nsGkAtoms.h"
+#include "nsAbsoluteContainingBlock.h"
 
 class nsPresContext;
 
 /**
   * ViewportFrame is the parent of a single child - the doc root frame or a scroll frame 
   * containing the doc root frame. ViewportFrame stores this child in its primary child 
-  * list.
+  * list. It stores fixed positioned items in a secondary child list and its mFixedContainer 
+  * delegate handles them. 
   */
 class ViewportFrame : public nsContainerFrame {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   typedef nsContainerFrame Super;
 
   ViewportFrame(nsStyleContext* aContext)
     : nsContainerFrame(aContext)
+    , mFixedContainer(nsGkAtoms::fixedList)
   {}
   virtual ~ViewportFrame() { } // useful for debugging
 
   virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        asPrevInFlow);
@@ -78,16 +81,20 @@ public:
 
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
                           nsFrameList&    aFrameList);
 
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
 
+  virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
+
+  virtual nsFrameList GetChildList(nsIAtom* aListName) const;
+
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists);
 
   virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext);
   virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext);
   NS_IMETHOD Reflow(nsPresContext*          aPresContext,
                     nsHTMLReflowMetrics&     aDesiredSize,
@@ -106,17 +113,19 @@ public:
   virtual void InvalidateInternal(const nsRect& aDamageRect,
                                   nscoord aX, nscoord aY, nsIFrame* aForChild,
                                   PRUint32 aFlags);
 
 #ifdef DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
 
-private:
-  virtual nsIAtom* GetAbsoluteListName() const { return nsGkAtoms::fixedList; }
+protected:
+  nsPoint AdjustReflowStateForScrollbars(nsHTMLReflowState* aReflowState) const;
 
 protected:
-  nsPoint AdjustReflowStateForScrollbars(nsHTMLReflowState* aReflowState) const;
+  // position: fixed content is really content which is absolutely positioned with
+  // respect to the viewport.
+  nsAbsoluteContainingBlock mFixedContainer;
 };
 
 
 #endif // nsViewportFrame_h___
deleted file mode 100644
--- a/layout/reftests/bugs/656875.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE html>
-
-<div>test</div>
-
-<style>
-  body {
-      width: 100px; height: 300px;
-      position: absolute;
-      -moz-transform: scale(0.5);
-  }
-  div { position: absolute; }
-</style>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1638,12 +1638,11 @@ HTTP(..) == 635639-2.html 635639-2-ref.h
 == 645491-1.html 645491-1-ref.html
 == 645768-1.html 645768-1-ref.html
 fails-if(layersGPUAccelerated&&cocoaWidget) == 650228-1.html 650228-1-ref.html # Quartz alpha blending doesn't match GL alpha blending
 == 653930-1.html 653930-1-ref.html
 HTTP(..) == 654057-1.html 654057-1-ref.html
 fails-if(layersGPUAccelerated&&cocoaWidget) == 654950-1.html 654950-1-ref.html # Quartz alpha blending doesn't match GL alpha blending
 == 652775-1.html 652775-1-ref.html
 == 655549-1.html 655549-1-ref.html
-!= 656875.html about:blank
 == 658952.html 658952-ref.html
 == 664127-1.xul 664127-1-ref.xul
 == 660682-1.html 660682-1-ref.html
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -1081,17 +1081,17 @@ nsIAtom*
 nsTableFrame::GetAdditionalChildListName(PRInt32 aIndex) const
 {
   if (aIndex == NS_TABLE_FRAME_COLGROUP_LIST_INDEX) {
     return nsGkAtoms::colGroupList;
   }
   if (aIndex == NS_TABLE_FRAME_OVERFLOW_LIST_INDEX) {
     return nsGkAtoms::overflowList;
   }
-  return nsHTMLContainerFrame::GetAdditionalChildListName(aIndex);
+  return nsnull;
 }
 
 nsRect
 nsDisplayTableItem::GetBounds(nsDisplayListBuilder* aBuilder) {
   return mFrame->GetVisualOverflowRect() + ToReferenceFrame();
 }
 
 PRBool
--- a/layout/tables/nsTableOuterFrame.cpp
+++ b/layout/tables/nsTableOuterFrame.cpp
@@ -222,26 +222,26 @@ nsFrameList
 nsTableOuterFrame::GetChildList(nsIAtom* aListName) const
 {
   if (nsGkAtoms::captionList == aListName) {
     return mCaptionFrames;
   }
   if (!aListName) {
     return mFrames;
   }
-  return nsHTMLContainerFrame::GetChildList(aListName);
+  return nsFrameList::EmptyList();
 }
 
 nsIAtom*
 nsTableOuterFrame::GetAdditionalChildListName(PRInt32 aIndex) const
 {
   if (aIndex == NS_TABLE_FRAME_CAPTION_LIST_INDEX) {
     return nsGkAtoms::captionList;
   }
-  return nsHTMLContainerFrame::GetAdditionalChildListName(aIndex);
+  return nsnull;
 }
 
 NS_IMETHODIMP 
 nsTableOuterFrame::SetInitialChildList(nsIAtom*        aListName,
                                        nsFrameList&    aChildList)
 {
   if (nsGkAtoms::captionList == aListName) {
     // the frame constructor already checked for table-caption display type
--- a/layout/xul/base/src/nsMenuFrame.cpp
+++ b/layout/xul/base/src/nsMenuFrame.cpp
@@ -393,17 +393,17 @@ nsMenuFrame::SetInitialChildList(nsIAtom
 }
 
 nsIAtom*
 nsMenuFrame::GetAdditionalChildListName(PRInt32 aIndex) const
 {
   if (NS_MENU_POPUP_LIST_INDEX == aIndex) {
     return nsGkAtoms::popupList;
   }
-  return nsBoxFrame::GetAdditionalChildListName(aIndex);
+  return nsnull;
 }
 
 void
 nsMenuFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // Kill our timer if one is active. This is not strictly necessary as
   // the pointer to this frame will be cleared from the mediator, but
   // this is done for added safety.