Bug 478820 part 3. Switch ConstructFrameByDisplayType to FrameConstructionData. r+sr=roc
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 18 Feb 2009 08:25:29 -0500
changeset 25131 2d2a34c4233d3760661798a0eb0c2c4dc01883e5
parent 25130 b89f860e0ee34d3f7cfc804846b4c18af4ed8ae4
child 25132 fad4b32df3745b3fb3eac9c1b888df12e452c477
push idunknown
push userunknown
push dateunknown
bugs478820
milestone1.9.2a1pre
Bug 478820 part 3. Switch ConstructFrameByDisplayType to FrameConstructionData. r+sr=roc
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSFrameConstructor.h
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -3090,45 +3090,44 @@ nsCSSFrameConstructor::AdjustParentFrame
                                          const nsStyleDisplay*        aDisplay,
                                          nsFrameItems* &              aFrameItems,
                                          nsFrameConstructorSaveState& aSaveState,
                                          PRBool&                      aSuppressFrame,
                                          PRBool&                      aCreatedPseudo)
 {
   NS_PRECONDITION(aDisplay, "Must have child's style context");
   NS_PRECONDITION(aFrameItems, "Must have frame items to work with");
+  NS_PRECONDITION(aFCData, "Must have frame construction data");
 
   aSuppressFrame = PR_FALSE;
   aCreatedPseudo = PR_FALSE;
   if (!aParentFrame) {
     // Nothing to do here
     return NS_OK;
   }
 
+  PRBool tablePart = ((aFCData->mBits & FCDATA_IS_TABLE_PART) != 0);
+
   // Only use the outer table frame as parent if the child is going to use a
   // tableCaptionFrame, otherwise the inner table frame is the parent
   // (bug 341858).
   nsIAtom* parentType = aParentFrame->GetType();
   NS_ASSERTION(parentType != nsGkAtoms::tableOuterFrame,
                "Shouldn't be happening");
   if (parentType == nsGkAtoms::tableColGroupFrame) {
-    if (aFCData || aDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_COLUMN) {
+    if (!tablePart || aDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_COLUMN) {
       aSuppressFrame = PR_TRUE;
       return NS_OK;
     }
   }
  
   // 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(aParentFrame->GetType(), PR_FALSE) &&
-      (!IsTableRelated(aDisplay->mDisplay) ||
-       // Also need to create a pseudo-parent if the child is going to end up
-       // with a frame based on something other than display.
-       aFCData)) {
+  if (IsTableRelated(aParentFrame->GetType(), 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;
 
@@ -4368,16 +4367,17 @@ nsCSSFrameConstructor::CreatePlaceholder
   }
 }
 
 nsresult
 nsCSSFrameConstructor::ConstructButtonFrame(nsFrameConstructorState& aState,
                                             nsIContent*              aContent,
                                             nsIFrame*                aParentFrame,
                                             nsIAtom*                 aTag,
+                                            PRInt32                  aNameSpaceID,
                                             nsStyleContext*          aStyleContext,
                                             const nsStyleDisplay*    aStyleDisplay,
                                             nsFrameItems&            aFrameItems,
                                             nsIFrame**               aNewFrame)
 {
   *aNewFrame = nsnull;
   nsIFrame* buttonFrame = nsnull;
   
@@ -4487,16 +4487,17 @@ nsCSSFrameConstructor::ConstructButtonFr
   return NS_OK;  
 }
 
 nsresult
 nsCSSFrameConstructor::ConstructSelectFrame(nsFrameConstructorState& aState,
                                             nsIContent*              aContent,
                                             nsIFrame*                aParentFrame,
                                             nsIAtom*                 aTag,
+                                            PRInt32                  aNameSpaceID,
                                             nsStyleContext*          aStyleContext,
                                             const nsStyleDisplay*    aStyleDisplay,
                                             nsFrameItems&            aFrameItems,
                                             nsIFrame**               aNewFrame)
 {
   nsresult rv = NS_OK;
   const PRInt32 kNoSizeSpecified = -1;
 
@@ -4711,16 +4712,17 @@ nsCSSFrameConstructor::InitializeSelectF
   return NS_OK;
 }
 
 nsresult
 nsCSSFrameConstructor::ConstructFieldSetFrame(nsFrameConstructorState& aState,
                                               nsIContent*              aContent,
                                               nsIFrame*                aParentFrame,
                                               nsIAtom*                 aTag,
+                                              PRInt32                  aNameSpaceID,
                                               nsStyleContext*          aStyleContext,
                                               const nsStyleDisplay*    aStyleDisplay,
                                               nsFrameItems&            aFrameItems,
                                               nsIFrame**               aNewFrame)
 {
   nsIFrame* newFrame = NS_NewFieldSetFrame(mPresShell, aStyleContext);
   if (NS_UNLIKELY(!newFrame)) {
     return NS_ERROR_OUT_OF_MEMORY;
@@ -4815,16 +4817,18 @@ FindAncestorWithGeneratedContentPseudo(n
       return f;
   }
   return nsnull;
 }
 
 #define FCDATA_DECL(_flags, _func) \
   { _flags, { (FrameCreationFunc)_func } }
 #define SIMPLE_FCDATA(_func) FCDATA_DECL(0, _func)
+#define FULL_CTOR_FCDATA(_flags, _func)                     \
+  { _flags | FCDATA_FUNC_IS_FULL_CTOR, { nsnull }, _func }
 
 /* static */
 const nsCSSFrameConstructor::FrameConstructionData*
 nsCSSFrameConstructor::FindTextData(nsIFrame* aParentFrame)
 {
 #ifdef MOZ_SVG
   if (aParentFrame->IsFrameOfType(nsIFrame::eSVG)) {
     nsIFrame *ancestorFrame =
@@ -4849,20 +4853,17 @@ nsresult
 nsCSSFrameConstructor::ConstructTextFrame(const FrameConstructionData* aData,
                                           nsFrameConstructorState& aState,
                                           nsIContent*              aContent,
                                           nsIFrame*                aParentFrame,
                                           nsStyleContext*          aStyleContext,
                                           nsFrameItems&            aFrameItems,
                                           PRBool                   aPseudoParent)
 {
-  if (!aData) {
-    // Nothing to do here: suppressed text inside SVG, say
-    return NS_OK;
-  }
+  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);
 
@@ -4951,25 +4952,25 @@ nsCSSFrameConstructor::FindDataByTag(nsI
 
   return nsnull;
 }
 
 #define SUPPRESS_FCDATA() FCDATA_DECL(FCDATA_SUPPRESS_FRAME, nsnull)
 #define SIMPLE_INT_CREATE(_int, _func) { _int, SIMPLE_FCDATA(_func) }
 #define SIMPLE_INT_CHAIN(_int, _func)                       \
   { _int, FCDATA_DECL(FCDATA_FUNC_IS_DATA_GETTER, _func) }
-#define COMPLEX_INT_CREATE(_int, _func)                     \
-  { _int, { FCDATA_FUNC_IS_FULL_CTOR, { nsnull }, _func } }
+#define COMPLEX_INT_CREATE(_int, _func)         \
+  { _int, FULL_CTOR_FCDATA(0, _func) }
 
 #define SIMPLE_TAG_CREATE(_tag, _func)          \
   { &nsGkAtoms::_tag, SIMPLE_FCDATA(_func) }
 #define SIMPLE_TAG_CHAIN(_tag, _func)                                   \
   { &nsGkAtoms::_tag, FCDATA_DECL(FCDATA_FUNC_IS_DATA_GETTER,  _func) }
-#define COMPLEX_TAG_CREATE(_tag, _func)                                 \
-  { &nsGkAtoms::_tag, { FCDATA_FUNC_IS_FULL_CTOR, { nsnull }, _func } }
+#define COMPLEX_TAG_CREATE(_tag, _func)             \
+  { &nsGkAtoms::_tag, FULL_CTOR_FCDATA(0, _func) }
 
 /* static */
 const nsCSSFrameConstructor::FrameConstructionData*
 nsCSSFrameConstructor::FindHTMLData(nsIContent* aContent,
                                     nsIAtom* aTag,
                                     PRInt32 aNameSpaceID,
                                     nsIFrame* aParentFrame,
                                     nsStyleContext* aStyleContext)
@@ -5159,30 +5160,30 @@ nsCSSFrameConstructor::ConstructFrameFro
   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_MAY_NEED_SCROLLFRAME, FCDATA_FORCE_VIEW);
 #undef CHECK_ONLY_ONE_BIT
 
-  // We found something, so not creating by display type.  Process
-  // pseudo-frames now.
-  if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
+  // Process pseudo-frames now if this is not a table part.
+  if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty() &&
+      !(bits & FCDATA_IS_TABLE_PART)) {
     ProcessPseudoFrames(aState, aFrameItems); 
   }
 
   const nsStyleDisplay* display = aStyleContext->GetStyleDisplay();
 
   nsIFrame* newFrame;
   if (bits & FCDATA_FUNC_IS_FULL_CTOR) {
     nsresult rv =
       (this->*(aData->mFullConstructor))(aState, aContent, aParentFrame,
-                                         aTag, aStyleContext, display,
-                                         aFrameItems, &newFrame);
+                                         aTag, aNameSpaceID, aStyleContext,
+                                         display, aFrameItems, &newFrame);
     if (NS_FAILED(rv)) {
       return rv;
     }
   } else {
     newFrame =
       (*aData->mFunc.mCreationFunc)(mPresShell, aStyleContext);
     if (!newFrame) {
       return NS_ERROR_OUT_OF_MEMORY;
@@ -5698,17 +5699,16 @@ already_AddRefed<nsStyleContext>
 nsCSSFrameConstructor::BeginBuildingScrollFrame(nsFrameConstructorState& aState,
                                                 nsIContent*              aContent,
                                                 nsStyleContext*          aContentStyle,
                                                 nsIFrame*                aParentFrame,
                                                 nsIAtom*                 aScrolledPseudo,
                                                 PRBool                   aIsRoot,
                                                 nsIFrame*&               aNewFrame)
 {
-  nsIFrame* parentFrame = nsnull;
   nsIFrame* gfxScrollFrame = aNewFrame;
 
   nsFrameItems anonymousItems;
 
   nsRefPtr<nsStyleContext> contentStyle = aContentStyle;
 
   if (!gfxScrollFrame) {
     // Build a XULScrollFrame when the child is a box, otherwise an
@@ -5726,17 +5726,16 @@ nsCSSFrameConstructor::BeginBuildingScro
     // Create a view
     nsHTMLContainerFrame::CreateViewForFrame(gfxScrollFrame, PR_FALSE);
   }
 
   // if there are any anonymous children for the scroll frame, create
   // frames for them.
   CreateAnonymousFrames(aState, aContent, gfxScrollFrame, anonymousItems);
 
-  parentFrame = gfxScrollFrame;
   aNewFrame = gfxScrollFrame;
 
   // we used the style that was passed in. So resolve another one.
   nsStyleSet *styleSet = mPresShell->StyleSet();
   nsStyleContext* aScrolledChildStyle = styleSet->ResolvePseudoStyleFor(aContent,
                                                                         aScrolledPseudo,
                                                                         contentStyle).get();
 
@@ -5815,244 +5814,252 @@ nsCSSFrameConstructor::BuildScrollFrame(
     FinishBuildingScrollFrame(aNewFrame, aScrolledFrame);
 
     // now set the primary frame to the ScrollFrame
     aState.mFrameManager->SetPrimaryFrameFor( aContent, aNewFrame );
     return NS_OK;
 
 }
 
-nsresult
-nsCSSFrameConstructor::ConstructFrameByDisplayType(nsFrameConstructorState& aState,
-                                                   const nsStyleDisplay*    aDisplay,
-                                                   nsIContent*              aContent,
-                                                   PRInt32                  aNameSpaceID,
-                                                   nsIAtom*                 aTag,
-                                                   nsIFrame*                aParentFrame,
-                                                   nsStyleContext*          aStyleContext,
-                                                   nsFrameItems&            aFrameItems,
-                                                   PRBool                   aHasPseudoParent)
-{
-  nsIFrame* newFrame = nsnull;  // the frame we construct
-  PRBool    addToHashTable = PR_TRUE;
-  PRBool    addedToFrameList = PR_FALSE;
-  nsresult  rv = NS_OK;
-
+const nsCSSFrameConstructor::FrameConstructionData*
+nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay* aDisplay,
+                                       nsIContent* aContent)
+{
   // 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
   // Note that we need to do this even if the body is NOT scrollable;
   // it might have dynamically changed from scrollable to not scrollable,
   // and that might need to be propagated.
+  // XXXbz is this the right place to do this?  If this code moves,
+  // make this function static.
   PRBool propagatedScrollToViewport = PR_FALSE;
   if (aContent->NodeInfo()->Equals(nsGkAtoms::body) &&
       aContent->IsNodeOfType(nsINode::eHTML)) {
     propagatedScrollToViewport =
       PropagateScrollToViewport() == aContent;
   }
 
   // If the frame is a block-level frame and is scrollable, then wrap it
   // in a scroll frame.
   // XXX Ignore tables for the time being
   // XXXbz it would be nice to combine this with the other block
   // case... Think about how do do this?
   if (aDisplay->IsBlockInside() &&
       aDisplay->IsScrollableOverflow() &&
       !propagatedScrollToViewport) {
-
-    if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
-      ProcessPseudoFrames(aState, aFrameItems); 
-    }
-
-    nsRefPtr<nsStyleContext> scrolledContentStyle
-      = BeginBuildingScrollFrame(aState, aContent, aStyleContext,
-                                 aState.GetGeometricParent(aDisplay, aParentFrame),
-                                 nsCSSAnonBoxes::scrolledContent,
-                                 PR_FALSE, newFrame);
-    
-    // Initialize it
-    // pass a temporary stylecontext, the correct one will be set later
-    nsIFrame* scrolledFrame =
-      NS_NewBlockFormattingContext(mPresShell, aStyleContext);
-
-    nsFrameItems blockItem;
-    rv = ConstructBlock(aState,
-                        scrolledContentStyle->GetStyleDisplay(), aContent,
-                        newFrame, newFrame, scrolledContentStyle,
-                        &scrolledFrame, blockItem, aDisplay->IsPositioned());
-    NS_ASSERTION(blockItem.childList == scrolledFrame,
-                 "Scrollframe's frameItems should be exactly the scrolled frame");
-    FinishBuildingScrollFrame(newFrame, scrolledFrame);
-
-    rv = aState.AddChild(newFrame, aFrameItems, aContent, aStyleContext,
-                         aParentFrame);
-    addedToFrameList = PR_TRUE;
-  }
+    static const FrameConstructionData sScrollableBlockData =
+      FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructScrollableBlock);
+    return &sScrollableBlockData;
+  }
+
   // Handle various non-scrollable blocks
-  else if (aDisplay->IsBlockInside() ||
-           NS_STYLE_DISPLAY_RUN_IN == aDisplay->mDisplay ||
-           NS_STYLE_DISPLAY_COMPACT == aDisplay->mDisplay) {
-
-    if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
-      ProcessPseudoFrames(aState, aFrameItems); 
-    }
-
-    if (aDisplay->IsAbsolutelyPositioned() ||
-        aDisplay->IsFloating() ||
-        NS_STYLE_DISPLAY_INLINE_BLOCK == aDisplay->mDisplay) {
-      newFrame = NS_NewBlockFormattingContext(mPresShell, aStyleContext);
-    } else {
-      newFrame = NS_NewBlockFrame(mPresShell, aStyleContext);
-    }
-
-    rv = ConstructBlock(aState, aDisplay, aContent,
-                        aState.GetGeometricParent(aDisplay, aParentFrame),
-                        aParentFrame, aStyleContext, &newFrame,
-                        aFrameItems, aDisplay->IsPositioned());
-    addedToFrameList = PR_TRUE;
-  }
+  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
-  else if (NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay ||
-           NS_STYLE_DISPLAY_MARKER == aDisplay->mDisplay) {
-    if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
-      ProcessPseudoFrames(aState, aFrameItems); 
-    }
-
-    PRBool positioned =
-      NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay &&
-      (NS_STYLE_POSITION_RELATIVE == aDisplay->mPosition ||
-       aDisplay->HasTransform());
-    if (positioned) {
-      newFrame = NS_NewPositionedInlineFrame(mPresShell, aStyleContext);
-    } else {
-      newFrame = NS_NewInlineFrame(mPresShell, aStyleContext);
-    }
-
-    rv = ConstructInline(aState, aDisplay, aContent, aParentFrame,
-                         aStyleContext, positioned, newFrame);
-
+  if (NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay ||
+      NS_STYLE_DISPLAY_MARKER == aDisplay->mDisplay) {
     // 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!
-    addToHashTable = PR_FALSE;
-  }
-  // otherwise let the display property influence the frame type to create
-  else {
-    // XXX This section now only handles table frames; should be
-    // factored out probably
-
-    PRBool hasPseudoParent;
-    // Use the 'display' property to choose a frame type
-    switch (aDisplay->mDisplay) {
-    case NS_STYLE_DISPLAY_TABLE:
-    case NS_STYLE_DISPLAY_INLINE_TABLE:
-    {
-      nsIFrame* innerTable;
-      rv = ConstructTableFrame(aState, aContent, 
-                               aParentFrame, aStyleContext,
-                               aNameSpaceID, PR_FALSE, aFrameItems, newFrame,
-                               innerTable);
-      addedToFrameList = PR_TRUE;
-      // Note: table construction function takes care of initializing
-      // the frame, processing children, and setting the initial child
-      // list
-      break;
-    }
-  
-    // the next 5 cases are only relevant if the parent is not a table, ConstructTableFrame handles children
-    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, aContent, parentFrame,
-                                      aStyleContext, aNameSpaceID, aFrameItems,
-                                      newFrame, &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, aContent, aParentFrame,
-                                       aStyleContext, aNameSpaceID, PR_FALSE,
-                                       aFrameItems, newFrame,
-                                       &hasPseudoParent);
-      break;
-
-    case NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP:
-      rv = ConstructTableColGroupFrame(aState, aContent, aParentFrame,
-                                       aStyleContext, aNameSpaceID,
-                                       PR_FALSE, aFrameItems, newFrame,
-                                       &hasPseudoParent);
-      break;
+    static const FrameConstructionData sInlineData =
+      FULL_CTOR_FCDATA(FCDATA_SKIP_FRAMEMAP,
+                       &nsCSSFrameConstructor::ConstructInline);
+    return &sInlineData;
+  }
+
+  NS_ASSERTION(IsTableRelated(aDisplay->mDisplay), "Unexpected display type");
+
+  if (NS_STYLE_DISPLAY_TABLE == aDisplay->mDisplay ||
+      NS_STYLE_DISPLAY_INLINE_TABLE == aDisplay->mDisplay) {
+    static const FrameConstructionData sTableData =
+      FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART,
+                       &nsCSSFrameConstructor::ConstructTable);
+    return &sTableData;
+  }
+
+  static const FrameConstructionData sTablePartData =
+    FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP,
+                     &nsCSSFrameConstructor::ConstructTablePart);
+  return &sTablePartData;
+  
+}
+
+nsresult
+nsCSSFrameConstructor::ConstructScrollableBlock(nsFrameConstructorState& aState,
+                                                nsIContent*              aContent,
+                                                nsIFrame*                aParentFrame,
+                                                nsIAtom*                 aTag,
+                                                PRInt32                  aNameSpaceID,
+                                                nsStyleContext*          aStyleContext,
+                                                const nsStyleDisplay*    aDisplay,
+                                                nsFrameItems&            aFrameItems,
+                                                nsIFrame**               aNewFrame)
+{
+  *aNewFrame = nsnull;
+  nsRefPtr<nsStyleContext> scrolledContentStyle
+    = BeginBuildingScrollFrame(aState, aContent, aStyleContext,
+                               aState.GetGeometricParent(aDisplay, aParentFrame),
+                               nsCSSAnonBoxes::scrolledContent,
+                               PR_FALSE, *aNewFrame);
+
+  // Create our block frame
+  // pass a temporary stylecontext, the correct one will be set later
+  nsIFrame* scrolledFrame =
+    NS_NewBlockFormattingContext(mPresShell, aStyleContext);
+
+  nsFrameItems blockItem;
+  nsresult rv = ConstructBlock(aState,
+                               scrolledContentStyle->GetStyleDisplay(), aContent,
+                               *aNewFrame, *aNewFrame, scrolledContentStyle,
+                               &scrolledFrame, blockItem, aDisplay->IsPositioned());
+  if (NS_UNLIKELY(NS_FAILED(rv))) {
+    // XXXbz any cleanup needed here?
+    return rv;
+  }
+
+  NS_ASSERTION(blockItem.childList == scrolledFrame,
+               "Scrollframe's frameItems should be exactly the scrolled frame");
+  FinishBuildingScrollFrame(*aNewFrame, scrolledFrame);
+
+  rv = aState.AddChild(*aNewFrame, aFrameItems, aContent, aStyleContext,
+                       aParentFrame);
+  return rv;
+}
+
+nsresult
+nsCSSFrameConstructor::ConstructNonScrollableBlock(nsFrameConstructorState& aState,
+                                                   nsIContent*              aContent,
+                                                   nsIFrame*                aParentFrame,
+                                                   nsIAtom*                 aTag,
+                                                   PRInt32                  aNameSpaceID,
+                                                   nsStyleContext*          aStyleContext,
+                                                   const nsStyleDisplay*    aDisplay,
+                                                   nsFrameItems&            aFrameItems,
+                                                   nsIFrame**               aNewFrame)
+{
+  if (aDisplay->IsAbsolutelyPositioned() ||
+      aDisplay->IsFloating() ||
+      NS_STYLE_DISPLAY_INLINE_BLOCK == aDisplay->mDisplay) {
+    *aNewFrame = NS_NewBlockFormattingContext(mPresShell, aStyleContext);
+  } else {
+    *aNewFrame = NS_NewBlockFrame(mPresShell, aStyleContext);
+  }
+
+  return ConstructBlock(aState, aDisplay, aContent,
+                        aState.GetGeometricParent(aDisplay, aParentFrame),
+                        aParentFrame, aStyleContext, aNewFrame,
+                        aFrameItems, aDisplay->IsPositioned());
+}
+
+
+nsresult
+nsCSSFrameConstructor::ConstructTable(nsFrameConstructorState& aState,
+                                      nsIContent*              aContent,
+                                      nsIFrame*                aParentFrame,
+                                      nsIAtom*                 aTag,
+                                      PRInt32                  aNameSpaceID,
+                                      nsStyleContext*          aStyleContext,
+                                      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, aContent, aParentFrame, aStyleContext,
+                             aNameSpaceID, PR_FALSE, aFrameItems, *aNewFrame,
+                             innerTable);
+}
+
+nsresult
+nsCSSFrameConstructor::ConstructTablePart(nsFrameConstructorState& aState,
+                                          nsIContent*              aContent,
+                                          nsIFrame*                aParentFrame,
+                                          nsIAtom*                 aTag,
+                                          PRInt32                  aNameSpaceID,
+                                          nsStyleContext*          aStyleContext,
+                                          const nsStyleDisplay*    aDisplay,
+                                          nsFrameItems&            aFrameItems,
+                                          nsIFrame**               aNewFrame)
+{
+  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, aContent, parentFrame,
+                                    aStyleContext, aNameSpaceID, 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, aContent, aParentFrame,
+                                     aStyleContext, aNameSpaceID, PR_FALSE,
+                                     aFrameItems, *aNewFrame, &hasPseudoParent);
+    break;
+
+  case NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP:
+    rv = ConstructTableColGroupFrame(aState, aContent, aParentFrame,
+                                     aStyleContext, aNameSpaceID,
+                                     PR_FALSE, aFrameItems, *aNewFrame,
+                                     &hasPseudoParent);
+    break;
    
-    case NS_STYLE_DISPLAY_TABLE_COLUMN:
-      rv = ConstructTableColFrame(aState, aContent, aParentFrame,
-                                  aStyleContext, aNameSpaceID, PR_FALSE,
-                                  aFrameItems, newFrame, &hasPseudoParent);
-      break;
-
-    case NS_STYLE_DISPLAY_TABLE_ROW:
-      rv = ConstructTableRowFrame(aState, aContent, aParentFrame,
-                                  aStyleContext, aNameSpaceID, PR_FALSE,
-                                  aFrameItems, newFrame, &hasPseudoParent);
-      break;
-  
-    case NS_STYLE_DISPLAY_TABLE_CELL:
-      {
-        nsIFrame* innerTable;
-        rv = ConstructTableCellFrame(aState, aContent, aParentFrame,
-                                     aStyleContext, aNameSpaceID,
-                                     PR_FALSE, aFrameItems, newFrame,
-                                     innerTable, &hasPseudoParent);
-        break;
-      }
-  
-    default:
-      NS_NOTREACHED("How did we get here?");
-      break;
-    }
-
-    if (!addedToFrameList) { /* Everything except tables */
-      if (NS_SUCCEEDED(rv) && !hasPseudoParent) {
-        aFrameItems.AddChild(newFrame);
-      }
-      return rv;
-    }
-  }
-
-  if (NS_UNLIKELY(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  if (!addedToFrameList) {
-    // Gotta do it here
-    NS_ASSERTION(!aDisplay->IsAbsolutelyPositioned() &&
-                 !aDisplay->IsFloating(),
-                 "Things that could be out-of-flow need to handle adding "
-                 "to the frame list themselves");
-    
-    rv = aState.AddChild(newFrame, aFrameItems, aContent, aStyleContext,
-                         aParentFrame);
-    NS_ASSERTION(NS_SUCCEEDED(rv),
-                 "Cases where AddChild() can fail must handle it themselves");
-  }
-
-  if (newFrame && addToHashTable) {
-    // Add a mapping from content object to primary frame. Note that for
-    // floated and positioned frames this is the out-of-flow frame and not
-    // the placeholder frame
-    aState.mFrameManager->SetPrimaryFrameFor(aContent, newFrame);
+  case NS_STYLE_DISPLAY_TABLE_COLUMN:
+    rv = ConstructTableColFrame(aState, aContent, aParentFrame,
+                                aStyleContext, aNameSpaceID, PR_FALSE,
+                                aFrameItems, *aNewFrame, &hasPseudoParent);
+    break;
+
+  case NS_STYLE_DISPLAY_TABLE_ROW:
+    rv = ConstructTableRowFrame(aState, aContent, aParentFrame,
+                                aStyleContext, aNameSpaceID, PR_FALSE,
+                                aFrameItems, *aNewFrame, &hasPseudoParent);
+    break;
+  
+  case NS_STYLE_DISPLAY_TABLE_CELL:
+  {
+    nsIFrame* innerTable;
+    rv = ConstructTableCellFrame(aState, aContent, aParentFrame,
+                                 aStyleContext, aNameSpaceID,
+                                 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;
 }
 
 nsresult 
 nsCSSFrameConstructor::InitAndRestoreFrame(const nsFrameConstructorState& aState,
                                            nsIContent*              aContent,
@@ -6411,16 +6418,17 @@ nsCSSFrameConstructor::FindSVGData(nsICo
   return data;
 }
 
 nsresult
 nsCSSFrameConstructor::ConstructSVGForeignObjectFrame(nsFrameConstructorState& aState,
                                                       nsIContent* aContent,
                                                       nsIFrame* aParentFrame,
                                                       nsIAtom* aTag,
+                                                      PRInt32 aNameSpaceID,
                                                       nsStyleContext* aStyleContext,
                                                       const nsStyleDisplay* aStyleDisplay,
                                                       nsFrameItems& aFrameItems,
                                                       nsIFrame** aNewFrame)
 {
   nsIFrame* newFrame = NS_NewSVGForeignObjectFrame(mPresShell, aStyleContext);
   if (NS_UNLIKELY(!newFrame)) {
     return NS_ERROR_OUT_OF_MEMORY;
@@ -6645,17 +6653,34 @@ nsCSSFrameConstructor::ConstructFrameInt
     return NS_OK;
   }
 
   PRBool isText = aContent->IsNodeOfType(nsINode::eTEXT);
   // Try to find frame construction data for this content
   const FrameConstructionData* data;
   if (isText) {
     data = FindTextData(aParentFrame);
+#ifdef MOZ_SVG
+    if (!data) {
+      // Nothing to do here; suppressed text inside SVG
+      return NS_OK;
+    }
+#endif /* MOZ_SVG */
   } else {
+#ifdef MOZ_SVG
+    // Don't create frames for non-SVG element children of SVG elements.
+    if (aNameSpaceID != kNameSpaceID_SVG &&
+        aParentFrame &&
+        aParentFrame->IsFrameOfType(nsIFrame::eSVG) &&
+        !aParentFrame->IsFrameOfType(nsIFrame::eSVGForeignObject)
+        ) {
+      return NS_OK;
+    }
+#endif /* MOZ_SVG */
+
     data = FindHTMLData(aContent, aTag, aNameSpaceID, aParentFrame,
                         styleContext);
     if (!data) {
       data = FindXULTagData(aContent, aTag, aNameSpaceID, styleContext);
     }
 #ifdef MOZ_MATHML
     if (!data) {
       data = FindMathMLData(aContent, aTag, aNameSpaceID, styleContext);
@@ -6663,17 +6688,29 @@ nsCSSFrameConstructor::ConstructFrameInt
 #endif
 #ifdef MOZ_SVG
     if (!data) {
       data = FindSVGData(aContent, aTag, aNameSpaceID, aParentFrame,
                          styleContext);
     }
 #endif /* MOZ_SVG */
 
-    if (data && (data->mBits & FCDATA_SUPPRESS_FRAME)) {
+    // Now check for XUL display types
+    if (!data) {
+      data = FindXULDisplayData(display, aContent, aStyleContext);
+    }
+
+    // And general display types
+    if (!data) {
+      data = FindDisplayData(display, aContent);
+    }
+
+    NS_ASSERTION(data, "Should have frame construction data now");
+
+    if (data->mBits & FCDATA_SUPPRESS_FRAME) {
       return NS_OK;
     }
   }
   
   nsIFrame* adjParentFrame = aParentFrame;
   nsFrameItems* frameItems = &aFrameItems;
   PRBool pseudoParent = PR_FALSE;
   PRBool suppressFrame = PR_FALSE;
@@ -6685,66 +6722,43 @@ nsCSSFrameConstructor::ConstructFrameInt
     return rv;
   }
 
   if (isText) {
     return ConstructTextFrame(data, aState, aContent, adjParentFrame,
                               styleContext, *frameItems, pseudoParent);
   }
 
-#ifdef MOZ_SVG
-  // Don't create frames for non-SVG element children of SVG elements
-  if (aNameSpaceID != kNameSpaceID_SVG &&
-      aParentFrame &&
-      aParentFrame->IsFrameOfType(nsIFrame::eSVG) &&
-      !aParentFrame->IsFrameOfType(nsIFrame::eSVGForeignObject)
-      ) {
-    return NS_OK;
-  }
-#endif
-
   // 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.
   {
     if (styleContext->GetStyleVisibility()->mDirection ==
         NS_STYLE_DIRECTION_RTL)
       aState.mPresContext->SetBidiEnabled();
   }
   // Start background loads during frame construction. This is just
   // a hint; the paint code will do the right thing in any case.
   {
     styleContext->GetStyleBackground();
   }
 
-  // Now check for XUL display types
-  if (!data) {
-    data = FindXULDisplayData(display, aContent, aStyleContext);
-  }
-
-  if (data) {
 #ifdef MOZ_XUL
-    if ((data->mBits & FCDATA_IS_POPUP) &&
-        adjParentFrame->GetType() != nsGkAtoms::menuFrame &&
-        !aState.mPopupItems.containingBlock) {
-      return NS_OK;
-    }
+  if ((data->mBits & FCDATA_IS_POPUP) &&
+      adjParentFrame->GetType() != nsGkAtoms::menuFrame &&
+      !aState.mPopupItems.containingBlock) {
+    return NS_OK;
+  }
 #endif /* MOZ_XUL */
 
-    return ConstructFrameFromData(data, aState, aContent, adjParentFrame, aTag,
-                                  aNameSpaceID, styleContext, *frameItems,
-                                  pseudoParent);
-
-  }
-  
-  return ConstructFrameByDisplayType(aState, display, aContent, aNameSpaceID,
-                                     aTag, adjParentFrame, styleContext,
-                                     *frameItems, pseudoParent);
+  return ConstructFrameFromData(data, aState, aContent, adjParentFrame, aTag,
+                                aNameSpaceID, styleContext, *frameItems,
+                                pseudoParent);
 }
 
 
 inline PRBool
 IsRootBoxFrame(nsIFrame *aFrame)
 {
   return (aFrame->GetType() == nsGkAtoms::rootFrame);
 }
@@ -11551,50 +11565,68 @@ AreAllKidsInline(nsIFrame* aFrameList)
     }
     kid = kid->GetNextSibling();
   }
   return PR_TRUE;
 }
 
 nsresult
 nsCSSFrameConstructor::ConstructInline(nsFrameConstructorState& aState,
-                                       const nsStyleDisplay*    aDisplay,
                                        nsIContent*              aContent,
                                        nsIFrame*                aParentFrame,
+                                       nsIAtom*                 aTag,
+                                       PRInt32                  aNameSpaceID,
                                        nsStyleContext*          aStyleContext,
-                                       PRBool                   aIsPositioned,
-                                       nsIFrame*                aNewFrame)
-{
+                                       const nsStyleDisplay*    aDisplay,
+                                       nsFrameItems&            aFrameItems,
+                                       nsIFrame**               aNewFrame)
+{
+  nsIFrame *newFrame;
+
+  PRBool positioned =
+    NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay &&
+    (NS_STYLE_POSITION_RELATIVE == aDisplay->mPosition ||
+     aDisplay->HasTransform());
+  if (positioned) {
+    newFrame = NS_NewPositionedInlineFrame(mPresShell, aStyleContext);
+  } else {
+    newFrame = NS_NewInlineFrame(mPresShell, aStyleContext);
+  }
+
   // Initialize the frame
-  InitAndRestoreFrame(aState, aContent, aParentFrame, nsnull, aNewFrame);
+  InitAndRestoreFrame(aState, aContent, aParentFrame, nsnull, newFrame);
 
   nsFrameConstructorSaveState absoluteSaveState;  // definition cannot be inside next block
                                                   // because the object's destructor is significant
                                                   // this is part of the fix for bug 42372
 
   // Any inline frame might need a view (because of opacity, or fixed background)
-  nsHTMLContainerFrame::CreateViewForFrame(aNewFrame, PR_FALSE);
-
-  if (aIsPositioned) {                            
+  nsHTMLContainerFrame::CreateViewForFrame(newFrame, PR_FALSE);
+
+  if (positioned) {                            
     // Relatively positioned frames becomes a container for child
     // frames that are positioned
-    aState.PushAbsoluteContainingBlock(aNewFrame, absoluteSaveState);
+    aState.PushAbsoluteContainingBlock(newFrame, absoluteSaveState);
   }
 
   // Process the child content
   nsFrameItems childItems;
   PRBool kidsAllInline;
-  nsresult rv = ProcessInlineChildren(aState, aContent, aNewFrame, PR_TRUE,
+  nsresult rv = ProcessInlineChildren(aState, aContent, newFrame, PR_TRUE,
                                       childItems, &kidsAllInline);
   if (kidsAllInline) {
     // Set the inline frame's initial child list
-    CreateAnonymousFrames(aContent->Tag(), aState, aContent, aNewFrame,
+    CreateAnonymousFrames(aContent->Tag(), aState, aContent, newFrame,
                           childItems);
 
-    aNewFrame->SetInitialChildList(nsnull, childItems.childList);
+    newFrame->SetInitialChildList(nsnull, childItems.childList);
+    if (NS_SUCCEEDED(rv)) {
+      aState.AddChild(newFrame, aFrameItems, aContent, aStyleContext, aParentFrame);
+      *aNewFrame = newFrame;
+    }
     return rv;
   }
 
   // This inline frame contains several types of children. Therefore
   // this frame has to be chopped into several pieces. We will produce
   // as a result of this 3 lists of children. The first list contains
   // all of the inline children that precede the first block child
   // (and may be empty). The second list contains all of the block
@@ -11620,25 +11652,25 @@ nsCSSFrameConstructor::ConstructInline(n
   nsIFrame* lastBlock = FindLastBlock(afterFirstBlock);
   if (!lastBlock) {
     lastBlock = list2;
   }
   list3 = lastBlock->GetNextSibling();
   lastBlock->SetNextSibling(nsnull);
 
   // list1's frames belong to this inline frame so go ahead and take them
-  aNewFrame->SetInitialChildList(nsnull, list1);
+  newFrame->SetInitialChildList(nsnull, list1);
                                              
   // list2's frames belong to an anonymous block that we create right
   // now. The anonymous block will be the parent of the block children
   // of the inline.
   nsIAtom* blockStyle;
   nsRefPtr<nsStyleContext> blockSC;
   nsIFrame* blockFrame;
-  if (aIsPositioned) {
+  if (positioned) {
     blockStyle = nsCSSAnonBoxes::mozAnonymousPositionedBlock;
     
     blockSC = mPresShell->StyleSet()->
       ResolvePseudoStyleFor(aContent, blockStyle, aStyleContext);
   }
   else {
     blockStyle = nsCSSAnonBoxes::mozAnonymousBlock;
 
@@ -11647,17 +11679,17 @@ nsCSSFrameConstructor::ConstructInline(n
   }
   blockFrame = NS_NewBlockFrame(mPresShell, blockSC);
 
   InitAndRestoreFrame(aState, aContent, aParentFrame, nsnull, blockFrame, PR_FALSE);  
 
   // Any inline frame could have a view (e.g., opacity)
   nsHTMLContainerFrame::CreateViewForFrame(blockFrame, PR_FALSE);
 
-  if (blockFrame->HasView() || aNewFrame->HasView()) {
+  if (blockFrame->HasView() || newFrame->HasView()) {
     // Move list2's frames into the new view
     nsHTMLContainerFrame::ReparentFrameViewList(aState.mPresContext, list2,
                                                 list2->GetParent(), blockFrame);
   }
 
   blockFrame->SetInitialChildList(nsnull, list2);
 
   nsFrameConstructorState state(mPresShell, mFixedContainingBlock,
@@ -11676,53 +11708,57 @@ nsCSSFrameConstructor::ConstructInline(n
   nsIFrame* inlineFrame = nsnull;
 
   // If we ever start constructing a second inline in the split even when
   // list3 is null, the logic in MaybeRecreateContainerForIBSplitterFrame
   // needs to be adjusted.  Also, if you're changing this code also change
   // AppendFrames().
   if (list3) {
     inlineFrame = MoveFramesToEndOfIBSplit(aState, nsnull,
-                                           aIsPositioned, aContent,
+                                           positioned, aContent,
                                            aStyleContext, list3,
                                            blockFrame, nsnull);
     
   }
 
   // Mark the frames as special (note: marking for inlineFrame is handled by
   // MoveFramesToEndOfIBSplit). That way if any of the append/insert/remove
   // methods try to fiddle with the children, the containing block will be
   // reframed instead.
-  SetFrameIsSpecial(aNewFrame, blockFrame);
+  SetFrameIsSpecial(newFrame, blockFrame);
   SetFrameIsSpecial(blockFrame, inlineFrame);
-  MarkIBSpecialPrevSibling(blockFrame, aNewFrame);
+  MarkIBSpecialPrevSibling(blockFrame, newFrame);
   if (inlineFrame) {
     MarkIBSpecialPrevSibling(inlineFrame, blockFrame);
   }
 
   #ifdef DEBUG
   if (gNoisyInlineConstruction) {
     nsIFrameDebug*  frameDebug;
 
     printf("nsCSSFrameConstructor::ConstructInline:\n");
-    if ( (frameDebug = do_QueryFrame(aNewFrame)) ) {
+    if ( (frameDebug = do_QueryFrame(*aNewFrame)) ) {
       printf("  ==> leading inline frame:\n");
       frameDebug->List(stdout, 2);
     }
     if ( (frameDebug = do_QueryFrame(blockFrame)) ) {
       printf("  ==> block frame:\n");
       frameDebug->List(stdout, 2);
     }
     if ( (frameDebug = do_QueryFrame(inlineFrame)) ) {
       printf("  ==> trailing inline frame:\n");
       frameDebug->List(stdout, 2);
     }
   }
 #endif
 
+  if (NS_SUCCEEDED(rv)) {
+    aState.AddChild(newFrame, aFrameItems, aContent, aStyleContext, aParentFrame);
+    *aNewFrame = newFrame;
+  }
   return rv;
 }
 
 nsIFrame*
 nsCSSFrameConstructor::MoveFramesToEndOfIBSplit(nsFrameConstructorState& aState,
                                                 nsIFrame* aExistingEndFrame,
                                                 PRBool aIsPositioned,
                                                 nsIContent* aContent,
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -388,16 +388,44 @@ private:
   nsresult AppendFrames(nsFrameConstructorState&       aState,
                         nsIContent*                    aContainer,
                         nsIFrame*                      aParentFrame,
                         nsFrameItems&                  aFrameList,
                         nsIFrame*                      aAfterFrame);
 
   // BEGIN TABLE SECTION
   /**
+   * Construct an outer table frame.  This is the FrameConstructionData
+   * callback used for the job.
+   */
+  nsresult ConstructTable(nsFrameConstructorState& aState,
+                          nsIContent*              aContent,
+                          nsIFrame*                aParentFrame,
+                          nsIAtom*                 aTag,
+                          PRInt32                  aNameSpaceID,
+                          nsStyleContext*          aStyleContext,
+                          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,
+                              nsIContent*              aContent,
+                              nsIFrame*                aParentFrame,
+                              nsIAtom*                 aTag,
+                              PRInt32                  aNameSpaceID,
+                              nsStyleContext*          aStyleContext,
+                              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).
    */ 
@@ -547,27 +575,29 @@ private:
      into this as a followup!), process children as needed, etc.  It is NOT
      expected to deal with the primary frame map.
 
      @param aState the frame construction state to use.
      @param aContent the content node to construct the frame for.
      @param aParentFrame the frame to set as the parent of the
                          newly-constructed frame.
      @param aTag the content's XBL-resolved tag.
+     @param aNameSpaceID the content's XBL-resolved namespace.
      @param aStyleContext the style context to use for the new frame.
      @param aFrameItems the frame list to add the new frame (or its
                         placeholder) to.
      @param aFrame out param handing out the frame that was constructed.  This
                    frame is what the caller will add to the primary frame map.
   */
   typedef nsresult
     (nsCSSFrameConstructor::* FrameFullConstructor)(nsFrameConstructorState& aState,
                                                     nsIContent* aContent,
                                                     nsIFrame* aParentFrame,
                                                     nsIAtom* aTag,
+                                                    PRInt32 aNameSpaceID,
                                                     nsStyleContext* aStyleContext,
                                                     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
@@ -619,16 +649,20 @@ private:
      this is only used if a scrollframe is not created and a full constructor
      isn't used, so this flag shouldn't be used with
      FCDATA_MAY_NEED_SCROLLFRAME or FCDATA_FUNC_IS_FULL_CTOR.  */
 #define FCDATA_FORCE_VIEW 0x400
   /* If FCDATA_DISALLOW_GENERATED_CONTENT is set, then don't allow generated
      content when processing kids of this frame.  This should not be used with
      FCDATA_FUNC_IS_FULL_CTOR */
 #define FCDATA_DISALLOW_GENERATED_CONTENT 0x800
+  /* If FCDATA_IS_TABLE_PART is set, then the frame is some sort of
+     table-related thing and we should not attempt to fetch a table-cell parent
+     for it if it's inside another table-related frame. */
+#define FCDATA_IS_TABLE_PART 0x1000
 
   /* 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,18 +722,17 @@ private:
   /**
    * 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
    * @param aParentFrame the frame we think should be the parent.  This will be
    *        adjusted to point to a pseudo-frame if needed.
    * @param aFCData the FrameConstructionData that would be used for frame
-   *        construction.  If this is null, then frame construction will be
-   *        done based on the CSS display value.   
+   *        construction.
    * @param aNameSpaceID namespace that will be used for frame construction
    * @param aDisplay the display style struct 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 aSuppressFrame whether we should not create a frame below this
@@ -735,38 +768,41 @@ protected:
 
 private:
   // ConstructButtonFrame puts the new frame in aFrameItems and
   // handles the kids of the button.
   nsresult ConstructButtonFrame(nsFrameConstructorState& aState,
                                 nsIContent*              aContent,
                                 nsIFrame*                aParentFrame,
                                 nsIAtom*                 aTag,
+                                PRInt32                  aNameSpaceID,
                                 nsStyleContext*          aStyleContext,
                                 const nsStyleDisplay*    aStyleDisplay,
                                 nsFrameItems&            aFrameItems,
                                 nsIFrame**               aNewFrame);
 
   // ConstructSelectFrame puts the new frame in aFrameItems and
   // handles the kids of the select.
   nsresult ConstructSelectFrame(nsFrameConstructorState& aState,
                                 nsIContent*              aContent,
                                 nsIFrame*                aParentFrame,
                                 nsIAtom*                 aTag,
+                                PRInt32                  aNameSpaceID,
                                 nsStyleContext*          aStyleContext,
                                 const nsStyleDisplay*    aStyleDisplay,
                                 nsFrameItems&            aFrameItems,
                                 nsIFrame**               aNewFrame);
 
   // ConstructFieldSetFrame puts the new frame in aFrameItems and
   // handles the kids of the fieldset
   nsresult ConstructFieldSetFrame(nsFrameConstructorState& aState,
                                   nsIContent*              aContent,
                                   nsIFrame*                aParentFrame,
                                   nsIAtom*                 aTag,
+                                  PRInt32                  aNameSpaceID,
                                   nsStyleContext*          aStyleContext,
                                   const nsStyleDisplay*    aStyleDisplay,
                                   nsFrameItems&            aFrameItems,
                                   nsIFrame**               aNewFrame);
 
   static const FrameConstructionData* FindTextData(nsIFrame* aParentFrame);
 
   nsresult ConstructTextFrame(const FrameConstructionData* aData,
@@ -920,31 +956,53 @@ private:
                                                   PRInt32 aNameSpaceID,
                                                   nsIFrame* aParentFrame,
                                                   nsStyleContext* aStyleContext);
 
   nsresult ConstructSVGForeignObjectFrame(nsFrameConstructorState& aState,
                                           nsIContent* aContent,
                                           nsIFrame* aParentFrame,
                                           nsIAtom* aTag,
+                                          PRInt32 aNameSpaceID,
                                           nsStyleContext* aStyleContext,
                                           const nsStyleDisplay* aStyleDisplay,
                                           nsFrameItems& aFrameItems,
                                           nsIFrame** aNewFrame);
 #endif
 
-  nsresult ConstructFrameByDisplayType(nsFrameConstructorState& aState,
-                                       const nsStyleDisplay*    aDisplay,
+  /* Not static because it does PropagateScrollToViewport.  If this
+     changes, make this static */
+  const FrameConstructionData*
+    FindDisplayData(const nsStyleDisplay* aDisplay, nsIContent* aContent);
+
+  /**
+   * Construct a scrollable block frame
+   */
+  nsresult ConstructScrollableBlock(nsFrameConstructorState& aState,
+                                    nsIContent*              aContent,
+                                    nsIFrame*                aParentFrame,
+                                    nsIAtom*                 aTag,
+                                    PRInt32                  aNameSpaceID,
+                                    nsStyleContext*          aStyleContext,
+                                    const nsStyleDisplay*    aDisplay,
+                                    nsFrameItems&            aFrameItems,
+                                    nsIFrame**               aNewFrame);
+
+  /**
+   * Construct a non-scrollable block frame
+   */
+  nsresult ConstructNonScrollableBlock(nsFrameConstructorState& aState,
                                        nsIContent*              aContent,
-                                       PRInt32                  aNameSpaceID,
+                                       nsIFrame*                aParentFrame,
                                        nsIAtom*                 aTag,
-                                       nsIFrame*                aParentFrame,
+                                       PRInt32                  aNameSpaceID,
                                        nsStyleContext*          aStyleContext,
+                                       const nsStyleDisplay*    aDisplay,
                                        nsFrameItems&            aFrameItems,
-                                       PRBool                   aHasPseudoParent);
+                                       nsIFrame**               aNewFrame);
 
   /**
    * Construct the frames for the children of aContent.  "children" is defined
    * as "whatever ChildIterator returns for aContent".  This means we're
    * basically operating on children in the "flattened tree" per sXBL/XBL2.
    * This method will also handle constructing ::before, ::after,
    * ::first-letter, and ::first-line frames, as needed and if allowed.
    *
@@ -1110,22 +1168,24 @@ private:
                           nsIFrame*                aParentFrame,
                           nsIFrame*                aContentParentFrame,
                           nsStyleContext*          aStyleContext,
                           nsIFrame**               aNewFrame,
                           nsFrameItems&            aFrameItems,
                           PRBool                   aAbsPosContainer);
 
   nsresult ConstructInline(nsFrameConstructorState& aState,
-                           const nsStyleDisplay*    aDisplay,
                            nsIContent*              aContent,
                            nsIFrame*                aParentFrame,
+                           nsIAtom*                 aTag,
+                           PRInt32                  aNameSpaceID,
                            nsStyleContext*          aStyleContext,
-                           PRBool                   aIsPositioned,
-                           nsIFrame*                aNewFrame);
+                           const nsStyleDisplay*    aDisplay,
+                           nsFrameItems&            aFrameItems,
+                           nsIFrame**               aNewFrame);
 
   /**
    * Move an already-constructed framelist into the inline frame at
    * the tail end of an {ib} split.  Creates said inline if it doesn't
    * already exist.
    *
    * @param aState the frame construction state we're using right now.
    * @param aExistingEndFrame if non-null, the already-existing end frame.