Bug 482889 Part 2. Refactor calls to CreateRequiredPseudoFrames so that they all happen in AdjustParentFrame. r=bernd, r+sr=roc
authorBoris Zbarsky <bzbarsky@mit.edu>
Sun, 15 Mar 2009 15:57:46 -0400
changeset 26207 523942ee51c838a08bf9342fdb2550f8ce3dd1e4
parent 26206 da61aad96bf9c491f9fcbbde7f5b203d18bb11e5
child 26208 237db3258d19208e37cc171e77bbeeee4ab23c8c
push id5948
push userbzbarsky@mozilla.com
push dateSun, 15 Mar 2009 20:02:32 +0000
treeherdermozilla-central@237db3258d19 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbernd, r
bugs482889
milestone1.9.2a1pre
Bug 482889 Part 2. Refactor calls to CreateRequiredPseudoFrames so that they all happen in AdjustParentFrame. r=bernd, r+sr=roc
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSFrameConstructor.h
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -2592,23 +2592,24 @@ nsCSSFrameConstructor::CreatePseudoRowGr
 
   childStyle = mPresShell->StyleSet()->ResolvePseudoStyleFor(parentContent,
                                                              nsCSSAnonBoxes::tableRowGroup, 
                                                              parentStyle);
 
   nsPseudoFrameData& pseudo = aState.mPseudoFrames.mRowGroup;
 
   // construct the pseudo row group as part of the pseudo frames
-  PRBool pseudoParent;
-  nsFrameItems items;
-  rv = ConstructTableRowGroupFrame(aState, parentContent,
-                                   parentFrame, childStyle, aNameSpaceID,
-                                   PR_TRUE, items, pseudo.mFrame, &pseudoParent);
-  if (NS_FAILED(rv)) return rv;
-
+  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
@@ -2639,21 +2640,23 @@ nsCSSFrameConstructor::CreatePseudoColGr
 
   childStyle = mPresShell->StyleSet()->ResolvePseudoStyleFor(parentContent,
                                                              nsCSSAnonBoxes::tableColGroup, 
                                                              parentStyle);
 
   nsPseudoFrameData& pseudo = aState.mPseudoFrames.mColGroup;
 
   // construct the pseudo col group as part of the pseudo frames
-  PRBool pseudoParent;
-  nsFrameItems items;
-  rv = ConstructTableColGroupFrame(aState, parentContent,
-                                   parentFrame, childStyle, aNameSpaceID,
-                                   PR_TRUE, items, pseudo.mFrame, &pseudoParent);
+  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
@@ -2690,21 +2693,20 @@ nsCSSFrameConstructor::CreatePseudoRowFr
 
   childStyle = mPresShell->StyleSet()->ResolvePseudoStyleFor(parentContent,
                                                              nsCSSAnonBoxes::tableRow, 
                                                              parentStyle);
 
   nsPseudoFrameData& pseudo = aState.mPseudoFrames.mRow;
 
   // construct the pseudo row as part of the pseudo frames
-  PRBool pseudoParent;
   nsFrameItems items;
   rv = ConstructTableRowFrame(aState, parentContent,
                               parentFrame, childStyle, aNameSpaceID,
-                              PR_TRUE, items, pseudo.mFrame, &pseudoParent);
+                              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);
   }
@@ -2737,22 +2739,20 @@ nsCSSFrameConstructor::CreatePseudoCellF
   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
-  PRBool pseudoParent;
   nsFrameItems items;
   rv = ConstructTableCellFrame(aState, parentContent, parentFrame, childStyle,
                                aNameSpaceID, PR_TRUE, items,
-                               pseudoOuter.mFrame, pseudoInner.mFrame,
-                               &pseudoParent);
+                               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
@@ -3069,42 +3069,114 @@ nsCSSFrameConstructor::AdjustParentFrame
 
   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 (IsTableRelated(parentType, PR_FALSE) && !tablePart) {
-    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 everythign
-    // below that cell, so that our later siblings don't see those
-    // pseudo-frames.
-    if (aState.mPseudoFrames.mTableOuter.mFrame) {
-      ProcessPseudoFrames(aState, nsGkAtoms::tableOuterFrame);
+  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;
 }
 
 // Pull all the captions present in aItems out  into aCaptions
 static void
 PullOutCaptionFrames(nsFrameItems& aItems, nsFrameItems& aCaptions)
@@ -3214,320 +3286,106 @@ nsCSSFrameConstructor::ConstructTableFra
                                             captionItems.childList);
     }
  }
 
   return rv;
 }
 
 nsresult
-nsCSSFrameConstructor::ConstructTableCaptionFrame(nsFrameConstructorState& aState,
-                                                  nsIContent*              aContent,
-                                                  nsIFrame*                aParentFrameIn,
-                                                  nsStyleContext*          aStyleContext,
-                                                  PRInt32                  aNameSpaceID,
-                                                  nsFrameItems&            aChildItems,
-                                                  nsIFrame*&               aNewFrame,
-                                                  PRBool*                  aHasPseudoParent)
-
-{
-  if (!aParentFrameIn) return NS_ERROR_UNEXPECTED;
-
-  nsIFrame* parentFrame = aParentFrameIn;
-  *aHasPseudoParent = PR_FALSE;
-  // this frame may have a pseudo parent
-  CreateRequiredPseudoFrames(aNameSpaceID, *aParentFrameIn,
-                             nsGkAtoms::tableCaptionFrame, aState, parentFrame,
-                             *aHasPseudoParent);
-  if (!*aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
-    ProcessPseudoFrames(aState, aChildItems);
-  }
-
-  aNewFrame = NS_NewTableCaptionFrame(mPresShell, aStyleContext);
-  if (NS_UNLIKELY(!aNewFrame)) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  InitAndRestoreFrame(aState, aContent, parentFrame, nsnull, aNewFrame);
-  nsHTMLContainerFrame::CreateViewForFrame(aNewFrame, PR_FALSE);
-
-  nsFrameItems childItems;
-  nsresult rv = ProcessChildren(aState, aContent, aStyleContext, aNewFrame,
-                                PR_TRUE, childItems, PR_TRUE);
-  if (NS_FAILED(rv)) return rv;
-  aNewFrame->SetInitialChildList(nsnull, childItems.childList);
-  if (*aHasPseudoParent) {
-    aState.mPseudoFrames.mTableOuter.mChildList2.AddChild(aNewFrame);
-  }
-  
-  return rv;
-}
-
-
-nsresult
-nsCSSFrameConstructor::ConstructTableRowGroupFrame(nsFrameConstructorState& aState,
-                                                   nsIContent*              aContent,
-                                                   nsIFrame*                aParentFrameIn,
-                                                   nsStyleContext*          aStyleContext,
-                                                   PRInt32                  aNameSpaceID,
-                                                   PRBool                   aIsPseudo,
-                                                   nsFrameItems&            aChildItems,
-                                                   nsIFrame*&               aNewFrame, 
-                                                   PRBool*                  aHasPseudoParent)
-{
-  if (!aParentFrameIn) return NS_ERROR_UNEXPECTED;
-
-  nsIFrame* parentFrame = aParentFrameIn;
-  *aHasPseudoParent = PR_FALSE;
-  if (!aIsPseudo) {
-    // this frame may have a pseudo parent
-    CreateRequiredPseudoFrames(aNameSpaceID, *aParentFrameIn,
-                               nsGkAtoms::tableRowGroupFrame, aState,
-                               parentFrame, *aHasPseudoParent);
-    if (!*aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
-      ProcessPseudoFrames(aState, aChildItems);
-    }
-    if (!aIsPseudo && *aHasPseudoParent &&
-        aState.mPseudoFrames.mRowGroup.mFrame) {
-      ProcessPseudoFrames(aState, nsGkAtoms::tableRowGroupFrame);
-    }
-  }
-
-  const nsStyleDisplay* styleDisplay = aStyleContext->GetStyleDisplay();
-
-  aNewFrame = NS_NewTableRowGroupFrame(mPresShell, aStyleContext);
-
-  nsIFrame* scrollFrame = nsnull;
-  if (styleDisplay->IsScrollableOverflow()) {
-    // Create an area container for the frame
-    BuildScrollFrame(aState, aContent, aStyleContext, aNewFrame, parentFrame,
-                     scrollFrame);
-
-  } 
-  else {
-    if (NS_UNLIKELY(!aNewFrame)) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-    InitAndRestoreFrame(aState, aContent, parentFrame, 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);
-    if (*aHasPseudoParent) {
-      nsIFrame* child = (scrollFrame) ? scrollFrame : aNewFrame;
-      aState.mPseudoFrames.mTableInner.mChildList.AddChild(child);
-    }
-  } 
-
-  // if there is a scroll frame, use it as the one constructed
-  if (scrollFrame) {
-    aNewFrame = scrollFrame;
-  }
-
-  return NS_OK;
-}
-
-nsresult
-nsCSSFrameConstructor::ConstructTableColGroupFrame(nsFrameConstructorState& aState,
-                                                   nsIContent*              aContent,
-                                                   nsIFrame*                aParentFrameIn,
-                                                   nsStyleContext*          aStyleContext,
-                                                   PRInt32                  aNameSpaceID,
-                                                   PRBool                   aIsPseudo,
-                                                   nsFrameItems&            aChildItems,
-                                                   nsIFrame*&               aNewFrame, 
-                                                   PRBool*                  aHasPseudoParent)
-{
-  if (!aParentFrameIn) return NS_ERROR_UNEXPECTED;
-
-  nsIFrame* parentFrame = aParentFrameIn;
-  *aHasPseudoParent = PR_FALSE;
-  if (!aIsPseudo) {
-    // this frame may have a pseudo parent
-    CreateRequiredPseudoFrames(aNameSpaceID, *aParentFrameIn,
-                               nsGkAtoms::tableColGroupFrame, aState,
-                               parentFrame, *aHasPseudoParent);
-    if (!*aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
-      ProcessPseudoFrames(aState, aChildItems);
-    }
-    if (!aIsPseudo && *aHasPseudoParent &&
-        aState.mPseudoFrames.mColGroup.mFrame) {
-      ProcessPseudoFrames(aState, nsGkAtoms::tableColGroupFrame);
-    }
-  }
-
-  aNewFrame = NS_NewTableColGroupFrame(mPresShell, aStyleContext);
-  if (NS_UNLIKELY(!aNewFrame)) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  InitAndRestoreFrame(aState, aContent, parentFrame, nsnull, aNewFrame);
-
-  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);
-    if (*aHasPseudoParent) {
-      aState.mPseudoFrames.mTableInner.mChildList.AddChild(aNewFrame);
-    }
-  }
-
-  return NS_OK;
-}
-
-nsresult
 nsCSSFrameConstructor::ConstructTableRowFrame(nsFrameConstructorState& aState,
                                               nsIContent*              aContent,
                                               nsIFrame*                aParentFrameIn,
                                               nsStyleContext*          aStyleContext,
                                               PRInt32                  aNameSpaceID,
                                               PRBool                   aIsPseudo,
                                               nsFrameItems&            aChildItems,
-                                              nsIFrame*&               aNewFrame,
-                                              PRBool*                  aHasPseudoParent)
-{
-  if (!aParentFrameIn) return NS_ERROR_UNEXPECTED;
-
-  nsIFrame* parentFrame = aParentFrameIn;
-  *aHasPseudoParent = PR_FALSE;
-  if (!aIsPseudo) {
-    // this frame may have a pseudo parent
-    CreateRequiredPseudoFrames(aNameSpaceID, *aParentFrameIn,
-                               nsGkAtoms::tableRowFrame, aState, parentFrame,
-                               *aHasPseudoParent);
-    if (!*aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
-      ProcessPseudoFrames(aState, aChildItems);
-    }
-    if (!aIsPseudo && *aHasPseudoParent && aState.mPseudoFrames.mRow.mFrame) {
-      ProcessPseudoFrames(aState, nsGkAtoms::tableRowFrame);
-    }
-  }
-
+                                              nsIFrame*&               aNewFrame)
+{
 #ifdef MOZ_MATHML
   if (kNameSpaceID_MathML == aNameSpaceID)
     aNewFrame = NS_NewMathMLmtrFrame(mPresShell, aStyleContext);
   else
 #endif
     aNewFrame = NS_NewTableRowFrame(mPresShell, aStyleContext);
 
   if (NS_UNLIKELY(!aNewFrame)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
-  InitAndRestoreFrame(aState, aContent, parentFrame, nsnull, aNewFrame);
+  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);
-    if (*aHasPseudoParent) {
-      aState.mPseudoFrames.mRowGroup.mChildList.AddChild(aNewFrame);
-    }
+    aChildItems.AddChild(aNewFrame);
   }
 
   return NS_OK;
 }
-      
+
 nsresult
-nsCSSFrameConstructor::ConstructTableColFrame(nsFrameConstructorState& aState,
-                                              nsIContent*              aContent,
-                                              nsIFrame*                aParentFrameIn,
-                                              nsStyleContext*          aStyleContext,
-                                              PRInt32                  aNameSpaceID,
-                                              PRBool                   aIsPseudo,
-                                              nsFrameItems&            aChildItems,
-                                              nsIFrame*&               aNewFrame,
-                                              PRBool*                  aHasPseudoParent)
-{
-  if (!aParentFrameIn || !aStyleContext) return NS_ERROR_UNEXPECTED;
-
-  nsIFrame* parentFrame = aParentFrameIn;
-  *aHasPseudoParent = PR_FALSE;
-  if (!aIsPseudo) {
-    // this frame may have a pseudo parent
-    CreateRequiredPseudoFrames(aNameSpaceID, *aParentFrameIn,
-                               nsGkAtoms::tableColFrame, aState, parentFrame,
-                               *aHasPseudoParent);
-    if (!*aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
-      ProcessPseudoFrames(aState, aChildItems);
-    }
-  }
-
-  nsTableColFrame* colFrame = NS_NewTableColFrame(mPresShell, aStyleContext);
-  aNewFrame = colFrame;
+nsCSSFrameConstructor::ConstructTableCol(nsFrameConstructorState& aState,
+                                         FrameConstructionItem&   aItem,
+                                         nsIFrame*                aParentFrame,
+                                         const nsStyleDisplay*    aStyleDisplay,
+                                         nsFrameItems&            aFrameItems,
+                                         nsIFrame**               aNewFrame)
+{
+  nsIContent* const content = aItem.mContent;
+  nsStyleContext* const styleContext = aItem.mStyleContext;
+
+  nsTableColFrame* colFrame = NS_NewTableColFrame(mPresShell, styleContext);
   if (NS_UNLIKELY(!aNewFrame)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
-  InitAndRestoreFrame(aState, aContent, parentFrame, nsnull, aNewFrame);
+  InitAndRestoreFrame(aState, content, aParentFrame, nsnull, colFrame);
+
+  NS_ASSERTION(colFrame->GetStyleContext() == styleContext,
+               "Unexpected style context");
 
   // construct additional col frames if the col frame has a span > 1
   PRInt32 span = colFrame->GetSpan();
-  nsIFrame* lastCol = aNewFrame;
-  nsStyleContext* styleContext = nsnull;
+  nsIFrame* lastCol = colFrame;
   for (PRInt32 spanX = 1; spanX < span; spanX++) {
-    // The same content node should always resolve to the same style context.
-    if (1 == spanX)
-      styleContext = aNewFrame->GetStyleContext();
     nsTableColFrame* newCol = NS_NewTableColFrame(mPresShell, styleContext);
     if (NS_UNLIKELY(!newCol)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
-    InitAndRestoreFrame(aState, aContent, parentFrame, nsnull, newCol, PR_FALSE);
+    InitAndRestoreFrame(aState, content, aParentFrame, nsnull, newCol,
+                        PR_FALSE);
     lastCol->SetNextSibling(newCol);
     lastCol->SetNextContinuation(newCol);
     newCol->SetPrevContinuation(lastCol);
     newCol->SetColType(eColAnonymousCol);
     lastCol = newCol;
   }
 
-  if (!aIsPseudo && *aHasPseudoParent) {
-      aState.mPseudoFrames.mColGroup.mChildList.AddChild(aNewFrame);
-  }
+  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,
-                                               PRBool*                  aHasPseudoParent)
-{
-  if (!aParentFrameIn) return NS_ERROR_UNEXPECTED;
+                                               nsIFrame*&               aNewCellInnerFrame)
+{
 
   nsIFrame* parentFrame = aParentFrameIn;
-  *aHasPseudoParent = PR_FALSE;
-  if (!aIsPseudo) {
-    // this frame may have a pseudo parent
-    // use nsGkAtoms::tableCellFrame which will match if it is really nsGkAtoms::bcTableCellFrame
-    CreateRequiredPseudoFrames(aNameSpaceID, *aParentFrameIn,
-                               nsGkAtoms::tableCellFrame, aState, parentFrame,
-                               *aHasPseudoParent);
-    if (!*aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
-      ProcessPseudoFrames(aState, aChildItems);
-    }
-    if (!aIsPseudo && *aHasPseudoParent && aState.mPseudoFrames.mCellOuter.mFrame) {
-      ProcessPseudoFrames(aState, nsGkAtoms::tableCellFrame);
-    }
-  }
 #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.
   // 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.
@@ -3592,19 +3450,17 @@ nsCSSFrameConstructor::ConstructTableCel
       aNewCellInnerFrame = nsnull;
       aNewCellOuterFrame->Destroy();
       aNewCellOuterFrame = nsnull;
       return rv;
     }
 
     aNewCellInnerFrame->SetInitialChildList(nsnull, childItems.childList);
     aNewCellOuterFrame->SetInitialChildList(nsnull, aNewCellInnerFrame);
-    if (*aHasPseudoParent) {
-      aState.mPseudoFrames.mRow.mChildList.AddChild(aNewCellOuterFrame);
-    }
+    aChildItems.AddChild(aNewCellOuterFrame);
   }
 
   return NS_OK;
 }
 
 static PRBool 
 NeedFrameFor(nsIFrame*   aParentFrame,
              nsIContent* aChildContent) 
@@ -5084,33 +4940,32 @@ nsCSSFrameConstructor::ConstructFrameFro
 
   NS_ASSERTION(!(bits & FCDATA_FUNC_IS_DATA_GETTER),
                "Should have dealt with this inside the data finder");
 
   // Some sets of bits are not compatible with each other
 #define CHECK_ONLY_ONE_BIT(_bit1, _bit2)               \
   NS_ASSERTION(!(bits & _bit1) || !(bits & _bit2),     \
                "Only one of these bits should be set")
-  CHECK_ONLY_ONE_BIT(FCDATA_SKIP_FRAMEMAP, FCDATA_MAY_NEED_SCROLLFRAME);
   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_FORCE_NULL_ABSPOS_CONTAINER);
 #ifdef MOZ_MATHML
   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_WRAP_KIDS_IN_BLOCKS);
 #endif
   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_MAY_NEED_SCROLLFRAME);
   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_IS_POPUP);
   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 this is not a table part.
-  if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty() &&
-      !(bits & FCDATA_IS_TABLE_PART)) {
+  // 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) {
@@ -5187,22 +5042,21 @@ 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.  Don't allow block styles; anything that's a
-    // special HTML or MathML or XUL frame but wants those should do its own
-    // ProcessChildren.
+    // Process the child frames.
     rv = ProcessChildren(aState, content, styleContext, newFrame,
                          !(bits & FCDATA_DISALLOW_GENERATED_CONTENT),
-                         childItems, PR_FALSE);
+                         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);
@@ -5740,17 +5594,18 @@ nsCSSFrameConstructor::BuildScrollFrame(
     // now set the primary frame to the ScrollFrame
     aState.mFrameManager->SetPrimaryFrameFor( aContent, aNewFrame );
     return NS_OK;
 
 }
 
 const nsCSSFrameConstructor::FrameConstructionData*
 nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay* aDisplay,
-                                       nsIContent* aContent)
+                                       nsIContent* aContent,
+                                       nsStyleContext* aStyleContext)
 {
   // 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");
 
@@ -5784,42 +5639,66 @@ nsCSSFrameConstructor::FindDisplayData(c
   if (aDisplay->IsBlockInside() ||
       NS_STYLE_DISPLAY_RUN_IN == aDisplay->mDisplay ||
       NS_STYLE_DISPLAY_COMPACT == aDisplay->mDisplay) {  
     static const FrameConstructionData sNonScrollableBlockData =
       FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructNonScrollableBlock);
     return &sNonScrollableBlockData;
   }
 
-  // Handle various inlines
-  if (NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay ||
-      NS_STYLE_DISPLAY_MARKER == aDisplay->mDisplay) {
+  static const FrameConstructionDataByInt sDisplayData[] = {
     // To keep the hash table small don't add inline frames (they're
     // typically things like FONT and B), because we can quickly
     // find them if we need to.
     // XXXbz the "quickly" part is a bald-faced lie!
-    static const FrameConstructionData sInlineData =
+    { 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);
-    return &sInlineData;
-  }
-
-  if (NS_STYLE_DISPLAY_TABLE == aDisplay->mDisplay ||
-      NS_STYLE_DISPLAY_INLINE_TABLE == aDisplay->mDisplay) {
-    static const FrameConstructionData sTableData =
-      FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructTable);
-    return &sTableData;
-  }
-
-  static const FrameConstructionData sTablePartData =
-    FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP,
-                     &nsCSSFrameConstructor::ConstructTablePart);
-  return &sTablePartData;
-  
+                       &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_CAPTION,
+      FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
+                  FCDATA_ALLOW_BLOCK_STYLES | FCDATA_DISALLOW_OUT_OF_FLOW,
+                  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,
+                  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,
+                  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,
+                  NS_NewTableRowGroupFrame) },
+    { NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP,
+      FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
+                  FCDATA_DISALLOW_OUT_OF_FLOW,
+                  NS_NewTableColGroupFrame) },
+    { NS_STYLE_DISPLAY_TABLE_COLUMN,
+      FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP,
+                       &nsCSSFrameConstructor::ConstructTableCol) },
+    { NS_STYLE_DISPLAY_TABLE_ROW,
+      FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP,
+                       &nsCSSFrameConstructor::ConstructTableRow) },
+    { NS_STYLE_DISPLAY_TABLE_CELL,
+      FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP,
+                       &nsCSSFrameConstructor::ConstructTableCell) }
+  };
+
+  return FindDataByInt(aDisplay->mDisplay, aContent, aStyleContext,
+                       sDisplayData, NS_ARRAY_LENGTH(sDisplayData));
 }
 
 nsresult
 nsCSSFrameConstructor::ConstructScrollableBlock(nsFrameConstructorState& aState,
                                                 FrameConstructionItem&   aItem,
                                                 nsIFrame*                aParentFrame,
                                                 const nsStyleDisplay*    aDisplay,
                                                 nsFrameItems&            aFrameItems,
@@ -5898,90 +5777,46 @@ nsCSSFrameConstructor::ConstructTable(ns
   
   nsIFrame* innerTable;
   return ConstructTableFrame(aState, aItem.mContent, aParentFrame,
                              aItem.mStyleContext, aItem.mNameSpaceID,
                              PR_FALSE, aFrameItems, *aNewFrame, innerTable);
 }
 
 nsresult
-nsCSSFrameConstructor::ConstructTablePart(nsFrameConstructorState& aState,
+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)
 {
-  nsIContent* const content = aItem.mContent;
-  nsStyleContext* const styleContext = aItem.mStyleContext;
-  PRInt32 namespaceID = aItem.mNameSpaceID;
-
-  nsresult  rv = NS_ERROR_UNEXPECTED;
-  PRBool hasPseudoParent;
-
-  // Use the 'display' property to choose a frame type
-  switch (aDisplay->mDisplay) {
-  case NS_STYLE_DISPLAY_TABLE_CAPTION:
-  {
-    // aParentFrame may be an inner table frame rather than an outer frame 
-    // In this case we need to get the outer frame.
-    nsIFrame* parentFrame = AdjustCaptionParentFrame(aParentFrame);
-    rv = ConstructTableCaptionFrame(aState, content, parentFrame,
-                                    styleContext, namespaceID, aFrameItems,
-                                    *aNewFrame, &hasPseudoParent);
-    break;
-  }
-
-  case NS_STYLE_DISPLAY_TABLE_ROW_GROUP:
-  case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP:
-  case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP:
-    rv = ConstructTableRowGroupFrame(aState, content, aParentFrame,
-                                     styleContext, namespaceID, PR_FALSE,
-                                     aFrameItems, *aNewFrame, &hasPseudoParent);
-    break;
-
-  case NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP:
-    rv = ConstructTableColGroupFrame(aState, content, aParentFrame,
-                                     styleContext, namespaceID,
-                                     PR_FALSE, aFrameItems, *aNewFrame,
-                                     &hasPseudoParent);
-    break;
-   
-  case NS_STYLE_DISPLAY_TABLE_COLUMN:
-    rv = ConstructTableColFrame(aState, content, aParentFrame,
-                                styleContext, namespaceID, PR_FALSE,
-                                aFrameItems, *aNewFrame, &hasPseudoParent);
-    break;
-
-  case NS_STYLE_DISPLAY_TABLE_ROW:
-    rv = ConstructTableRowFrame(aState, content, aParentFrame,
-                                styleContext, namespaceID, PR_FALSE,
-                                aFrameItems, *aNewFrame, &hasPseudoParent);
-    break;
-  
-  case NS_STYLE_DISPLAY_TABLE_CELL:
-  {
-    nsIFrame* innerTable;
-    rv = ConstructTableCellFrame(aState, content, aParentFrame,
-                                 styleContext, namespaceID,
+  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,
-                                 innerTable, &hasPseudoParent);
-    break;
-  }
-  
-  default:
-    NS_NOTREACHED("How did we get here?");
-    break;
-  }
-
-  if (NS_SUCCEEDED(rv) && !hasPseudoParent) {
-    aFrameItems.AddChild(*aNewFrame);
-  }
-
-  return rv;
+                                 innerTableCell);
 }
 
 nsresult 
 nsCSSFrameConstructor::InitAndRestoreFrame(const nsFrameConstructorState& aState,
                                            nsIContent*              aContent,
                                            nsIFrame*                aParentFrame,
                                            nsIFrame*                aPrevInFlow,
                                            nsIFrame*                aNewFrame,
@@ -6589,17 +6424,17 @@ nsCSSFrameConstructor::AddFrameConstruct
 
     // Now check for XUL display types
     if (!data) {
       data = FindXULDisplayData(display, aContent, styleContext);
     }
 
     // And general display types
     if (!data) {
-      data = FindDisplayData(display, aContent);
+      data = FindDisplayData(display, aContent, styleContext);
     }
 
     NS_ASSERTION(data, "Should have frame construction data now");
 
     if (data->mBits & FCDATA_SUPPRESS_FRAME) {
       return;
     }
 
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -410,28 +410,17 @@ private:
    * callback used for the job.
    */
   nsresult ConstructTable(nsFrameConstructorState& aState,
                           FrameConstructionItem&   aItem,
                           nsIFrame*                aParentFrame,
                           const nsStyleDisplay*    aDisplay,
                           nsFrameItems&            aFrameItems,
                           nsIFrame**               aNewFrame);
-  
-  /**
-   * Construct some part of a table other than the outer table frame.  This is
-   * the FrameConstructionData callback used for the job.
-   */
-  nsresult ConstructTablePart(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).
@@ -441,75 +430,70 @@ private:
                                nsIFrame*                aContentParent,
                                nsStyleContext*          aStyleContext,
                                PRInt32                  aNameSpaceID,
                                PRBool                   aIsPseudo,
                                nsFrameItems&            aChildItems,
                                nsIFrame*&               aNewOuterFrame,
                                nsIFrame*&               aNewInnerFrame);
 
-  nsresult ConstructTableCaptionFrame(nsFrameConstructorState& aState,
-                                      nsIContent*              aContent,
-                                      nsIFrame*                aParent,
-                                      nsStyleContext*          aStyleContext,
-                                      PRInt32                  aNameSpaceID,
-                                      nsFrameItems&            aChildItems,
-                                      nsIFrame*&               aNewFrame,
-                                      PRBool*                  aHasPseudoParent);
+  /**
+   * FrameConstructionData callback used for constructing table rows.
+   */
+  nsresult ConstructTableRow(nsFrameConstructorState& aState,
+                             FrameConstructionItem&   aItem,
+                             nsIFrame*                aParentFrame,
+                             const nsStyleDisplay*    aStyleDisplay,
+                             nsFrameItems&            aFrameItems,
+                             nsIFrame**               aNewFrame);
 
-  nsresult ConstructTableRowGroupFrame(nsFrameConstructorState& aState,
-                                       nsIContent*              aContent,
-                                       nsIFrame*                aParent,
-                                       nsStyleContext*          aStyleContext,
-                                       PRInt32                  aNameSpaceID,
-                                       PRBool                   aIsPseudo,
-                                       nsFrameItems&            aChildItems,
-                                       nsIFrame*&               aNewFrame,
-                                       PRBool*                  aHasPseudoParent);
-
-  nsresult ConstructTableColGroupFrame(nsFrameConstructorState& aState,
-                                       nsIContent*              aContent,
-                                       nsIFrame*                aParent,
-                                       nsStyleContext*          aStyleContext,
-                                       PRInt32                  aNameSpaceID,
-                                       PRBool                   aIsPseudo,
-                                       nsFrameItems&            aChildItems,
-                                       nsIFrame*&               aNewFrame,
-                                       PRBool*                  aHasPseudoParent);
-
+  /**
+   * 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,
-                                  PRBool*                  aHasPseudoParent);
+                                  nsIFrame*&               aNewFrame);
+
+  /**
+   * FrameConstructionData callback used for constructing table columns.
+   */
+  nsresult ConstructTableCol(nsFrameConstructorState& aState,
+                             FrameConstructionItem&   aItem,
+                             nsIFrame*                aParentFrame,
+                             const nsStyleDisplay*    aStyleDisplay,
+                             nsFrameItems&            aFrameItems,
+                             nsIFrame**               aNewFrame);
 
-  nsresult ConstructTableColFrame(nsFrameConstructorState& aState,
-                                  nsIContent*              aContent,
-                                  nsIFrame*                aParent,
-                                  nsStyleContext*          aStyleContext,
-                                  PRInt32                  aNameSpaceID,
-                                  PRBool                   aIsPseudo,
-                                  nsFrameItems&            aChildItems,
-                                  nsIFrame*&               aNewFrame,
-                                  PRBool*                  aHasPseudoParent);
+  /**
+   * FrameConstructionData callback used for constructing table cells.
+   */
+  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,
-                                   PRBool*                  aHasPseudoParent);
+                                   nsIFrame*&               aNewCellInnerFrame);
 
   nsresult CreatePseudoTableFrame(PRInt32                  aNameSpaceID,
                                   nsFrameConstructorState& aState, 
                                   nsIFrame*                aParentFrameIn = nsnull);
 
   nsresult CreatePseudoRowGroupFrame(PRInt32                  aNameSpaceID,
                                      nsFrameConstructorState& aState, 
                                      nsIFrame*                aParentFrameIn = nsnull);
@@ -598,19 +582,19 @@ private:
                                                     nsIFrame* aParentFrame,
                                                     const nsStyleDisplay* aStyleDisplay,
                                                     nsFrameItems& aFrameItems,
                                                     nsIFrame** aFrame);
 
   /* Bits that modify the way a FrameConstructionData is handled */
 
   /* If the FCDATA_SKIP_FRAMEMAP bit is set, then the frame created should not
-     be added to the primary frame map.  This flag should not be used with
-     FCDATA_MAY_NEED_SCROLLFRAME, since scrollframe construction will add to
-     the frame map. */
+     be added to the primary frame map.  This flag might get ignored when used
+     with FCDATA_MAY_NEED_SCROLLFRAME, since scrollframe construction will add
+     to the frame map. */
 #define FCDATA_SKIP_FRAMEMAP 0x1
   /* If the FCDATA_FUNC_IS_DATA_GETTER bit is set, then the mFunc of the
      FrameConstructionData is a getter function that can be used to get the
      actual FrameConstructionData to use. */
 #define FCDATA_FUNC_IS_DATA_GETTER 0x2
   /* If the FCDATA_FUNC_IS_FULL_CTOR bit is set, then the FrameConstructionData
      has an mFullConstructor.  In this case, there is no relevant mData or
      mFunc */
@@ -631,19 +615,19 @@ private:
      moment. */
 #define FCDATA_WRAP_KIDS_IN_BLOCKS 0x20
 #endif /* MOZ_MATHML */
   /* If FCDATA_SUPPRESS_FRAME is set, no frame should be created for the
      content.  If this bit is set, nothing else in the struct needs to be
      set. */
 #define FCDATA_SUPPRESS_FRAME 0x40
   /* If FCDATA_MAY_NEED_SCROLLFRAME is set, the new frame should be wrapped in
-     a scrollframe if its overflow type so requires.  This flag should not be
-     used with FCDATA_SKIP_FRAMEMAP, since scrollframe construction will add to
-     the frame map. */
+     a scrollframe if its overflow type so requires.  This flag might override
+     FCDATA_SKIP_FRAMEMAP, since scrollframe construction will add to the frame
+     map. */
 #define FCDATA_MAY_NEED_SCROLLFRAME 0x80
 #ifdef MOZ_XUL
   /* If FCDATA_IS_POPUP is set, the new frame is a XUL popup frame.  These need
      some really weird special handling.  */
 #define FCDATA_IS_POPUP 0x100
 #endif /* MOZ_XUL */
   /* If FCDATA_SKIP_ABSPOS_PUSH is set, don't push this frame as an
      absolute containing block, no matter what its style says. */
@@ -662,16 +646,19 @@ private:
      for it if it's inside another table-related frame. */
 #define FCDATA_IS_TABLE_PART 0x1000
   /* If FCDATA_IS_INLINE is set, then the frame is a non-replaced CSS
      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
 
   /* 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
@@ -1113,17 +1100,18 @@ private:
                                           const nsStyleDisplay* aStyleDisplay,
                                           nsFrameItems& aFrameItems,
                                           nsIFrame** aNewFrame);
 #endif
 
   /* Not static because it does PropagateScrollToViewport.  If this
      changes, make this static */
   const FrameConstructionData*
-    FindDisplayData(const nsStyleDisplay* aDisplay, nsIContent* aContent);
+    FindDisplayData(const nsStyleDisplay* aDisplay, nsIContent* aContent,
+                    nsStyleContext* aStyleContext);
 
   /**
    * Construct a scrollable block frame
    */
   nsresult ConstructScrollableBlock(nsFrameConstructorState& aState,
                                     FrameConstructionItem&   aItem,
                                     nsIFrame*                aParentFrame,
                                     const nsStyleDisplay*    aDisplay,