Bug 10209 - Part 6: Implement the CSS "containing block" concept correctly as a binary relation, as opposed to a unary relation; r=bzbarsky
authorEhsan Akhgari <ehsan@mozilla.com>
Thu, 12 May 2011 00:04:30 -0400
changeset 77841 00f422b2cf36505e1ee8768e09997237be8294c0
parent 77840 34f184d2a6f8d1932016ac7cfb379b5bc60cb45b
child 77842 731bbf32a6fdc2205648fc9122e8d50626ea2276
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewersbzbarsky
bugs10209
milestone10.0a1
Bug 10209 - Part 6: Implement the CSS "containing block" concept correctly as a binary relation, as opposed to a unary relation; r=bzbarsky
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/forms/nsFieldSetFrame.cpp
layout/forms/nsHTMLButtonControlFrame.cpp
layout/forms/nsHTMLButtonControlFrame.h
layout/forms/nsListControlFrame.cpp
layout/forms/nsListControlFrame.h
layout/generic/nsBlockFrame.cpp
layout/generic/nsBlockFrame.h
layout/generic/nsCanvasFrame.h
layout/generic/nsFrame.cpp
layout/generic/nsFrame.h
layout/generic/nsHTMLReflowState.cpp
layout/generic/nsHTMLReflowState.h
layout/generic/nsIFrame.h
layout/generic/nsPageContentFrame.cpp
layout/generic/nsPageContentFrame.h
layout/generic/nsPageFrame.cpp
layout/generic/nsPageFrame.h
layout/generic/nsViewportFrame.cpp
layout/generic/nsViewportFrame.h
layout/reftests/bugs/10209-1.html
layout/reftests/bugs/10209-2.html
layout/reftests/bugs/10209-3-ref.html
layout/reftests/bugs/10209-3.html
layout/reftests/bugs/10209-ref.html
layout/reftests/bugs/reftest.list
layout/style/nsComputedDOMStyle.cpp
layout/tables/nsTableCellFrame.cpp
layout/tables/nsTableCellFrame.h
layout/tables/nsTableColGroupFrame.cpp
layout/tables/nsTableColGroupFrame.h
layout/tables/nsTableFrame.cpp
layout/tables/nsTableFrame.h
layout/tables/nsTableOuterFrame.cpp
layout/tables/nsTableOuterFrame.h
layout/tables/nsTableRowGroupFrame.cpp
layout/tables/nsTableRowGroupFrame.h
layout/xul/base/src/nsScrollbarFrame.cpp
layout/xul/base/src/nsScrollbarFrame.h
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -2103,20 +2103,17 @@ static bool GetAbsoluteCoord(const nsSty
 static bool
 GetPercentHeight(const nsStyleCoord& aStyle,
                  nsIFrame* aFrame,
                  nscoord& aResult)
 {
   if (eStyleUnit_Percent != aStyle.GetUnit())
     return PR_FALSE;
 
-  nsIFrame *f;
-  for (f = aFrame->GetParent(); f && !f->IsContainingBlock();
-       f = f->GetParent())
-    ;
+  nsIFrame *f = aFrame->GetContainingBlock();
   if (!f) {
     NS_NOTREACHED("top of frame tree not a containing block");
     return PR_FALSE;
   }
 
   const nsStylePosition *pos = f->GetStylePosition();
   nscoord h;
   if (!GetAbsoluteCoord(pos->mHeight, h) &&
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -775,16 +775,23 @@ public:
   static nsIFrame* GetNonGeneratedAncestor(nsIFrame* aFrame);
 
   /**
    * Cast aFrame to an nsBlockFrame* or return null if it's not
    * an nsBlockFrame.
    */
   static nsBlockFrame* GetAsBlock(nsIFrame* aFrame);
 
+  /*
+   * Whether the frame is an nsBlockFrame which is not a wrapper block.
+   */
+  static bool IsNonWrapperBlock(nsIFrame* aFrame) {
+    return GetAsBlock(aFrame) && !aFrame->IsBlockWrapper();
+  }
+
   /**
    * If aFrame is an out of flow frame, return its placeholder, otherwise
    * return its parent.
    */
   static nsIFrame* GetParentOrPlaceholderFor(nsFrameManager* aFrameManager,
                                              nsIFrame* aFrame);
 
   /**
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -101,17 +101,16 @@ public:
                           nsFrameList&   aFrameList);
   NS_IMETHOD InsertFrames(ChildListID    aListID,
                           nsIFrame*      aPrevFrame,
                           nsFrameList&   aFrameList);
   NS_IMETHOD RemoveFrame(ChildListID    aListID,
                          nsIFrame*      aOldFrame);
 
   virtual nsIAtom* GetType() const;
-  virtual bool IsContainingBlock() const;
 
 #ifdef ACCESSIBILITY  
   virtual already_AddRefed<nsAccessible> CreateAccessible();
 #endif
 
 #ifdef DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const {
     return MakeFrameName(NS_LITERAL_STRING("FieldSet"), aResult);
@@ -146,22 +145,16 @@ nsFieldSetFrame::nsFieldSetFrame(nsStyle
 }
 
 nsIAtom*
 nsFieldSetFrame::GetType() const
 {
   return nsGkAtoms::fieldSetFrame;
 }
 
-bool
-nsFieldSetFrame::IsContainingBlock() const
-{
-  return PR_TRUE;
-}
-
 NS_IMETHODIMP
 nsFieldSetFrame::SetInitialChildList(ChildListID    aListID,
                                      nsFrameList&   aChildList)
 {
   // Get the content and legend frames.
   if (!aChildList.OnlyChild()) {
     NS_ASSERTION(aChildList.GetLength() == 2, "Unexpected child list");
     mContentFrame = aChildList.LastChild();
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -356,22 +356,16 @@ nsHTMLButtonControlFrame::ReflowButtonCo
   if (aDesiredSize.ascent == nsHTMLReflowMetrics::ASK_FOR_BASELINE)
     aDesiredSize.ascent = aFirstKid->GetBaseline();
 
   // Adjust the baseline by our offset (since we moved the child's
   // baseline by that much).
   aDesiredSize.ascent += yoff;
 }
 
-/* virtual */ bool
-nsHTMLButtonControlFrame::IsContainingBlock() const
-{
-  return PR_TRUE;
-}
-
 PRIntn
 nsHTMLButtonControlFrame::GetSkipSides() const
 {
   return 0;
 }
 
 nsresult nsHTMLButtonControlFrame::SetFormProperty(nsIAtom* aName, const nsAString& aValue)
 {
--- a/layout/forms/nsHTMLButtonControlFrame.h
+++ b/layout/forms/nsHTMLButtonControlFrame.h
@@ -74,18 +74,16 @@ public:
 
   virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext);
 
   NS_IMETHOD Reflow(nsPresContext*          aPresContext,
                     nsHTMLReflowMetrics&     aDesiredSize,
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus&          aStatus);
 
-  virtual bool IsContainingBlock() const;
-  
   NS_IMETHOD HandleEvent(nsPresContext* aPresContext, 
                          nsGUIEvent* aEvent,
                          nsEventStatus* aEventStatus);
 
   NS_IMETHOD  Init(nsIContent*      aContent,
                    nsIFrame*        aParent,
                    nsIFrame*        asPrevInFlow);
 
--- a/layout/forms/nsListControlFrame.cpp
+++ b/layout/forms/nsListControlFrame.cpp
@@ -1753,25 +1753,16 @@ nsListControlFrame::DidReflow(nsPresCont
 }
 
 nsIAtom*
 nsListControlFrame::GetType() const
 {
   return nsGkAtoms::listControlFrame; 
 }
 
-bool
-nsListControlFrame::IsContainingBlock() const
-{
-  // We are in fact the containing block for our options.  They should
-  // certainly not use our parent block (or worse yet our parent combobox) for
-  // their sizing.
-  return PR_TRUE;
-}
-
 void
 nsListControlFrame::InvalidateInternal(const nsRect& aDamageRect,
                                        nscoord aX, nscoord aY, nsIFrame* aForChild,
                                        PRUint32 aFlags)
 {
   if (!IsInDropDownMode()) {
     nsHTMLScrollFrame::InvalidateInternal(aDamageRect, aX, aY, this, aFlags);
     return;
--- a/layout/forms/nsListControlFrame.h
+++ b/layout/forms/nsListControlFrame.h
@@ -119,18 +119,16 @@ public:
   virtual nsIAtom* GetType() const;
 
   virtual bool IsFrameOfType(PRUint32 aFlags) const
   {
     return nsHTMLScrollFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
   }
 
-  virtual bool IsContainingBlock() const;
-
   virtual void InvalidateInternal(const nsRect& aDamageRect,
                                   nscoord aX, nscoord aY, nsIFrame* aForChild,
                                   PRUint32 aFlags);
 
 #ifdef DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
 
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -625,32 +625,16 @@ nsBlockFrame::GetChildLists(nsTArray<Chi
   }
   list = GetPushedFloats();
   if (list) {
     list->AppendIfNonempty(aLists, kPushedFloatsList);
   }
 }
 
 /* virtual */ bool
-nsBlockFrame::IsContainingBlock() const
-{
-  // The block wrappers we use to wrap blocks inside inlines aren't
-  // described in the CSS spec.  We need to make them not be containing
-  // blocks for the cases where we care about the 'direction' property
-  // of an element's containing block.
-  // Since the parent of such a block is either a normal block or
-  // another such pseudo, this shouldn't cause anything bad to happen.
-  // Also the anonymous blocks inside table cells are not containing blocks.
-  nsIAtom *pseudoType = GetStyleContext()->GetPseudo();
-  return pseudoType != nsCSSAnonBoxes::mozAnonymousBlock &&
-         pseudoType != nsCSSAnonBoxes::mozAnonymousPositionedBlock &&
-         pseudoType != nsCSSAnonBoxes::cellContent;
-}
-
-/* virtual */ bool
 nsBlockFrame::IsFloatContainingBlock() const
 {
   return PR_TRUE;
 }
 
 static void ReparentFrame(nsIFrame* aFrame, nsIFrame* aOldParent,
                           nsIFrame* aNewParent) {
   NS_ASSERTION(aOldParent == aFrame->GetParent(),
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -176,17 +176,16 @@ public:
   NS_IMETHOD  RemoveFrame(ChildListID     aListID,
                           nsIFrame*       aOldFrame);
   virtual nsFrameList GetChildList(ChildListID aListID) const;
   virtual void GetChildLists(nsTArray<ChildList>* aLists) const;
   virtual nscoord GetBaseline() const;
   virtual nscoord GetCaretBaseline() const;
   virtual void DestroyFrom(nsIFrame* aDestructRoot);
   virtual nsSplittableType GetSplittableType() const;
-  virtual bool IsContainingBlock() const;
   virtual bool IsFloatContainingBlock() const;
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists);
   virtual void InvalidateInternal(const nsRect& aDamageRect,
                                   nscoord aX, nscoord aY, nsIFrame* aForChild,
                                   PRUint32 aFlags);
   virtual nsIAtom* GetType() const;
--- a/layout/generic/nsCanvasFrame.h
+++ b/layout/generic/nsCanvasFrame.h
@@ -83,17 +83,16 @@ public:
                          nsIFrame*       aOldFrame);
 
   virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext);
   virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext);
   NS_IMETHOD Reflow(nsPresContext*          aPresContext,
                     nsHTMLReflowMetrics&     aDesiredSize,
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus&          aStatus);
-  virtual bool IsContainingBlock() const { return true; }
   virtual bool IsFrameOfType(PRUint32 aFlags) const
   {
     return nsHTMLContainerFrame::IsFrameOfType(aFlags &
              ~(nsIFrame::eCanContainOverflowContainers));
   }
 
   /** SetHasFocus tells the CanvasFrame to draw with focus ring
    *  @param aHasFocus PR_TRUE to show focus ring, PR_FALSE to hide it
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1782,17 +1782,16 @@ nsIFrame::BuildDisplayListForChild(nsDis
 
   const nsStyleDisplay* disp = aChild->GetStyleDisplay();
   // PR_TRUE if this is a real or pseudo stacking context
   bool pseudoStackingContext =
     (aFlags & DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT) != 0;
   // XXX we REALLY need a "are you an inline-block sort of thing?" here!!!
   if ((aFlags & DISPLAY_CHILD_INLINE) &&
       (disp->mDisplay != NS_STYLE_DISPLAY_INLINE ||
-       aChild->IsContainingBlock() ||
        (aChild->IsFrameOfType(eReplaced)))) {
     // child is a non-inline frame in an inline context, i.e.,
     // it acts like inline-block or inline-table. Therefore it is a
     // pseudo-stacking-context.
     pseudoStackingContext = PR_TRUE;
   }
 
   // dirty rect in child-relative coordinates
@@ -4900,26 +4899,53 @@ nsFrame::IsFrameTreeTooDeep(const nsHTML
     }
 
     return PR_TRUE;
   }
   mState &= ~NS_FRAME_TOO_DEEP_IN_FRAME_TREE;
   return PR_FALSE;
 }
 
-/* virtual */ bool nsFrame::IsContainingBlock() const
-{
-  const nsStyleDisplay* display = GetStyleDisplay();
-
-  // Absolute positioning causes |display->mDisplay| to be set to block,
-  // if needed.
-  return display->mDisplay == NS_STYLE_DISPLAY_BLOCK || 
-         display->mDisplay == NS_STYLE_DISPLAY_INLINE_BLOCK || 
-         display->mDisplay == NS_STYLE_DISPLAY_LIST_ITEM ||
-         display->mDisplay == NS_STYLE_DISPLAY_TABLE_CELL;
+bool
+nsIFrame::IsBlockWrapper() const
+{
+  nsIAtom *pseudoType = GetStyleContext()->GetPseudo();
+  return (pseudoType == nsCSSAnonBoxes::mozAnonymousBlock ||
+          pseudoType == nsCSSAnonBoxes::mozAnonymousPositionedBlock ||
+          pseudoType == nsCSSAnonBoxes::cellContent);
+}
+
+static nsIFrame*
+GetNearestBlockContainer(nsIFrame* frame)
+{
+  // The block wrappers we use to wrap blocks inside inlines aren't
+  // described in the CSS spec.  We need to make them not be containing
+  // blocks.
+  // Since the parent of such a block is either a normal block or
+  // another such pseudo, this shouldn't cause anything bad to happen.
+  // Also the anonymous blocks inside table cells are not containing blocks.
+  while (frame->IsFrameOfType(nsIFrame::eLineParticipant) ||
+         frame->IsBlockWrapper()) {
+    frame = frame->GetParent();
+    NS_ASSERTION(frame, "How come we got to the root frame without seeing a containing block?");
+  }
+  return frame;
+}
+
+nsIFrame*
+nsIFrame::GetContainingBlock() const
+{
+  // MathML frames might have absolute positioning style, but they would
+  // still be in-flow.  So we have to check to make sure that the frame
+  // is really out-of-flow too.
+  if (GetStyleDisplay()->IsAbsolutelyPositioned() &&
+      (GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
+    return GetParent(); // the parent is always the containing block
+  }
+  return GetNearestBlockContainer(GetParent());
 }
 
 #ifdef NS_DEBUG
 
 PRInt32 nsFrame::ContentIndexInContainer(const nsIFrame* aFrame)
 {
   PRInt32 result = -1;
 
--- a/layout/generic/nsFrame.h
+++ b/layout/generic/nsFrame.h
@@ -226,17 +226,16 @@ public:
   virtual nsIFrame* GetNextContinuation() const;
   NS_IMETHOD  SetNextContinuation(nsIFrame*);
   virtual nsIFrame* GetPrevInFlowVirtual() const;
   NS_IMETHOD  SetPrevInFlow(nsIFrame*);
   virtual nsIFrame* GetNextInFlowVirtual() const;
   NS_IMETHOD  SetNextInFlow(nsIFrame*);
   NS_IMETHOD  GetOffsetFromView(nsPoint& aOffset, nsIView** aView) const;
   virtual nsIAtom* GetType() const;
-  virtual bool IsContainingBlock() const;
 
   NS_IMETHOD  GetSelected(bool *aSelected) const;
   NS_IMETHOD  IsSelectable(bool* aIsSelectable, PRUint8* aSelectStyle) const;
 
   NS_IMETHOD  GetSelectionController(nsPresContext *aPresContext, nsISelectionController **aSelCon);
 
   virtual bool PeekOffsetNoAmount(bool aForward, PRInt32* aOffset);
   virtual bool PeekOffsetCharacter(bool aForward, PRInt32* aOffset,
--- a/layout/generic/nsHTMLReflowState.cpp
+++ b/layout/generic/nsHTMLReflowState.cpp
@@ -294,41 +294,27 @@ nsHTMLReflowState::Init(nsPresContext* a
 
 void nsHTMLReflowState::InitCBReflowState()
 {
   if (!parentReflowState) {
     mCBReflowState = nsnull;
     return;
   }
 
-  // If outer tables ever become containing blocks, we need to make sure to use
-  // their mCBReflowState in the non-absolutely-positioned case for inner
-  // tables.
-  NS_ASSERTION(frame->GetType() != nsGkAtoms::tableFrame ||
-               !frame->GetParent()->IsContainingBlock(),
-               "Outer table should not be containing block");
-
-  if (parentReflowState->frame->IsContainingBlock() ||
-      // Absolutely positioned frames should always be kids of the frames that
-      // determine their containing block....
-      (NS_FRAME_GET_TYPE(mFrameType) == NS_CSS_FRAME_TYPE_ABSOLUTE)) {
-    // an absolutely positioned inner table needs to use the parent of
-    // the outer table.  So the above comment about absolutely
-    // positioned frames is sort of a lie.
-    if (parentReflowState->parentReflowState &&
-        frame->GetType() == nsGkAtoms::tableFrame) {
-      mCBReflowState = parentReflowState->parentReflowState;
+  if (parentReflowState->frame == frame->GetContainingBlock()) {
+    // Inner table frames need to use the containing block of the outer
+    // table frame.
+    if (frame->GetType() == nsGkAtoms::tableFrame) {
+      mCBReflowState = parentReflowState->mCBReflowState;
     } else {
       mCBReflowState = parentReflowState;
     }
-      
-    return;
+  } else {
+    mCBReflowState = parentReflowState->mCBReflowState;
   }
-  
-  mCBReflowState = parentReflowState->mCBReflowState;
 }
 
 /* Check whether CalcQuirkContainingBlockHeight would stop on the
  * given reflow state, using its block as a height.  (essentially 
  * returns false for any case in which CalcQuirkContainingBlockHeight 
  * has a "continue" in its main loop.)
  *
  * XXX Maybe refactor CalcQuirkContainingBlockHeight so it uses 
@@ -368,17 +354,17 @@ nsHTMLReflowState::InitResizeFlags(nsPre
       (mFlags.mSpecialHeightReflow ||
        (frame->GetFirstInFlow()->GetStateBits() &
          NS_TABLE_CELL_HAD_SPECIAL_REFLOW)) &&
       (frame->GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_HEIGHT)) {
     // Need to set the bit on the cell so that
     // mCBReflowState->mFlags.mVResize is set correctly below when
     // reflowing descendant.
     mFlags.mVResize = PR_TRUE;
-  } else if (mCBReflowState && !frame->IsContainingBlock()) {
+  } else if (mCBReflowState && !nsLayoutUtils::IsNonWrapperBlock(frame)) {
     // XXX Is this problematic for relatively positioned inlines acting
     // as containing block for absolutely positioned elements?
     // Possibly; in that case we should at least be checking
     // NS_SUBTREE_DIRTY, I'd think.
     mFlags.mVResize = mCBReflowState->mFlags.mVResize;
   } else if (mComputedHeight == NS_AUTOHEIGHT) {
     if (eCompatibility_NavQuirks == aPresContext->CompatibilityMode() &&
         mCBReflowState) {
@@ -410,17 +396,17 @@ nsHTMLReflowState::InitResizeFlags(nsPre
   if (mStyleText->mLineHeight.GetUnit() == eStyleUnit_Enumerated) {
     NS_ASSERTION(mStyleText->mLineHeight.GetIntValue() ==
                  NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT,
                  "bad line-height value");
 
     // line-height depends on block height
     frame->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT);
     // but only on containing blocks if this frame is not a suitable block
-    dependsOnCBHeight |= !frame->IsContainingBlock();
+    dependsOnCBHeight |= !nsLayoutUtils::IsNonWrapperBlock(frame);
   }
 
   // If we're the descendant of a table cell that performs special height
   // reflows and we could be the child that requires them, always set
   // the vertical resize in case this is the first pass before the
   // special height reflow.  However, don't do this if it actually is
   // the special height reflow, since in that case it will already be
   // set correctly above if we need it set.
@@ -483,33 +469,16 @@ nscoord
 nsHTMLReflowState::GetContainingBlockContentWidth(const nsHTMLReflowState* aReflowState)
 {
   const nsHTMLReflowState* rs = aReflowState->mCBReflowState;
   if (!rs)
     return 0;
   return rs->mComputedWidth;
 }
 
-/* static */
-nsIFrame*
-nsHTMLReflowState::GetContainingBlockFor(const nsIFrame* aFrame)
-{
-  NS_PRECONDITION(aFrame, "Must have frame to work with");
-  nsIFrame* container = aFrame->GetParent();
-  if (aFrame->GetStyleDisplay()->IsAbsolutelyPositioned()) {
-    // Absolutely positioned frames are just kids of their containing
-    // blocks (which may happen to be inlines).
-    return container;
-  }
-  while (container && !container->IsContainingBlock()) {
-    container = container->GetParent();
-  }
-  return container;
-}
-
 void
 nsHTMLReflowState::InitFrameType()
 {
   const nsStyleDisplay *disp = mStyleDisplay;
   nsCSSFrameType frameType;
 
   // Section 9.7 of the CSS2 spec indicates that absolute position
   // takes precedence over float which takes precedence over display.
@@ -696,32 +665,22 @@ nsHTMLReflowState::ComputeRelativeOffset
   if (offsets) {
     offsets->MoveTo(mComputedOffsets.left, mComputedOffsets.top);
   } else {
     props.Set(nsIFrame::ComputedOffsetProperty(),
               new nsPoint(mComputedOffsets.left, mComputedOffsets.top));
   }
 }
 
-static nsIFrame*
-GetNearestContainingBlock(nsIFrame *aFrame)
-{
-  nsIFrame *cb = aFrame;
-  do {
-    cb = cb->GetParent();
-  } while (!cb->IsContainingBlock());
-  return cb;
-}
-
 nsIFrame*
 nsHTMLReflowState::GetHypotheticalBoxContainer(nsIFrame* aFrame,
                                                nscoord& aCBLeftEdge,
                                                nscoord& aCBWidth)
 {
-  aFrame = GetNearestContainingBlock(aFrame);
+  aFrame = aFrame->GetContainingBlock();
   NS_ASSERTION(aFrame != frame, "How did that happen?");
 
   /* Now aFrame is the containing block we want */
 
   /* Check whether the containing block is currently being reflowed.
      If so, use the info from the reflow state. */
   const nsHTMLReflowState* state;
   if (aFrame->GetStateBits() & NS_FRAME_IN_REFLOW) {
@@ -1185,17 +1144,17 @@ nsHTMLReflowState::InitAbsoluteConstrain
                                  mStylePosition->mOffset.GetRight());
   }
 
   // Use the horizontal component of the hypothetical box in the cases
   // where it's needed.
   if (leftIsAuto && rightIsAuto) {
     // Use the direction of the original ("static-position") containing block
     // to dictate whether 'left' or 'right' is treated like 'static-position'.
-    if (NS_STYLE_DIRECTION_LTR == GetNearestContainingBlock(placeholderFrame)
+    if (NS_STYLE_DIRECTION_LTR == placeholderFrame->GetContainingBlock()
                                     ->GetStyleVisibility()->mDirection) {
       NS_ASSERTION(hypotheticalBox.mLeftIsExact, "should always have "
                    "exact value on containing block's start side");
       mComputedOffsets.left = hypotheticalBox.mLeft;
       leftIsAuto = PR_FALSE;
     } else {
       NS_ASSERTION(hypotheticalBox.mRightIsExact, "should always have "
                    "exact value on containing block's start side");
@@ -1565,18 +1524,23 @@ nsHTMLReflowState::ComputeContainingBloc
                                                    const nsHTMLReflowState* aContainingBlockRS,
                                                    nscoord&                 aContainingBlockWidth,
                                                    nscoord&                 aContainingBlockHeight)
 {
   // Unless the element is absolutely positioned, the containing block is
   // formed by the content edge of the nearest block-level ancestor
   aContainingBlockWidth = aContainingBlockRS->mComputedWidth;
   aContainingBlockHeight = aContainingBlockRS->mComputedHeight;
-  
-  if (NS_FRAME_GET_TYPE(mFrameType) == NS_CSS_FRAME_TYPE_ABSOLUTE) {
+
+  // mFrameType for abs-pos tables is NS_CSS_FRAME_TYPE_BLOCK, so we need to
+  // special case them here.
+  if (NS_FRAME_GET_TYPE(mFrameType) == NS_CSS_FRAME_TYPE_ABSOLUTE ||
+      (frame->GetType() == nsGkAtoms::tableFrame &&
+       frame->GetStyleDisplay()->IsAbsolutelyPositioned() &&
+       (frame->GetParent()->GetStateBits() & NS_FRAME_OUT_OF_FLOW))) {
     // See if the ancestor is block-level or inline-level
     if (NS_FRAME_GET_TYPE(aContainingBlockRS->mFrameType) == NS_CSS_FRAME_TYPE_INLINE) {
       // Base our size on the actual size of the frame.  In cases when this is
       // completely bogus (eg initial reflow), this code shouldn't even be
       // called, since the code in nsInlineFrame::Reflow will pass in
       // the containing block dimensions to our constructor.
       // XXXbz we should be taking the in-flows into account too, but
       // that's very hard.
@@ -2163,17 +2127,17 @@ ComputeLineHeight(nsStyleContext* aStyle
                                                getter_AddRefs(fm));
   return GetNormalLineHeight(fm);
 }
 
 nscoord
 nsHTMLReflowState::CalcLineHeight() const
 {
   nscoord blockHeight =
-    frame->IsContainingBlock() ? mComputedHeight :
+    nsLayoutUtils::IsNonWrapperBlock(frame) ? mComputedHeight :
     (mCBReflowState ? mCBReflowState->mComputedHeight : NS_AUTOHEIGHT);
 
   return CalcLineHeight(frame->GetStyleContext(), blockHeight);
 }
 
 /* static */ nscoord
 nsHTMLReflowState::CalcLineHeight(nsStyleContext* aStyleContext,
                                   nscoord aBlockHeight)
--- a/layout/generic/nsHTMLReflowState.h
+++ b/layout/generic/nsHTMLReflowState.h
@@ -401,23 +401,16 @@ public:
             const nsMargin* aPadding = nsnull);
   /**
    * Find the content width of the containing block of aReflowState
    */
   static nscoord
     GetContainingBlockContentWidth(const nsHTMLReflowState* aReflowState);
 
   /**
-   * Find the containing block of aFrame.  This may return null if
-   * there isn't one (but that should really only happen for root
-   * frames).
-   */
-  static nsIFrame* GetContainingBlockFor(const nsIFrame* aFrame);
-
-  /**
    * Calculate the used line-height property. The return value will be >= 0.
    */
   nscoord CalcLineHeight() const;
 
   /**
    * Same as CalcLineHeight() above, but doesn't need a reflow state.
    *
    * @param aBlockHeight The computed height of the content rect of the block
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1977,19 +1977,27 @@ public:
 #ifdef DEBUG
     return !(aFlags & ~(nsIFrame::eDEBUGAllFrames));
 #else
     return !aFlags;
 #endif
   }
 
   /**
-   * Is this frame a containing block for non-positioned elements?
+   * Returns true if the frame is a block wrapper.
    */
-  virtual bool IsContainingBlock() const = 0;
+  bool IsBlockWrapper() const;
+
+  /**
+   * Get this frame's CSS containing block.
+   *
+   * The algorithm is defined in
+   * http://www.w3.org/TR/CSS2/visudet.html#containing-block-details.
+   */
+  nsIFrame* GetContainingBlock() const;
 
   /**
    * Is this frame a containing block for floating elements?
    * Note that very few frames are, so default to false.
    */
   virtual bool IsFloatContainingBlock() const { return false; }
 
   /**
--- a/layout/generic/nsPageContentFrame.cpp
+++ b/layout/generic/nsPageContentFrame.cpp
@@ -163,14 +163,8 @@ nsPageContentFrame::GetType() const
 
 #ifdef DEBUG
 NS_IMETHODIMP
 nsPageContentFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("PageContent"), aResult);
 }
 #endif
-
-/* virtual */ bool
-nsPageContentFrame::IsContainingBlock() const
-{
-  return PR_TRUE;
-}
--- a/layout/generic/nsPageContentFrame.h
+++ b/layout/generic/nsPageContentFrame.h
@@ -51,17 +51,16 @@ public:
   friend class nsPageFrame;
 
   // nsIFrame
   NS_IMETHOD  Reflow(nsPresContext*      aPresContext,
                      nsHTMLReflowMetrics& aDesiredSize,
                      const nsHTMLReflowState& aMaxSize,
                      nsReflowStatus&      aStatus);
 
-  virtual bool IsContainingBlock() const;
   virtual bool IsFrameOfType(PRUint32 aFlags) const
   {
     return ViewportFrame::IsFrameOfType(aFlags &
              ~(nsIFrame::eCanContainOverflowContainers));
   }
 
   virtual void SetSharedPageData(nsSharedPageData* aPD) { mPD = aPD; }
 
--- a/layout/generic/nsPageFrame.cpp
+++ b/layout/generic/nsPageFrame.cpp
@@ -170,22 +170,16 @@ nsPageFrame::GetType() const
 #ifdef DEBUG
 NS_IMETHODIMP
 nsPageFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("Page"), aResult);
 }
 #endif
 
-/* virtual */ bool
-nsPageFrame::IsContainingBlock() const
-{
-  return PR_TRUE;
-}
-
 void 
 nsPageFrame::ProcessSpecialCodes(const nsString& aStr, nsString& aNewStr)
 {
 
   aNewStr = aStr;
 
   // Search to see if the &D code is in the string 
   // then subst in the current date/time
--- a/layout/generic/nsPageFrame.h
+++ b/layout/generic/nsPageFrame.h
@@ -54,18 +54,16 @@ public:
                      nsHTMLReflowMetrics& aDesiredSize,
                      const nsHTMLReflowState& aMaxSize,
                      nsReflowStatus&      aStatus);
 
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists);
 
-  virtual bool IsContainingBlock() const;
-
   /**
    * Get the "type" of the frame
    *
    * @see nsGkAtoms::pageFrame
    */
   virtual nsIAtom* GetType() const;
   
 #ifdef NS_DEBUG
--- a/layout/generic/nsViewportFrame.cpp
+++ b/layout/generic/nsViewportFrame.cpp
@@ -285,22 +285,16 @@ ViewportFrame::Reflow(nsPresContext*    
 }
 
 nsIAtom*
 ViewportFrame::GetType() const
 {
   return nsGkAtoms::viewportFrame;
 }
 
-/* virtual */ bool
-ViewportFrame::IsContainingBlock() const
-{
-  return PR_TRUE;
-}
-
 void
 ViewportFrame::InvalidateInternal(const nsRect& aDamageRect,
                                   nscoord aX, nscoord aY, nsIFrame* aForChild,
                                   PRUint32 aFlags)
 {
   nsRect r = aDamageRect + nsPoint(aX, aY);
   nsPresContext* presContext = PresContext();
   presContext->NotifyInvalidation(r, aFlags);
--- a/layout/generic/nsViewportFrame.h
+++ b/layout/generic/nsViewportFrame.h
@@ -95,18 +95,16 @@ public:
                     nsReflowStatus&          aStatus);
 
   /**
    * Get the "type" of the frame
    *
    * @see nsGkAtoms::viewportFrame
    */
   virtual nsIAtom* GetType() const;
-  
-  virtual bool IsContainingBlock() const;
 
   virtual void InvalidateInternal(const nsRect& aDamageRect,
                                   nscoord aX, nscoord aY, nsIFrame* aForChild,
                                   PRUint32 aFlags);
 
 #ifdef DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/10209-1.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<style>
+@font-face {
+  font-family: Ahem;
+  src: url(../fonts/Ahem.ttf);
+}
+* {
+  font-family: Ahem;
+}
+</style>
+<body style="font-size: 100px; padding-top: 5px">
+  <div style="position: relative; display: inline;">
+    <table style="height: 50%; position: absolute; width: 50px; background: green">
+    </table>
+  </div>
+</body>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/10209-2.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<style>
+@font-face {
+  font-family: Ahem;
+  src: url(../fonts/Ahem.ttf);
+}
+* {
+  font-family: Ahem;
+}
+</style>
+<body style="font-size: 100px">
+  <div style="position: relative; height:100px;">
+    <table style="height: 50%; position: absolute; width: 50px; background: green">
+    </table>
+  </div>
+</body>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/10209-3-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<style>
+@font-face {
+  font-family: Ahem;
+  src: url(../fonts/Ahem.ttf);
+}
+* {
+  font-family: Ahem;
+}
+</style>
+<body style="margin: 0">
+  <div style="width: 100px; height: 100px; background: green">
+  </div>
+</body>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/10209-3.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<style>
+@font-face {
+  font-family: Ahem;
+  src: url(../fonts/Ahem.ttf);
+}
+* {
+  font-family: Ahem;
+}
+</style>
+<body style="position: relative; display: inline; border-right: 1px solid black; font-size: 100px; line-height: 100px; margin: 0">
+  <table style="position: absolute; width: 100px; height: 100%; top: 0; left: 0; background: green"></table>
+</body>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/10209-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<style>
+@font-face {
+  font-family: Ahem;
+  src: url(../fonts/Ahem.ttf);
+}
+* {
+  font-family: Ahem;
+}
+</style>
+<body>
+  <div style="width: 50px; height: 50px; background: green">
+  </div>
+</body>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -13,16 +13,19 @@
 == 9458-width-2a.html 9458-width-2-ref.html
 == 9458-width-2b.html 9458-width-2-ref.html
 == 9458-zorder-1.html 9458-zorder-ref.html
 == 9458-zorder-2.html 9458-zorder-ref.html
 == 9458-zorder-3.html 9458-zorder-ref-inline.html
 == 9458-zorder-4.html 9458-zorder-ref-inline-block.html
 == 9458-zorder-5.html 9458-zorder-ref-inline-block.html
 == 10036-1.html 10036-1-ref.html
+skip-if(!cocoaWidget) HTTP(..) == 10209-1.html 10209-ref.html # Bug 667079
+HTTP(..) == 10209-2.html 10209-ref.html
+asserts(4) skip-if(!cocoaWidget) HTTP(..) == 10209-3.html 10209-3-ref.html # Assertions: bug 666606, skip because of bug 667079
 == 18217-basic-1.html 18217-basic-1-ref.html
 == 18217-basic-2a.html 18217-basic-2-ref.html
 == 18217-basic-2b.html 18217-basic-2-ref.html
 == 18217-valign-1.html 18217-valign-1-ref.html
 == 18217-height-1.html 18217-height-1-ref.html
 == 18217-height-2.html 18217-height-2-ref.html
 == 18217-width-1a.html 18217-width-1-ref.html
 == 18217-width-1b.html 18217-width-1-ref.html
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -126,17 +126,17 @@ NS_NewComputedDOMStyle(nsIDOMElement *aE
   return NS_OK;
 }
 
 static nsIFrame*
 GetContainingBlockFor(nsIFrame* aFrame) {
   if (!aFrame) {
     return nsnull;
   }
-  return nsHTMLReflowState::GetContainingBlockFor(aFrame);
+  return aFrame->GetContainingBlock();
 }
 
 nsComputedDOMStyle::nsComputedDOMStyle()
   : mDocumentWeak(nsnull), mOuterFrame(nsnull),
     mInnerFrame(nsnull), mPresShell(nsnull),
     mExposeVisitedStyle(PR_FALSE)
 {
 }
@@ -3327,17 +3327,17 @@ nsComputedDOMStyle::GetLineHeightCoord(n
 {
   AssertFlushedPendingReflows();
 
   nscoord blockHeight = NS_AUTOHEIGHT;
   if (GetStyleText()->mLineHeight.GetUnit() == eStyleUnit_Enumerated) {
     if (!mInnerFrame)
       return PR_FALSE;
 
-    if (mInnerFrame->IsContainingBlock()) {
+    if (nsLayoutUtils::IsNonWrapperBlock(mInnerFrame)) {
       blockHeight = mInnerFrame->GetContentRect().height;
     } else {
       GetCBContentHeight(blockHeight);
     }
   }
 
   aCoord = nsHTMLReflowState::CalcLineHeight(mStyleContextHolder,
                                              blockHeight);
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -1038,22 +1038,16 @@ nsTableCellFrame::GetBorderWidth(nsMargi
 }
 
 nsIAtom*
 nsTableCellFrame::GetType() const
 {
   return nsGkAtoms::tableCellFrame;
 }
 
-/* virtual */ bool
-nsTableCellFrame::IsContainingBlock() const
-{
-  return PR_TRUE;
-}
-
 #ifdef DEBUG
 NS_IMETHODIMP
 nsTableCellFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("TableCell"), aResult);
 }
 #endif
 
--- a/layout/tables/nsTableCellFrame.h
+++ b/layout/tables/nsTableCellFrame.h
@@ -144,18 +144,16 @@ public:
 
   /**
    * Get the "type" of the frame
    *
    * @see nsLayoutAtoms::tableCellFrame
    */
   virtual nsIAtom* GetType() const;
 
-  virtual bool IsContainingBlock() const;
-
 #ifdef DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
 
   void VerticallyAlignChild(nscoord aMaxAscent);
 
   /*
    * Get the value of vertical-align adjusted for CSS 2's rules for a
--- a/layout/tables/nsTableColGroupFrame.cpp
+++ b/layout/tables/nsTableColGroupFrame.cpp
@@ -424,22 +424,16 @@ NS_METHOD nsTableColGroupFrame::Reflow(n
 
   aDesiredSize.width=0;
   aDesiredSize.height=0;
   aStatus = NS_FRAME_COMPLETE;
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return rv;
 }
 
-/* virtual */ bool
-nsTableColGroupFrame::IsContainingBlock() const
-{
-  return PR_TRUE;
-}
-
 nsTableColFrame * nsTableColGroupFrame::GetFirstColumn()
 {
   return GetNextColumn(nsnull);
 }
 
 nsTableColFrame * nsTableColGroupFrame::GetNextColumn(nsIFrame *aChildFrame)
 {
   nsTableColFrame *result = nsnull;
--- a/layout/tables/nsTableColGroupFrame.h
+++ b/layout/tables/nsTableColGroupFrame.h
@@ -137,20 +137,16 @@ public:
     * don't play directly in the rendering game.  They do however
     * maintain important state that effects table and cell layout.
     */
   NS_IMETHOD Reflow(nsPresContext*          aPresContext,
                     nsHTMLReflowMetrics&     aDesiredSize,
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus&          aStatus);
 
-  /* needed only because we use Reflow in a hacky way, see
-     nsTableFrame::ReflowColGroups */
-  virtual bool IsContainingBlock() const;
-
   /**
    * Get the "type" of the frame
    *
    * @see nsGkAtoms::tableColGroupFrame
    */
   virtual nsIAtom* GetType() const;
 
   /** Add column frames to the table storages: colframe cache and cellmap
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -354,22 +354,16 @@ nsTableFrame::SetInitialChildList(ChildL
       nsRect damageArea(0, 0, GetColCount(), GetRowCount());
       SetBCDamageArea(damageArea);
     }
   }
 
   return NS_OK;
 }
 
-/* virtual */ bool
-nsTableFrame::IsContainingBlock() const
-{
-  return PR_TRUE;
-}
-
 void nsTableFrame::AttributeChangedFor(nsIFrame*       aFrame,
                                        nsIContent*     aContent,
                                        nsIAtom*        aAttribute)
 {
   nsTableCellFrame *cellFrame = do_QueryFrame(aFrame);
   if (cellFrame) {
     if ((nsGkAtoms::rowspan == aAttribute) ||
         (nsGkAtoms::colspan == aAttribute)) {
--- a/layout/tables/nsTableFrame.h
+++ b/layout/tables/nsTableFrame.h
@@ -159,18 +159,16 @@ public:
   // See if a special height reflow will occur due to having a pct height when
   // the pct height basis may not yet be valid.
   static void CheckRequestSpecialHeightReflow(const nsHTMLReflowState& aReflowState);
 
   // Notify the frame and its ancestors (up to the containing table) that a special
   // height reflow will occur. 
   static void RequestSpecialHeightReflow(const nsHTMLReflowState& aReflowState);
 
-  virtual bool IsContainingBlock() const;
-
   static void RePositionViews(nsIFrame* aFrame);
 
   static bool PageBreakAfter(nsIFrame* aSourceFrame,
                                nsIFrame* aNextFrame);
 
   nsPoint GetFirstSectionOrigin(const nsHTMLReflowState& aReflowState) const;
   /*
    * Notification that aAttribute has changed for content inside a table (cell, row, etc)
--- a/layout/tables/nsTableOuterFrame.cpp
+++ b/layout/tables/nsTableOuterFrame.cpp
@@ -194,22 +194,16 @@ nsTableOuterFrame::CreateAccessible()
     return accService->CreateHTMLTableAccessible(mContent,
                                                  PresContext()->PresShell());
   }
 
   return nsnull;
 }
 #endif
 
-/* virtual */ bool
-nsTableOuterFrame::IsContainingBlock() const
-{
-  return PR_FALSE;
-}
-
 void
 nsTableOuterFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   DestroyAbsoluteFrames(aDestructRoot);
   mCaptionFrames.DestroyFramesFrom(aDestructRoot);
   nsHTMLContainerFrame::DestroyFrom(aDestructRoot);
 }
 
--- a/layout/tables/nsTableOuterFrame.h
+++ b/layout/tables/nsTableOuterFrame.h
@@ -93,18 +93,16 @@ public:
     *
     * @return           the frame that was created
     */
   friend nsIFrame* NS_NewTableOuterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   
   // nsIFrame overrides - see there for a description
 
   virtual void DestroyFrom(nsIFrame* aDestructRoot);
-  
-  virtual bool IsContainingBlock() const;
 
   NS_IMETHOD SetInitialChildList(ChildListID     aListID,
                                  nsFrameList&    aChildList);
  
   virtual nsFrameList GetChildList(ChildListID aListID) const;
   virtual void GetChildLists(nsTArray<ChildList>* aLists) const;
 
   NS_IMETHOD AppendFrames(ChildListID     aListID,
--- a/layout/tables/nsTableRowGroupFrame.cpp
+++ b/layout/tables/nsTableRowGroupFrame.cpp
@@ -64,22 +64,16 @@ nsTableRowGroupFrame::nsTableRowGroupFra
 nsTableRowGroupFrame::~nsTableRowGroupFrame()
 {
 }
 
 NS_QUERYFRAME_HEAD(nsTableRowGroupFrame)
   NS_QUERYFRAME_ENTRY(nsTableRowGroupFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsHTMLContainerFrame)
 
-/* virtual */ bool
-nsTableRowGroupFrame::IsContainingBlock() const
-{
-  return PR_TRUE;
-}
-
 PRInt32
 nsTableRowGroupFrame::GetRowCount()
 {
 #ifdef DEBUG
   for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) {
     NS_ASSERTION(e.get()->GetStyleDisplay()->mDisplay ==
                    NS_STYLE_DISPLAY_TABLE_ROW,
                  "Unexpected display");
--- a/layout/tables/nsTableRowGroupFrame.h
+++ b/layout/tables/nsTableRowGroupFrame.h
@@ -144,18 +144,16 @@ public:
 
   /**
    * Get the "type" of the frame
    *
    * @see nsGkAtoms::tableRowGroupFrame
    */
   virtual nsIAtom* GetType() const;
 
-  virtual bool IsContainingBlock() const;
-
   nsTableRowFrame* GetFirstRow();
 
 #ifdef DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
 
   /** return the number of child rows (not necessarily == number of child frames) */
   PRInt32 GetRowCount();
--- a/layout/xul/base/src/nsScrollbarFrame.cpp
+++ b/layout/xul/base/src/nsScrollbarFrame.cpp
@@ -97,24 +97,16 @@ nsScrollbarFrame::Reflow(nsPresContext* 
   }
   if (aReflowState.availableHeight == 0) {
     aDesiredSize.height = 0;
   }
 
   return NS_OK;
 }
 
-/* virtual */ bool
-nsScrollbarFrame::IsContainingBlock() const
-{
-  // Return true so that the nsHTMLReflowState code is happy with us
-  // being a reflow root.
-  return PR_TRUE;
-}
-
 nsIAtom*
 nsScrollbarFrame::GetType() const
 {
   return nsGkAtoms::scrollbarFrame;
 }
 
 NS_IMETHODIMP
 nsScrollbarFrame::AttributeChanged(PRInt32 aNameSpaceID,
--- a/layout/xul/base/src/nsScrollbarFrame.h
+++ b/layout/xul/base/src/nsScrollbarFrame.h
@@ -91,18 +91,16 @@ public:
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
 
   NS_IMETHOD Reflow(nsPresContext*          aPresContext,
                     nsHTMLReflowMetrics&     aDesiredSize,
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus&          aStatus);
 
-  virtual bool IsContainingBlock() const;
-
   virtual nsIAtom* GetType() const;  
 
   void SetScrollbarMediatorContent(nsIContent* aMediator);
   nsIScrollbarMediator* GetScrollbarMediator();
 
   // nsBox methods
 
   /**