Bug 482889 Part 3. Switch to a new algorithm for creating anonymous table objects. r=bernd, r+sr=roc
authorBoris Zbarsky <bzbarsky@mit.edu>
Sun, 15 Mar 2009 16:01:48 -0400
changeset 26208 237db3258d19208e37cc171e77bbeeee4ab23c8c
parent 26207 523942ee51c838a08bf9342fdb2550f8ce3dd1e4
child 26209 388c17a510e8870b39f045bfe1d75ff7b470c525
push idunknown
push userunknown
push dateunknown
reviewersbernd, r
bugs482889
milestone1.9.2a1pre
Bug 482889 Part 3. Switch to a new algorithm for creating anonymous table objects. r=bernd, r+sr=roc
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSFrameConstructor.h
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -238,29 +238,27 @@ nsIXBLService * nsCSSFrameConstructor::g
 #ifdef DEBUG
 // Set the environment variable GECKO_FRAMECTOR_DEBUG_FLAGS to one or
 // more of the following flags (comma separated) for handy debug
 // output.
 static PRBool gNoisyContentUpdates = PR_FALSE;
 static PRBool gReallyNoisyContentUpdates = PR_FALSE;
 static PRBool gNoisyInlineConstruction = PR_FALSE;
 static PRBool gVerifyFastFindFrame = PR_FALSE;
-static PRBool gTablePseudoFrame = PR_FALSE;
 
 struct FrameCtorDebugFlags {
   const char* name;
   PRBool* on;
 };
 
 static FrameCtorDebugFlags gFlags[] = {
   { "content-updates",              &gNoisyContentUpdates },
   { "really-noisy-content-updates", &gReallyNoisyContentUpdates },
   { "noisy-inline",                 &gNoisyInlineConstruction },
-  { "fast-find-frame",              &gVerifyFastFindFrame },
-  { "table-pseudo",                 &gTablePseudoFrame },
+  { "fast-find-frame",              &gVerifyFastFindFrame }
 };
 
 #define NUM_DEBUG_FLAGS (sizeof(gFlags) / sizeof(gFlags[0]))
 #endif
 
 
 #ifdef MOZ_XUL
 #include "nsMenuFrame.h"
@@ -806,246 +804,16 @@ nsAbsoluteItems::AddChild(nsIFrame* aChi
 {
   NS_ASSERTION(aChild->PresContext()->FrameManager()->
                GetPlaceholderFrameFor(aChild),
                "Child without placeholder being added to nsAbsoluteItems?");
   aChild->AddStateBits(NS_FRAME_OUT_OF_FLOW);
   nsFrameItems::AddChild(aChild);
 }
 
-// Structures used to record the creation of pseudo table frames where 
-// the content belongs to some ancestor. 
-// PseudoFrames are necessary when the childframe cannot be the direct
-// ancestor of the content based parent frame. The amount of necessary pseudo
-// frames is limited as the worst case would be table frame nested directly
-// into another table frame. So the member structures of nsPseudoFrames can be
-// viewed as a ring buffer where you start with the necessary frame type and
-// add higher frames as long as necessary to fit into the initial parent frame.
-// mLowestType is some sort of stack pointer which shows the start of the
-// ringbuffer. The insertion of pseudo frames can happen between every
-// two frames so we need to push and pop the pseudo frame data when children
-// of a frame are created.
-// The colgroup frame is special as it can harbour only col children.
-// Once all children of given frame are known, the pseudo frames can be
-// processed that means attached to the corresponding parent frames.
-// The behaviour is in general described at
-// http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes
-// however there are implementation details that extend the CSS 2.1
-// specification:
-// 1. every table frame is wrapped in an outer table frame, which is always a
-//    pseudo frame.
-// 2. the outer table frame will be also created to hold a caption.
-// 3. each table cell will have a pseudo inner table cell frame.
-// 4. a colgroup frame is created between a column and a table
-// 5. a rowgroup frame is created between a row and a table
-// A table frame can only have rowgroups or column groups as children.
-// A outer table frame can only have one caption and one table frame
-// as children.
-// Every table even if all table frames are specified will require the
-// creation of two types of pseudo frames: the outer table frame and the inner
-// table cell frames.
-
-struct nsPseudoFrameData {
-  nsIFrame*    mFrame; // created pseudo frame
-  nsFrameItems mChildList;  // child frames pending to be added to the pseudo
-  nsFrameItems mChildList2; // child frames pending to be added to the pseudo
-
-  nsPseudoFrameData();
-  nsPseudoFrameData(nsPseudoFrameData& aOther);
-  void Reset();
-#ifdef DEBUG
-  void Dump();
-#endif
-};
-
-struct nsPseudoFrames {
-  nsPseudoFrameData mTableOuter; 
-  nsPseudoFrameData mTableInner;  
-  nsPseudoFrameData mRowGroup;   
-  nsPseudoFrameData mColGroup;
-  nsPseudoFrameData mRow;   
-  nsPseudoFrameData mCellOuter;
-  nsPseudoFrameData mCellInner;
-
-  // the frame type of the most descendant pseudo frame, no AddRef
-  nsIAtom*          mLowestType;
-
-  nsPseudoFrames();
-  nsPseudoFrames& operator=(const nsPseudoFrames& aOther);
-  void Reset(nsPseudoFrames* aSave = nsnull);
-  PRBool IsEmpty() { return (!mLowestType && !mColGroup.mFrame); }
-#ifdef DEBUG
-  void Dump();
-#endif
-};
-
-nsPseudoFrameData::nsPseudoFrameData()
-: mFrame(nsnull), mChildList(), mChildList2()
-{}
-
-nsPseudoFrameData::nsPseudoFrameData(nsPseudoFrameData& aOther)
-: mFrame(aOther.mFrame), mChildList(aOther.mChildList), 
-  mChildList2(aOther.mChildList2)
-{}
-
-void
-nsPseudoFrameData::Reset()
-{
-  mFrame = nsnull;
-  mChildList.childList  = mChildList.lastChild  = nsnull;
-  mChildList2.childList = mChildList2.lastChild = nsnull;
-}
-
-#ifdef DEBUG
-void
-nsPseudoFrameData::Dump()
-{
-  nsIFrame* main = nsnull;
-  nsIFrame* second = nsnull;
-  printf("        %p\n", static_cast<void*>(mFrame));
-  main = mChildList.childList;
-
- 
-  second = mChildList2.childList;
-  while (main || second) {
-    printf("          %p   %p\n", static_cast<void*>(main),
-           static_cast<void*>(second));
-    if (main)
-      main = main->GetNextSibling();
-    if (second)
-      second = second->GetNextSibling();
-  }
-}
-#endif
-nsPseudoFrames::nsPseudoFrames() 
-: mTableOuter(), mTableInner(), mRowGroup(), mColGroup(), 
-  mRow(), mCellOuter(), mCellInner(), mLowestType(nsnull)
-{}
-
-nsPseudoFrames& nsPseudoFrames::operator=(const nsPseudoFrames& aOther)
-{
-  mTableOuter = aOther.mTableOuter;
-  mTableInner = aOther.mTableInner;
-  mColGroup   = aOther.mColGroup;
-  mRowGroup   = aOther.mRowGroup;
-  mRow        = aOther.mRow;
-  mCellOuter  = aOther.mCellOuter;
-  mCellInner  = aOther.mCellInner;
-  mLowestType = aOther.mLowestType;
-
-  return *this;
-}
-void
-nsPseudoFrames::Reset(nsPseudoFrames* aSave) 
-{
-  if (aSave) {
-    *aSave = *this;
-  }
-
-  mTableOuter.Reset();
-  mTableInner.Reset();
-  mColGroup.Reset();
-  mRowGroup.Reset();
-  mRow.Reset();
-  mCellOuter.Reset();
-  mCellInner.Reset();
-  mLowestType = nsnull;
-}
-
-#ifdef DEBUG
-void
-nsPseudoFrames::Dump()
-{
-  if (IsEmpty()) {
-    // check that it is really empty, warn otherwise
-    NS_ASSERTION(!mTableOuter.mFrame,    "Pseudo Outer Table Frame not empty");
-    NS_ASSERTION(!mTableOuter.mChildList.childList, "Pseudo Outer Table Frame has primary children");
-    NS_ASSERTION(!mTableOuter.mChildList2.childList,"Pseudo Outer Table Frame has secondary children");
-    NS_ASSERTION(!mTableInner.mFrame,    "Pseudo Inner Table Frame not empty");
-    NS_ASSERTION(!mTableInner.mChildList.childList, "Pseudo Inner Table Frame has primary children");
-    NS_ASSERTION(!mTableInner.mChildList2.childList,"Pseudo Inner Table Frame has secondary children");
-    NS_ASSERTION(!mColGroup.mFrame,      "Pseudo Colgroup Frame not empty");
-    NS_ASSERTION(!mColGroup.mChildList.childList,   "Pseudo Colgroup Table Frame has primary children");
-    NS_ASSERTION(!mColGroup.mChildList2.childList,  "Pseudo Colgroup Table Frame has secondary children");
-    NS_ASSERTION(!mRowGroup.mFrame,      "Pseudo Rowgroup Frame not empty");
-    NS_ASSERTION(!mRowGroup.mChildList.childList,   "Pseudo Rowgroup Frame has primary children");
-    NS_ASSERTION(!mRowGroup.mChildList2.childList,  "Pseudo Rowgroup Frame has secondary children");
-    NS_ASSERTION(!mRow.mFrame,           "Pseudo Row Frame not empty");
-    NS_ASSERTION(!mRow.mChildList.childList,        "Pseudo Row Frame has primary children");
-    NS_ASSERTION(!mRow.mChildList2.childList,       "Pseudo Row Frame has secondary children");
-    NS_ASSERTION(!mCellOuter.mFrame,     "Pseudo Outer Cell Frame not empty");
-    NS_ASSERTION(!mCellOuter.mChildList.childList,  "Pseudo Outer Cell Frame has primary children");
-    NS_ASSERTION(!mCellOuter.mChildList2.childList, "Pseudo Outer Cell Frame has secondary children");
-    NS_ASSERTION(!mCellInner.mFrame,     "Pseudo Inner Cell Frame not empty");
-    NS_ASSERTION(!mCellInner.mChildList.childList,  "Pseudo Inner Cell Frame has primary children");
-    NS_ASSERTION(!mCellInner.mChildList2.childList, "Pseudo inner Cell Frame has secondary children");
-  }
-  else {
-    if (mTableOuter.mFrame || mTableOuter.mChildList.childList || mTableOuter.mChildList2.childList) {
-      if (nsGkAtoms::tableOuterFrame == mLowestType) {
-        printf("LOW OuterTable\n");
-      }
-      else {
-        printf("    OuterTable\n");
-      }
-      mTableOuter.Dump();
-    }
-    if (mTableInner.mFrame || mTableInner.mChildList.childList || mTableInner.mChildList2.childList) {
-      if (nsGkAtoms::tableFrame == mLowestType) {
-        printf("LOW InnerTable\n");
-      }
-      else {
-        printf("    InnerTable\n");
-      }
-      mTableInner.Dump();
-    }
-    if (mColGroup.mFrame || mColGroup.mChildList.childList || mColGroup.mChildList2.childList) {
-      if (nsGkAtoms::tableColGroupFrame == mLowestType) {
-        printf("LOW ColGroup\n");
-      }
-      else {
-        printf("    ColGroup\n");
-      }
-      mColGroup.Dump();
-    }
-    if (mRowGroup.mFrame || mRowGroup.mChildList.childList || mRowGroup.mChildList2.childList) {
-      if (nsGkAtoms::tableRowGroupFrame == mLowestType) {
-        printf("LOW RowGroup\n");
-      }
-      else {
-        printf("    RowGroup\n");
-      }
-      mRowGroup.Dump();
-    }
-    if (mRow.mFrame || mRow.mChildList.childList || mRow.mChildList2.childList) {
-      if (nsGkAtoms::tableRowFrame == mLowestType) {
-        printf("LOW Row\n");
-      }
-      else {
-        printf("    Row\n");
-      }
-      mRow.Dump();
-    }
-    
-    if (mCellOuter.mFrame || mCellOuter.mChildList.childList || mCellOuter.mChildList2.childList) {
-      if (IS_TABLE_CELL(mLowestType)) {
-        printf("LOW OuterCell\n");
-      }
-      else {
-        printf("    OuterCell\n");
-      }
-      mCellOuter.Dump();
-    }
-    if (mCellInner.mFrame || mCellInner.mChildList.childList || mCellInner.mChildList2.childList) {
-      printf("    InnerCell\n");
-      mCellInner.Dump();
-    }
-  }
-}
-#endif
 // -----------------------------------------------------------
 
 // Structure for saving the existing state when pushing/poping containing
 // blocks. The destructor restores the state to its previous state
 class NS_STACK_CLASS nsFrameConstructorSaveState {
 public:
   nsFrameConstructorSaveState();
   ~nsFrameConstructorSaveState();
@@ -1090,17 +858,16 @@ public:
   PRPackedBool              mFixedPosIsAbsPos;
 
   // A boolean to indicate whether we have a "pending" popupgroup.  That is, we
   // have already created the FrameConstructionItem for the root popupgroup but
   // we have not yet created the relevant frame.
   PRPackedBool              mHavePendingPopupgroup;
 
   nsCOMPtr<nsILayoutHistoryState> mFrameState;
-  nsPseudoFrames            mPseudoFrames;
   // These bits will be added to the state bits of any frame we construct
   // using this state.
   nsFrameState              mAdditionalStateBits; 
 
   // Constructor
   // Use the passed-in history state.
   nsFrameConstructorState(nsIPresShell*          aPresShell,
                           nsIFrame*              aFixedContainingBlock,
@@ -1212,17 +979,16 @@ nsFrameConstructorState::nsFrameConstruc
     mAbsoluteItems(aAbsoluteContainingBlock),
     mFloatedItems(aFloatContainingBlock),
     // See PushAbsoluteContaningBlock below
     mFixedPosIsAbsPos(aAbsoluteContainingBlock &&
                       aAbsoluteContainingBlock->GetStyleDisplay()->
                         HasTransform()),
     mHavePendingPopupgroup(PR_FALSE),
     mFrameState(aHistoryState),
-    mPseudoFrames(),
     mAdditionalStateBits(0)
 {
 #ifdef MOZ_XUL
   nsIRootBox* rootBox = nsIRootBox::GetRootBox(aPresShell);
   if (rootBox) {
     mPopupItems.containingBlock = rootBox->GetPopupSetFrame();
   }
 #endif
@@ -1242,17 +1008,16 @@ nsFrameConstructorState::nsFrameConstruc
     mFixedItems(aFixedContainingBlock),
     mAbsoluteItems(aAbsoluteContainingBlock),
     mFloatedItems(aFloatContainingBlock),
     // See PushAbsoluteContaningBlock below
     mFixedPosIsAbsPos(aAbsoluteContainingBlock &&
                       aAbsoluteContainingBlock->GetStyleDisplay()->
                         HasTransform()),
     mHavePendingPopupgroup(PR_FALSE),
-    mPseudoFrames(),
     mAdditionalStateBits(0)
 {
 #ifdef MOZ_XUL
   nsIRootBox* rootBox = nsIRootBox::GetRootBox(aPresShell);
   if (rootBox) {
     mPopupItems.containingBlock = rootBox->GetPopupSetFrame();
   }
 #endif
@@ -2176,32 +1941,47 @@ TextIsOnlyWhitespace(nsIContent* aConten
 // frame has been used elsewhere to refer to frames that have generated content
 
 // aIncludeSpecial applies to captions, col groups, cols and cells.
 // These do not generate pseudo frame wrappers for foreign children.
 // In fact, colgroups never have any children that are not cols and
 // cols never have any children at all.
 
 static PRBool
-IsTableRelated(nsIAtom* aParentType,
-               PRBool   aIncludeSpecial)
-{
-  if ((nsGkAtoms::tableFrame         == aParentType)  ||
-      (nsGkAtoms::tableRowGroupFrame == aParentType)  ||
-      (nsGkAtoms::tableRowFrame      == aParentType)) {
-    return PR_TRUE;
-  }
-  else if (aIncludeSpecial && 
-           ((nsGkAtoms::tableCaptionFrame  == aParentType)  ||
-            (nsGkAtoms::tableColGroupFrame == aParentType)  ||
-            (nsGkAtoms::tableColFrame      == aParentType)  ||
-            IS_TABLE_CELL(aParentType))) {
-    return PR_TRUE;
-  }
-  else return PR_FALSE;
+IsTableRelated(nsIAtom* aParentType)
+{
+  return
+    nsGkAtoms::tableFrame         == aParentType ||
+    nsGkAtoms::tableRowGroupFrame == aParentType ||
+    nsGkAtoms::tableRowFrame      == aParentType ||
+    nsGkAtoms::tableCaptionFrame  == aParentType ||
+    nsGkAtoms::tableColGroupFrame == aParentType ||
+    nsGkAtoms::tableColFrame      == aParentType ||
+    IS_TABLE_CELL(aParentType);
+}
+
+/* static */
+nsCSSFrameConstructor::ParentType
+nsCSSFrameConstructor::GetParentType(nsIFrame* aParentFrame)
+{
+  nsIAtom* type = aParentFrame->GetType();
+  if (type == nsGkAtoms::tableFrame) {
+    return eTypeTable;
+  }
+  if (type == nsGkAtoms::tableRowGroupFrame) {
+    return eTypeRowGroup;
+  }
+  if (type == nsGkAtoms::tableRowFrame) {
+    return eTypeRow;
+  }
+  if (type == nsGkAtoms::tableColGroupFrame) {
+    return eTypeColGroup;
+  }
+
+  return eTypeBlock;
 }
            
 static nsIFrame*
 AdjustCaptionParentFrame(nsIFrame* aParentFrame) 
 {
   if (nsGkAtoms::tableFrame == aParentFrame->GetType()) {
     return aParentFrame->GetParent();;
   }
@@ -2223,963 +2003,31 @@ GetCaptionAdjustedParent(nsIFrame*      
   PRBool haveCaption = PR_FALSE;
 
   if (nsGkAtoms::tableCaptionFrame == aChildFrame->GetType()) {
     haveCaption = PR_TRUE;
     *aAdjParentFrame = AdjustCaptionParentFrame(aParentFrame);
   }
   return haveCaption;
 }
-   
-static nsresult 
-ProcessPseudoFrame(nsPseudoFrameData& aPseudoData,
-                   nsIFrame*&         aParent)
-{
-  nsresult rv = NS_OK;
-
-  aParent = aPseudoData.mFrame;
-  nsFrameItems* items = &aPseudoData.mChildList;
-  if (items && items->childList) {
-    rv = aParent->SetInitialChildList(nsnull, items->childList);
-    if (NS_FAILED(rv)) return rv;
-  }
-  aPseudoData.Reset();
-  return rv;
-}
-
-static nsresult 
-ProcessPseudoRowGroupFrame(nsPseudoFrameData& aPseudoData,
-                           nsIFrame*&         aParent)
-{
-  nsresult rv = NS_OK;
-
-  aParent = aPseudoData.mFrame;
-  nsFrameItems* items = &aPseudoData.mChildList;
-  if (items && items->childList) {
-    nsTableRowGroupFrame* rgFrame = nsTableFrame::GetRowGroupFrame(aParent);
-    rv = rgFrame->SetInitialChildList(nsnull, items->childList);
-    if (NS_FAILED(rv)) return rv;
-  }
-  aPseudoData.Reset();
-  return rv;
-}
-
-static nsresult 
-ProcessPseudoTableFrame(nsPseudoFrames& aPseudoFrames,
-                        nsIFrame*&      aParent)
-{
-  nsresult rv = NS_OK;
-
-  // process the col group frame, if it exists
-  if (aPseudoFrames.mColGroup.mFrame) {
-    rv = ProcessPseudoFrame(aPseudoFrames.mColGroup, aParent);
-  }
-
-  // process the inner table frame
-  rv = ProcessPseudoFrame(aPseudoFrames.mTableInner, aParent);
-
-  // process the outer table frame
-  aParent = aPseudoFrames.mTableOuter.mFrame;
-  nsFrameItems* items = &aPseudoFrames.mTableOuter.mChildList;
-  if (items && items->childList) {
-    rv = aParent->SetInitialChildList(nsnull, items->childList);
-    if (NS_FAILED(rv)) return rv;
-  }
-  nsFrameItems* captions = &aPseudoFrames.mTableOuter.mChildList2;
-  if (captions && captions->childList) {
-    rv = aParent->SetInitialChildList(nsGkAtoms::captionList, captions->childList);
-  }
-  aPseudoFrames.mTableOuter.Reset();
-  return rv;
-}
-
-static nsresult 
-ProcessPseudoCellFrame(nsPseudoFrames& aPseudoFrames,
-                       nsIFrame*&      aParent)
-{
-  nsresult rv = NS_OK;
-
-  rv = ProcessPseudoFrame(aPseudoFrames.mCellInner, aParent);
-  if (NS_FAILED(rv)) return rv;
-  rv = ProcessPseudoFrame(aPseudoFrames.mCellOuter, aParent);
-  return rv;
-}
-
-// limit the processing up to the frame type indicated by aHighestType.
-// make a complete processing when aHighestType is null
-static nsresult 
-ProcessPseudoFrames(nsFrameConstructorState& aState,
-                    nsIAtom*        aHighestType,
-                    nsIFrame*&      aHighestFrame)
-{
-  nsresult rv = NS_OK;
-
-  aHighestFrame = nsnull;
-
-#ifdef DEBUG
-  if (gTablePseudoFrame) {
-    printf("*** ProcessPseudoFrames enter***\n");
-    aState.mPseudoFrames.Dump();
-  }
-#endif
-
-  nsPseudoFrames& pseudoFrames = aState.mPseudoFrames;
-
-  if (nsGkAtoms::tableFrame == pseudoFrames.mLowestType) {
-    if (pseudoFrames.mColGroup.mFrame) {
-      rv = ProcessPseudoFrame(pseudoFrames.mColGroup, aHighestFrame);
-      if (nsGkAtoms::tableColGroupFrame == aHighestType) return rv;
-    }
-    rv = ProcessPseudoTableFrame(pseudoFrames, aHighestFrame);
-    if (nsGkAtoms::tableOuterFrame == aHighestType) return rv;
-    
-    if (pseudoFrames.mCellOuter.mFrame) {
-      rv = ProcessPseudoCellFrame(pseudoFrames, aHighestFrame);
-      if (IS_TABLE_CELL(aHighestType)) return rv;
-    }
-    if (pseudoFrames.mRow.mFrame) {
-      rv = ProcessPseudoFrame(pseudoFrames.mRow, aHighestFrame);
-      if (nsGkAtoms::tableRowFrame == aHighestType) return rv;
-    }
-    if (pseudoFrames.mRowGroup.mFrame) {
-      rv = ProcessPseudoRowGroupFrame(pseudoFrames.mRowGroup, aHighestFrame);
-      if (nsGkAtoms::tableRowGroupFrame == aHighestType) return rv;
-    }
-  }
-  else if (nsGkAtoms::tableRowGroupFrame == pseudoFrames.mLowestType) {
-    rv = ProcessPseudoRowGroupFrame(pseudoFrames.mRowGroup, aHighestFrame);
-    if (nsGkAtoms::tableRowGroupFrame == aHighestType) return rv;
-    if (pseudoFrames.mColGroup.mFrame) {
-      nsIFrame* colGroupHigh;
-      rv = ProcessPseudoFrame(pseudoFrames.mColGroup, colGroupHigh);
-      if (aHighestFrame &&
-          nsGkAtoms::tableRowGroupFrame == aHighestFrame->GetType() &&
-          !pseudoFrames.mTableInner.mFrame) {
-        // table frames are special they can have two types of pseudo frames as
-        // children that need to be processed in one pass, we only need to link
-        // them if the parent is not a pseudo where the link is already done
-        // We sort this later out inside nsTableFrame.
-        colGroupHigh->SetNextSibling(aHighestFrame); 
-      }
-      aHighestFrame = colGroupHigh;
-      if (nsGkAtoms::tableColGroupFrame == aHighestType) return rv;
-    }
-    if (pseudoFrames.mTableOuter.mFrame) {
-      rv = ProcessPseudoTableFrame(pseudoFrames, aHighestFrame);
-      if (nsGkAtoms::tableOuterFrame == aHighestType) return rv;
-    }
-    if (pseudoFrames.mCellOuter.mFrame) {
-      rv = ProcessPseudoCellFrame(pseudoFrames, aHighestFrame);
-      if (IS_TABLE_CELL(aHighestType)) return rv;
-    }
-    if (pseudoFrames.mRow.mFrame) {
-      rv = ProcessPseudoFrame(pseudoFrames.mRow, aHighestFrame);
-      if (nsGkAtoms::tableRowFrame == aHighestType) return rv;
-    }
-  }
-  else if (nsGkAtoms::tableRowFrame == pseudoFrames.mLowestType) {
-    rv = ProcessPseudoFrame(pseudoFrames.mRow, aHighestFrame);
-    if (nsGkAtoms::tableRowFrame == aHighestType) return rv;
-
-    if (pseudoFrames.mRowGroup.mFrame) {
-      rv = ProcessPseudoRowGroupFrame(pseudoFrames.mRowGroup, aHighestFrame);
-      if (nsGkAtoms::tableRowGroupFrame == aHighestType) return rv;
-    }
-    if (pseudoFrames.mColGroup.mFrame) {
-      nsIFrame* colGroupHigh;
-      rv = ProcessPseudoFrame(pseudoFrames.mColGroup, colGroupHigh);
-      if (aHighestFrame &&
-          nsGkAtoms::tableRowGroupFrame == aHighestFrame->GetType() &&
-          !pseudoFrames.mTableInner.mFrame) {
-        // table frames are special they can have two types of pseudo frames as
-        // children that need to be processed in one pass, we only need to link
-        // them if the parent is not a pseudo where the link is already done
-        // We sort this later out inside nsTableFrame.
-        colGroupHigh->SetNextSibling(aHighestFrame); 
-      }
-      aHighestFrame = colGroupHigh;
-      if (nsGkAtoms::tableColGroupFrame == aHighestType) return rv;
-    }
-    if (pseudoFrames.mTableOuter.mFrame) {
-      rv = ProcessPseudoTableFrame(pseudoFrames, aHighestFrame);
-      if (nsGkAtoms::tableOuterFrame == aHighestType) return rv;
-    }
-    if (pseudoFrames.mCellOuter.mFrame) {
-      rv = ProcessPseudoCellFrame(pseudoFrames, aHighestFrame);
-      if (IS_TABLE_CELL(aHighestType)) return rv;
-    }
-  }
-  else if (IS_TABLE_CELL(pseudoFrames.mLowestType)) {
-    rv = ProcessPseudoCellFrame(pseudoFrames, aHighestFrame);
-    if (IS_TABLE_CELL(aHighestType)) return rv;
-
-    if (pseudoFrames.mRow.mFrame) {
-      rv = ProcessPseudoFrame(pseudoFrames.mRow, aHighestFrame);
-      if (nsGkAtoms::tableRowFrame == aHighestType) return rv;
-    }
-    if (pseudoFrames.mRowGroup.mFrame) {
-      rv = ProcessPseudoRowGroupFrame(pseudoFrames.mRowGroup, aHighestFrame);
-      if (nsGkAtoms::tableRowGroupFrame == aHighestType) return rv;
-    }
-    if (pseudoFrames.mColGroup.mFrame) {
-      nsIFrame* colGroupHigh;
-      rv = ProcessPseudoFrame(pseudoFrames.mColGroup, colGroupHigh);
-      if (aHighestFrame &&
-          nsGkAtoms::tableRowGroupFrame == aHighestFrame->GetType() &&
-          !pseudoFrames.mTableInner.mFrame) {
-        // table frames are special they can have two types of pseudo frames as
-        // children that need to be processed in one pass, we only need to link
-        // them if the parent is not a pseudo where the link is already done
-        // We sort this later out inside nsTableFrame.
-        colGroupHigh->SetNextSibling(aHighestFrame); 
-      }
-      aHighestFrame = colGroupHigh;
-      if (nsGkAtoms::tableColGroupFrame == aHighestType) return rv;
-    }
-    if (pseudoFrames.mTableOuter.mFrame) {
-      rv = ProcessPseudoTableFrame(pseudoFrames, aHighestFrame);
-    }
-  }
-  else if (pseudoFrames.mColGroup.mFrame) { 
-    // process the col group frame
-    rv = ProcessPseudoFrame(pseudoFrames.mColGroup, aHighestFrame);
-  }
-
-  return rv;
-}
-
-static nsresult 
-ProcessPseudoFrames(nsFrameConstructorState& aState,
-                    nsFrameItems&   aItems)
-{
-
-#ifdef DEBUG
-  if (gTablePseudoFrame) {
-    printf("*** ProcessPseudoFrames complete enter***\n");
-    aState.mPseudoFrames.Dump();
-  }
-#endif
- 
-  nsIFrame* highestFrame;
-  nsresult rv = ProcessPseudoFrames(aState, nsnull, highestFrame);
-  if (highestFrame) {
-    aItems.AddChild(highestFrame);
-  }
- 
-#ifdef DEBUG
-  if (gTablePseudoFrame) {
-    printf("*** ProcessPseudoFrames complete leave, highestframe:%p***\n",
-           static_cast<void*>(highestFrame));
-    aState.mPseudoFrames.Dump();
-  }
-#endif
-  aState.mPseudoFrames.Reset();
-  return rv;
-}
-
-static nsresult 
-ProcessPseudoFrames(nsFrameConstructorState& aState,
-                    nsIAtom*        aHighestType)
-{
-#ifdef DEBUG
-  if (gTablePseudoFrame) {
-    printf("*** ProcessPseudoFrames limited enter highest:");
-    if (nsGkAtoms::tableOuterFrame == aHighestType) 
-      printf("OuterTable");
-    else if (nsGkAtoms::tableFrame == aHighestType) 
-      printf("InnerTable");
-    else if (nsGkAtoms::tableColGroupFrame == aHighestType) 
-      printf("ColGroup");
-    else if (nsGkAtoms::tableRowGroupFrame == aHighestType) 
-      printf("RowGroup");
-    else if (nsGkAtoms::tableRowFrame == aHighestType) 
-      printf("Row");
-    else if (IS_TABLE_CELL(aHighestType)) 
-      printf("Cell");
-    else 
-      NS_ASSERTION(PR_FALSE, "invalid call to ProcessPseudoFrames ");
-    printf("***\n");
-    aState.mPseudoFrames.Dump();
-  }
-#endif
- 
-  nsIFrame* highestFrame;
-  nsresult rv = ProcessPseudoFrames(aState, aHighestType, highestFrame);
-
-#ifdef DEBUG
-  if (gTablePseudoFrame) {
-    printf("*** ProcessPseudoFrames limited leave:%p***\n",
-           static_cast<void*>(highestFrame));
-    aState.mPseudoFrames.Dump();
-  }
-#endif
-  return rv;
-}
-
-nsresult
-nsCSSFrameConstructor::CreatePseudoTableFrame(PRInt32                  aNameSpaceID,
-                                              nsFrameConstructorState& aState, 
-                                              nsIFrame*                aParentFrameIn)
-{
-  nsresult rv = NS_OK;
-
-  nsIFrame* parentFrame = (aState.mPseudoFrames.mCellInner.mFrame) 
-                          ? aState.mPseudoFrames.mCellInner.mFrame : aParentFrameIn;
-  if (!parentFrame) return rv;
-
-  nsStyleContext *parentStyle;
-  nsRefPtr<nsStyleContext> childStyle;
-
-  parentStyle = parentFrame->GetStyleContext(); 
-  nsIContent* parentContent = parentFrame->GetContent();   
-
-  // Thankfully, the parent can't change display type without causing
-  // frame reconstruction, so this won't need to change.
-  nsIAtom *pseudoType;
-  if (parentStyle->GetStyleDisplay()->mDisplay == NS_STYLE_DISPLAY_INLINE)
-    pseudoType = nsCSSAnonBoxes::inlineTable;
-  else
-    pseudoType = nsCSSAnonBoxes::table;
-
-  // create the SC for the inner table which will be the parent of the outer table's SC
-  childStyle = mPresShell->StyleSet()->ResolvePseudoStyleFor(parentContent,
-                                                             pseudoType,
-                                                             parentStyle);
-
-  nsPseudoFrameData& pseudoOuter = aState.mPseudoFrames.mTableOuter;
-  nsPseudoFrameData& pseudoInner = aState.mPseudoFrames.mTableInner;
-
-  // construct the pseudo outer and inner as part of the pseudo frames
-  nsFrameItems items;
-  rv = ConstructTableFrame(aState, parentContent,
-                           parentFrame, childStyle, aNameSpaceID,
-                           PR_TRUE, items, pseudoOuter.mFrame, 
-                           pseudoInner.mFrame);
-
-  if (NS_FAILED(rv)) return rv;
-
-  // set pseudo data for the newly created frames
-  pseudoOuter.mChildList.AddChild(pseudoInner.mFrame);
-  aState.mPseudoFrames.mLowestType = nsGkAtoms::tableFrame;
-
-  // set pseudo data for the parent
-  if (aState.mPseudoFrames.mCellInner.mFrame) {
-    aState.mPseudoFrames.mCellInner.mChildList.AddChild(pseudoOuter.mFrame);
-  }
-#ifdef DEBUG
-  if (gTablePseudoFrame) {
-     printf("*** CreatePseudoTableFrame ***\n");
-    aState.mPseudoFrames.Dump();
-  }
-#endif
-  return rv;
-}
-
-nsresult
-nsCSSFrameConstructor::CreatePseudoRowGroupFrame(PRInt32                  aNameSpaceID,
-                                                 nsFrameConstructorState& aState, 
-                                                 nsIFrame*                aParentFrameIn)
-{
-  nsresult rv = NS_OK;
-
-  nsIFrame* parentFrame = (aState.mPseudoFrames.mTableInner.mFrame) 
-                          ? aState.mPseudoFrames.mTableInner.mFrame : aParentFrameIn;
-  if (!parentFrame) return rv;
-
-  nsStyleContext *parentStyle;
-  nsRefPtr<nsStyleContext> childStyle;
-
-  parentStyle = parentFrame->GetStyleContext();
-  nsIContent* parentContent = parentFrame->GetContent();
-
-  childStyle = mPresShell->StyleSet()->ResolvePseudoStyleFor(parentContent,
-                                                             nsCSSAnonBoxes::tableRowGroup, 
-                                                             parentStyle);
-
-  nsPseudoFrameData& pseudo = aState.mPseudoFrames.mRowGroup;
-
-  // construct the pseudo row group as part of the pseudo frames
-  pseudo.mFrame = NS_NewTableRowGroupFrame(mPresShell, childStyle);
-  if (NS_UNLIKELY(!pseudo.mFrame)) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  InitAndRestoreFrame(aState, parentContent, parentFrame, nsnull,
-                      pseudo.mFrame);
-  nsHTMLContainerFrame::CreateViewForFrame(pseudo.mFrame, PR_FALSE);
-  
-  // set pseudo data for the newly created frames
-  aState.mPseudoFrames.mLowestType = nsGkAtoms::tableRowGroupFrame;
-
-  // set pseudo data for the parent
-  if (aState.mPseudoFrames.mTableInner.mFrame) {
-    aState.mPseudoFrames.mTableInner.mChildList.AddChild(pseudo.mFrame);
-  }
-#ifdef DEBUG
-  if (gTablePseudoFrame) {
-     printf("*** CreatePseudoRowGroupFrame ***\n");
-    aState.mPseudoFrames.Dump();
-  }
-#endif
-  return rv;
-}
-
-nsresult 
-nsCSSFrameConstructor::CreatePseudoColGroupFrame(PRInt32                  aNameSpaceID,
-                                                 nsFrameConstructorState& aState, 
-                                                 nsIFrame*                aParentFrameIn)
-{
-  nsresult rv = NS_OK;
-
-  nsIFrame* parentFrame = (aState.mPseudoFrames.mTableInner.mFrame) 
-                          ? aState.mPseudoFrames.mTableInner.mFrame : aParentFrameIn;
-  if (!parentFrame) return rv;
-
-  nsStyleContext *parentStyle;
-  nsRefPtr<nsStyleContext> childStyle;
-
-  parentStyle = parentFrame->GetStyleContext();
-  nsIContent* parentContent = parentFrame->GetContent();
-
-  childStyle = mPresShell->StyleSet()->ResolvePseudoStyleFor(parentContent,
-                                                             nsCSSAnonBoxes::tableColGroup, 
-                                                             parentStyle);
-
-  nsPseudoFrameData& pseudo = aState.mPseudoFrames.mColGroup;
-
-  // construct the pseudo col group as part of the pseudo frames
-  pseudo.mFrame = NS_NewTableColGroupFrame(mPresShell, childStyle);
-  if (NS_UNLIKELY(!pseudo.mFrame)) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  InitAndRestoreFrame(aState, parentContent, parentFrame, nsnull,
-                      pseudo.mFrame);
-
-  if (NS_FAILED(rv)) return rv;
-  ((nsTableColGroupFrame*)pseudo.mFrame)->SetColType(eColGroupAnonymousCol);
-
-  // Do not set  aState.mPseudoFrames.mLowestType here as colgroup frame will
-  // be always below a table frame but we can not descent any further as col
-  // frames can not have children and will not wrap table foreign frames.
-
-  // set pseudo data for the parent
-  if (aState.mPseudoFrames.mTableInner.mFrame) {
-    aState.mPseudoFrames.mTableInner.mChildList.AddChild(pseudo.mFrame);
-  }
-#ifdef DEBUG
-  if (gTablePseudoFrame) {
-     printf("*** CreatePseudoColGroupFrame ***\n");
-    aState.mPseudoFrames.Dump();
-  }
-#endif
-  return rv;
-}
-
-nsresult
-nsCSSFrameConstructor::CreatePseudoRowFrame(PRInt32                  aNameSpaceID,
-                                            nsFrameConstructorState& aState, 
-                                            nsIFrame*                aParentFrameIn)
-{
-  nsresult rv = NS_OK;
-
-  nsIFrame* parentFrame = aParentFrameIn;
-  if (aState.mPseudoFrames.mRowGroup.mFrame) {
-    parentFrame = (nsIFrame*) nsTableFrame::GetRowGroupFrame(aState.mPseudoFrames.mRowGroup.mFrame);
-  }
-  if (!parentFrame) return rv;
-
-  nsStyleContext *parentStyle;
-  nsRefPtr<nsStyleContext> childStyle;
-
-  parentStyle = parentFrame->GetStyleContext();
-  nsIContent* parentContent = parentFrame->GetContent();
-
-  childStyle = mPresShell->StyleSet()->ResolvePseudoStyleFor(parentContent,
-                                                             nsCSSAnonBoxes::tableRow, 
-                                                             parentStyle);
-
-  nsPseudoFrameData& pseudo = aState.mPseudoFrames.mRow;
-
-  // construct the pseudo row as part of the pseudo frames
-  nsFrameItems items;
-  rv = ConstructTableRowFrame(aState, parentContent,
-                              parentFrame, childStyle, aNameSpaceID,
-                              PR_TRUE, items, pseudo.mFrame);
-  if (NS_FAILED(rv)) return rv;
-
-  aState.mPseudoFrames.mLowestType = nsGkAtoms::tableRowFrame;
-
-  // set pseudo data for the parent
-  if (aState.mPseudoFrames.mRowGroup.mFrame) {
-    aState.mPseudoFrames.mRowGroup.mChildList.AddChild(pseudo.mFrame);
-  }
-#ifdef DEBUG
-  if (gTablePseudoFrame) {
-     printf("*** CreatePseudoRowFrame ***\n");
-    aState.mPseudoFrames.Dump();
-  }
-#endif
-  return rv;
-}
-
-nsresult
-nsCSSFrameConstructor::CreatePseudoCellFrame(PRInt32                  aNameSpaceID,
-                                             nsFrameConstructorState& aState, 
-                                             nsIFrame*                aParentFrameIn)
-{
-  nsresult rv = NS_OK;
-
-  nsIFrame* parentFrame = (aState.mPseudoFrames.mRow.mFrame) 
-                          ? aState.mPseudoFrames.mRow.mFrame : aParentFrameIn;
-  if (!parentFrame) return rv;
-
-  nsStyleContext *parentStyle;
-  nsRefPtr<nsStyleContext> childStyle;
-
-  parentStyle = parentFrame->GetStyleContext();
-  nsIContent* parentContent = parentFrame->GetContent();
-
-  childStyle = mPresShell->StyleSet()->ResolvePseudoStyleFor(parentContent,
-                                                             nsCSSAnonBoxes::tableCell, 
-                                                             parentStyle);
-
-  nsPseudoFrameData& pseudoOuter = aState.mPseudoFrames.mCellOuter;
-  nsPseudoFrameData& pseudoInner = aState.mPseudoFrames.mCellInner;
-
-  // construct the pseudo outer and inner as part of the pseudo frames
-  nsFrameItems items;
-  rv = ConstructTableCellFrame(aState, parentContent, parentFrame, childStyle,
-                               aNameSpaceID, PR_TRUE, items,
-                               pseudoOuter.mFrame, pseudoInner.mFrame);
-  if (NS_FAILED(rv)) return rv;
-
-  // set pseudo data for the newly created frames
-  pseudoOuter.mChildList.AddChild(pseudoInner.mFrame);
-  // give it nsGkAtoms::tableCellFrame, if it is really nsGkAtoms::bcTableCellFrame, it will match later
-  aState.mPseudoFrames.mLowestType = nsGkAtoms::tableCellFrame;
-
-  // set pseudo data for the parent
-  if (aState.mPseudoFrames.mRow.mFrame) {
-    aState.mPseudoFrames.mRow.mChildList.AddChild(pseudoOuter.mFrame);
-  }
-#ifdef DEBUG
-  if (gTablePseudoFrame) {
-     printf("*** CreatePseudoCellFrame ***\n");
-    aState.mPseudoFrames.Dump();
-  }
-#endif
-  return rv;
-}
-
-// called if the parent is not a table
-nsresult 
-nsCSSFrameConstructor::GetPseudoTableFrame(PRInt32                  aNameSpaceID,
-                                           nsFrameConstructorState& aState, 
-                                           nsIFrame&                aParentFrameIn)
-{
-  nsresult rv = NS_OK;
-
-  nsPseudoFrames& pseudoFrames = aState.mPseudoFrames;
-  nsIAtom* parentFrameType = aParentFrameIn.GetType();
-
-  if (pseudoFrames.IsEmpty()) {
-    PRBool created = PR_FALSE;
-    if (nsGkAtoms::tableRowGroupFrame == parentFrameType) { // row group parent
-      rv = CreatePseudoRowFrame(aNameSpaceID, aState, &aParentFrameIn);
-      if (NS_FAILED(rv)) return rv;
-      created = PR_TRUE;
-    }
-    if (created || (nsGkAtoms::tableRowFrame == parentFrameType)) { // row parent
-      rv = CreatePseudoCellFrame(aNameSpaceID, aState, &aParentFrameIn);
-      if (NS_FAILED(rv)) return rv;
-    }
-    rv = CreatePseudoTableFrame(aNameSpaceID, aState, &aParentFrameIn);
-  }
-  else {
-    if (!pseudoFrames.mTableInner.mFrame) { 
-      if (pseudoFrames.mRowGroup.mFrame && !(pseudoFrames.mRow.mFrame)) {
-        rv = CreatePseudoRowFrame(aNameSpaceID, aState);
-        if (NS_FAILED(rv)) return rv;
-      }
-      if (pseudoFrames.mRow.mFrame && !(pseudoFrames.mCellOuter.mFrame)) {
-        rv = CreatePseudoCellFrame(aNameSpaceID, aState);
-        if (NS_FAILED(rv)) return rv;
-      }
-      CreatePseudoTableFrame(aNameSpaceID, aState);
-    }
-  }
-  return rv;
-}
-
-// called if the parent is not a col group
-nsresult 
-nsCSSFrameConstructor::GetPseudoColGroupFrame(PRInt32                  aNameSpaceID,
-                                              nsFrameConstructorState& aState, 
-                                              nsIFrame&                aParentFrameIn)
-{
-  nsresult rv = NS_OK;
-
-  nsPseudoFrames& pseudoFrames = aState.mPseudoFrames;
-  nsIAtom* parentFrameType = aParentFrameIn.GetType();
-
-  if (pseudoFrames.IsEmpty()) {
-    PRBool created = PR_FALSE;
-    if (nsGkAtoms::tableRowGroupFrame == parentFrameType) {  // row group parent
-      rv = CreatePseudoRowFrame(aNameSpaceID, aState, &aParentFrameIn);
-      created = PR_TRUE;
-    }
-    if (created || (nsGkAtoms::tableRowFrame == parentFrameType)) { // row parent
-      rv = CreatePseudoCellFrame(aNameSpaceID, aState, &aParentFrameIn);
-      created = PR_TRUE;
-    }
-    if (created || IS_TABLE_CELL(parentFrameType) || // cell parent
-        (nsGkAtoms::tableCaptionFrame == parentFrameType)  || // caption parent
-        !IsTableRelated(parentFrameType, PR_TRUE)) { // block parent
-      rv = CreatePseudoTableFrame(aNameSpaceID, aState, &aParentFrameIn);
-    }
-    rv = CreatePseudoColGroupFrame(aNameSpaceID, aState, &aParentFrameIn);
-  }
-  else {
-    if (!pseudoFrames.mColGroup.mFrame) {
-      if (!pseudoFrames.mTableInner.mFrame) {
-        if (pseudoFrames.mRowGroup.mFrame && !(pseudoFrames.mRow.mFrame)) {
-          rv = CreatePseudoRowFrame(aNameSpaceID, aState);
-        }
-        if (pseudoFrames.mRow.mFrame && !(pseudoFrames.mCellOuter.mFrame)) {
-          rv = CreatePseudoCellFrame(aNameSpaceID, aState);
-        }
-        if (pseudoFrames.mCellOuter.mFrame && !(pseudoFrames.mTableOuter.mFrame)) {
-          rv = CreatePseudoTableFrame(aNameSpaceID, aState);
-        }
-      }
-      rv = CreatePseudoColGroupFrame(aNameSpaceID, aState);
-    }
-  }
-  return rv;
-}
-
-// called if the parent is not a row group
-nsresult 
-nsCSSFrameConstructor::GetPseudoRowGroupFrame(PRInt32                  aNameSpaceID,
-                                              nsFrameConstructorState& aState, 
-                                              nsIFrame&                aParentFrameIn)
-{
-  nsresult rv = NS_OK;
-
-  nsPseudoFrames& pseudoFrames = aState.mPseudoFrames;
-  nsIAtom* parentFrameType = aParentFrameIn.GetType();
-
-  if (!pseudoFrames.mLowestType) {
-    PRBool created = PR_FALSE;
-    if (nsGkAtoms::tableRowFrame == parentFrameType) {  // row parent
-      rv = CreatePseudoCellFrame(aNameSpaceID, aState, &aParentFrameIn);
-      created = PR_TRUE;
-    }
-    if (created || IS_TABLE_CELL(parentFrameType) || // cell parent
-        (nsGkAtoms::tableCaptionFrame == parentFrameType)  || // caption parent
-        !IsTableRelated(parentFrameType, PR_TRUE)) { // block parent
-      rv = CreatePseudoTableFrame(aNameSpaceID, aState, &aParentFrameIn);
-    }
-    rv = CreatePseudoRowGroupFrame(aNameSpaceID, aState, &aParentFrameIn);
-  }
-  else {
-    if (!pseudoFrames.mRowGroup.mFrame) { 
-      if (pseudoFrames.mRow.mFrame && !(pseudoFrames.mCellOuter.mFrame)) {
-        rv = CreatePseudoCellFrame(aNameSpaceID, aState);
-      }
-      if (pseudoFrames.mCellOuter.mFrame && !(pseudoFrames.mTableOuter.mFrame)) {
-        rv = CreatePseudoTableFrame(aNameSpaceID, aState);
-      }
-      rv = CreatePseudoRowGroupFrame(aNameSpaceID, aState);
-    }
-  }
-  return rv;
-}
-
-// called if the parent is not a row
-nsresult
-nsCSSFrameConstructor::GetPseudoRowFrame(PRInt32                  aNameSpaceID,
-                                         nsFrameConstructorState& aState, 
-                                         nsIFrame&                aParentFrameIn)
-{
-  nsresult rv = NS_OK;
-
-  nsPseudoFrames& pseudoFrames = aState.mPseudoFrames;
-  nsIAtom* parentFrameType = aParentFrameIn.GetType();
-
-  if (!pseudoFrames.mLowestType) {
-    PRBool created = PR_FALSE;
-    if (IS_TABLE_CELL(parentFrameType) || // cell parent
-       (nsGkAtoms::tableCaptionFrame == parentFrameType)  || // caption parent
-        !IsTableRelated(parentFrameType, PR_TRUE)) { // block parent
-      rv = CreatePseudoTableFrame(aNameSpaceID, aState, &aParentFrameIn);
-      created = PR_TRUE;
-    }
-    if (created || (nsGkAtoms::tableFrame == parentFrameType)) { // table parent
-      rv = CreatePseudoRowGroupFrame(aNameSpaceID, aState, &aParentFrameIn);
-    }
-    rv = CreatePseudoRowFrame(aNameSpaceID, aState, &aParentFrameIn);
-  }
-  else {
-    if (!pseudoFrames.mRow.mFrame) { 
-      if (pseudoFrames.mCellOuter.mFrame && !pseudoFrames.mTableOuter.mFrame) {
-        rv = CreatePseudoTableFrame(aNameSpaceID, aState);
-      }
-      if (pseudoFrames.mTableInner.mFrame && !(pseudoFrames.mRowGroup.mFrame)) {
-        rv = CreatePseudoRowGroupFrame(aNameSpaceID, aState);
-      }
-      rv = CreatePseudoRowFrame(aNameSpaceID, aState);
-    }
-  }
-  return rv;
-}
-
-// called if the parent is not a cell or block
-nsresult 
-nsCSSFrameConstructor::GetPseudoCellFrame(PRInt32                  aNameSpaceID,
-                                          nsFrameConstructorState& aState, 
-                                          nsIFrame&                aParentFrameIn)
-{
-  nsresult rv = NS_OK;
-
-  nsPseudoFrames& pseudoFrames = aState.mPseudoFrames;
-  nsIAtom* parentFrameType = aParentFrameIn.GetType();
-
-  if (!pseudoFrames.mLowestType) {
-    PRBool created = PR_FALSE;
-    if (nsGkAtoms::tableFrame == parentFrameType) { // table parent
-      rv = CreatePseudoRowGroupFrame(aNameSpaceID, aState, &aParentFrameIn);
-      created = PR_TRUE;
-    }
-    if (created || (nsGkAtoms::tableRowGroupFrame == parentFrameType)) { // row group parent
-      rv = CreatePseudoRowFrame(aNameSpaceID, aState, &aParentFrameIn);
-      created = PR_TRUE;
-    }
-    rv = CreatePseudoCellFrame(aNameSpaceID, aState, &aParentFrameIn);
-  }
-  else if (!pseudoFrames.mCellOuter.mFrame) { 
-    if (pseudoFrames.mTableInner.mFrame && !(pseudoFrames.mRowGroup.mFrame)) {
-      rv = CreatePseudoRowGroupFrame(aNameSpaceID, aState);
-    }
-    if (pseudoFrames.mRowGroup.mFrame && !(pseudoFrames.mRow.mFrame)) {
-      rv = CreatePseudoRowFrame(aNameSpaceID, aState);
-    }
-    rv = CreatePseudoCellFrame(aNameSpaceID, aState);
-  }
-  return rv;
-}
-
-nsresult 
-nsCSSFrameConstructor::CreateRequiredPseudoFrames(PRInt32                  aNameSpaceID,
-                                                  nsIFrame&                aParentFrameIn,
-                                                  nsIAtom*                 aChildFrameType,
-                                                  nsFrameConstructorState& aState,
-                                                  nsIFrame*&               aParentFrame,
-                                                  PRBool&                  aIsPseudoParent)
-{
-  nsresult rv = NS_OK;
-
-  nsIAtom* parentFrameType = aParentFrameIn.GetType();
-  nsIFrame* pseudoParentFrame = nsnull;
-  nsPseudoFrames& pseudoFrames = aState.mPseudoFrames;
-  aParentFrame = &aParentFrameIn;
-  aIsPseudoParent = PR_FALSE;
-
-  nsFrameState savedStateBits  = aState.mAdditionalStateBits;
-  aState.mAdditionalStateBits &= ~NS_FRAME_GENERATED_CONTENT;
-
-  if (nsGkAtoms::tableCaptionFrame == aChildFrameType) { // caption child
-    if (nsGkAtoms::tableOuterFrame != parentFrameType) { // need pseudo table parent
-      rv = GetPseudoTableFrame(aNameSpaceID, aState, aParentFrameIn);
-      if (NS_FAILED(rv)) return rv;
-      pseudoParentFrame = pseudoFrames.mTableOuter.mFrame;
-    }
-  }
-  else if (nsGkAtoms::tableColGroupFrame == aChildFrameType) { // col group child
-    if (nsGkAtoms::tableFrame != parentFrameType) { // need pseudo table parent
-      rv = GetPseudoTableFrame(aNameSpaceID, aState, aParentFrameIn);
-      if (NS_FAILED(rv)) return rv;
-      pseudoParentFrame = pseudoFrames.mTableInner.mFrame;
-    }
-  }
-  else if (nsGkAtoms::tableColFrame == aChildFrameType) { // col child
-    if (nsGkAtoms::tableColGroupFrame != parentFrameType) { // need pseudo col group parent
-      rv = GetPseudoColGroupFrame(aNameSpaceID, aState, aParentFrameIn);
-      if (NS_FAILED(rv)) return rv;
-      pseudoParentFrame = pseudoFrames.mColGroup.mFrame;
-    }
-  }
-  else if (nsGkAtoms::tableRowGroupFrame == aChildFrameType) { // row group child
-    // XXX can this go away?
-    if (nsGkAtoms::tableFrame != parentFrameType) {
-      // trees allow row groups to contain row groups, so don't create pseudo frames
-        rv = GetPseudoTableFrame(aNameSpaceID, aState, aParentFrameIn);
-        if (NS_FAILED(rv)) return rv;
-        pseudoParentFrame = pseudoFrames.mTableInner.mFrame;
-     }
-  }
-  else if (nsGkAtoms::tableRowFrame == aChildFrameType) { // row child
-    if (nsGkAtoms::tableRowGroupFrame != parentFrameType) { // need pseudo row group parent
-      rv = GetPseudoRowGroupFrame(aNameSpaceID, aState, aParentFrameIn);
-      if (NS_FAILED(rv)) return rv;
-      pseudoParentFrame = pseudoFrames.mRowGroup.mFrame;
-    }
-  }
-  else if (IS_TABLE_CELL(aChildFrameType)) { // cell child
-    if (nsGkAtoms::tableRowFrame != parentFrameType) { // need pseudo row parent
-      rv = GetPseudoRowFrame(aNameSpaceID, aState, aParentFrameIn);
-      if (NS_FAILED(rv)) return rv;
-      pseudoParentFrame = pseudoFrames.mRow.mFrame;
-    }
-  }
-#ifdef DEBUG
-  else {
-    NS_ERROR("Unexpected frame type in CreateRequiredPseudoFrames");
-  }
-#endif
-  
-  if (pseudoParentFrame) {
-    aParentFrame = pseudoParentFrame;
-    aIsPseudoParent = PR_TRUE;
-  }
-
-  aState.mAdditionalStateBits = savedStateBits;
-  return rv;
-}
-
-nsresult
-nsCSSFrameConstructor::AdjustParentFrame(nsFrameConstructorState&     aState,
-                                         nsIContent*                  aChildContent,
-                                         nsIFrame* &                  aParentFrame,
+
+void
+nsCSSFrameConstructor::AdjustParentFrame(nsIFrame* &                  aParentFrame,
                                          const FrameConstructionData* aFCData,
-                                         PRInt32                      aNameSpaceID,
-                                         nsStyleContext*              aStyleContext,
-                                         nsFrameItems* &              aFrameItems,
-                                         nsFrameConstructorSaveState& aSaveState,
-                                         PRBool&                      aCreatedPseudo)
+                                         nsStyleContext*              aStyleContext)
 {
   NS_PRECONDITION(aStyleContext, "Must have child's style context");
-  NS_PRECONDITION(aFrameItems, "Must have frame items to work with");
   NS_PRECONDITION(aFCData, "Must have frame construction data");
 
-  aCreatedPseudo = PR_FALSE;
-  if (!aParentFrame) {
-    // Nothing to do here
-    return NS_OK;
-  }
-
   PRBool tablePart = ((aFCData->mBits & FCDATA_IS_TABLE_PART) != 0);
 
-  nsIAtom* parentType = aParentFrame->GetType();
-  NS_ASSERTION(parentType != nsGkAtoms::tableOuterFrame,
-               "Shouldn't be happening");
- 
-  // If our parent is a table, table-row-group, or table-row, and
-  // we're not table-related in any way, we have to create table
-  // pseudo-frames so that we have a table cell to live in.
-  if (!tablePart) {
-    if (IsTableRelated(parentType, PR_FALSE)) {
-      nsFrameState savedStateBits  = aState.mAdditionalStateBits;
-      aState.mAdditionalStateBits &= ~NS_FRAME_GENERATED_CONTENT;
-      nsresult rv = GetPseudoCellFrame(aNameSpaceID, aState, *aParentFrame);
-      if (NS_FAILED(rv)) {
-        return rv;
-      }
-      aState.mAdditionalStateBits = savedStateBits;
-
-      NS_ASSERTION(aState.mPseudoFrames.mCellInner.mFrame,
-                   "Must have inner cell frame now!");
-
-      aParentFrame = aState.mPseudoFrames.mCellInner.mFrame;
-      aFrameItems = &aState.mPseudoFrames.mCellInner.mChildList;
-      // We pushed an anonymous table cell.  The inner block of this
-      // needs to become the float containing block.
-      aState.PushFloatContainingBlock(aParentFrame, aSaveState);
-      aCreatedPseudo = PR_TRUE;
-
-      // Now it might be that we had existing pseudo-frames and in
-      // particular an existing pseudo-cell (so that the pseudo cell
-      // we just got is not the lowest pseudo-frame).  If that's the
-      // case, we need to process everything below that cell, so that
-      // our later siblings don't see those pseudo-frames.
-      if (aState.mPseudoFrames.mTableOuter.mFrame) {
-        ProcessPseudoFrames(aState, nsGkAtoms::tableOuterFrame);
-      }
-    }
-  } else {
-    // For a table part, just make sure we have the right pseudo-frames
-    // XXXbz write tests for this stuff?
-    switch (aStyleContext->GetStyleDisplay()->mDisplay) {
-      case NS_STYLE_DISPLAY_TABLE_CAPTION:
-        aParentFrame = AdjustCaptionParentFrame(aParentFrame);
-        CreateRequiredPseudoFrames(aNameSpaceID, *aParentFrame,
-                                   nsGkAtoms::tableCaptionFrame, aState,
-                                   aParentFrame, aCreatedPseudo);
-        if (aCreatedPseudo) {
-          aFrameItems = &aState.mPseudoFrames.mTableOuter.mChildList2;
-        }
-        break;
-      case NS_STYLE_DISPLAY_TABLE_ROW_GROUP:
-      case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP:
-      case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP:
-        CreateRequiredPseudoFrames(aNameSpaceID, *aParentFrame,
-                                   nsGkAtoms::tableRowGroupFrame, aState,
-                                   aParentFrame, aCreatedPseudo);
-        if (aCreatedPseudo) {
-          if (aState.mPseudoFrames.mRowGroup.mFrame) {
-            ProcessPseudoFrames(aState, nsGkAtoms::tableRowGroupFrame);
-          }
-          aFrameItems = &aState.mPseudoFrames.mTableInner.mChildList;
-        }
-        break;
-      case NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP:
-        CreateRequiredPseudoFrames(aNameSpaceID, *aParentFrame,
-                                   nsGkAtoms::tableColGroupFrame, aState,
-                                   aParentFrame, aCreatedPseudo);
-        if (aCreatedPseudo) {
-          if (aState.mPseudoFrames.mColGroup.mFrame) {
-            ProcessPseudoFrames(aState, nsGkAtoms::tableColGroupFrame);
-          }
-          aFrameItems = &aState.mPseudoFrames.mTableInner.mChildList;
-        }
-        break;
-      case NS_STYLE_DISPLAY_TABLE_COLUMN:
-        CreateRequiredPseudoFrames(aNameSpaceID, *aParentFrame,
-                                   nsGkAtoms::tableColFrame, aState,
-                                   aParentFrame, aCreatedPseudo);
-        if (aCreatedPseudo) {
-          aFrameItems = &aState.mPseudoFrames.mColGroup.mChildList;
-        }
-        break;
-      case NS_STYLE_DISPLAY_TABLE_ROW:
-        CreateRequiredPseudoFrames(aNameSpaceID, *aParentFrame,
-                                   nsGkAtoms::tableRowFrame, aState,
-                                   aParentFrame, aCreatedPseudo);
-        if (aCreatedPseudo) {
-          if (aState.mPseudoFrames.mRow.mFrame) {
-            ProcessPseudoFrames(aState, nsGkAtoms::tableRowFrame);
-          }
-          aFrameItems = &aState.mPseudoFrames.mRowGroup.mChildList;
-        }
-        break;
-      case NS_STYLE_DISPLAY_TABLE_CELL:
-        // use nsGkAtoms::tableCellFrame which works to get ther right
-        // pseudo-frames even if this is really a bcTableCellFrame
-        CreateRequiredPseudoFrames(aNameSpaceID, *aParentFrame,
-                                   nsGkAtoms::tableCellFrame, aState,
-                                   aParentFrame, aCreatedPseudo);
-        if (aCreatedPseudo) {
-          if (aState.mPseudoFrames.mCellOuter.mFrame) {
-            ProcessPseudoFrames(aState, nsGkAtoms::tableCellFrame);
-          }
-          aFrameItems = &aState.mPseudoFrames.mRow.mChildList;
-        }
-        break;
-    }
-  }
-  return NS_OK;
+  if (tablePart && aStyleContext->GetStyleDisplay()->mDisplay ==
+      NS_STYLE_DISPLAY_TABLE_CAPTION) {
+    aParentFrame = AdjustCaptionParentFrame(aParentFrame);
+  }
 }
 
 // Pull all the captions present in aItems out  into aCaptions
 static void
 PullOutCaptionFrames(nsFrameItems& aItems, nsFrameItems& aCaptions)
 {
   nsIFrame *child = aItems.childList;
   nsIFrame* prev = nsnull;
@@ -3196,136 +2044,151 @@ PullOutCaptionFrames(nsFrameItems& aItem
 }
 
 
 // Construct the outer, inner table frames and the children frames for the table. 
 // XXX Page break frames for pseudo table frames are not constructed to avoid the risk
 // associated with revising the pseudo frame mechanism. The long term solution
 // of having frames handle page-break-before/after will solve the problem. 
 nsresult
-nsCSSFrameConstructor::ConstructTableFrame(nsFrameConstructorState& aState,
-                                           nsIContent*              aContent,
-                                           nsIFrame*                aContentParent,
-                                           nsStyleContext*          aStyleContext,
-                                           PRInt32                  aNameSpaceID,
-                                           PRBool                   aIsPseudo,
-                                           nsFrameItems&            aChildItems,
-                                           nsIFrame*&               aNewOuterFrame,
-                                           nsIFrame*&               aNewInnerFrame)
-{
+nsCSSFrameConstructor::ConstructTable(nsFrameConstructorState& aState,
+                                      FrameConstructionItem&   aItem,
+                                      nsIFrame*                aParentFrame,
+                                      const nsStyleDisplay*    aDisplay,
+                                      nsFrameItems&            aFrameItems,
+                                      nsIFrame**               aNewFrame)
+{
+  NS_PRECONDITION(aDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE ||
+                  aDisplay->mDisplay == NS_STYLE_DISPLAY_INLINE_TABLE,
+                  "Unexpected call");
+
+  nsIContent* const content = aItem.mContent;
+  nsStyleContext* const styleContext = aItem.mStyleContext;
+  const PRUint32 nameSpaceID = aItem.mNameSpaceID;
+  
   nsresult rv = NS_OK;
 
-
   // create the pseudo SC for the outer table as a child of the inner SC
   nsRefPtr<nsStyleContext> outerStyleContext;
   outerStyleContext = mPresShell->StyleSet()->
-    ResolvePseudoStyleFor(aContent, nsCSSAnonBoxes::tableOuter, aStyleContext);
+    ResolvePseudoStyleFor(content, nsCSSAnonBoxes::tableOuter, styleContext);
 
   // Create the outer table frame which holds the caption and inner table frame
+  nsIFrame* newFrame;
 #ifdef MOZ_MATHML
-  if (kNameSpaceID_MathML == aNameSpaceID)
-    aNewOuterFrame = NS_NewMathMLmtableOuterFrame(mPresShell,
-                                                  outerStyleContext);
+  if (kNameSpaceID_MathML == nameSpaceID)
+    newFrame = NS_NewMathMLmtableOuterFrame(mPresShell, outerStyleContext);
   else
 #endif
-    aNewOuterFrame = NS_NewTableOuterFrame(mPresShell, outerStyleContext);
-
-  NS_ASSERTION(!IsTableRelated(aContentParent->GetType(), PR_TRUE) ||
-               aContentParent->GetType() == nsGkAtoms::tableCaptionFrame,
-               "Unexpected parent frame for table");
-
-  nsIFrame* geometricParent = aState.GetGeometricParent
-                                (outerStyleContext->GetStyleDisplay(),
-                                 aContentParent);
+    newFrame = NS_NewTableOuterFrame(mPresShell, outerStyleContext);
+
+  nsIFrame* geometricParent =
+    aState.GetGeometricParent(outerStyleContext->GetStyleDisplay(),
+                              aParentFrame);
 
   // Init the table outer frame and see if we need to create a view, e.g.
   // the frame is absolutely positioned  
-  InitAndRestoreFrame(aState, aContent, geometricParent, nsnull, aNewOuterFrame);  
-  nsHTMLContainerFrame::CreateViewForFrame(aNewOuterFrame, PR_FALSE);
+  InitAndRestoreFrame(aState, content, geometricParent, nsnull, newFrame);  
+  nsHTMLContainerFrame::CreateViewForFrame(newFrame, PR_FALSE);
 
   // Create the inner table frame
+  nsIFrame* innerFrame;
 #ifdef MOZ_MATHML
-  if (kNameSpaceID_MathML == aNameSpaceID)
-    aNewInnerFrame = NS_NewMathMLmtableFrame(mPresShell, aStyleContext);
+  if (kNameSpaceID_MathML == nameSpaceID)
+    innerFrame = NS_NewMathMLmtableFrame(mPresShell, styleContext);
   else
 #endif
-    aNewInnerFrame = NS_NewTableFrame(mPresShell, aStyleContext);
+    innerFrame = NS_NewTableFrame(mPresShell, styleContext);
  
-  InitAndRestoreFrame(aState, aContent, aNewOuterFrame, nsnull,
-                      aNewInnerFrame);
-
-  if (!aIsPseudo) {
-    // Put the newly created frames into the right child list
-    aNewOuterFrame->SetInitialChildList(nsnull, aNewInnerFrame);
-
-    rv = aState.AddChild(aNewOuterFrame, aChildItems, aContent,
-                         aStyleContext, aContentParent);
-    if (NS_FAILED(rv)) {
-      return rv;
-    }
-
-    if (!mRootElementFrame) {
-      // The frame we're constructing will be the root element frame.
-      // Set mRootElementFrame before processing children.
-      mRootElementFrame = aNewOuterFrame;
-    }
-
-    nsFrameItems childItems;
-    rv = ProcessChildren(aState, aContent, aStyleContext, aNewInnerFrame,
+  InitAndRestoreFrame(aState, content, newFrame, nsnull, innerFrame);
+
+  // Put the newly created frames into the right child list
+  newFrame->SetInitialChildList(nsnull, innerFrame);
+
+  rv = aState.AddChild(newFrame, aFrameItems, content, styleContext,
+                       aParentFrame);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  if (!mRootElementFrame) {
+    // The frame we're constructing will be the root element frame.
+    // Set mRootElementFrame before processing children.
+    mRootElementFrame = newFrame;
+  }
+
+  nsFrameItems childItems;
+  if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
+    rv = ConstructFramesFromItemList(aState, aItem.mChildItems,
+                                     innerFrame, childItems);
+  } else {
+    rv = ProcessChildren(aState, content, styleContext, innerFrame,
                          PR_TRUE, childItems, PR_FALSE);
-    // XXXbz what about cleaning up?
-    if (NS_FAILED(rv)) return rv;
-
-    nsFrameItems captionItems;
-    PullOutCaptionFrames(childItems, captionItems);
-
-    // Set the inner table frame's initial primary list 
-    aNewInnerFrame->SetInitialChildList(nsnull, childItems.childList);
-
-    // Set the outer table frame's secondary childlist lists
-    if (captionItems.childList) {
-        aNewOuterFrame->SetInitialChildList(nsGkAtoms::captionList,
-                                            captionItems.childList);
-    }
- }
-
+  }
+  // XXXbz what about cleaning up?
+  if (NS_FAILED(rv)) return rv;
+
+  nsFrameItems captionItems;
+  PullOutCaptionFrames(childItems, captionItems);
+
+  // Set the inner table frame's initial primary list 
+  innerFrame->SetInitialChildList(nsnull, childItems.childList);
+
+  // Set the outer table frame's secondary childlist lists
+  if (captionItems.childList) {
+    newFrame->SetInitialChildList(nsGkAtoms::captionList,
+                                  captionItems.childList);
+  }
+
+  *aNewFrame = newFrame;
   return rv;
 }
 
 nsresult
-nsCSSFrameConstructor::ConstructTableRowFrame(nsFrameConstructorState& aState,
-                                              nsIContent*              aContent,
-                                              nsIFrame*                aParentFrameIn,
-                                              nsStyleContext*          aStyleContext,
-                                              PRInt32                  aNameSpaceID,
-                                              PRBool                   aIsPseudo,
-                                              nsFrameItems&            aChildItems,
-                                              nsIFrame*&               aNewFrame)
-{
+nsCSSFrameConstructor::ConstructTableRow(nsFrameConstructorState& aState,
+                                         FrameConstructionItem&   aItem,
+                                         nsIFrame*                aParentFrame,
+                                         const nsStyleDisplay*    aDisplay,
+                                         nsFrameItems&            aFrameItems,
+                                         nsIFrame**               aNewFrame)
+{
+  NS_PRECONDITION(aDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_ROW,
+                  "Unexpected call");
+  nsIContent* const content = aItem.mContent;
+  nsStyleContext* const styleContext = aItem.mStyleContext;
+  const PRUint32 nameSpaceID = aItem.mNameSpaceID;
+
+  nsIFrame* newFrame;
 #ifdef MOZ_MATHML
-  if (kNameSpaceID_MathML == aNameSpaceID)
-    aNewFrame = NS_NewMathMLmtrFrame(mPresShell, aStyleContext);
+  if (kNameSpaceID_MathML == nameSpaceID)
+    newFrame = NS_NewMathMLmtrFrame(mPresShell, styleContext);
   else
 #endif
-    aNewFrame = NS_NewTableRowFrame(mPresShell, aStyleContext);
-
-  if (NS_UNLIKELY(!aNewFrame)) {
+    newFrame = NS_NewTableRowFrame(mPresShell, styleContext);
+
+  if (NS_UNLIKELY(!newFrame)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
-  InitAndRestoreFrame(aState, aContent, aParentFrameIn, nsnull, aNewFrame);
-  nsHTMLContainerFrame::CreateViewForFrame(aNewFrame, PR_FALSE);
-  if (!aIsPseudo) {
-    nsFrameItems childItems;
-    nsresult rv = ProcessChildren(aState, aContent, aStyleContext, aNewFrame,
-                                  PR_TRUE, childItems, PR_FALSE);
-    if (NS_FAILED(rv)) return rv;
-
-    aNewFrame->SetInitialChildList(nsnull, childItems.childList);
-    aChildItems.AddChild(aNewFrame);
-  }
+  InitAndRestoreFrame(aState, content, aParentFrame, nsnull, newFrame);
+  nsHTMLContainerFrame::CreateViewForFrame(newFrame, PR_FALSE);
+
+  nsFrameItems childItems;
+  nsresult rv;
+  if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
+    rv = ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame,
+                                     childItems);
+  } else {
+    rv = ProcessChildren(aState, content, styleContext, newFrame,
+                         PR_TRUE, childItems, PR_FALSE);
+  }
+  if (NS_FAILED(rv)) return rv;
+
+  newFrame->SetInitialChildList(nsnull, childItems.childList);
+  aFrameItems.AddChild(newFrame);
+  *aNewFrame = newFrame;
 
   return NS_OK;
 }
 
 nsresult
 nsCSSFrameConstructor::ConstructTableCol(nsFrameConstructorState& aState,
                                          FrameConstructionItem&   aItem,
                                          nsIFrame*                aParentFrame,
@@ -3364,104 +2227,118 @@ nsCSSFrameConstructor::ConstructTableCol
 
   aFrameItems.AddChild(colFrame);
   *aNewFrame = colFrame;
   
   return NS_OK;
 }
 
 nsresult
-nsCSSFrameConstructor::ConstructTableCellFrame(nsFrameConstructorState& aState,
-                                               nsIContent*              aContent,
-                                               nsIFrame*                aParentFrameIn,
-                                               nsStyleContext*          aStyleContext,
-                                               PRInt32                  aNameSpaceID,
-                                               PRBool                   aIsPseudo,
-                                               nsFrameItems&            aChildItems,
-                                               nsIFrame*&               aNewCellOuterFrame,
-                                               nsIFrame*&               aNewCellInnerFrame)
-{
-
-  nsIFrame* parentFrame = aParentFrameIn;
+nsCSSFrameConstructor::ConstructTableCell(nsFrameConstructorState& aState,
+                                          FrameConstructionItem&   aItem,
+                                          nsIFrame*                aParentFrame,
+                                          const nsStyleDisplay*    aDisplay,
+                                          nsFrameItems&            aFrameItems,
+                                          nsIFrame**               aNewFrame)
+{
+  NS_PRECONDITION(aDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_CELL,
+                  "Unexpected call");
+
+  nsIContent* const content = aItem.mContent;
+  nsStyleContext* const styleContext = aItem.mStyleContext;
+  const PRUint32 nameSpaceID = aItem.mNameSpaceID;
+
+  PRBool borderCollapse = IsBorderCollapse(aParentFrame);
+  nsIFrame* newFrame;
 #ifdef MOZ_MATHML
   // <mtable> is border separate in mathml.css and the MathML code doesn't implement
   // border collapse. For those users who style <mtable> with border collapse,
-  // give them the default non-MathML table frames that understand border collpase.
+  // give them the default non-MathML table frames that understand border collapse.
   // This won't break us because MathML table frames are all subclasses of the default
   // table code, and so we can freely mix <mtable> with <mtr> or <tr>, <mtd> or <td>.
   // What will happen is just that non-MathML frames won't understand MathML attributes
   // and will therefore miss the special handling that the MathML code does.
-  if (kNameSpaceID_MathML == aNameSpaceID && !IsBorderCollapse(parentFrame))
-    aNewCellOuterFrame = NS_NewMathMLmtdFrame(mPresShell, aStyleContext);
+  if (kNameSpaceID_MathML == nameSpaceID && !borderCollapse)
+    newFrame = NS_NewMathMLmtdFrame(mPresShell, styleContext);
   else
 #endif
     // Warning: If you change this and add a wrapper frame around table cell
     // frames, make sure Bug 368554 doesn't regress!
     // See IsInAutoWidthTableCellForQuirk() in nsImageFrame.cpp.    
-    aNewCellOuterFrame = NS_NewTableCellFrame(mPresShell, aStyleContext,
-                                              IsBorderCollapse(parentFrame));
-
-  if (NS_UNLIKELY(!aNewCellOuterFrame)) {
+    newFrame = NS_NewTableCellFrame(mPresShell, styleContext, borderCollapse);
+
+  if (NS_UNLIKELY(!newFrame)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   // Initialize the table cell frame
-  InitAndRestoreFrame(aState, aContent, parentFrame, nsnull, aNewCellOuterFrame);
-  nsHTMLContainerFrame::CreateViewForFrame(aNewCellOuterFrame, PR_FALSE);
+  InitAndRestoreFrame(aState, content, aParentFrame, nsnull, newFrame);
+  nsHTMLContainerFrame::CreateViewForFrame(newFrame, PR_FALSE);
   
   // Resolve pseudo style and initialize the body cell frame
   nsRefPtr<nsStyleContext> innerPseudoStyle;
   innerPseudoStyle = mPresShell->StyleSet()->
-    ResolvePseudoStyleFor(aContent,
-                          nsCSSAnonBoxes::cellContent, aStyleContext);
+    ResolvePseudoStyleFor(content, nsCSSAnonBoxes::cellContent, styleContext);
 
   // Create a block frame that will format the cell's content
   PRBool isBlock;
+  nsIFrame* cellInnerFrame;
 #ifdef MOZ_MATHML
-  if (kNameSpaceID_MathML == aNameSpaceID) {
-    aNewCellInnerFrame = NS_NewMathMLmtdInnerFrame(mPresShell, innerPseudoStyle);
+  if (kNameSpaceID_MathML == nameSpaceID) {
+    cellInnerFrame = NS_NewMathMLmtdInnerFrame(mPresShell, innerPseudoStyle);
     isBlock = PR_FALSE;
   }
   else
 #endif
   {
-    aNewCellInnerFrame = NS_NewBlockFormattingContext(mPresShell,
-                                                      innerPseudoStyle);
+    cellInnerFrame = NS_NewBlockFormattingContext(mPresShell, innerPseudoStyle);
     isBlock = PR_TRUE;
   }
 
-
-  if (NS_UNLIKELY(!aNewCellInnerFrame)) {
-    aNewCellOuterFrame->Destroy();
-    aNewCellOuterFrame = nsnull;
+  if (NS_UNLIKELY(!cellInnerFrame)) {
+    newFrame->Destroy();
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  InitAndRestoreFrame(aState, aContent, aNewCellOuterFrame, nsnull, aNewCellInnerFrame);
-
-  if (!aIsPseudo) {
+  InitAndRestoreFrame(aState, content, newFrame, nsnull, cellInnerFrame);
+
+  nsFrameItems childItems;
+  nsresult rv;
+  if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
+    // Need to push ourselves as a float containing block.
+    // XXXbz it might be nice to work on getting the parent
+    // FrameConstructionItem down into ProcessChildren and just making use of
+    // the push there, but that's a bit of work.
+    nsFrameConstructorSaveState floatSaveState;
+    if (!isBlock) { /* MathML case */
+      aState.PushFloatContainingBlock(nsnull, floatSaveState);
+    } else {
+      aState.PushFloatContainingBlock(cellInnerFrame, floatSaveState);
+    }
+
+    rv = ConstructFramesFromItemList(aState, aItem.mChildItems, cellInnerFrame,
+                                     childItems);
+  } else {
     // Process the child content
-    nsFrameItems childItems;
-    nsresult rv = ProcessChildren(aState, aContent, aStyleContext,
-                                  aNewCellInnerFrame, PR_TRUE, childItems, isBlock);
-
-    if (NS_FAILED(rv)) {
-      // Clean up
-      // XXXbz kids of this stuff need to be cleaned up too!
-      aNewCellInnerFrame->Destroy();
-      aNewCellInnerFrame = nsnull;
-      aNewCellOuterFrame->Destroy();
-      aNewCellOuterFrame = nsnull;
-      return rv;
-    }
-
-    aNewCellInnerFrame->SetInitialChildList(nsnull, childItems.childList);
-    aNewCellOuterFrame->SetInitialChildList(nsnull, aNewCellInnerFrame);
-    aChildItems.AddChild(aNewCellOuterFrame);
-  }
+    rv = ProcessChildren(aState, content, styleContext, cellInnerFrame,
+                         PR_TRUE, childItems, isBlock);
+  }
+  
+  if (NS_FAILED(rv)) {
+    // Clean up
+    // XXXbz kids of this stuff need to be cleaned up too!
+    cellInnerFrame->Destroy();
+    newFrame->Destroy();
+    return rv;
+  }
+
+  cellInnerFrame->SetInitialChildList(nsnull, childItems.childList);
+  newFrame->SetInitialChildList(nsnull, cellInnerFrame);
+  aFrameItems.AddChild(newFrame);
+  *aNewFrame = newFrame;
 
   return NS_OK;
 }
 
 static PRBool 
 NeedFrameFor(nsIFrame*   aParentFrame,
              nsIContent* aChildContent) 
 {
@@ -3722,23 +2599,34 @@ nsCSSFrameConstructor::ConstructDocEleme
       return NS_ERROR_FAILURE;
     }
   }
   else
 #endif
   {
     PRBool docElemIsTable = (display->mDisplay == NS_STYLE_DISPLAY_TABLE);
     if (docElemIsTable) {
-      nsIFrame* innerTableFrame;
+      // We're going to call the right function ourselves, so no need to give a
+      // function to this FrameConstructionData.
+
+      // XXXbz on the other hand, if we converted this whole function to
+      // FrameConstructionData/Item, then we'd need the right function
+      // here... but would probably be able to get away with less code in this
+      // function in general.
+      static const FrameConstructionData rootTableData = { 0, nsnull };
+      nsRefPtr<nsStyleContext> extraRef(styleContext);
+      FrameConstructionItem item(&rootTableData, aDocElement,
+                                 aDocElement->Tag(), kNameSpaceID_None,
+                                 extraRef.forget());
+
       nsFrameItems frameItems;
       // if the document is a table then just populate it.
-      rv = ConstructTableFrame(aState, aDocElement,
-                               aParentFrame, styleContext,
-                               kNameSpaceID_None, PR_FALSE, frameItems,
-                               contentFrame, innerTableFrame);
+      rv = ConstructTable(aState, item, aParentFrame,
+                          styleContext->GetStyleDisplay(),
+                          frameItems, &contentFrame);
       if (NS_FAILED(rv))
         return rv;
       if (!contentFrame || !frameItems.childList)
         return NS_ERROR_FAILURE;
       *aNewFrame = frameItems.childList;
       NS_ASSERTION(!frameItems.childList->GetNextSibling(),
                    "multiple root element frames");
     } else {
@@ -4647,26 +3535,20 @@ nsCSSFrameConstructor::FindTextData(nsIF
 }
 
 nsresult
 nsCSSFrameConstructor::ConstructTextFrame(const FrameConstructionData* aData,
                                           nsFrameConstructorState& aState,
                                           nsIContent*              aContent,
                                           nsIFrame*                aParentFrame,
                                           nsStyleContext*          aStyleContext,
-                                          nsFrameItems&            aFrameItems,
-                                          PRBool                   aPseudoParent)
+                                          nsFrameItems&            aFrameItems)
 {
   NS_PRECONDITION(aData, "Must have frame construction data");
 
-  // process pending pseudo frames. whitespace doesn't have an effect.
-  if (!aPseudoParent && !aState.mPseudoFrames.IsEmpty() &&
-      !TextIsOnlyWhitespace(aContent))
-    ProcessPseudoFrames(aState, aFrameItems);
-
   nsIFrame* newFrame = (*aData->mFunc.mCreationFunc)(mPresShell, aStyleContext);
 
   if (NS_UNLIKELY(!newFrame))
     return NS_ERROR_OUT_OF_MEMORY;
 
   nsresult rv = InitAndRestoreFrame(aState, aContent, aParentFrame,
                                     nsnull, newFrame);
 
@@ -4925,18 +3807,17 @@ nsCSSFrameConstructor::FindObjectData(ns
   return FindDataByInt((PRInt32)type, aContent, aStyleContext,
                        sObjectData, NS_ARRAY_LENGTH(sObjectData));
 }
 
 nsresult
 nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aItem,
                                                       nsFrameConstructorState& aState,
                                                       nsIFrame* aParentFrame,
-                                                      nsFrameItems& aFrameItems,
-                                                      PRBool aHasPseudoParent)
+                                                      nsFrameItems& aFrameItems)
 {
   const FrameConstructionData* data = aItem.mFCData;
   NS_ASSERTION(data, "Must have frame construction data");
 
   PRUint32 bits = data->mBits;
 
   NS_ASSERTION(!(bits & FCDATA_FUNC_IS_DATA_GETTER),
                "Should have dealt with this inside the data finder");
@@ -4954,21 +3835,16 @@ nsCSSFrameConstructor::ConstructFrameFro
   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_SKIP_ABSPOS_PUSH);
   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_FORCE_VIEW);
   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR,
                      FCDATA_DISALLOW_GENERATED_CONTENT);
   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_ALLOW_BLOCK_STYLES);
   CHECK_ONLY_ONE_BIT(FCDATA_MAY_NEED_SCROLLFRAME, FCDATA_FORCE_VIEW);
 #undef CHECK_ONLY_ONE_BIT
 
-  // Process pseudo-frames now if needed.
-  if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
-    ProcessPseudoFrames(aState, aFrameItems); 
-  }
-
   nsStyleContext* const styleContext = aItem.mStyleContext;
   const nsStyleDisplay* display = styleContext->GetStyleDisplay();
 
   nsIFrame* newFrame;
   if (bits & FCDATA_FUNC_IS_FULL_CTOR) {
     nsresult rv =
       (this->*(data->mFullConstructor))(aState, aItem, aParentFrame,
                                         display, aFrameItems, &newFrame);
@@ -5042,21 +3918,26 @@ nsCSSFrameConstructor::ConstructFrameFro
     nsFrameConstructorSaveState absoluteSaveState;
 
     if (bits & FCDATA_FORCE_NULL_ABSPOS_CONTAINER) {
       aState.PushAbsoluteContainingBlock(nsnull, absoluteSaveState);
     } else if (!(bits & FCDATA_SKIP_ABSPOS_PUSH) && display->IsPositioned()) {
       aState.PushAbsoluteContainingBlock(newFrame, absoluteSaveState);
     }
 
-    // Process the child frames.
-    rv = ProcessChildren(aState, content, styleContext, newFrame,
-                         !(bits & FCDATA_DISALLOW_GENERATED_CONTENT),
-                         childItems,
-                         (bits & FCDATA_ALLOW_BLOCK_STYLES) != 0);
+    if (bits & FCDATA_USE_CHILD_ITEMS) {
+      rv = ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame,
+                                       childItems);
+    } else {
+      // Process the child frames.
+      rv = ProcessChildren(aState, content, styleContext, newFrame,
+                           !(bits & FCDATA_DISALLOW_GENERATED_CONTENT),
+                           childItems,
+                           (bits & FCDATA_ALLOW_BLOCK_STYLES) != 0);
+    }
 
 #ifdef MOZ_XUL
     // More icky XUL stuff
     if (aItem.mNameSpaceID == kNameSpaceID_XUL &&
         (aItem.mTag == nsGkAtoms::treechildren || // trees always need titletips
          content->HasAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext) ||
          content->HasAttr(kNameSpaceID_None, nsGkAtoms::tooltip))) {
       nsIRootBox* rootBox = nsIRootBox::GetRootBox(mPresShell);
@@ -5131,43 +4012,30 @@ nsCSSFrameConstructor::CreateAnonymousFr
   if (count == 0) {
     return NS_OK;
   }
 
   nsIAnonymousContentCreator* creator = do_QueryFrame(aParentFrame);
   NS_ASSERTION(creator,
                "How can that happen if we have nodes to construct frames for?");
 
-  // save the incoming pseudo frame state, so that we don't end up
-  // with those pseudoframes in aChildItems
-  nsPseudoFrames priorPseudoFrames; 
-  aState.mPseudoFrames.Reset(&priorPseudoFrames);
-
   for (PRUint32 i=0; i < count; i++) {
     nsIContent* content = newAnonymousItems[i];
     NS_ASSERTION(content, "null anonymous content?");
 
     nsIFrame* newFrame = creator->CreateFrameFor(content);
     if (newFrame) {
       aChildItems.AddChild(newFrame);
     }
     else {
       // create the frame and attach it to our frame
       ConstructFrame(aState, content, aParentFrame, aChildItems);
     }
   }
 
-  // process the current pseudo frame state
-  if (!aState.mPseudoFrames.IsEmpty()) {
-    ProcessPseudoFrames(aState, aChildItems);
-  }
-
-  // restore the incoming pseudo frame state
-  aState.mPseudoFrames = priorPseudoFrames;
-
   return NS_OK;
 }
 
 nsresult
 nsCSSFrameConstructor::GetAnonymousContent(nsIContent* aParent,
                                            nsIFrame* aParentFrame,
                                            nsTArray<nsIContent*>& aContent)
 {
@@ -5597,16 +4465,18 @@ nsCSSFrameConstructor::BuildScrollFrame(
 
 }
 
 const nsCSSFrameConstructor::FrameConstructionData*
 nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay* aDisplay,
                                        nsIContent* aContent,
                                        nsStyleContext* aStyleContext)
 {
+  PR_STATIC_ASSERT(eParentTypeCount < (1 << (32 - FCDATA_PARENT_TYPE_OFFSET)));
+
   // The style system ensures that floated and positioned frames are
   // block-level.
   NS_ASSERTION(!(aDisplay->IsFloating() ||
                  aDisplay->IsAbsolutelyPositioned()) ||
                aDisplay->IsBlockOutside(),
                "Style system did not apply CSS2.1 section 9.7 fixups");
 
   // If this is "body", try propagating its scroll style to the viewport
@@ -5652,48 +4522,56 @@ nsCSSFrameConstructor::FindDisplayData(c
     { NS_STYLE_DISPLAY_INLINE,
       FULL_CTOR_FCDATA(FCDATA_SKIP_FRAMEMAP | FCDATA_IS_INLINE |
                        FCDATA_IS_LINE_PARTICIPANT,
                        &nsCSSFrameConstructor::ConstructInline) },
     { NS_STYLE_DISPLAY_MARKER,
       FULL_CTOR_FCDATA(FCDATA_SKIP_FRAMEMAP | FCDATA_IS_INLINE |
                        FCDATA_IS_LINE_PARTICIPANT,
                        &nsCSSFrameConstructor::ConstructInline) },
-    COMPLEX_INT_CREATE(NS_STYLE_DISPLAY_TABLE,
-                       &nsCSSFrameConstructor::ConstructTable),
-    COMPLEX_INT_CREATE(NS_STYLE_DISPLAY_INLINE_TABLE,
-                       &nsCSSFrameConstructor::ConstructTable),
+    { NS_STYLE_DISPLAY_TABLE,
+      FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructTable) },
+    { NS_STYLE_DISPLAY_INLINE_TABLE,
+      FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructTable) },
     { NS_STYLE_DISPLAY_TABLE_CAPTION,
       FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
-                  FCDATA_ALLOW_BLOCK_STYLES | FCDATA_DISALLOW_OUT_OF_FLOW,
+                  FCDATA_ALLOW_BLOCK_STYLES | FCDATA_DISALLOW_OUT_OF_FLOW |
+                  FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
                   NS_NewTableCaptionFrame) },
     { NS_STYLE_DISPLAY_TABLE_ROW_GROUP,
       FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
-                  FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_MAY_NEED_SCROLLFRAME,
+                  FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_MAY_NEED_SCROLLFRAME |
+                  FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
                   NS_NewTableRowGroupFrame) },
     { NS_STYLE_DISPLAY_TABLE_HEADER_GROUP,
       FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
-                  FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_MAY_NEED_SCROLLFRAME,
+                  FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_MAY_NEED_SCROLLFRAME |
+                  FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
                   NS_NewTableRowGroupFrame) },
     { NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP,
       FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
-                  FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_MAY_NEED_SCROLLFRAME,
+                  FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_MAY_NEED_SCROLLFRAME |
+                  FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
                   NS_NewTableRowGroupFrame) },
     { NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP,
       FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
-                  FCDATA_DISALLOW_OUT_OF_FLOW,
+                  FCDATA_DISALLOW_OUT_OF_FLOW |
+                  FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
                   NS_NewTableColGroupFrame) },
     { NS_STYLE_DISPLAY_TABLE_COLUMN,
-      FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP,
+      FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
+                       FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeColGroup),
                        &nsCSSFrameConstructor::ConstructTableCol) },
     { NS_STYLE_DISPLAY_TABLE_ROW,
-      FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP,
+      FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
+                       FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRowGroup),
                        &nsCSSFrameConstructor::ConstructTableRow) },
     { NS_STYLE_DISPLAY_TABLE_CELL,
-      FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP,
+      FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
+                       FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRow),
                        &nsCSSFrameConstructor::ConstructTableCell) }
   };
 
   return FindDataByInt(aDisplay->mDisplay, aContent, aStyleContext,
                        sDisplayData, NS_ARRAY_LENGTH(sDisplayData));
 }
 
 nsresult
@@ -5758,67 +4636,16 @@ nsCSSFrameConstructor::ConstructNonScrol
 
   return ConstructBlock(aState, aDisplay, aItem.mContent,
                         aState.GetGeometricParent(aDisplay, aParentFrame),
                         aParentFrame, styleContext, aNewFrame,
                         aFrameItems, aDisplay->IsPositioned());
 }
 
 
-nsresult
-nsCSSFrameConstructor::ConstructTable(nsFrameConstructorState& aState,
-                                      FrameConstructionItem&   aItem,
-                                      nsIFrame*                aParentFrame,
-                                      const nsStyleDisplay*    aDisplay,
-                                      nsFrameItems&            aFrameItems,
-                                      nsIFrame**               aNewFrame)
-{
-  NS_PRECONDITION(aDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE ||
-                  aDisplay->mDisplay == NS_STYLE_DISPLAY_INLINE_TABLE,
-                  "Unexpected call");
-  
-  nsIFrame* innerTable;
-  return ConstructTableFrame(aState, aItem.mContent, aParentFrame,
-                             aItem.mStyleContext, aItem.mNameSpaceID,
-                             PR_FALSE, aFrameItems, *aNewFrame, innerTable);
-}
-
-nsresult
-nsCSSFrameConstructor::ConstructTableRow(nsFrameConstructorState& aState,
-                                         FrameConstructionItem&   aItem,
-                                         nsIFrame*                aParentFrame,
-                                         const nsStyleDisplay*    aDisplay,
-                                         nsFrameItems&            aFrameItems,
-                                         nsIFrame**               aNewFrame)
-{
-  NS_PRECONDITION(aDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_ROW,
-                  "Unexpected call");
-  return ConstructTableRowFrame(aState, aItem.mContent, aParentFrame,
-                                aItem.mStyleContext, aItem.mNameSpaceID,
-                                PR_FALSE, aFrameItems, *aNewFrame);
-}
-
-nsresult
-nsCSSFrameConstructor::ConstructTableCell(nsFrameConstructorState& aState,
-                                          FrameConstructionItem&   aItem,
-                                          nsIFrame*                aParentFrame,
-                                          const nsStyleDisplay*    aDisplay,
-                                          nsFrameItems&            aFrameItems,
-                                          nsIFrame**               aNewFrame)
-{
-  NS_PRECONDITION(aDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_CELL,
-                  "Unexpected call");
-
-  nsIFrame* innerTableCell;
-  return ConstructTableCellFrame(aState, aItem.mContent, aParentFrame,
-                                 aItem.mStyleContext, aItem.mNameSpaceID,
-                                 PR_FALSE, aFrameItems, *aNewFrame,
-                                 innerTableCell);
-}
-
 nsresult 
 nsCSSFrameConstructor::InitAndRestoreFrame(const nsFrameConstructorState& aState,
                                            nsIContent*              aContent,
                                            nsIFrame*                aParentFrame,
                                            nsIFrame*                aPrevInFlow,
                                            nsIFrame*                aNewFrame,
                                            PRBool                   aAllowCounters)
 {
@@ -6291,16 +5118,18 @@ nsCSSFrameConstructor::ConstructFrame(ns
                                       nsFrameItems&            aFrameItems)
 
 {
   NS_PRECONDITION(nsnull != aParentFrame, "no parent frame");
   FrameConstructionItemList items;
   AddFrameConstructionItems(aState, aContent, aParentFrame, items);
 
   for (FCItemIterator iter(items); !iter.IsDone(); iter.Next()) {
+    NS_ASSERTION(iter.item().DesiredParentType() == GetParentType(aParentFrame),
+                 "This is not going to work");
     nsresult rv =
       ConstructFramesFromItem(aState, iter, aParentFrame, aFrameItems);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
@@ -6553,32 +5382,23 @@ static void DestroyContent(void *aObject
 
 nsresult
 nsCSSFrameConstructor::ConstructFramesFromItem(nsFrameConstructorState& aState,
                                                FrameConstructionItem& aItem,
                                                nsIFrame* aParentFrame,
                                                nsFrameItems& aFrameItems)
 {
   nsIFrame* adjParentFrame = aParentFrame;
-  nsFrameItems* frameItems = &aFrameItems;
-  PRBool pseudoParent = PR_FALSE;
   nsStyleContext* styleContext = aItem.mStyleContext;
-  nsFrameConstructorSaveState pseudoSaveState;
-  nsresult rv = AdjustParentFrame(aState, aItem.mContent, adjParentFrame,
-                                  aItem.mFCData, aItem.mNameSpaceID,
-                                  styleContext, frameItems, pseudoSaveState,
-                                  pseudoParent);
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
+  AdjustParentFrame(adjParentFrame, aItem.mFCData, styleContext);
 
   if (aItem.mIsText) {
     return ConstructTextFrame(aItem.mFCData, aState, aItem.mContent,
                               adjParentFrame, styleContext,
-                              *frameItems, pseudoParent);
+                              aFrameItems);
   }
 
   // If the page contains markup that overrides text direction, and
   // does not contain any characters that would activate the Unicode
   // bidi algorithm, we need to call |SetBidiEnabled| on the pres
   // context before reflow starts.  This requires us to resolve some
   // style information now.  See bug 115921.
   {
@@ -6593,27 +5413,32 @@ nsCSSFrameConstructor::ConstructFramesFr
   }
 
   nsFrameState savedStateBits = aState.mAdditionalStateBits;
   if (aItem.mIsGeneratedContent) {
     // Ensure that frames created here are all tagged with
     // NS_FRAME_GENERATED_CONTENT.
     aState.mAdditionalStateBits |= NS_FRAME_GENERATED_CONTENT;
 
+    // Note that we're not necessarily setting this property on the primary
+    // frame for the content for which this is generated content.  We might be
+    // setting it on a table pseudo-frame inserted under that instead.  That's
+    // OK, though; we just need to do the property set so that the content will
+    // get cleaned up when the frame is destroyed.
     aParentFrame->SetProperty(styleContext->GetPseudoType(),
                               aItem.mContent, DestroyContent);
 
     // Now that we've passed ownership of aItem.mContent to the frame, unset
     // our generated content flag so we don't release or unbind it ourselves.
     aItem.mIsGeneratedContent = PR_FALSE;
   }
 
   // XXXbz maybe just inline ConstructFrameFromItemInternal here or something?
-  rv = ConstructFrameFromItemInternal(aItem, aState, adjParentFrame,
-                                      *frameItems, pseudoParent);
+  nsresult rv = ConstructFrameFromItemInternal(aItem, aState, adjParentFrame,
+                                               aFrameItems);
 
   aState.mAdditionalStateBits = savedStateBits;
 
   return rv;
 }
 
 
 inline PRBool
@@ -6776,17 +5601,17 @@ nsCSSFrameConstructor::GetAbsoluteContai
     }
     
     // Is it positioned?
     // If it's table-related then ignore it, because for the time
     // being table-related frames are not containers for absolutely
     // positioned child frames.
     const nsStyleDisplay* disp = frame->GetStyleDisplay();
 
-    if (disp->IsPositioned() && !IsTableRelated(frame->GetType(), PR_TRUE)) {
+    if (disp->IsPositioned() && !IsTableRelated(frame->GetType())) {
       // 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
@@ -7345,16 +6170,21 @@ nsCSSFrameConstructor::ContentAppended(n
   // a special inline frame.
   // If we're appending before :after content, then we're not really
   // appending, so let WipeContainingBlock know that.
   if (WipeContainingBlock(state, containingBlock, parentFrame, items,
                           !parentAfterFrame, nsnull)) {
     return NS_OK;
   }
 
+  if (NS_FAILED(CreateNeededTablePseudos(items, parentFrame))) {
+    // Pretend this never happened, I gues
+    return NS_OK;
+  }
+
   // if the container is a table and a caption was appended, it needs to be put in
   // the outer table frame's additional child list. 
   nsFrameItems frameItems;
   nsFrameItems captionItems;
 
   for (FCItemIterator iter(items); !iter.IsDone(); iter.Next()) {
     nsresult rv =
       ConstructFramesFromItem(state, iter, parentFrame, frameItems);
@@ -7370,25 +6200,21 @@ nsCSSFrameConstructor::ContentAppended(n
       InvalidateCanvasIfNeeded(frameItems.lastChild);
   }
 
   if (nsGkAtoms::tableFrame == frameType) {
     // Pull out the captions.  Note that we don't want to do that as we go,
     // because processing a single caption can add a whole bunch of things to
     // the frame items due to pseudoframe processing.  So we'd have to pull
     // captions from a list anyway; might as well do that here.
+    // XXXbz this is no longer true; we could pull captions directly out of the
+    // FrameConstructionItemList now.
     PullOutCaptionFrames(frameItems, captionItems);
   }
   
-
-  // process the current pseudo frame state
-  if (!state.mPseudoFrames.IsEmpty()) {
-    ProcessPseudoFrames(state, frameItems);
-  }
-
   if (haveFirstLineStyle && parentFrame == containingBlock) {
     // It's possible that some of the new frames go into a
     // first-line frame. Look at them and see...
     AppendFirstLineFrames(state, containingBlock->GetContent(),
                           containingBlock, frameItems); 
   }
 
   nsresult result = NS_OK;
@@ -7765,16 +6591,21 @@ nsCSSFrameConstructor::ContentInserted(n
   // a special inline frame.
   // If we're appending before :after content, then we're not really
   // appending, so let WipeContainingBlock know that.
   if (WipeContainingBlock(state, containingBlock, parentFrame, items,
                           isAppend && !appendAfterFrame, prevSibling))
     return NS_OK;
 
 
+  if (NS_FAILED(CreateNeededTablePseudos(items, parentFrame))) {
+    // Pretend this never happened, I gues
+    return NS_OK;
+  }
+
   // if the container is a table and a caption will be appended, it needs to be
   // put in the outer table frame's additional child list.
   
   nsFrameItems frameItems, captionItems;
   for (FCItemIterator iter(items); !iter.IsDone(); iter.Next()) {
     ConstructFramesFromItem(state, iter, parentFrame, frameItems);
   }
   if (frameItems.childList) {
@@ -7783,20 +6614,16 @@ nsCSSFrameConstructor::ContentInserted(n
     if (nsGkAtoms::tableCaptionFrame == frameItems.childList->GetType()) {
       NS_ASSERTION(frameItems.childList == frameItems.lastChild ,
                    "adding a non caption frame to the caption childlist?");
       captionItems.AddChild(frameItems.childList);
       frameItems = nsFrameItems();
     }
   }
 
-  // process the current pseudo frame state
-  if (!state.mPseudoFrames.IsEmpty())
-    ProcessPseudoFrames(state, frameItems);
-
   // If the parent of our current prevSibling is different from the frame we'll
   // actually use as the parent, then the calculated insertion point is now
   // invalid and as it is unknown where to insert correctly we append instead
   // (bug 341858).
   // This can affect our appendAfterFrame, but should not have any effect on
   // the WipeContainingBlock above, since this should only happen when neither
   // parent is a special frame (and in fact, only when one is an outer table
   // and one is an inner table or when the parent is a fieldset or fieldset
@@ -10099,43 +8926,280 @@ nsCSSFrameConstructor::ShouldHaveSpecial
                                                    PRBool* aHaveFirstLineStyle)
 {
   *aHaveFirstLetterStyle =
     ShouldHaveFirstLetterStyle(aContent, aStyleContext);
   *aHaveFirstLineStyle =
     ShouldHaveFirstLineStyle(aContent, aStyleContext);
 }
 
+/* static */
+const nsCSSFrameConstructor::PseudoParentData
+nsCSSFrameConstructor::sPseudoParentData[eParentTypeCount] = {
+  { // Cell
+    FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
+                     FCDATA_USE_CHILD_ITEMS |
+                     FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRow),
+                     &nsCSSFrameConstructor::ConstructTableCell),
+    &nsCSSAnonBoxes::tableCell
+  },
+  { // Row
+    FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
+                     FCDATA_USE_CHILD_ITEMS |
+                     FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRowGroup),
+                     &nsCSSFrameConstructor::ConstructTableRow),
+    &nsCSSAnonBoxes::tableRow
+  },
+  { // Row group
+    FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
+                FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_USE_CHILD_ITEMS |
+                FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
+                NS_NewTableRowGroupFrame),
+    &nsCSSAnonBoxes::tableRowGroup
+  },
+  { // Column group
+    FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
+                FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_USE_CHILD_ITEMS |
+                FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
+                NS_NewTableColGroupFrame),
+    &nsCSSAnonBoxes::tableColGroup
+  },
+  { // Table
+    FULL_CTOR_FCDATA(FCDATA_SKIP_FRAMEMAP | FCDATA_USE_CHILD_ITEMS,
+                     &nsCSSFrameConstructor::ConstructTable),
+    &nsCSSAnonBoxes::table
+  }
+};
+
+/*
+ * This function works as follows: we walk through the child list (aItems) and
+ * find items that cannot have aParentFrame as their parent.  We wrap
+ * continuous runs of such items into a FrameConstructionItem for a frame that
+ * gets them closer to their desired parents.  For example, a run of non-row
+ * children of a row-group will get wrapped in a row.  When we later construct
+ * the frame for this wrapper (in this case for the row), it'll be the correct
+ * parent for the cells in the set of items we wrapped or we'll wrap cells
+ * around everything else.  At the end of this method, aItems is guaranteed to
+ * contain only items for frames that can be direct kids of aParentFrame.
+ */
+nsresult
+nsCSSFrameConstructor::CreateNeededTablePseudos(FrameConstructionItemList& aItems,
+                                                nsIFrame* aParentFrame)
+{
+  ParentType ourParentType = GetParentType(aParentFrame);
+  if (aItems.AllWantParentType(ourParentType)) {
+    // Nothing to do here
+    return NS_OK;
+  }
+
+  FCItemIterator iter(aItems);
+  do {
+    NS_ASSERTION(!iter.IsDone(), "How did that happen?");
+
+    // Advance to the next item that wants a different parent type.
+    while (iter.item().DesiredParentType() == ourParentType) {
+      iter.Next();
+      if (iter.IsDone()) {
+        // Nothing else to do here; we're finished
+        return NS_OK;
+      }
+    }
+
+    NS_ASSERTION(!iter.IsDone() &&
+                 iter.item().DesiredParentType() != ourParentType,
+                 "Why did we stop?");
+
+    // Now we're pointing to the first child that wants a different parent
+    // type.  Except for generated content, we should have already enforced the
+    // fact that no such items are whitespace (either in this method when
+    // constructing wrapping items, or when constructing the original
+    // FrameConstructionItemList).
+    NS_ASSERTION(aParentFrame->IsGeneratedContentFrame() ||
+                 !iter.item().mIsText ||
+                 !iter.item().mContent->TextIsOnlyWhitespace(),
+                 "Why do we have whitespace under a known-table parent?");
+
+    // Now try to figure out what kids we can group together.  We can generally
+    // group everything that has a different desired parent type from us.  Two
+    // exceptions to this:
+    // 1) If our parent type is table, we can't group columns with anything
+    //    else other than whitespace.
+    // 2) Whitespace that lies between two things we can group should
+    //    be dropped, even if we can't group them with each other.
+    // XXXbz it's not clear to me that rule 2 is a good one, it's not called
+    // for by the (admittedly vague) spec, and in fact it leads to some pretty
+    // crappy behavior if you have some inlines and whitespace as kids of a
+    // table-row, say, but it's more or less what we used to do.  More
+    // precisely, we shipped all whitespace out to the nearest block parent of
+    // the whole mess, sort of.  In any case this aspect of things, and in fact
+    // this whole function might need changes as the spec here gets
+    // clarified...  I happen to think we should not drop whitespace that comes
+    // between things that want a block parent.
+
+    FCItemIterator endIter(iter); /* iterator to find the end of the group */
+    ParentType groupingParentType = endIter.item().DesiredParentType();
+    // If we decide to, we could optimize this by checking whether
+    // aItems.AllWantParentType(groupingParentType) and if so just setting
+    // endIter to the end of the list, which is an O(1) operation.  That
+    // requires not dropping whitespace between items that want a block parent,
+    // though, per the XXX comment above, since a whole bunch of spans and
+    // whitespace would test true to all wanting a block parent.
+    do {
+      endIter.Next();
+      if (endIter.IsDone()) {
+        break;
+      }
+
+      if (!aParentFrame->IsGeneratedContentFrame() &&
+          endIter.item().IsWhitespace()) {
+        // Whitespace coming after some groupable items
+        FCItemIterator textSkipIter(endIter);
+        do {
+          textSkipIter.Next();
+        } while (!textSkipIter.IsDone() && textSkipIter.item().IsWhitespace());
+
+        PRBool trailingSpace = textSkipIter.IsDone();
+        if (// Trailing whitespace we can't handle
+            (trailingSpace && ourParentType != eTypeBlock) ||
+            // Whitespace before kids needing wrapping
+            (!trailingSpace &&
+             textSkipIter.item().DesiredParentType() != ourParentType)) {
+          // Drop all the whitespace here so that |endIter| now points to the
+          // same thing as |textSkipIter|.  This doesn't affect where |iter|
+          // points, since that's guaranted to point to before endIter.
+          do {
+            endIter.DeleteItem();
+          } while (endIter != textSkipIter);
+
+          NS_ASSERTION(endIter.IsDone() == trailingSpace,
+                       "endIter == skipIter now!");
+          if (trailingSpace) {
+            break; // The loop advancing endIter
+          }
+        }
+      }
+
+      ParentType itemParentType = endIter.item().DesiredParentType();
+
+      if (itemParentType == ourParentType) {
+        break;
+      }
+
+      if (ourParentType == eTypeTable &&
+          (itemParentType == eTypeColGroup) !=
+          (groupingParentType == eTypeColGroup)) {
+        // Either we started with columns and now found something else, or vice
+        // versa.  In any case, end the grouping.
+        break;
+      }
+    } while (1);
+
+    NS_ASSERTION(iter != endIter, "How did that happen?");
+
+    // Now group together all the items between iter and endIter.  The right
+    // parent type to use depends on ourParentType.
+    ParentType wrapperType;
+    switch (ourParentType) {
+      case eTypeBlock:
+        wrapperType = eTypeTable;
+        break;
+      case eTypeRow:
+        // The parent type for a cell is eTypeBlock, since that's what a cell
+        // looks like to its kids.
+        wrapperType = eTypeBlock;
+        break;
+      case eTypeRowGroup:
+        wrapperType = eTypeRow;
+        break;
+      case eTypeTable:
+        // Either colgroup or rowgroup, depending on what we're grouping.
+        wrapperType = groupingParentType == eTypeColGroup ?
+          eTypeColGroup : eTypeRowGroup;
+        break;
+      default:
+        NS_NOTREACHED("Colgroups should be suppresing non-col child items");
+        break;
+    }
+
+    const PseudoParentData& pseudoData = sPseudoParentData[wrapperType];
+    nsIAtom* pseudoType = *pseudoData.mPseudoType;
+    nsStyleContext* parentStyle = aParentFrame->GetStyleContext();
+    nsIContent* parentContent = aParentFrame->GetContent();
+
+    if (pseudoType == nsCSSAnonBoxes::table &&
+        parentStyle->GetStyleDisplay()->mDisplay == NS_STYLE_DISPLAY_INLINE) {
+      pseudoType = nsCSSAnonBoxes::inlineTable;
+    }
+
+    nsRefPtr<nsStyleContext> wrapperStyle =
+      mPresShell->StyleSet()->ResolvePseudoStyleFor(parentContent,
+                                                    pseudoType,
+                                                    parentStyle);
+    FrameConstructionItem* newItem =
+      new FrameConstructionItem(&pseudoData.mFCData,
+                                // Use the content of our parent frame
+                                parentContent,
+                                // Lie about the tag; it doesn't matter anyway
+                                pseudoType,
+                                // The namespace does matter, however; it needs
+                                // to match that of our first child item to
+                                // match the old behavior
+                                iter.item().mNameSpaceID,
+                                wrapperStyle.forget());
+
+    if (!newItem) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+
+    // Here we're cheating a tad... technically, table-internal items should be
+    // inline if aParentFrame is inline, but they'll get wrapped in an
+    // inline-table in the end, so it'll all work out.  In any case, arguably
+    // we don't need to maintain this state at this point... but it's better
+    // to, I guess.
+    newItem->mIsAllInline = newItem->mHasInlineEnds =
+      newItem->mStyleContext->GetStyleDisplay()->IsInlineOutside();
+
+    // Eat up all items between |iter| and |endIter| and put them in our wrapper
+    // Advances |iter| to point to |endIter|.
+    iter.AppendItemsToList(endIter, newItem->mChildItems);
+
+    iter.InsertItem(newItem);
+
+    // Now |iter| points to the item that was the first one we didn't wrap;
+    // loop and see whether we need to skip it or wrap it in something
+    // different.
+  } while (!iter.IsDone());
+
+  return NS_OK;
+}
+
 nsresult
 nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState& aState,
                                                    FrameConstructionItemList& aItems,
                                                    nsIFrame* aParentFrame,
                                                    nsFrameItems& aFrameItems)
 {
-  // save the incoming pseudo frame state
-  nsPseudoFrames priorPseudoFrames;
-  aState.mPseudoFrames.Reset(&priorPseudoFrames);
+  nsresult rv = CreateNeededTablePseudos(aItems, aParentFrame);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+#ifdef DEBUG
+  for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
+    NS_ASSERTION(iter.item().DesiredParentType() == GetParentType(aParentFrame),
+                 "Needed pseudos didn't get created; expect bad things");
+  }
+#endif
 
   for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
-    nsresult rv =
-      ConstructFramesFromItem(aState, iter, aParentFrame, aFrameItems);
+    rv = ConstructFramesFromItem(aState, iter, aParentFrame, aFrameItems);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   NS_ASSERTION(!aState.mHavePendingPopupgroup,
                "Should have proccessed it by now");
 
-  // process the current pseudo frame state
-  if (!aState.mPseudoFrames.IsEmpty()) {
-    ProcessPseudoFrames(aState, aFrameItems);
-  }
-
-  // restore the incoming pseudo frame state
-  aState.mPseudoFrames = priorPseudoFrames;
-
   return NS_OK;
 }
 
 /**
  * Request to process the child content elements and create frames.
  *
  * @param   aContent the content object whose child elements to process
  * @param   aFrame the frame associated with aContent. This will be the
@@ -10236,19 +9300,31 @@ nsCSSFrameConstructor::ProcessChildren(n
 
   if (haveFirstLetterStyle) {
     rv = WrapFramesInFirstLetterFrame(aContent, aFrame, aFrameItems);
   }
   if (haveFirstLineStyle) {
     rv = WrapFramesInFirstLineFrame(aState, aContent, aFrame, aFrameItems);
   }
 
-  nsIContent *badKid;
-  if (aFrame->IsBoxFrame() &&
-      (badKid = AnyKidsNeedBlockParent(aFrameItems.childList))) {
+  // We might end up with first-line frames that change
+  // AnyKidsNeedBlockParent() without changing itemsToConstruct, but that
+  // should never happen for cases whan aFrame->IsBoxFrame().
+  NS_ASSERTION(!haveFirstLineStyle || !aFrame->IsBoxFrame(),
+               "Shouldn't have first-line style if we're a box");
+  NS_ASSERTION(!aFrame->IsBoxFrame() ||
+               itemsToConstruct.AnyItemsNeedBlockParent() ==
+                 (AnyKidsNeedBlockParent(aFrameItems.childList) != nsnull),
+               "Something went awry in our block parent calculations");
+
+  if (aFrame->IsBoxFrame() && itemsToConstruct.AnyItemsNeedBlockParent()) {
+    // XXXbz we could do this on the FrameConstructionItemList level,
+    // no?  And if we cared we could look through the item list
+    // instead of groveling through the framelist here..
+    nsIContent *badKid = AnyKidsNeedBlockParent(aFrameItems.childList);
     nsAutoString parentTag, kidTag;
     aContent->Tag()->ToString(parentTag);
     badKid->Tag()->ToString(kidTag);
     const PRUnichar* params[] = { parentTag.get(), kidTag.get() };
     nsStyleContext *frameStyleContext = aFrame->GetStyleContext();
     const nsStyleDisplay *display = frameStyleContext->GetStyleDisplay();
     const char *message =
       (display->mDisplay == NS_STYLE_DISPLAY_INLINE_BOX)
@@ -11387,18 +10463,18 @@ nsCSSFrameConstructor::ConstructInline(n
   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, childItems);
+  nsresult rv = ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame,
+                                            childItems);
   if (NS_FAILED(rv)) {
     // Clean up?
     return rv;
   }
 
   nsIFrame* list1 = childItems.childList;
   nsIFrame* prevToFirstBlock;
   nsIFrame* list2;
@@ -12367,8 +11443,100 @@ nsCSSFrameConstructor::LazyGenerateChild
       mCallback(mContent, frame, mArg);
 
     // call XBL constructors after the frames are created
     mPresShell->GetDocument()->BindingManager()->ProcessAttachedQueue();
   }
 
   return NS_OK;
 }
+
+//////////////////////////////////////////////////////////////
+// nsCSSFrameConstructor::FrameConstructionItemList methods //
+//////////////////////////////////////////////////////////////
+void
+nsCSSFrameConstructor::FrameConstructionItemList::
+AdjustCountsForItem(FrameConstructionItem* aItem, PRInt32 aDelta)
+{
+  NS_PRECONDITION(aDelta == 1 || aDelta == -1, "Unexpected delta");
+  mItemCount += aDelta;
+  if (aItem->mIsAllInline) {
+    mInlineCount += aDelta;
+  }
+  if (aItem->mFCData->mBits & FCDATA_IS_LINE_PARTICIPANT) {
+    mLineParticipantCount += aDelta;
+  }
+  mDesiredParentCounts[aItem->DesiredParentType()] += aDelta;
+}
+
+////////////////////////////////////////////////////////////////////////
+// nsCSSFrameConstructor::FrameConstructionItemList::Iterator methods //
+////////////////////////////////////////////////////////////////////////
+void
+nsCSSFrameConstructor::FrameConstructionItemList::
+Iterator::AppendItemToList(FrameConstructionItemList& aTargetList)
+{
+  NS_ASSERTION(&aTargetList != &mList, "Unexpected call");
+  NS_PRECONDITION(!IsDone(), "should not be done");
+
+  FrameConstructionItem* item = ToItem(mCurrent);
+  Next();
+  PR_REMOVE_LINK(item);
+  PR_APPEND_LINK(item, &aTargetList.mItems);
+
+  mList.AdjustCountsForItem(item, -1);
+  aTargetList.AdjustCountsForItem(item, 1);
+}
+
+void
+nsCSSFrameConstructor::FrameConstructionItemList::
+Iterator::AppendItemsToList(const Iterator& aEnd,
+                            FrameConstructionItemList& aTargetList)
+{
+  NS_ASSERTION(&aTargetList != &mList, "Unexpected call");
+  NS_PRECONDITION(mEnd == aEnd.mEnd, "end iterator for some other list?");
+
+  if (!AtStart() || !aEnd.IsDone() || !aTargetList.IsEmpty()) {
+    do {
+      AppendItemToList(aTargetList);
+    } while (*this != aEnd);
+    return;
+  }
+
+  // move over the list of items
+  PR_INSERT_AFTER(&aTargetList.mItems, &mList.mItems);
+  PR_REMOVE_LINK(&mList.mItems);
+
+  // Copy over the various counters
+  aTargetList.mInlineCount = mList.mInlineCount;
+  aTargetList.mLineParticipantCount = mList.mLineParticipantCount;
+  aTargetList.mItemCount = mList.mItemCount;
+  memcpy(aTargetList.mDesiredParentCounts, mList.mDesiredParentCounts,
+         sizeof(aTargetList.mDesiredParentCounts));
+
+  // reset mList
+  new (&mList) FrameConstructionItemList();
+
+  // Point ourselves to aEnd, as advertised
+  mCurrent = mEnd = &mList.mItems;
+  NS_POSTCONDITION(*this == aEnd, "How did that happen?");
+}
+
+void
+nsCSSFrameConstructor::FrameConstructionItemList::
+Iterator::InsertItem(FrameConstructionItem* aItem)
+{
+  // Just insert the item before us.  There's no magic here.
+  PR_INSERT_BEFORE(aItem, mCurrent);
+  mList.AdjustCountsForItem(aItem, 1);
+
+  NS_POSTCONDITION(PR_NEXT_LINK(aItem) == mCurrent, "How did that happen?");
+}
+
+void
+nsCSSFrameConstructor::FrameConstructionItemList::Iterator::DeleteItem()
+{
+  FrameConstructionItem* item = ToItem(mCurrent);
+  Next();
+  PR_REMOVE_LINK(item);
+  mList.AdjustCountsForItem(item, -1);
+  delete item;
+}
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -63,16 +63,17 @@ struct nsStyleDisplay;
 class nsIPresShell;
 class nsFrameManager;
 class nsIDOMHTMLSelectElement;
 class nsPresContext;
 class nsStyleChangeList;
 class nsIFrame;
 struct nsGenConInitializer;
 class ChildIterator;
+class nsICSSAnonBoxPseudo;
 
 struct nsFindFrameHint
 {
   nsIFrame *mPrimaryFrameForPrevSibling;  // weak ref to the primary frame for the content for which we need a frame
   nsFindFrameHint() : mPrimaryFrameForPrevSibling(nsnull) { }
 };
 
 typedef void (nsLazyFrameConstructionCallback)
@@ -316,16 +317,19 @@ private:
 
   already_AddRefed<nsStyleContext>
   ResolveStyleContext(nsIFrame*         aParentFrame,
                       nsIContent*       aContent);
   already_AddRefed<nsStyleContext>
   ResolveStyleContext(nsStyleContext* aParentStyleContext,
                       nsIContent* aContent);
 
+  // Construct a frame for aContent and put it in aFrameItems.  This should
+  // only be used in cases when it's known that the frame won't need table
+  // pseudo-frame construction and the like.
   nsresult ConstructFrame(nsFrameConstructorState& aState,
                           nsIContent*              aContent,
                           nsIFrame*                aParentFrame,
                           nsFrameItems&            aFrameItems);
 
   // Add the frame construction items for the given aContent and aParentFrame
   // to the list.  This might add more than one item in some rare cases.
   void AddFrameConstructionItems(nsFrameConstructorState& aState,
@@ -412,57 +416,26 @@ private:
   nsresult ConstructTable(nsFrameConstructorState& aState,
                           FrameConstructionItem&   aItem,
                           nsIFrame*                aParentFrame,
                           const nsStyleDisplay*    aDisplay,
                           nsFrameItems&            aFrameItems,
                           nsIFrame**               aNewFrame);
 
   /**
-   * ConstructTableFrame will construct the outer and inner table frames and
-   * return them.  Unless aIsPseudo is PR_TRUE, it will put the inner frame in
-   * the child list of the outer frame, and will put any pseudo frames it had
-   * to create into aChildItems.  The newly-created outer frame will either be
-   * in aChildItems or a descendant of a pseudo in aChildItems (unless it's
-   * positioned or floated, in which case its placeholder will be in
-   * aChildItems).
-   */ 
-  nsresult ConstructTableFrame(nsFrameConstructorState& aState,
-                               nsIContent*              aContent,
-                               nsIFrame*                aContentParent,
-                               nsStyleContext*          aStyleContext,
-                               PRInt32                  aNameSpaceID,
-                               PRBool                   aIsPseudo,
-                               nsFrameItems&            aChildItems,
-                               nsIFrame*&               aNewOuterFrame,
-                               nsIFrame*&               aNewInnerFrame);
-
-  /**
    * FrameConstructionData callback used for constructing table rows.
    */
   nsresult ConstructTableRow(nsFrameConstructorState& aState,
                              FrameConstructionItem&   aItem,
                              nsIFrame*                aParentFrame,
                              const nsStyleDisplay*    aStyleDisplay,
                              nsFrameItems&            aFrameItems,
                              nsIFrame**               aNewFrame);
 
   /**
-   * Method used by both ConstructTableRow and pseudo-frame creation.
-   */
-  nsresult ConstructTableRowFrame(nsFrameConstructorState& aState,
-                                  nsIContent*              aContent,
-                                  nsIFrame*                aParent,
-                                  nsStyleContext*          aStyleContext,
-                                  PRInt32                  aNameSpaceID,
-                                  PRBool                   aIsPseudo,
-                                  nsFrameItems&            aChildItems,
-                                  nsIFrame*&               aNewFrame);
-
-  /**
    * FrameConstructionData callback used for constructing table columns.
    */
   nsresult ConstructTableCol(nsFrameConstructorState& aState,
                              FrameConstructionItem&   aItem,
                              nsIFrame*                aParentFrame,
                              const nsStyleDisplay*    aStyleDisplay,
                              nsFrameItems&            aFrameItems,
                              nsIFrame**               aNewFrame);
@@ -472,77 +445,40 @@ private:
    */
   nsresult ConstructTableCell(nsFrameConstructorState& aState,
                               FrameConstructionItem&   aItem,
                               nsIFrame*                aParentFrame,
                               const nsStyleDisplay*    aStyleDisplay,
                               nsFrameItems&            aFrameItems,
                               nsIFrame**               aNewFrame);
 
-  /**
-   * Method used by both ConstructTableCell and pseudo-frame creation.
-   */
-  nsresult ConstructTableCellFrame(nsFrameConstructorState& aState,
-                                   nsIContent*              aContent,
-                                   nsIFrame*                aParentFrame,
-                                   nsStyleContext*          aStyleContext,
-                                   PRInt32                  aNameSpaceID,
-                                   PRBool                   aIsPseudo,
-                                   nsFrameItems&            aChildItems,
-                                   nsIFrame*&               aNewCellOuterFrame,
-                                   nsIFrame*&               aNewCellInnerFrame);
-
-  nsresult CreatePseudoTableFrame(PRInt32                  aNameSpaceID,
-                                  nsFrameConstructorState& aState, 
-                                  nsIFrame*                aParentFrameIn = nsnull);
-
-  nsresult CreatePseudoRowGroupFrame(PRInt32                  aNameSpaceID,
-                                     nsFrameConstructorState& aState, 
-                                     nsIFrame*                aParentFrameIn = nsnull);
-
-  nsresult CreatePseudoColGroupFrame(PRInt32                  aNameSpaceID,
-                                     nsFrameConstructorState& aState, 
-                                     nsIFrame*                aParentFrameIn = nsnull);
-
-  nsresult CreatePseudoRowFrame(PRInt32                  aNameSpaceID,
-                                nsFrameConstructorState& aState, 
-                                nsIFrame*                aParentFrameIn = nsnull);
+private:
+  /* An enum of possible parent types for anonymous table object construction */
+  enum ParentType {
+    eTypeBlock = 0, /* This includes all non-table-related frames */
+    eTypeRow,
+    eTypeRowGroup,
+    eTypeColGroup,
+    eTypeTable,
+    eParentTypeCount
+  };
 
-  nsresult CreatePseudoCellFrame(PRInt32                  aNameSpaceID,
-                                 nsFrameConstructorState& aState, 
-                                 nsIFrame*                aParentFrameIn = nsnull);
-
-  nsresult GetPseudoTableFrame(PRInt32                  aNameSpaceID,
-                               nsFrameConstructorState& aState, 
-                               nsIFrame&                aParentFrameIn);
-
-  nsresult GetPseudoColGroupFrame(PRInt32                  aNameSpaceID,
-                                  nsFrameConstructorState& aState, 
-                                  nsIFrame&                aParentFrameIn);
-
-  nsresult GetPseudoRowGroupFrame(PRInt32                  aNameSpaceID,
-                                  nsFrameConstructorState& aState, 
-                                  nsIFrame&                aParentFrameIn);
+  /* 3 bits is enough to handle our ParentType values */
+#define FCDATA_PARENT_TYPE_OFFSET 29
+  /* Macro to get the desired parent type out of an mBits member of
+     FrameConstructionData */
+#define FCDATA_DESIRED_PARENT_TYPE(_bits)           \
+  ParentType((_bits) >> FCDATA_PARENT_TYPE_OFFSET)
+  /* Macro to create FrameConstructionData bits out of a desired parent type */
+#define FCDATA_DESIRED_PARENT_TYPE_TO_BITS(_type)     \
+  (((PRUint32)(_type)) << FCDATA_PARENT_TYPE_OFFSET)
 
-  nsresult GetPseudoRowFrame(PRInt32                  aNameSpaceID,
-                             nsFrameConstructorState& aState, 
-                             nsIFrame&                aParentFrameIn);
-
-  nsresult GetPseudoCellFrame(PRInt32                  aNameSpaceID,
-                              nsFrameConstructorState& aState, 
-                              nsIFrame&                aParentFrameIn);
+  /* Get the parent type that aParentFrame has. */
+  static ParentType GetParentType(nsIFrame* aParentFrame);
 
-  nsresult CreateRequiredPseudoFrames(PRInt32                  aNameSpaceID,
-                                      nsIFrame&                aParentFrameIn,
-                                      nsIAtom*                 aChildFrameType,
-                                      nsFrameConstructorState& aState,
-                                      nsIFrame*&               aParentFrame,
-                                      PRBool&                  aIsPseudoParent);
-
-private:
   /* A constructor function that just creates an nsIFrame object.  The caller
      is responsible for initializing the object, adding it to frame lists,
      constructing frames for the children, etc.
 
      @param nsIPresShell the presshell whose arena should be used to allocate
                          the frame.
      @param nsStyleContext the style context to use for the frame. */
   typedef nsIFrame* (* FrameCreationFunc)(nsIPresShell*, nsStyleContext*);
@@ -649,16 +585,21 @@ private:
      inline box. */
 #define FCDATA_IS_INLINE 0x2000
   /* If FCDATA_IS_LINE_PARTICIPANT is set, the the frame is something that will
      return true for IsFrameOfType(nsIFrame::eLineParticipant) */
 #define FCDATA_IS_LINE_PARTICIPANT 0x4000
   /* If FCDATA_ALLOW_BLOCK_STYLES is set, allow block styles when processing
      children.  This should not be used with FCDATA_FUNC_IS_FULL_CTOR. */
 #define FCDATA_ALLOW_BLOCK_STYLES 0x8000
+  /* If FCDATA_USE_CHILD_ITEMS is set, then use the mChildItems in the relevant
+     FrameConstructionItem instead of trying to process the content's children.
+     This can be used with or without FCDATA_FUNC_IS_FULL_CTOR.
+     The child items might still need table pseudo processing. */
+#define FCDATA_USE_CHILD_ITEMS 0x10000
 
   /* Structure representing information about how a frame should be
      constructed.  */
   struct FrameConstructionData {
     // Flag bits that can modify the way the construction happens
     PRUint32 mBits;
     // We have exactly one of three types of functions, so use a union for
     // better cache locality for the ones that aren't pointer-to-member.  That
@@ -688,16 +629,26 @@ private:
   /* Structure representing a mapping of an integer to a
      FrameConstructionData. There are no magic integer values here. */
   struct FrameConstructionDataByInt {
     /* Could be used for display or whatever else */
     const PRInt32 mInt;
     const FrameConstructionData mData;
   };
 
+  /* Structure that has a FrameConstructionData and style context pseudo-type
+     for a table pseudo-frame */
+  struct PseudoParentData {
+    const FrameConstructionData mFCData;
+    nsICSSAnonBoxPseudo * const * const mPseudoType;
+  };
+  /* Array of such structures that we use to properly construct table
+     pseudo-frames as needed */
+  static const PseudoParentData sPseudoParentData[eParentTypeCount];
+
   /* A function that takes an integer, content, style context, and array of
      FrameConstructionDataByInts and finds the appropriate frame construction
      data to use and returns it.  This can return null if none of the integers
      match or if the matching integer has a FrameConstructionDataGetter that
      returns null. */
   static const FrameConstructionData*
     FindDataByInt(PRInt32 aInt, nsIContent* aContent,
                   nsStyleContext* aStyleContext,
@@ -719,16 +670,17 @@ private:
   class FrameConstructionItemList {
   public:
     FrameConstructionItemList() :
       mInlineCount(0),
       mLineParticipantCount(0),
       mItemCount(0)
     {
       PR_INIT_CLIST(&mItems);
+      memset(mDesiredParentCounts, 0, sizeof(mDesiredParentCounts));
     }
 
     ~FrameConstructionItemList() {
       PRCList* cur = PR_NEXT_LINK(&mItems);
       while (cur != &mItems) {
         PRCList* next = PR_NEXT_LINK(cur);
         delete ToItem(cur);
         cur = next;
@@ -744,70 +696,127 @@ private:
     PRBool IsStartInline() const {
       NS_ASSERTION(!IsEmpty(), "Someone forgot to check IsEmpty()");
       return ToItem(PR_LIST_HEAD(&mItems))->mHasInlineEnds;
     }
     PRBool IsEndInline() const {
       NS_ASSERTION(!IsEmpty(), "Someone forgot to check IsEmpty()");
       return ToItem(PR_LIST_TAIL(&mItems))->mHasInlineEnds;
     }
+    PRBool AllWantParentType(ParentType aDesiredParentType) const {
+      return mDesiredParentCounts[aDesiredParentType] == mItemCount;
+    }
 
     FrameConstructionItem* AppendItem(const FrameConstructionData* aFCData,
                                       nsIContent* aContent,
                                       nsIAtom* aTag,
                                       PRInt32 aNameSpaceID,
                                       already_AddRefed<nsStyleContext> aStyleContext)
     {
       FrameConstructionItem* item =
         new FrameConstructionItem(aFCData, aContent, aTag, aNameSpaceID,
                                   aStyleContext);
       if (item) {
         PR_APPEND_LINK(item, &mItems);
         ++mItemCount;
+        ++mDesiredParentCounts[item->DesiredParentType()];
       } else {
         // Clean up the style context
         nsRefPtr<nsStyleContext> sc(aStyleContext);
       }
       return item;
     }
 
     void InlineItemAdded() { ++mInlineCount; }
     void LineParticipantItemAdded() { ++mLineParticipantCount; }
 
     class Iterator;
     friend class Iterator;
+
     class Iterator {
     public:
       Iterator(FrameConstructionItemList& list) :
         mCurrent(PR_NEXT_LINK(&list.mItems)),
-        mEnd(&list.mItems)
+        mEnd(&list.mItems),
+        mList(list)
+      {}
+      Iterator(const Iterator& aOther) :
+        mCurrent(aOther.mCurrent),
+        mEnd(aOther.mEnd),
+        mList(aOther.mList)
       {}
 
+      PRBool operator==(const Iterator& aOther) const {
+        NS_ASSERTION(mEnd == aOther.mEnd, "Iterators for different lists?");
+        return mCurrent == aOther.mCurrent;
+      }
+      PRBool operator!=(const Iterator& aOther) const {
+        return !(*this == aOther);
+      }
+
       operator FrameConstructionItem& () {
+        return item();
+      }
+
+      FrameConstructionItem& item() {
         return *FrameConstructionItemList::ToItem(mCurrent);
       }
       PRBool IsDone() const { return mCurrent == mEnd; }
+      PRBool AtStart() const { return mCurrent == PR_NEXT_LINK(mEnd); }
       void Next() {
         NS_ASSERTION(!IsDone(), "Should have checked IsDone()!");
         mCurrent = PR_NEXT_LINK(mCurrent);
       }
+
+      // Remove the item pointed to by this iterator from its current list and
+      // Append it to aTargetList.  This iterator is advanced to point to the
+      // next item in its list.  aIter must not be done.  aOther must not be
+      // the list this iterator is iterating over..
+      void AppendItemToList(FrameConstructionItemList& aTargetList);
+
+      // As above, but moves all items starting with this iterator until we
+      // get to aEnd; the item pointed to by aEnd is not stolen.  This method
+      // might have optimizations over just looping and doing StealItem for
+      // some special cases.  After this method returns, this iterator will
+      // point to the item aEnd points to now; aEnd is not modified.
+      // aTargetList must not be the list this iterator is iterating over.
+      void AppendItemsToList(const Iterator& aEnd,
+                             FrameConstructionItemList& aTargetList);
+
+      // Insert aItem in this iterator's list right before the item pointed to
+      // by this iterator.  After the insertion, this iterator will continue to
+      // point to the item it now points to (the one just after the
+      // newly-inserted item).  This iterator is allowed to be done; in that
+      // case this call just appends the given item to the list.
+      void InsertItem(FrameConstructionItem* aItem);
+
+      // Delete the item pointed to by this iterator, and point ourselves to
+      // the next item in the list.
+      void DeleteItem();
+
     private:
       PRCList* mCurrent;
       PRCList* mEnd;
+      FrameConstructionItemList& mList;
     };
 
   private:
     static FrameConstructionItem* ToItem(PRCList* item) {
       return static_cast<FrameConstructionItem*>(item);
     }
 
+    // Adjust our various counts for aItem being added or removed.  aDelta
+    // should be either +1 or -1 depending on which is happening.
+    void AdjustCountsForItem(FrameConstructionItem* aItem, PRInt32 aDelta);
+
     PRCList mItems;
     PRUint32 mInlineCount;
     PRUint32 mLineParticipantCount;
     PRUint32 mItemCount;
+    PRUint32 mDesiredParentCounts[eParentTypeCount];
   };
 
   typedef FrameConstructionItemList::Iterator FCItemIterator;
 
   /* A struct representing an item for which frames might need to be
    * constructed.  This contains all the information needed to construct the
    * frame other than the parent frame and whatever would be stored in the
    * frame constructor state. */
@@ -827,16 +836,23 @@ private:
     {}
     ~FrameConstructionItem() {
       if (mIsGeneratedContent) {
         mContent->UnbindFromTree();
         NS_RELEASE(mContent);
       }
     }
 
+    ParentType DesiredParentType() {
+      return FCDATA_DESIRED_PARENT_TYPE(mFCData->mBits);
+    }
+    PRBool IsWhitespace() const {
+      return mIsText && mContent->TextIsOnlyWhitespace();
+    }
+
     // The FrameConstructionData to use.
     const FrameConstructionData* mFCData;
     // The nsIContent node to use when initializing the new frame.
     nsIContent* mContent;
     // The XBL-resolved tag name to use for frame construction.
     nsIAtom* mTag;
     // The XBL-resolved namespace to use for frame construction.
     PRInt32 mNameSpaceID;
@@ -857,55 +873,45 @@ private:
     // items, where it's always true, whereas mIsAllInline might be false due
     // to {ib} splits.
     PRPackedBool mHasInlineEnds;
     // Whether construction from this item will create a popup that needs to
     // go into the global popup items.
     PRPackedBool mIsPopup;
 
     // Child frame construction items.
-    // Only used for inline frame items for now.
     FrameConstructionItemList mChildItems;
 
   private:
     FrameConstructionItem(const FrameConstructionItem& aOther); /* not implemented */
   };
 
   /**
-   * Function to adjust aParentFrame and aFrameItems to deal with table
-   * pseudo-frames that may have to be inserted.
-   * @param aState the nsFrameConstructorState we're using.
-   * @param aChildContent the content node we want to construct a frame for
+   * Function to create the table pseudo items we need.
+   * @param aItems the child frame construction items before pseudo creation
+   * @param aParentFrame the parent frame we're creating pseudos for
+   */
+  nsresult CreateNeededTablePseudos(FrameConstructionItemList& aItems,
+                                    nsIFrame* aParentFrame);
+
+  /**
+   * Function to adjust aParentFrame to deal with captions.
    * @param aParentFrame the frame we think should be the parent.  This will be
-   *        adjusted to point to a pseudo-frame if needed.
+   *        adjusted to point to the right parent frame.
    * @param aFCData the FrameConstructionData that would be used for frame
    *        construction.
-   * @param aNameSpaceID namespace that will be used for frame construction
    * @param aStyleContext the style context for aChildContent
-   * @param aFrameItems the framelist we think we need to put the child frame
-   *        into.  If we have to construct pseudo-frames, we'll modify the
-   *        pointer to point to the list the child frame should go into.
-   * @param aSaveState the nsFrameConstructorSaveState we can use for pushing a
-   *        float containing block if we have to do it.
-   * @param aCreatedPseudo whether we had to create a pseudo-parent
-   * @return NS_OK on success, NS_ERROR_OUT_OF_MEMORY and such as needed.
    */
   // XXXbz this function should really go away once we rework pseudo-frame
   // handling to be better. This should simply be part of the job of
   // GetGeometricParent, and stuff like the frameitems and parent frame should
   // be kept track of in the state...
-  nsresult AdjustParentFrame(nsFrameConstructorState&     aState,
-                             nsIContent*                  aChildContent,
-                             nsIFrame* &                  aParentFrame,
-                             const FrameConstructionData* aFCData,
-                             PRInt32                      aNameSpaceID,
-                             nsStyleContext*              aStyleContext,
-                             nsFrameItems* &              aFrameItems,
-                             nsFrameConstructorSaveState& aSaveState,
-                             PRBool&                      aCreatedPseudo);
+  void AdjustParentFrame(nsIFrame* &                  aParentFrame,
+                         const FrameConstructionData* aFCData,
+                         nsStyleContext*              aStyleContext);
 
   // END TABLE SECTION
 
 protected:
   static nsresult CreatePlaceholderFrameFor(nsIPresShell*    aPresShell, 
                                             nsIContent*      aContent,
                                             nsIFrame*        aFrame,
                                             nsStyleContext*  aStyleContext,
@@ -945,18 +951,17 @@ private:
   // inline frame.
   static const FrameConstructionData* FindTextData(nsIFrame* aParentFrame);
 
   nsresult ConstructTextFrame(const FrameConstructionData* aData,
                               nsFrameConstructorState& aState,
                               nsIContent*              aContent,
                               nsIFrame*                aParentFrame,
                               nsStyleContext*          aStyleContext,
-                              nsFrameItems&            aFrameItems,
-                              PRBool                   aPseudoParent);
+                              nsFrameItems&            aFrameItems);
 
   void AddPageBreakItem(nsIContent* aContent,
                         nsStyleContext* aMainStyleContext,
                         FrameConstructionItemList& aItems);
 
   // Function to find FrameConstructionData for aContent.  Will return
   // null if aContent is not HTML.
   // aParentFrame might be null.  If it is, that means it was an
@@ -981,23 +986,21 @@ private:
      it to the primary frame map, and so forth.
 
      @param aItem the FrameConstructionItem to use.
      @param aState the frame construction state to use.
      @param aParentFrame the frame to set as the parent of the
                          newly-constructed frame.
      @param aFrameItems the frame list to add the new frame (or its
                         placeholder) to.
-     @param aHasPseudoParent whether aParentFrame is a table pseudo-frame.
   */
   nsresult ConstructFrameFromItemInternal(FrameConstructionItem& aItem,
                                           nsFrameConstructorState& aState,
                                           nsIFrame* aParentFrame,
-                                          nsFrameItems& aFrameItems,
-                                          PRBool aHasPseudoParent);
+                                          nsFrameItems& aFrameItems);
 
   // possible flags for AddFrameConstructionItemInternal's aFlags argument
   /* Allow xbl:base to affect the tag/namespace used. */
 #define ITEM_ALLOW_XBL_BASE 0x1
   /* Allow page-break before and after items to be created if the
      style asks for them. */
 #define ITEM_ALLOW_PAGE_BREAK 0x2
   /* The item is a generated content item. */
@@ -1329,19 +1332,18 @@ private:
   /**
    * For an inline aParentItem, construct its list of child
    * FrameConstructionItems and set its mIsAllInline flag appropriately.
    */
   void BuildInlineChildItems(nsFrameConstructorState& aState,
                              FrameConstructionItem& aParentItem);
 
   /**
-   * Construct frames for the given item list and put the resulting frames in
-   * aFrameItems.  This function will save pseudoframes on entry and restore on
-   * exit.
+   * Construct frames for the given item list and parent frame, and put the
+   * resulting frames in aFrameItems.
    */
   nsresult ConstructFramesFromItemList(nsFrameConstructorState& aState,
                                        FrameConstructionItemList& aItems,
                                        nsIFrame* aParentFrame,
                                        nsFrameItems& aFrameItems);
 
   // Determine whether we need to wipe out what we just did and start over
   // because we're doing something like adding block kids to an inline frame