Bug 1131451 part 1 - Replace containerWidth with containerSize in logical-coordinate classes and APIs, frame classes, etc. r=dholbert
authorJonathan Kew <jkew@mozilla.com>
Thu, 16 Jul 2015 10:07:57 +0100
changeset 253152 28673cc5e68b48d6a397b027a6ef5321703dea4a
parent 253151 b0f47defe8106f673aea5fdd4f91e64aaa5e6ff5
child 253153 e6eed9f588de74077f18248d72508418d7061c23
push id29061
push userryanvm@gmail.com
push dateThu, 16 Jul 2015 18:53:45 +0000
treeherdermozilla-central@a0f4a688433d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1131451
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1131451 part 1 - Replace containerWidth with containerSize in logical-coordinate classes and APIs, frame classes, etc. r=dholbert
layout/base/nsBidiPresUtils.cpp
layout/base/nsLayoutUtils.cpp
layout/forms/nsComboboxControlFrame.cpp
layout/forms/nsFieldSetFrame.cpp
layout/forms/nsHTMLButtonControlFrame.cpp
layout/forms/nsNumberControlFrame.cpp
layout/generic/TextOverflow.cpp
layout/generic/TextOverflow.h
layout/generic/WritingModes.h
layout/generic/nsAbsoluteContainingBlock.cpp
layout/generic/nsBlockFrame.cpp
layout/generic/nsBlockFrame.h
layout/generic/nsBlockReflowContext.cpp
layout/generic/nsBlockReflowContext.h
layout/generic/nsBlockReflowState.cpp
layout/generic/nsBlockReflowState.h
layout/generic/nsCanvasFrame.cpp
layout/generic/nsColumnSetFrame.cpp
layout/generic/nsContainerFrame.cpp
layout/generic/nsContainerFrame.h
layout/generic/nsFlexContainerFrame.cpp
layout/generic/nsFlexContainerFrame.h
layout/generic/nsFloatManager.cpp
layout/generic/nsFloatManager.h
layout/generic/nsFrame.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsGridContainerFrame.cpp
layout/generic/nsHTMLReflowMetrics.h
layout/generic/nsHTMLReflowState.cpp
layout/generic/nsHTMLReflowState.h
layout/generic/nsIFrame.h
layout/generic/nsLineBox.cpp
layout/generic/nsLineBox.h
layout/generic/nsLineLayout.cpp
layout/generic/nsLineLayout.h
layout/generic/nsRubyFrame.cpp
layout/generic/nsRubyTextContainerFrame.cpp
layout/mathml/nsMathMLmtableFrame.cpp
layout/tables/nsTableCellFrame.cpp
layout/tables/nsTableFrame.cpp
layout/tables/nsTableFrame.h
layout/tables/nsTableOuterFrame.cpp
layout/tables/nsTableRowFrame.cpp
layout/tables/nsTableRowGroupFrame.cpp
layout/tables/nsTableRowGroupFrame.h
layout/xul/nsTextBoxFrame.cpp
--- a/layout/base/nsBidiPresUtils.cpp
+++ b/layout/base/nsBidiPresUtils.cpp
@@ -1461,20 +1461,21 @@ nsBidiPresUtils::RepositionRubyContentFr
   }
   nscoord residualISize = aFrame->ISize(aFrameWM) - isize;
   if (residualISize <= 0) {
     return;
   }
 
   // When ruby-align is not "start", if the content does not fill this
   // frame, we need to center the children.
+  const nsSize dummyContainerSize;
   for (nsIFrame* child : childList) {
-    LogicalRect rect = child->GetLogicalRect(aFrameWM, 0);
+    LogicalRect rect = child->GetLogicalRect(aFrameWM, dummyContainerSize);
     rect.IStart(aFrameWM) += residualISize / 2;
-    child->SetRect(aFrameWM, rect, 0);
+    child->SetRect(aFrameWM, rect, dummyContainerSize);
   }
 }
 
 /* static */ nscoord
 nsBidiPresUtils::RepositionRubyFrame(
   nsIFrame* aFrame,
   const nsContinuationStates* aContinuationStates,
   const WritingMode aContainerWM,
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -5614,17 +5614,17 @@ nsLayoutUtils::GetFirstLinePosition(Writ
     }
 
     if (fType == nsGkAtoms::fieldSetFrame) {
       LinePosition kidPosition;
       nsIFrame* kid = aFrame->GetFirstPrincipalChild();
       // kid might be a legend frame here, but that's ok.
       if (GetFirstLinePosition(aWM, kid, &kidPosition)) {
         *aResult = kidPosition +
-          kid->GetLogicalNormalPosition(aWM, aFrame->GetSize().width).B(aWM);
+          kid->GetLogicalNormalPosition(aWM, aFrame->GetSize()).B(aWM);
         return true;
       }
       return false;
     }
 
     // No baseline.
     return false;
   }
@@ -5634,19 +5634,19 @@ nsLayoutUtils::GetFirstLinePosition(Writ
        line != line_end; ++line) {
     if (line->IsBlock()) {
       nsIFrame *kid = line->mFirstChild;
       LinePosition kidPosition;
       if (GetFirstLinePosition(aWM, kid, &kidPosition)) {
         //XXX Not sure if this is the correct value to use for container
         //    width here. It will only be used in vertical-rl layout,
         //    which we don't have full support and testing for yet.
-        nscoord containerWidth = line->mContainerWidth;
+        const nsSize& containerSize = line->mContainerSize;
         *aResult = kidPosition +
-                   kid->GetLogicalNormalPosition(aWM, containerWidth).B(aWM);
+                   kid->GetLogicalNormalPosition(aWM, containerSize).B(aWM);
         return true;
       }
     } else {
       // XXX Is this the right test?  We have some bogus empty lines
       // floating around, but IsEmpty is perhaps too weak.
       if (line->BSize() != 0 || !line->IsEmpty()) {
         nscoord bStart = line->BStart();
         aResult->mBStart = bStart;
@@ -5669,26 +5669,26 @@ nsLayoutUtils::GetLastLineBaseline(Writi
     return false;
 
   for (nsBlockFrame::const_reverse_line_iterator line = block->rbegin_lines(),
                                              line_end = block->rend_lines();
        line != line_end; ++line) {
     if (line->IsBlock()) {
       nsIFrame *kid = line->mFirstChild;
       nscoord kidBaseline;
-      nscoord containerWidth = line->mContainerWidth;
+      const nsSize& containerSize = line->mContainerSize;
       if (GetLastLineBaseline(aWM, kid, &kidBaseline)) {
         // Ignore relative positioning for baseline calculations
         *aResult = kidBaseline +
-          kid->GetLogicalNormalPosition(aWM, containerWidth).B(aWM);
+          kid->GetLogicalNormalPosition(aWM, containerSize).B(aWM);
         return true;
       } else if (kid->GetType() == nsGkAtoms::scrollFrame) {
         // Use the bottom of the scroll frame.
         // XXX CSS2.1 really doesn't say what to do here.
-        *aResult = kid->GetLogicalNormalPosition(aWM, containerWidth).B(aWM) +
+        *aResult = kid->GetLogicalNormalPosition(aWM, containerSize).B(aWM) +
                    kid->BSize(aWM);
         return true;
       }
     } else {
       // XXX Is this the right test?  We have some bogus empty lines
       // floating around, but IsEmpty is perhaps too weak.
       if (line->BSize() != 0 || !line->IsEmpty()) {
         *aResult = line->BStart() + line->GetLogicalAscent();
@@ -5706,19 +5706,19 @@ CalculateBlockContentBEnd(WritingMode aW
 
   nscoord contentBEnd = 0;
 
   for (nsBlockFrame::line_iterator line = aFrame->begin_lines(),
                                    line_end = aFrame->end_lines();
        line != line_end; ++line) {
     if (line->IsBlock()) {
       nsIFrame* child = line->mFirstChild;
-      nscoord containerWidth = line->mContainerWidth;
+      const nsSize& containerSize = line->mContainerSize;
       nscoord offset =
-        child->GetLogicalNormalPosition(aWM, containerWidth).B(aWM);
+        child->GetLogicalNormalPosition(aWM, containerSize).B(aWM);
       contentBEnd =
         std::max(contentBEnd,
                  nsLayoutUtils::CalculateContentBEnd(aWM, child) + offset);
     }
     else {
       contentBEnd = std::max(contentBEnd, line->BEnd());
     }
   }
@@ -5748,17 +5748,17 @@ nsLayoutUtils::CalculateContentBEnd(Writ
     nsIFrame::ChildListIterator lists(aFrame);
     for (; !lists.IsDone(); lists.Next()) {
       if (!skip.Contains(lists.CurrentID())) {
         nsFrameList::Enumerator childFrames(lists.CurrentList()); 
         for (; !childFrames.AtEnd(); childFrames.Next()) {
           nsIFrame* child = childFrames.get();
           nscoord offset =
             child->GetLogicalNormalPosition(aWM,
-                                            aFrame->GetSize().width).B(aWM);
+                                            aFrame->GetSize()).B(aWM);
           contentBEnd = std::max(contentBEnd,
                                  CalculateContentBEnd(aWM, child) + offset);
         }
       }
     }
   }
   return contentBEnd;
 }
--- a/layout/forms/nsComboboxControlFrame.cpp
+++ b/layout/forms/nsComboboxControlFrame.cpp
@@ -458,29 +458,30 @@ nsComboboxControlFrame::ReflowDropdown(n
   // dropped down
   int32_t flags = mDroppedDown ? 0
                                : NS_FRAME_NO_MOVE_FRAME |
                                  NS_FRAME_NO_VISIBILITY |
                                  NS_FRAME_NO_SIZE_VIEW;
 
   //XXX Can this be different from the dropdown's writing mode?
   // That would be odd!
-  // Note that we don't need to pass the true frame position or container width
+  // Note that we don't need to pass the true frame position or container size
   // to ReflowChild or FinishReflowChild here; it will be positioned as needed
   // by AbsolutelyPositionDropDown().
   WritingMode outerWM = GetWritingMode();
+  const nsSize dummyContainerSize;
   nsHTMLReflowMetrics desiredSize(aReflowState);
   nsReflowStatus ignoredStatus;
   ReflowChild(mDropdownFrame, aPresContext, desiredSize,
-              kidReflowState, outerWM, LogicalPoint(outerWM), 0,
-              flags, ignoredStatus);
+              kidReflowState, outerWM, LogicalPoint(outerWM),
+              dummyContainerSize, flags, ignoredStatus);
 
    // Set the child's width and height to its desired size
   FinishReflowChild(mDropdownFrame, aPresContext, desiredSize, &kidReflowState,
-                    outerWM, LogicalPoint(outerWM), 0, flags);
+                    outerWM, LogicalPoint(outerWM), dummyContainerSize, flags);
 }
 
 nsPoint
 nsComboboxControlFrame::GetCSSTransformTranslation()
 {
   nsIFrame* frame = this;
   bool is3DTransform = false;
   Matrix transform;
@@ -570,39 +571,42 @@ nsComboboxControlFrame::GetAvailableDrop
   // location can change based on whether the dropdown is placed after
   // or before the display frame.  The approach taken here is to get the
   // absolute position of the display frame and use its location to
   // determine if the dropdown will go offscreen.
 
   // Normal frame geometry (eg GetOffsetTo, mRect) doesn't include transforms.
   // In the special case that our transform is only a 2D translation we
   // introduce this hack so that the dropdown will show up in the right place.
-  *aTranslation = LogicalPoint(aWM, GetCSSTransformTranslation(), 0);
+  // Use null container size when converting a vector from logical to physical.
+  const nsSize nullContainerSize;
+  *aTranslation = LogicalPoint(aWM, GetCSSTransformTranslation(),
+                               nullContainerSize);
   *aBefore = 0;
   *aAfter = 0;
 
   nsRect screen = nsFormControlFrame::GetUsableScreenRect(PresContext());
-  nscoord containerWidth = screen.width;
-  LogicalRect logicalScreen(aWM, screen, containerWidth);
+  nsSize containerSize = screen.Size();
+  LogicalRect logicalScreen(aWM, screen, containerSize);
   if (mLastDropDownAfterScreenBCoord == nscoord_MIN) {
     LogicalRect thisScreenRect(aWM, GetScreenRectInAppUnits(),
-                               containerWidth);
+                               containerSize);
     mLastDropDownAfterScreenBCoord = thisScreenRect.BEnd(aWM) +
                                      aTranslation->B(aWM);
     mLastDropDownBeforeScreenBCoord = thisScreenRect.BEnd(aWM) +
                                      aTranslation->B(aWM);
   }
 
   nscoord minBCoord;
   nsPresContext* pc = PresContext()->GetToplevelContentDocumentPresContext();
   nsIFrame* root = pc ? pc->PresShell()->GetRootFrame() : nullptr;
   if (root) {
     minBCoord = LogicalRect(aWM,
                             root->GetScreenRectInAppUnits(),
-                            containerWidth).BStart(aWM);
+                            containerSize).BStart(aWM);
     if (mLastDropDownAfterScreenBCoord < minBCoord) {
       // Don't allow the drop-down to be placed before the content area.
       return;
     }
   } else {
     minBCoord = logicalScreen.BStart(aWM);
   }
 
@@ -664,22 +668,22 @@ nsComboboxControlFrame::AbsolutelyPositi
   // Position the drop-down after if there is room, otherwise place it before
   // if there is room.  If there is no room for it on either side then place
   // it after (to avoid overlapping UI like the URL bar).
   bool b = dropdownSize.BSize(wm)<= after || dropdownSize.BSize(wm) > before;
   LogicalPoint dropdownPosition(wm, 0, b ? BSize(wm) : -dropdownSize.BSize(wm));
 
   // Don't position the view unless the position changed since it might cause
   // a call to NotifyGeometryChange() and an infinite loop here.
-  nscoord containerWidth = GetRect().width;
+  nsSize containerSize = GetSize();
   const LogicalPoint currentPos =
-    mDropdownFrame->GetLogicalPosition(containerWidth);
+    mDropdownFrame->GetLogicalPosition(containerSize);
   const LogicalPoint newPos = dropdownPosition + translation;
   if (currentPos != newPos) {
-    mDropdownFrame->SetPosition(wm, newPos, containerWidth);
+    mDropdownFrame->SetPosition(wm, newPos, containerSize);
     nsContainerFrame::PositionFrameView(mDropdownFrame);
   }
   return eDropDownPositionFinal;
 }
 
 void
 nsComboboxControlFrame::NotifyGeometryChange()
 {
@@ -861,32 +865,31 @@ nsComboboxControlFrame::Reflow(nsPresCon
   }
 
   mDisplayISize = aReflowState.ComputedISize() - buttonISize;
 
   nsBlockFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
 
   // The button should occupy the same space as a scrollbar
   WritingMode wm = aReflowState.GetWritingMode();
-  nscoord containerWidth =
-    aReflowState.ComputedSizeAsContainerIfConstrained().width;
-  LogicalRect buttonRect = mButtonFrame->GetLogicalRect(containerWidth);
+  nsSize containerSize = aReflowState.ComputedSizeAsContainerIfConstrained();
+  LogicalRect buttonRect = mButtonFrame->GetLogicalRect(containerSize);
 
   buttonRect.IStart(wm) =
     aReflowState.ComputedLogicalBorderPadding().IStartEnd(wm) +
     mDisplayISize -
     (aReflowState.ComputedLogicalBorderPadding().IEnd(wm) -
      aReflowState.ComputedLogicalPadding().IEnd(wm));
   buttonRect.ISize(wm) = buttonISize;
 
   buttonRect.BStart(wm) = this->GetLogicalUsedBorder(wm).BStart(wm);
   buttonRect.BSize(wm) = mDisplayFrame->BSize(wm) +
                          this->GetLogicalUsedPadding(wm).BStartEnd(wm);
 
-  mButtonFrame->SetRect(buttonRect, containerWidth);
+  mButtonFrame->SetRect(buttonRect, containerSize);
 
   if (!NS_INLINE_IS_BREAK_BEFORE(aStatus) &&
       !NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
     // This frame didn't fit inside a fragmentation container.  Splitting
     // a nsComboboxControlFrame makes no sense, so we override the status here.
     aStatus = NS_FRAME_COMPLETE;
   }
 }
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -50,23 +50,23 @@ nsFieldSetFrame::GetType() const
 
 nsRect
 nsFieldSetFrame::VisualBorderRectRelativeToSelf() const
 {
   WritingMode wm = GetWritingMode();
   css::Side legendSide = wm.PhysicalSide(eLogicalSideBStart);
   nscoord legendBorder = StyleBorder()->GetComputedBorderWidth(legendSide);
   LogicalRect r(wm, LogicalPoint(wm, 0, 0), GetLogicalSize(wm));
-  nscoord containerWidth = r.Width(wm);
+  nsSize containerSize = r.Size(wm).GetPhysicalSize(wm);
   if (legendBorder < mLegendRect.BSize(wm)) {
     nscoord off = (mLegendRect.BSize(wm) - legendBorder) / 2;
     r.BStart(wm) += off;
     r.BSize(wm) -= off;
   }
-  return r.GetPhysicalRect(wm, containerWidth);
+  return r.GetPhysicalRect(wm, containerSize);
 }
 
 nsIFrame*
 nsFieldSetFrame::GetInner() const
 {
   nsIFrame* last = mFrames.LastChild();
   if (last &&
       last->StyleContext()->GetPseudo() == nsCSSAnonBoxes::fieldsetContent) {
@@ -232,57 +232,56 @@ nsFieldSetFrame::PaintBorderBackground(n
 
   if (nsIFrame* legend = GetLegend()) {
     css::Side legendSide = wm.PhysicalSide(eLogicalSideBStart);
     nscoord legendBorderWidth =
       StyleBorder()->GetComputedBorderWidth(legendSide);
 
     // Use the rect of the legend frame, not mLegendRect, so we draw our
     // border under the legend's inline-start and -end margins.
-    LogicalRect legendRect(wm, legend->GetRect() + aPt, rect.width);
+    LogicalRect legendRect(wm, legend->GetRect() + aPt, rect.Size());
 
     // Compute clipRect using logical coordinates, so that the legend space
     // will be clipped out of the appropriate physical side depending on mode.
-    LogicalRect clipRect = LogicalRect(wm, rect, rect.width);
+    LogicalRect clipRect = LogicalRect(wm, rect, rect.Size());
     DrawTarget* drawTarget = aRenderingContext.GetDrawTarget();
     gfxContext* gfx = aRenderingContext.ThebesContext();
     int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
 
     // draw inline-start portion of the block-start side of the border
     clipRect.ISize(wm) = legendRect.IStart(wm) - clipRect.IStart(wm);
     clipRect.BSize(wm) = legendBorderWidth;
 
     gfx->Save();
-    gfx->Clip(NSRectToSnappedRect(clipRect.GetPhysicalRect(wm, rect.width),
+    gfx->Clip(NSRectToSnappedRect(clipRect.GetPhysicalRect(wm, rect.Size()),
                                   appUnitsPerDevPixel, *drawTarget));
     nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
                                 aDirtyRect, rect, mStyleContext);
     gfx->Restore();
 
     // draw inline-end portion of the block-start side of the border
-    clipRect = LogicalRect(wm, rect, rect.width);
+    clipRect = LogicalRect(wm, rect, rect.Size());
     clipRect.ISize(wm) = clipRect.IEnd(wm) - legendRect.IEnd(wm);
     clipRect.IStart(wm) = legendRect.IEnd(wm);
     clipRect.BSize(wm) = legendBorderWidth;
 
     gfx->Save();
-    gfx->Clip(NSRectToSnappedRect(clipRect.GetPhysicalRect(wm, rect.width),
+    gfx->Clip(NSRectToSnappedRect(clipRect.GetPhysicalRect(wm, rect.Size()),
                                   appUnitsPerDevPixel, *drawTarget));
     nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
                                 aDirtyRect, rect, mStyleContext);
     gfx->Restore();
 
     // draw remainder of the border (omitting the block-start side)
-    clipRect = LogicalRect(wm, rect, rect.width);
+    clipRect = LogicalRect(wm, rect, rect.Size());
     clipRect.BStart(wm) += legendBorderWidth;
-    clipRect.BSize(wm) =
-      GetLogicalRect(rect.width).BSize(wm) - (off + legendBorderWidth);
+    clipRect.BSize(wm) = BSize(wm) - (off + legendBorderWidth);
 
     gfx->Save();
-    gfx->Clip(NSRectToSnappedRect(clipRect.GetPhysicalRect(wm, rect.width),
+    gfx->Clip(NSRectToSnappedRect(clipRect.GetPhysicalRect(wm, rect.Size()),
                                   appUnitsPerDevPixel, *drawTarget));
     nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
                                 aDirtyRect, rect, mStyleContext);
     gfx->Restore();
   } else {
     nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
                                 aDirtyRect,
                                 nsRect(aPt, mRect.Size()),
@@ -444,18 +443,22 @@ nsFieldSetFrame::Reflow(nsPresContext*  
   Maybe<nsHTMLReflowState> legendReflowState;
   if (legend) {
     legendReflowState.emplace(aPresContext, aReflowState, legend,
                                 legendAvailSize);
   }
   if (reflowLegend) {
     nsHTMLReflowMetrics legendDesiredSize(aReflowState);
 
+    // We'll move the legend to its proper place later, so the position
+    // and containerSize passed here are unimportant.
+    const nsSize dummyContainerSize;
     ReflowChild(legend, aPresContext, legendDesiredSize, *legendReflowState,
-                wm, LogicalPoint(wm), 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
+                wm, LogicalPoint(wm), dummyContainerSize,
+                NS_FRAME_NO_MOVE_FRAME, aStatus);
 #ifdef NOISY_REFLOW
     printf("  returned (%d, %d)\n",
            legendDesiredSize.Width(), legendDesiredSize.Height());
 #endif
     // figure out the legend's rectangle
     legendMargin = legend->GetLogicalUsedMargin(wm);
     mLegendRect =
       LogicalRect(wm, 0, 0,
@@ -472,31 +475,32 @@ nsFieldSetFrame::Reflow(nsPresContext*  
     }
 
     // if the legend space changes then we need to reflow the
     // content area as well.
     if (mLegendSpace != oldSpace && inner) {
       reflowInner = true;
     }
 
-    // We'll move the legend to its proper place later.
     FinishReflowChild(legend, aPresContext, legendDesiredSize,
-                      legendReflowState.ptr(), wm, LogicalPoint(wm), 0,
-                      NS_FRAME_NO_MOVE_FRAME);
+                      legendReflowState.ptr(), wm, LogicalPoint(wm),
+                      dummyContainerSize, NS_FRAME_NO_MOVE_FRAME);
   } else if (!legend) {
     mLegendRect.SetEmpty();
     mLegendSpace = 0;
   } else {
     // mLegendSpace and mLegendRect haven't changed, but we need
     // the used margin when placing the legend.
     legendMargin = legend->GetLogicalUsedMargin(wm);
   }
 
-  nscoord containerWidth = (wm.IsVertical() ? mLegendSpace : 0) +
-                            border.LeftRight(wm);
+  // This containerSize is incomplete as yet: it does not include the size
+  // of the |inner| frame itself.
+  nsSize containerSize = (LogicalSize(wm, 0, mLegendSpace) +
+                          border.Size(wm)).GetPhysicalSize(wm);
   // reflow the content frame only if needed
   if (reflowInner) {
     nsHTMLReflowState kidReflowState(aPresContext, aReflowState, inner,
                                      innerAvailSize, nullptr,
                                      nsHTMLReflowState::CALLER_WILL_INIT);
     // Override computed padding, in case it's percentage padding
     kidReflowState.Init(aPresContext, nullptr, nullptr,
                         &aReflowState.ComputedPhysicalPadding());
@@ -520,36 +524,41 @@ nsFieldSetFrame::Reflow(nsPresContext*  
 
     nsHTMLReflowMetrics kidDesiredSize(kidReflowState,
                                        aDesiredSize.mFlags);
     // Reflow the frame
     NS_ASSERTION(kidReflowState.ComputedPhysicalMargin() == nsMargin(0,0,0,0),
                  "Margins on anonymous fieldset child not supported!");
     LogicalPoint pt(wm, border.IStart(wm), border.BStart(wm) + mLegendSpace);
 
+    // We don't know the correct containerSize until we have reflowed |inner|,
+    // so we use a dummy value for now; FinishReflowChild will fix the position
+    // if necessary.
+    const nsSize dummyContainerSize;
     ReflowChild(inner, aPresContext, kidDesiredSize, kidReflowState,
-                wm, pt, containerWidth, 0, aStatus);
+                wm, pt, dummyContainerSize, 0, aStatus);
 
-    // update the container width after reflowing the inner frame
+    // Update containerSize to account for size of the inner frame, so that
+    // FinishReflowChild can position it correctly.
+    containerSize += kidDesiredSize.PhysicalSize();
     FinishReflowChild(inner, aPresContext, kidDesiredSize,
-                      &kidReflowState, wm, pt,
-                      containerWidth + kidDesiredSize.Width(), 0);
+                      &kidReflowState, wm, pt, containerSize, 0);
     NS_FRAME_TRACE_REFLOW_OUT("FieldSet::Reflow", aStatus);
-  }
-
-  if (inner) {
-    containerWidth += inner->GetSize().width;
+  } else if (inner) {
+    // |inner| didn't need to be reflowed but we do need to include its size
+    // in containerSize.
+    containerSize += inner->GetSize();
   }
 
   LogicalRect contentRect(wm);
   if (inner) {
     // We don't support margins on inner, so our content rect is just the
-    // inner's border-box. We don't care about container-width at this point,
-    // as we'll figure out the actual positioning later.
-    contentRect = inner->GetLogicalRect(wm, containerWidth);
+    // inner's border-box. (We don't really care about container size at this
+    // point, as we'll figure out the actual positioning later.)
+    contentRect = inner->GetLogicalRect(wm, containerSize);
   }
 
   // Our content rect must fill up the available width
   LogicalSize availSize = aReflowState.ComputedSizeWithPadding(wm);
   if (availSize.ISize(wm) > contentRect.ISize(wm)) {
     contentRect.ISize(wm) = innerAvailSize.ISize(wm);
   }
 
@@ -602,19 +611,19 @@ nsFieldSetFrame::Reflow(nsPresContext*  
 
     // Note that legend's writing mode may be different from the fieldset's,
     // so we need to convert offsets before applying them to it (bug 1134534).
     LogicalMargin offsets =
       legendReflowState->ComputedLogicalOffsets().
         ConvertTo(wm, legendReflowState->GetWritingMode());
     nsHTMLReflowState::ApplyRelativePositioning(legend, wm, offsets,
                                                 &actualLegendPos,
-                                                containerWidth);
+                                                containerSize);
 
-    legend->SetPosition(wm, actualLegendPos, containerWidth);
+    legend->SetPosition(wm, actualLegendPos, containerSize);
     nsContainerFrame::PositionFrameView(legend);
     nsContainerFrame::PositionChildViews(legend);
   }
 
   // Return our size and our result.
   LogicalSize finalSize(wm, contentRect.ISize(wm) + border.IStartEnd(wm),
                         mLegendSpace + border.BStartEnd(wm) +
                         (inner ? inner->BSize(wm) : 0));
@@ -677,11 +686,11 @@ nsFieldSetFrame::AccessibleType()
   return a11y::eHTMLGroupboxType;
 }
 #endif
 
 nscoord
 nsFieldSetFrame::GetLogicalBaseline(WritingMode aWritingMode) const
 {
   nsIFrame* inner = GetInner();
-  return inner->BStart(aWritingMode, GetParent()->GetSize().width) +
+  return inner->BStart(aWritingMode, GetParent()->GetSize()) +
     inner->GetLogicalBaseline(aWritingMode);
 }
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -315,21 +315,22 @@ nsHTMLButtonControlFrame::ReflowButtonCo
                                         adjustedButtonReflowState,
                                         aFirstKid, availSize);
 
   nsReflowStatus contentsReflowStatus;
   nsHTMLReflowMetrics contentsDesiredSize(aButtonReflowState);
   childPos.B(wm) = 0; // This will be set properly later, after reflowing the
                       // child to determine its size.
 
-  // We just pass 0 for containerWidth here, as the child will be repositioned
-  // later by FinishReflowChild.
+  // We just pass a dummy containerSize here, as the child will be
+  // repositioned later by FinishReflowChild.
+  nsSize dummyContainerSize;
   ReflowChild(aFirstKid, aPresContext,
               contentsDesiredSize, contentsReflowState,
-              wm, childPos, 0, 0, contentsReflowStatus);
+              wm, childPos, dummyContainerSize, 0, contentsReflowStatus);
   MOZ_ASSERT(NS_FRAME_IS_COMPLETE(contentsReflowStatus),
              "We gave button-contents frame unconstrained available height, "
              "so it should be complete");
 
   // Compute the button's content-box size:
   LogicalSize buttonContentBox(wm);
   if (aButtonReflowState.ComputedBSize() != NS_INTRINSICSIZE) {
     // Button has a fixed block-size -- that's its content-box bSize.
@@ -368,22 +369,23 @@ nsHTMLButtonControlFrame::ReflowButtonCo
     contentsDesiredSize.BSize(wm);
 
   childPos.B(wm) = std::max(0, extraSpace / 2);
 
   // Adjust childPos.B() to be in terms of the button's frame-rect, instead of
   // its focus-padding rect:
   childPos.B(wm) += focusPadding.BStart(wm) + clbp.BStart(wm);
 
-  nscoord containerWidth = buttonContentBox.Width(wm) + clbp.LeftRight(wm);
+  nsSize containerSize =
+    (buttonContentBox + clbp.Size(wm)).GetPhysicalSize(wm);
 
   // Place the child
   FinishReflowChild(aFirstKid, aPresContext,
                     contentsDesiredSize, &contentsReflowState,
-                    wm, childPos, containerWidth, 0);
+                    wm, childPos, containerSize, 0);
 
   // Make sure we have a useful 'ascent' value for the child
   if (contentsDesiredSize.BlockStartAscent() ==
       nsHTMLReflowMetrics::ASK_FOR_BASELINE) {
     WritingMode wm = aButtonReflowState.GetWritingMode();
     contentsDesiredSize.SetBlockStartAscent(aFirstKid->GetLogicalBaseline(wm));
   }
 
--- a/layout/forms/nsNumberControlFrame.cpp
+++ b/layout/forms/nsNumberControlFrame.cpp
@@ -170,18 +170,22 @@ nsNumberControlFrame::Reflow(nsPresConte
     LogicalPoint
       wrapperOffset(myWM,
                     aReflowState.ComputedLogicalBorderPadding().IStart(myWM) +
                     wrapperMargin.IStart(myWM),
                     aReflowState.ComputedLogicalBorderPadding().BStart(myWM) +
                     wrapperMargin.BStart(myWM));
 
     nsReflowStatus childStatus;
+    // We initially reflow the child with a dummy containerSize; positioning
+    // will be fixed later.
+    const nsSize dummyContainerSize;
     ReflowChild(outerWrapperFrame, aPresContext, wrappersDesiredSize,
-                wrapperReflowState, myWM, wrapperOffset, 0, 0, childStatus);
+                wrapperReflowState, myWM, wrapperOffset, dummyContainerSize, 0,
+                childStatus);
     MOZ_ASSERT(NS_FRAME_IS_FULLY_COMPLETE(childStatus),
                "We gave our child unconstrained available block-size, "
                "so it should be complete");
 
     nscoord wrappersMarginBoxBSize =
       wrappersDesiredSize.BSize(myWM) + wrapperMargin.BStartEnd(myWM);
 
     if (contentBoxBSize == NS_INTRINSICSIZE) {
@@ -203,28 +207,31 @@ nsNumberControlFrame::Reflow(nsPresConte
         aReflowState.ComputedLogicalBorderPadding().BStartEnd(myWM);
     }
 
     // Center child in block axis
     nscoord extraSpace = contentBoxBSize - wrappersMarginBoxBSize;
     wrapperOffset.B(myWM) += std::max(0, extraSpace / 2);
 
     // Needed in FinishReflowChild, for logical-to-physical conversion:
-    nscoord borderBoxWidth = myWM.IsVertical() ?
-      borderBoxBSize : borderBoxISize;
+    nsSize borderBoxSize = LogicalSize(myWM, borderBoxISize, borderBoxBSize).
+                           GetPhysicalSize(myWM);
 
     // Place the child
     FinishReflowChild(outerWrapperFrame, aPresContext, wrappersDesiredSize,
                       &wrapperReflowState, myWM, wrapperOffset,
-                      borderBoxWidth, 0);
+                      borderBoxSize, 0);
 
+    nsSize contentBoxSize =
+      LogicalSize(myWM, contentBoxISize, contentBoxBSize).
+        GetPhysicalSize(myWM);
     aDesiredSize.SetBlockStartAscent(
        wrappersDesiredSize.BlockStartAscent() +
        outerWrapperFrame->BStart(aReflowState.GetWritingMode(),
-                                 contentBoxISize));
+                                 contentBoxSize));
   }
 
   LogicalSize logicalDesiredSize(myWM, borderBoxISize, borderBoxBSize);
   aDesiredSize.SetSize(myWM, logicalDesiredSize);
 
   aDesiredSize.SetOverflowAreasToDesiredBounds();
 
   if (outerWrapperFrame) {
--- a/layout/generic/TextOverflow.cpp
+++ b/layout/generic/TextOverflow.cpp
@@ -258,21 +258,21 @@ nsDisplayTextOverflowMarker::PaintTextTo
                               mStyle->mString.Length(), pt);
   }
 }
 
 TextOverflow::TextOverflow(nsDisplayListBuilder* aBuilder,
                            nsIFrame* aBlockFrame)
   : mContentArea(aBlockFrame->GetWritingMode(),
                  aBlockFrame->GetContentRectRelativeToSelf(),
-                 aBlockFrame->GetRect().width)
+                 aBlockFrame->GetSize())
   , mBuilder(aBuilder)
   , mBlock(aBlockFrame)
   , mScrollableFrame(nsLayoutUtils::GetScrollableFrameFor(aBlockFrame))
-  , mBlockWidth(aBlockFrame->GetRect().width)
+  , mBlockSize(aBlockFrame->GetSize())
   , mBlockWM(aBlockFrame->GetWritingMode())
   , mAdjustForPixelSnapping(false)
 {
 #ifdef MOZ_XUL
   if (!mScrollableFrame) {
     nsIAtom* pseudoType = aBlockFrame->StyleContext()->GetPseudo();
     if (pseudoType == nsCSSAnonBoxes::mozXULAnonymousBlock) {
       mScrollableFrame =
@@ -291,19 +291,22 @@ TextOverflow::TextOverflow(nsDisplayList
       mScrollableFrame->GetScrollbarStyles().mVertical :
       mScrollableFrame->GetScrollbarStyles().mHorizontal;
     mCanHaveInlineAxisScrollbar = scrollbarStyle != NS_STYLE_OVERFLOW_HIDDEN;
     if (!mAdjustForPixelSnapping) {
       // Scrolling to the end position can leave some text still overflowing due
       // to pixel snapping behaviour in our scrolling code.
       mAdjustForPixelSnapping = mCanHaveInlineAxisScrollbar;
     }
+    // Use a null containerSize to convert a vector from logical to physical.
+    const nsSize nullContainerSize;
     mContentArea.MoveBy(mBlockWM,
                         LogicalPoint(mBlockWM,
-                                     mScrollableFrame->GetScrollPosition(), 0));
+                                     mScrollableFrame->GetScrollPosition(),
+                                     nullContainerSize));
     nsIFrame* scrollFrame = do_QueryFrame(mScrollableFrame);
     scrollFrame->AddStateBits(NS_SCROLLFRAME_INVALIDATE_CONTENTS_ON_SCROLL);
   }
   uint8_t direction = aBlockFrame->StyleVisibility()->mDirection;
   const nsStyleTextReset* style = aBlockFrame->StyleTextReset();
   if (mBlockWM.IsBidiLTR()) {
     mIStart.Init(style->mTextOverflow.GetLeft(direction));
     mIEnd.Init(style->mTextOverflow.GetRight(direction));
@@ -389,17 +392,17 @@ TextOverflow::AnalyzeMarkerEdges(nsIFram
                                  FrameHashtable* aFramesToHide,
                                  AlignmentEdges* aAlignmentEdges,
                                  bool*           aFoundVisibleTextOrAtomic,
                                  InnerClipEdges* aClippedMarkerEdges)
 {
   LogicalRect borderRect(mBlockWM,
                          nsRect(aFrame->GetOffsetTo(mBlock),
                                 aFrame->GetSize()),
-                         mBlockWidth);
+                         mBlockSize);
   nscoord istartOverlap = std::max(
     aInsideMarkersArea.IStart(mBlockWM) - borderRect.IStart(mBlockWM), 0);
   nscoord iendOverlap = std::max(
     borderRect.IEnd(mBlockWM) - aInsideMarkersArea.IEnd(mBlockWM), 0);
   bool insideIStartEdge =
     aInsideMarkersArea.IStart(mBlockWM) <= borderRect.IEnd(mBlockWM);
   bool insideIEndEdge =
     borderRect.IStart(mBlockWM) <= aInsideMarkersArea.IEnd(mBlockWM);
@@ -463,36 +466,36 @@ TextOverflow::ExamineLineFrames(nsLineBo
                                 FrameHashtable* aFramesToHide,
                                 AlignmentEdges* aAlignmentEdges)
 {
   // No ellipsing for 'clip' style.
   bool suppressIStart = mIStart.mStyle->mType == NS_STYLE_TEXT_OVERFLOW_CLIP;
   bool suppressIEnd = mIEnd.mStyle->mType == NS_STYLE_TEXT_OVERFLOW_CLIP;
   if (mCanHaveInlineAxisScrollbar) {
     LogicalPoint pos(mBlockWM, mScrollableFrame->GetScrollPosition(),
-                     mBlockWidth);
+                     mBlockSize);
     LogicalRect scrollRange(mBlockWM, mScrollableFrame->GetScrollRange(),
-                            mBlockWidth);
+                            mBlockSize);
     // No ellipsing when nothing to scroll to on that side (this includes
     // overflow:auto that doesn't trigger a horizontal scrollbar).
     if (pos.I(mBlockWM) <= scrollRange.IStart(mBlockWM)) {
       suppressIStart = true;
     }
     if (pos.I(mBlockWM) >= scrollRange.IEnd(mBlockWM)) {
       suppressIEnd = true;
     }
   }
 
   LogicalRect contentArea = mContentArea;
   const nscoord scrollAdjust = mAdjustForPixelSnapping ?
     mBlock->PresContext()->AppUnitsPerDevPixel() : 0;
   InflateIStart(mBlockWM, &contentArea, scrollAdjust);
   InflateIEnd(mBlockWM, &contentArea, scrollAdjust);
   LogicalRect lineRect(mBlockWM, aLine->GetScrollableOverflowArea(),
-                       mBlockWidth);
+                       mBlockSize);
   const bool istartOverflow =
     !suppressIStart && lineRect.IStart(mBlockWM) < contentArea.IStart(mBlockWM);
   const bool iendOverflow =
     !suppressIEnd && lineRect.IEnd(mBlockWM) > contentArea.IEnd(mBlockWM);
   if (!istartOverflow && !iendOverflow) {
     // The line does not overflow on a side we should ellipsize.
     return;
   }
@@ -755,35 +758,35 @@ TextOverflow::CreateMarkers(const nsLine
   if (aCreateIStart) {
     DisplayListClipState::AutoSaveRestore clipState(mBuilder);
 
     LogicalRect markerLogicalRect(
       mBlockWM, aInsideMarkersArea.IStart(mBlockWM) - mIStart.mIntrinsicISize,
       aLine->BStart(), mIStart.mIntrinsicISize, aLine->BSize());
     nsPoint offset = mBuilder->ToReferenceFrame(mBlock);
     nsRect markerRect =
-      markerLogicalRect.GetPhysicalRect(mBlockWM, mBlockWidth) + offset;
-    ClipMarker(mContentArea.GetPhysicalRect(mBlockWM, mBlockWidth) + offset,
+      markerLogicalRect.GetPhysicalRect(mBlockWM, mBlockSize) + offset;
+    ClipMarker(mContentArea.GetPhysicalRect(mBlockWM, mBlockSize) + offset,
                markerRect, clipState);
     nsDisplayItem* marker = new (mBuilder)
       nsDisplayTextOverflowMarker(mBuilder, mBlock, markerRect,
                                   aLine->GetLogicalAscent(), mIStart.mStyle, 0);
     mMarkerList.AppendNewToTop(marker);
   }
 
   if (aCreateIEnd) {
     DisplayListClipState::AutoSaveRestore clipState(mBuilder);
 
     LogicalRect markerLogicalRect(
       mBlockWM, aInsideMarkersArea.IEnd(mBlockWM), aLine->BStart(),
       mIEnd.mIntrinsicISize, aLine->BSize());
     nsPoint offset = mBuilder->ToReferenceFrame(mBlock);
     nsRect markerRect =
-      markerLogicalRect.GetPhysicalRect(mBlockWM, mBlockWidth) + offset;
-    ClipMarker(mContentArea.GetPhysicalRect(mBlockWM, mBlockWidth) + offset,
+      markerLogicalRect.GetPhysicalRect(mBlockWM, mBlockSize) + offset;
+    ClipMarker(mContentArea.GetPhysicalRect(mBlockWM, mBlockSize) + offset,
                markerRect, clipState);
     nsDisplayItem* marker = new (mBuilder)
       nsDisplayTextOverflowMarker(mBuilder, mBlock, markerRect,
                                   aLine->GetLogicalAscent(), mIEnd.mStyle, 1);
     mMarkerList.AppendNewToTop(marker);
   }
 }
 
--- a/layout/generic/TextOverflow.h
+++ b/layout/generic/TextOverflow.h
@@ -112,17 +112,17 @@ class TextOverflow {
   };
 
   LogicalRect
     GetLogicalScrollableOverflowRectRelativeToBlock(nsIFrame* aFrame) const
   {
     return LogicalRect(mBlockWM,
                        aFrame->GetScrollableOverflowRect() +
                          aFrame->GetOffsetTo(mBlock),
-                       mBlockWidth);
+                       mBlockSize);
   }
 
   /**
    * Examines frames on the line to determine whether we should draw a left
    * and/or right marker, and if so, which frames should be completely hidden
    * and the bounds of what will be displayed between the markers.
    * @param aLine the line we're processing
    * @param aFramesToHide frames that should have their display items removed
@@ -205,17 +205,17 @@ class TextOverflow {
                      bool aCreateIStart, bool aCreateIEnd,
                      const LogicalRect& aInsideMarkersArea);
 
   LogicalRect            mContentArea;
   nsDisplayListBuilder*  mBuilder;
   nsIFrame*              mBlock;
   nsIScrollableFrame*    mScrollableFrame;
   nsDisplayList          mMarkerList;
-  nscoord                mBlockWidth;
+  nsSize                 mBlockSize;
   WritingMode            mBlockWM;
   bool                   mCanHaveInlineAxisScrollbar;
   bool                   mAdjustForPixelSnapping;
 
   class Marker {
   public:
     void Init(const nsStyleTextOverflowSide& aStyle) {
       mInitialized = false;
--- a/layout/generic/WritingModes.h
+++ b/layout/generic/WritingModes.h
@@ -636,64 +636,50 @@ public:
     :
 #ifdef DEBUG
       mWritingMode(aWritingMode),
 #endif
       mPoint(aI, aB)
   { }
 
   // Construct from a writing mode and a physical point, within a given
-  // containing rectangle's width (defining the conversion between LTR
+  // containing rectangle's size (defining the conversion between LTR
   // and RTL coordinates).
   LogicalPoint(WritingMode aWritingMode,
                const nsPoint& aPoint,
-               nscoord aContainerWidth)
+               const nsSize& aContainerSize)
 #ifdef DEBUG
     : mWritingMode(aWritingMode)
 #endif
   {
     if (aWritingMode.IsVertical()) {
       I() = aPoint.y;
-      B() = aWritingMode.IsVerticalLR() ? aPoint.x : aContainerWidth - aPoint.x;
+      B() = aWritingMode.IsVerticalLR() ? aPoint.x
+                                        : aContainerSize.width - aPoint.x;
     } else {
-      I() = aWritingMode.IsBidiLTR() ? aPoint.x : aContainerWidth - aPoint.x;
+      I() = aWritingMode.IsBidiLTR() ? aPoint.x
+                                     : aContainerSize.width - aPoint.x;
       B() = aPoint.y;
     }
   }
 
   /**
-   * Read-only (const) access to the coordinates, in both logical
-   * and physical terms.
+   * Read-only (const) access to the logical coordinates.
    */
   nscoord I(WritingMode aWritingMode) const // inline-axis
   {
     CHECK_WRITING_MODE(aWritingMode);
     return mPoint.x;
   }
   nscoord B(WritingMode aWritingMode) const // block-axis
   {
     CHECK_WRITING_MODE(aWritingMode);
     return mPoint.y;
   }
 
-  nscoord X(WritingMode aWritingMode, nscoord aContainerWidth) const
-  {
-    CHECK_WRITING_MODE(aWritingMode);
-    if (aWritingMode.IsVertical()) {
-      return aWritingMode.IsVerticalLR() ? B() : aContainerWidth - B();
-    } else {
-      return aWritingMode.IsBidiLTR() ? I() : aContainerWidth - I();
-    }
-  }
-  nscoord Y(WritingMode aWritingMode) const
-  {
-    CHECK_WRITING_MODE(aWritingMode);
-    return aWritingMode.IsVertical() ? I() : B();
-  }
-
   /**
    * These non-const accessors return a reference (lvalue) that can be
    * assigned to by callers.
    */
   nscoord& I(WritingMode aWritingMode) // inline-axis
   {
     CHECK_WRITING_MODE(aWritingMode);
     return mPoint.x;
@@ -704,39 +690,41 @@ public:
     return mPoint.y;
   }
 
   /**
    * Return a physical point corresponding to our logical coordinates,
    * converted according to our writing mode.
    */
   nsPoint GetPhysicalPoint(WritingMode aWritingMode,
-                           nscoord aContainerWidth) const
+                           const nsSize& aContainerSize) const
   {
     CHECK_WRITING_MODE(aWritingMode);
     if (aWritingMode.IsVertical()) {
-      return nsPoint(aWritingMode.IsVerticalLR() ? B() : aContainerWidth - B(),
+      return nsPoint(aWritingMode.IsVerticalLR()
+                     ? B() : aContainerSize.width - B(),
                      I());
     } else {
-      return nsPoint(aWritingMode.IsBidiLTR() ? I() : aContainerWidth - I(),
+      return nsPoint(aWritingMode.IsBidiLTR()
+                     ? I() : aContainerSize.width - I(),
                      B());
     }
   }
 
   /**
    * Return the equivalent point in a different writing mode.
    */
   LogicalPoint ConvertTo(WritingMode aToMode, WritingMode aFromMode,
-                         nscoord aContainerWidth) const
+                         const nsSize& aContainerSize) const
   {
     CHECK_WRITING_MODE(aFromMode);
     return aToMode == aFromMode ?
       *this : LogicalPoint(aToMode,
-                           GetPhysicalPoint(aFromMode, aContainerWidth),
-                           aContainerWidth);
+                           GetPhysicalPoint(aFromMode, aContainerSize),
+                           aContainerSize);
   }
 
   bool operator==(const LogicalPoint& aOther) const
   {
     CHECK_WRITING_MODE(aOther.GetWritingMode());
     return mPoint == aOther.mPoint;
   }
 
@@ -940,17 +928,17 @@ public:
     // expected writing mode
     CHECK_WRITING_MODE(aFromMode);
     return aToMode == aFromMode ?
       *this : LogicalSize(aToMode, GetPhysicalSize(aFromMode));
 #else
     // optimization for non-DEBUG builds where LogicalSize doesn't store
     // the writing mode
     return (aToMode == aFromMode || !aToMode.IsOrthogonalTo(aFromMode))
-             ? *this : LogicalSize(aToMode, BSize(), ISize());
+           ? *this : LogicalSize(aToMode, BSize(), ISize());
 #endif
   }
 
   /**
    * Test if a size is (0, 0).
    */
   bool IsAllZero() const
   {
@@ -1210,26 +1198,26 @@ public:
 
   /**
    * Return an nsMargin containing our physical coordinates
    */
   nsMargin GetPhysicalMargin(WritingMode aWritingMode) const
   {
     CHECK_WRITING_MODE(aWritingMode);
     return aWritingMode.IsVertical()
-      ? (aWritingMode.IsVerticalLR()
-        ? (aWritingMode.IsBidiLTR()
-          ? nsMargin(IStart(), BEnd(), IEnd(), BStart())
-          : nsMargin(IEnd(), BEnd(), IStart(), BStart()))
-        : (aWritingMode.IsBidiLTR()
-          ? nsMargin(IStart(), BStart(), IEnd(), BEnd())
-          : nsMargin(IEnd(), BStart(), IStart(), BEnd())))
-      : (aWritingMode.IsBidiLTR()
-        ? nsMargin(BStart(), IEnd(), BEnd(), IStart())
-        : nsMargin(BStart(), IStart(), BEnd(), IEnd()));
+           ? (aWritingMode.IsVerticalLR()
+             ? (aWritingMode.IsBidiLTR()
+               ? nsMargin(IStart(), BEnd(), IEnd(), BStart())
+               : nsMargin(IEnd(), BEnd(), IStart(), BStart()))
+             : (aWritingMode.IsBidiLTR()
+               ? nsMargin(IStart(), BStart(), IEnd(), BEnd())
+               : nsMargin(IEnd(), BStart(), IStart(), BEnd())))
+           : (aWritingMode.IsBidiLTR()
+             ? nsMargin(BStart(), IEnd(), BEnd(), IStart())
+             : nsMargin(BStart(), IStart(), BEnd(), IEnd()));
   }
 
   /**
    * Return a LogicalMargin representing this margin in a different
    * writing mode
    */
   LogicalMargin ConvertTo(WritingMode aToMode, WritingMode aFromMode) const
   {
@@ -1378,38 +1366,32 @@ public:
       mRect(aOrigin.mPoint, aSize.mSize)
   {
     CHECK_WRITING_MODE(aOrigin.GetWritingMode());
     CHECK_WRITING_MODE(aSize.GetWritingMode());
   }
 
   LogicalRect(WritingMode aWritingMode,
               const nsRect& aRect,
-              nscoord aContainerWidth)
+              const nsSize& aContainerSize)
 #ifdef DEBUG
     : mWritingMode(aWritingMode)
 #endif
   {
     if (aWritingMode.IsVertical()) {
-      if (aWritingMode.IsVerticalLR()) {
-        mRect.y = aRect.x;
-      } else {
-        mRect.y = aContainerWidth - aRect.XMost();
-      }
+      mRect.y = aWritingMode.IsVerticalLR()
+                ? aRect.x : aContainerSize.width - aRect.XMost();
+      mRect.x = aRect.y;
       mRect.height = aRect.width;
-      mRect.x = aRect.y;
       mRect.width = aRect.height;
     } else {
-      if (aWritingMode.IsBidiLTR()) {
-        mRect.x = aRect.x;
-      } else {
-        mRect.x = aContainerWidth - aRect.XMost();
-      }
+      mRect.x = aWritingMode.IsBidiLTR()
+                ? aRect.x : aContainerSize.width - aRect.XMost();
+      mRect.y = aRect.y;
       mRect.width = aRect.width;
-      mRect.y = aRect.y;
       mRect.height = aRect.height;
     }
   }
 
   /**
    * Inline- and block-dimension geometry.
    */
   nscoord IStart(WritingMode aWritingMode) const // inline-start edge
@@ -1467,34 +1449,36 @@ public:
   {
     CHECK_WRITING_MODE(aWritingMode);
     return mRect.height;
   }
 
   /**
    * Accessors for line-relative coordinates
    */
-  nscoord LineLeft(WritingMode aWritingMode, nscoord aContainerWidth) const
+  nscoord LineLeft(WritingMode aWritingMode,
+                   const nsSize& aContainerSize) const
   {
     CHECK_WRITING_MODE(aWritingMode);
     if (aWritingMode.IsVertical()) {
-      return IStart(); // sideways-left will require aContainerHeight
+      return IStart();
     } else {
       return aWritingMode.IsBidiLTR() ? IStart()
-                                      : aContainerWidth - IEnd();
+                                      : aContainerSize.width - IEnd();
     }
   }
-  nscoord LineRight(WritingMode aWritingMode, nscoord aContainerWidth) const
+  nscoord LineRight(WritingMode aWritingMode,
+                    const nsSize& aContainerSize) const
   {
     CHECK_WRITING_MODE(aWritingMode);
     if (aWritingMode.IsVertical()) {
-      return IEnd(); // sideways-left will require aContainerHeight
+      return IEnd();
     } else {
       return aWritingMode.IsBidiLTR() ? IEnd()
-                                      : aContainerWidth - IStart();
+                                      : aContainerSize.width - IStart();
     }
   }
 
   /**
    * Physical coordinates of the rect.
    */
   nscoord X(WritingMode aWritingMode, nscoord aContainerWidth) const
   {
@@ -1503,20 +1487,24 @@ public:
       return aWritingMode.IsVerticalLR() ?
              mRect.Y() : aContainerWidth - mRect.YMost();
     } else {
       return aWritingMode.IsBidiLTR() ?
              mRect.X() : aContainerWidth - mRect.XMost();
     }
   }
 
-  nscoord Y(WritingMode aWritingMode) const
+  nscoord Y(WritingMode aWritingMode, nscoord aContainerHeight) const
   {
     CHECK_WRITING_MODE(aWritingMode);
-    return aWritingMode.IsVertical() ? mRect.X() : mRect.Y();
+    if (aWritingMode.IsVertical()) {
+      return mRect.X();
+    } else {
+      return mRect.Y();
+    }
   }
 
   nscoord Width(WritingMode aWritingMode) const
   {
     CHECK_WRITING_MODE(aWritingMode);
     return aWritingMode.IsVertical() ? mRect.Height() : mRect.Width();
   }
 
@@ -1533,20 +1521,24 @@ public:
       return aWritingMode.IsVerticalLR() ?
              mRect.YMost() : aContainerWidth - mRect.Y();
     } else {
       return aWritingMode.IsBidiLTR() ?
              mRect.XMost() : aContainerWidth - mRect.X();
     }
   }
 
-  nscoord YMost(WritingMode aWritingMode) const
+  nscoord YMost(WritingMode aWritingMode, nscoord aContainerHeight) const
   {
     CHECK_WRITING_MODE(aWritingMode);
-    return aWritingMode.IsVertical() ? mRect.XMost() : mRect.YMost();
+    if (aWritingMode.IsVertical()) {
+      return mRect.XMost();
+    } else {
+      return mRect.YMost();
+    }
   }
 
   bool IsEmpty() const
   {
     return mRect.IsEmpty();
   }
 
   bool IsAllZero() const
@@ -1638,43 +1630,44 @@ public:
   {
     CHECK_WRITING_MODE(aWritingMode);
     CHECK_WRITING_MODE(aMargin.GetWritingMode());
     mRect.Deflate(aMargin.mMargin);
   }
 
   /**
    * Return an nsRect containing our physical coordinates within the given
-   * container width
+   * container size.
    */
   nsRect GetPhysicalRect(WritingMode aWritingMode,
-                         nscoord aContainerWidth) const
+                         const nsSize& aContainerSize) const
   {
     CHECK_WRITING_MODE(aWritingMode);
     if (aWritingMode.IsVertical()) {
-      return nsRect(aWritingMode.IsVerticalLR() ?
-                      BStart() : aContainerWidth - BEnd(),
-                    IStart(), BSize(), ISize());
+      return nsRect(aWritingMode.IsVerticalLR()
+                    ? BStart() : aContainerSize.width - BEnd(),
+                    IStart(),
+                    BSize(), ISize());
     } else {
-      return nsRect(aWritingMode.IsBidiLTR() ?
-                      IStart() : aContainerWidth - IEnd(),
+      return nsRect(aWritingMode.IsBidiLTR()
+                    ? IStart() : aContainerSize.width - IEnd(),
                     BStart(), ISize(), BSize());
     }
   }
 
   /**
    * Return a LogicalRect representing this rect in a different writing mode
    */
   LogicalRect ConvertTo(WritingMode aToMode, WritingMode aFromMode,
-                        nscoord aContainerWidth) const
+                        const nsSize& aContainerSize) const
   {
     CHECK_WRITING_MODE(aFromMode);
     return aToMode == aFromMode ?
-      *this : LogicalRect(aToMode, GetPhysicalRect(aFromMode, aContainerWidth),
-                          aContainerWidth);
+      *this : LogicalRect(aToMode, GetPhysicalRect(aFromMode, aContainerSize),
+                          aContainerSize);
   }
 
   /**
    * Set *this to be the rectangle containing the intersection of aRect1
    * and aRect2, return whether the intersection is non-empty.
    */
   bool IntersectRect(const LogicalRect& aRect1, const LogicalRect& aRect2)
   {
--- a/layout/generic/nsAbsoluteContainingBlock.cpp
+++ b/layout/generic/nsAbsoluteContainingBlock.cpp
@@ -403,17 +403,17 @@ nsAbsoluteContainingBlock::ReflowAbsolut
                              aReflowState.mStyleBorder->GetComputedBorder());
   const LogicalMargin margin =
     kidReflowState.ComputedLogicalMargin().ConvertTo(outerWM, wm);
   bool constrainBSize = (aReflowState.AvailableBSize() != NS_UNCONSTRAINEDSIZE)
     && aConstrainBSize
        // Don't split if told not to (e.g. for fixed frames)
     && (aDelegatingFrame->GetType() != nsGkAtoms::inlineFrame)
        //XXX we don't handle splitting frames for inline absolute containing blocks yet
-    && (aKidFrame->GetLogicalRect(aContainingBlock.width).BStart(wm) <=
+    && (aKidFrame->GetLogicalRect(aContainingBlock.Size()).BStart(wm) <=
         aReflowState.AvailableBSize());
        // Don't split things below the fold. (Ideally we shouldn't *have*
        // anything totally below the fold, but we can't position frames
        // across next-in-flow breaks yet.
   if (constrainBSize) {
     kidReflowState.AvailableBSize() =
       aReflowState.AvailableBSize() - border.ConvertTo(wm, outerWM).BStart(wm) -
       kidReflowState.ComputedLogicalMargin().BStart(wm);
@@ -463,18 +463,18 @@ nsAbsoluteContainingBlock::ReflowAbsolut
   // Position the child relative to our padding edge
   LogicalRect rect(outerWM,
                    border.IStart(outerWM) + offsets.IStart(outerWM) +
                      margin.IStart(outerWM),
                    border.BStart(outerWM) + offsets.BStart(outerWM) +
                      margin.BStart(outerWM),
                    kidSize.ISize(outerWM), kidSize.BSize(outerWM));
   nsRect r =
-    rect.GetPhysicalRect(outerWM, logicalCBSize.Width(wm) +
-                                  border.LeftRight(outerWM));
+    rect.GetPhysicalRect(outerWM, logicalCBSize.GetPhysicalSize(wm) +
+                         border.Size(outerWM).GetPhysicalSize(outerWM));
   // XXX hack to correct for lack of bidi support in vertical mode
   if (outerWM.IsVertical() && !outerWM.IsBidiLTR()) {
     r.y = logicalCBSize.Height(wm) + border.TopBottom(outerWM) - r.YMost();
   }
 
   // Offset the frame rect by the given origin of the absolute containing block.
   // If the frame is auto-positioned on both sides of an axis, it will be
   // positioned based on its containing block and we don't need to offset.
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -1239,50 +1239,49 @@ nsBlockFrame::Reflow(nsPresContext*     
 
     if (havePosition && !BulletIsEmpty()) {
       // We have some lines to align the bullet with.  
 
       // Doing the alignment using the baseline will also cater for
       // bullets that are placed next to a child block (bug 92896)
     
       // Tall bullets won't look particularly nice here...
-      LogicalRect bbox = bullet->GetLogicalRect(wm, metrics.Width());
+      LogicalRect bbox = bullet->GetLogicalRect(wm, metrics.PhysicalSize());
       bbox.BStart(wm) = position.mBaseline - metrics.BlockStartAscent();
-      bullet->SetRect(wm, bbox, metrics.Width());
+      bullet->SetRect(wm, bbox, metrics.PhysicalSize());
     }
     // Otherwise just leave the bullet where it is, up against our
     // block-start padding.
   }
 
   CheckFloats(state);
 
   // Compute our final size
   nscoord blockEndEdgeOfChildren;
   ComputeFinalSize(*reflowState, state, aMetrics, &blockEndEdgeOfChildren);
 
   // If the block direction is right-to-left, we need to update the bounds of
-  // lines that were placed relative to mContainerWidth during reflow, as
-  // we typically do not know the true container width (block-dir size of the
-  // finished paragraph/block) until we've reflowed all its children. So we
-  // use a "fake" mContainerWidth during reflow (see nsBlockReflowState's
-  // constructor) and then fix up the positions of the lines here, once the
-  // final block size is known.
+  // lines that were placed relative to mContainerSize during reflow, as
+  // we typically do not know the true container size until we've reflowed all
+  // its children. So we use a dummy mContainerSize during reflow (see
+  // nsBlockReflowState's constructor) and then fix up the positions of the
+  // lines here, once the final block size is known.
   //
   // Note that writing-mode:vertical-rl is the only case where the block
   // logical direction progresses in a negative physical direction, and
   // therefore block-dir coordinate conversion depends on knowing the width
   // of the coordinate space in order to translate between the logical and
   // physical origins.
   if (wm.IsVerticalRL()) {
-    nscoord containerWidth = aMetrics.Width();
-    nscoord deltaX = containerWidth - state.ContainerWidth();
-    if (deltaX) {
+    nsSize containerSize = aMetrics.PhysicalSize();
+    nscoord deltaX = containerSize.width - state.ContainerSize().width;
+    if (deltaX != 0) {
       for (line_iterator line = begin_lines(), end = end_lines();
            line != end; line++) {
-        UpdateLineContainerWidth(line, containerWidth);
+        UpdateLineContainerSize(line, containerSize);
       }
       for (nsIFrame* f : mFloats) {
         nsPoint physicalDelta(deltaX, 0);
         f->MovePositionBy(physicalDelta);
       }
       nsFrameList* bulletList = GetOutsideBulletList();
       if (bulletList) {
         nsPoint physicalDelta(deltaX, 0);
@@ -1928,19 +1927,19 @@ nsBlockFrame::PropagateFloatDamage(nsBlo
   if (floatManager->HasFloatDamage()) {
     // Need to check mBounds *and* mCombinedArea to find intersections 
     // with aLine's floats
     nscoord lineBCoordBefore = aLine->BStart() + aDeltaBCoord;
     nscoord lineBCoordAfter = lineBCoordBefore + aLine->BSize();
     // Scrollable overflow should be sufficient for things that affect
     // layout.
     WritingMode wm = aState.mReflowState.GetWritingMode();
-    nscoord containerWidth = aState.ContainerWidth();
+    nsSize containerSize = aState.ContainerSize();
     LogicalRect overflow = aLine->GetOverflowArea(eScrollableOverflow, wm,
-                                                  containerWidth);
+                                                  containerSize);
     nscoord lineBCoordCombinedBefore = overflow.BStart(wm) + aDeltaBCoord;
     nscoord lineBCoordCombinedAfter = lineBCoordCombinedBefore +
                                       overflow.BSize(wm);
 
     bool isDirty = floatManager->IntersectsDamage(wm, lineBCoordBefore,
                                                   lineBCoordAfter) ||
                    floatManager->IntersectsDamage(wm, lineBCoordCombinedBefore,
                                                   lineBCoordCombinedAfter);
@@ -2171,21 +2170,21 @@ nsBlockFrame::ReflowDirtyLines(nsBlockRe
     }
 
     if (!line->IsDirty()) {
       // See if there's any reflow damage that requires that we mark the
       // line dirty.
       PropagateFloatDamage(aState, line, deltaBCoord);
     }
 
-    // If the container width has changed reset the container width. If the
+    // If the container size has changed, reset mContainerSize. If the
     // line's writing mode is not ltr, or if the line is not left-aligned, also
     // mark the line dirty.
-    if (aState.ContainerWidth() != line->mContainerWidth) {
-      line->mContainerWidth = aState.ContainerWidth();
+    if (aState.ContainerSize() != line->mContainerSize) {
+      line->mContainerSize = aState.ContainerSize();
 
       bool isLastLine = line == mLines.back() &&
                         !GetNextInFlow() &&
                         NS_STYLE_TEXT_ALIGN_AUTO == StyleText()->mTextAlignLast;
       uint8_t align = isLastLine ?
         StyleText()->mTextAlign : StyleText()->mTextAlignLast;
 
       if (line->mWritingMode.IsVertical() ||
@@ -2812,36 +2811,36 @@ nsBlockFrame::PullFrameFrom(nsLineBox*  
 
 void
 nsBlockFrame::SlideLine(nsBlockReflowState& aState,
                         nsLineBox* aLine, nscoord aDeltaBCoord)
 {
   NS_PRECONDITION(aDeltaBCoord != 0, "why slide a line nowhere?");
 
   // Adjust line state
-  aLine->SlideBy(aDeltaBCoord, aState.ContainerWidth());
+  aLine->SlideBy(aDeltaBCoord, aState.ContainerSize());
 
   // Adjust the frames in the line
   MoveChildFramesOfLine(aLine, aDeltaBCoord);
 }
 
 void
-nsBlockFrame::UpdateLineContainerWidth(nsLineBox* aLine,
-                                       nscoord aNewContainerWidth)
-{
-  if (aNewContainerWidth == aLine->mContainerWidth) {
+nsBlockFrame::UpdateLineContainerSize(nsLineBox* aLine,
+                                      const nsSize& aNewContainerSize)
+{
+  if (aNewContainerSize == aLine->mContainerSize) {
     return;
   }
 
   // Adjust line state
-  nscoord widthDelta = aLine->UpdateContainerWidth(aNewContainerWidth);
+  nsSize sizeDelta = aLine->UpdateContainerSize(aNewContainerSize);
 
   // Changing container width only matters if writing mode is vertical-rl
   if (GetWritingMode().IsVerticalRL()) {
-    MoveChildFramesOfLine(aLine, widthDelta);
+    MoveChildFramesOfLine(aLine, sizeDelta.width);
   }
 }
 
 void
 nsBlockFrame::MoveChildFramesOfLine(nsLineBox* aLine, nscoord aDeltaBCoord)
 {
   // Adjust the frames in the line
   nsIFrame* kid = aLine->mFirstChild;
@@ -3677,17 +3676,17 @@ nsBlockFrame::DoReflowInlineFrames(nsBlo
   printf("nsBlockFrame::DoReflowInlineFrames %p impacted = %d\n",
          this, aFloatAvailableSpace.mHasFloats);
 #endif
 
   WritingMode outerWM = aState.mReflowState.GetWritingMode();
   WritingMode lineWM = GetWritingMode(aLine->mFirstChild);
   LogicalRect lineRect =
     aFloatAvailableSpace.mRect.ConvertTo(lineWM, outerWM,
-                                         aState.ContainerWidth());
+                                         aState.ContainerSize());
 
   nscoord iStart = lineRect.IStart(lineWM);
   nscoord availISize = lineRect.ISize(lineWM);
   nscoord availBSize;
   if (aState.GetFlag(BRS_UNCONSTRAINEDBSIZE)) {
     availBSize = NS_UNCONSTRAINEDSIZE;
   }
   else {
@@ -6150,64 +6149,64 @@ nsBlockFrame::ReflowPushedFloats(nsBlock
     if (prevBlock) {
       aState.mFloatBreakType = prevBlock->FindTrailingClear();
     }
   }
 }
 
 void
 nsBlockFrame::RecoverFloats(nsFloatManager& aFloatManager, WritingMode aWM,
-                            nscoord aContainerWidth)
+                            const nsSize& aContainerSize)
 {
   // Recover our own floats
   nsIFrame* stop = nullptr; // Stop before we reach pushed floats that
                            // belong to our next-in-flow
   for (nsIFrame* f = mFloats.FirstChild(); f && f != stop; f = f->GetNextSibling()) {
-    LogicalRect region = nsFloatManager::GetRegionFor(aWM, f, aContainerWidth);
-    aFloatManager.AddFloat(f, region, aWM, aContainerWidth);
+    LogicalRect region = nsFloatManager::GetRegionFor(aWM, f, aContainerSize);
+    aFloatManager.AddFloat(f, region, aWM, aContainerSize);
     if (!stop && f->GetNextInFlow())
       stop = f->GetNextInFlow();
   }
 
   // Recurse into our overflow container children
   for (nsIFrame* oc = GetFirstChild(kOverflowContainersList);
        oc; oc = oc->GetNextSibling()) {
-    RecoverFloatsFor(oc, aFloatManager, aWM, aContainerWidth);
+    RecoverFloatsFor(oc, aFloatManager, aWM, aContainerSize);
   }
 
   // Recurse into our normal children
   for (nsBlockFrame::line_iterator line = begin_lines(); line != end_lines(); ++line) {
     if (line->IsBlock()) {
-      RecoverFloatsFor(line->mFirstChild, aFloatManager, aWM, aContainerWidth);
+      RecoverFloatsFor(line->mFirstChild, aFloatManager, aWM, aContainerSize);
     }
   }
 }
 
 void
 nsBlockFrame::RecoverFloatsFor(nsIFrame*       aFrame,
                                nsFloatManager& aFloatManager,
                                WritingMode     aWM,
-                               nscoord         aContainerWidth)
+                               const nsSize&   aContainerSize)
 {
   NS_PRECONDITION(aFrame, "null frame");
   // Only blocks have floats
   nsBlockFrame* block = nsLayoutUtils::GetAsBlock(aFrame);
   // Don't recover any state inside a block that has its own space manager
   // (we don't currently have any blocks like this, though, thanks to our
   // use of extra frames for 'overflow')
   if (block && !nsBlockFrame::BlockNeedsFloatManager(block)) {
     // If the element is relatively positioned, then adjust x and y
     // accordingly so that we consider relatively positioned frames
     // at their original position.
 
-    LogicalRect rect(aWM, block->GetNormalRect(), aContainerWidth);
-    nscoord lineLeft = rect.LineLeft(aWM, aContainerWidth);
+    LogicalRect rect(aWM, block->GetNormalRect(), aContainerSize);
+    nscoord lineLeft = rect.LineLeft(aWM, aContainerSize);
     nscoord blockStart = rect.BStart(aWM);
     aFloatManager.Translate(lineLeft, blockStart);
-    block->RecoverFloats(aFloatManager, aWM, aContainerWidth);
+    block->RecoverFloats(aFloatManager, aWM, aContainerSize);
     aFloatManager.Translate(-lineLeft, -blockStart);
   }
 }
 
 //////////////////////////////////////////////////////////////////////
 // Painting, event handling
 
 #ifdef DEBUG
@@ -7046,17 +7045,17 @@ nsBlockFrame::ReflowBullet(nsIFrame* aBu
 
   // Approximate the bullets position; vertical alignment will provide
   // the final vertical location. We pass our writing-mode here, because
   // it may be different from the bullet frame's mode.
   nscoord bStart = floatAvailSpace.BStart(wm);
   aBulletFrame->SetRect(wm, LogicalRect(wm, iStart, bStart,
                                         aMetrics.ISize(wm),
                                         aMetrics.BSize(wm)),
-                        aState.ContainerWidth());
+                        aState.ContainerSize());
   aBulletFrame->DidReflow(aState.mPresContext, &aState.mReflowState,
                           nsDidReflowStatus::FINISHED);
 }
 
 // This is used to scan frames for any float placeholders, add their
 // floats to the list represented by aList, and remove the
 // floats from whatever list they might be in. We don't search descendants
 // that are float containing blocks.  Floats that or not children of 'this'
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -408,20 +408,20 @@ protected:
   }
 
   /** move the frames contained by aLine by aDeltaBCoord
     * if aLine is a block, its child floats are added to the state manager
     */
   void SlideLine(nsBlockReflowState& aState,
                  nsLineBox* aLine, nscoord aDeltaBCoord);
 
-  void UpdateLineContainerWidth(nsLineBox* aLine,
-                                nscoord aNewContainerWidth);
+  void UpdateLineContainerSize(nsLineBox* aLine,
+                               const nsSize& aNewContainerSize);
 
-  // helper for SlideLine and UpdateLineContainerWidth
+  // helper for SlideLine and UpdateLineContainerSize
   void MoveChildFramesOfLine(nsLineBox* aLine, nscoord aDeltaBCoord);
 
   void ComputeFinalSize(const nsHTMLReflowState& aReflowState,
                         nsBlockReflowState&      aState,
                         nsHTMLReflowMetrics&     aMetrics,
                         nscoord*                 aBottomEdgeOfChildren);
 
   void ComputeOverflowAreas(const nsRect&         aBounds,
@@ -479,17 +479,17 @@ public:
   /** Load all of aFrame's floats into the float manager iff aFrame is not a
    *  block formatting context. Handles all necessary float manager translations;
    *  assumes float manager is in aFrame's parent's coord system.
    *  Safe to call on non-blocks (does nothing).
    */
   static void RecoverFloatsFor(nsIFrame*            aFrame,
                                nsFloatManager&      aFloatManager,
                                mozilla::WritingMode aWM,
-                               nscoord              aContainerWidth);
+                               const nsSize&        aContainerSize);
 
   /**
    * Determine if we have any pushed floats from a previous continuation.
    *
    * @returns true, if any of the floats at the beginning of our mFloats list
    *          have the NS_FRAME_IS_PUSHED_FLOAT bit set; false otherwise.
    */
   bool HasPushedFloatsFromPrevContinuation() const {
@@ -551,17 +551,17 @@ protected:
    */
   void DrainPushedFloats();
 
   /** Load all our floats into the float manager (without reflowing them).
    *  Assumes float manager is in our own coordinate system.
    */
   void RecoverFloats(nsFloatManager&      aFloatManager,
                      mozilla::WritingMode aWM,
-                     nscoord              aContainerWidth);
+                     const nsSize&        aContainerSize);
 
   /** Reflow pushed floats
    */
   void ReflowPushedFloats(nsBlockReflowState& aState,
                           nsOverflowAreas&    aOverflowAreas,
                           nsReflowStatus&     aStatus);
 
   /** Find any trailing BR clear from the last line of the block (or its PIFs)
--- a/layout/generic/nsBlockReflowContext.cpp
+++ b/layout/generic/nsBlockReflowContext.cpp
@@ -223,17 +223,17 @@ nsBlockReflowContext::ReflowBlock(const 
                                   bool                aIsAdjacentWithBStart,
                                   nsLineBox*          aLine,
                                   nsHTMLReflowState&  aFrameRS,
                                   nsReflowStatus&     aFrameReflowStatus,
                                   nsBlockReflowState& aState)
 {
   mFrame = aFrameRS.frame;
   mWritingMode = aState.mReflowState.GetWritingMode();
-  mContainerWidth = aState.ContainerWidth();
+  mContainerSize = aState.ContainerSize();
   mSpace = aSpace;
 
   if (!aIsAdjacentWithBStart) {
     aFrameRS.mFlags.mIsTopOfPage = false;  // make sure this is cleared
   }
 
   if (aApplyBStartMargin) {
     mBStartMargin = aPrevMargin;
@@ -275,17 +275,17 @@ nsBlockReflowContext::ReflowBlock(const 
     mICoord = mSpace.IStart(mWritingMode) + usedMargin.IStart(mWritingMode);
     mBCoord = mSpace.BStart(mWritingMode) + mBStartMargin.get() + aClearance;
 
     LogicalRect space(mWritingMode, mICoord, mBCoord,
                       mSpace.ISize(mWritingMode) -
                       usedMargin.IStartEnd(mWritingMode),
                       mSpace.BSize(mWritingMode) -
                       usedMargin.BStartEnd(mWritingMode));
-    tI = space.LineLeft(mWritingMode, mContainerWidth);
+    tI = space.LineLeft(mWritingMode, mContainerSize);
     tB = mBCoord;
 
     if ((mFrame->GetStateBits() & NS_BLOCK_FLOAT_MGR) == 0)
       aFrameRS.mBlockDelta =
         mOuterReflowState.mBlockDelta + mBCoord - aLine->BStart();
   }
 
 #ifdef DEBUG
@@ -425,29 +425,30 @@ nsBlockReflowContext::PlaceBlock(const n
                         nsDidReflowStatus::FINISHED);
       return false;
     }
   }
 
   aLine->SetBounds(mWritingMode,
                    mICoord, mBCoord - backupContainingBlockAdvance,
                    mMetrics.ISize(mWritingMode), mMetrics.BSize(mWritingMode),
-                   mContainerWidth);
+                   mContainerSize);
 
   WritingMode frameWM = mFrame->GetWritingMode();
   LogicalPoint logPos =
     LogicalPoint(mWritingMode, mICoord, mBCoord).
-      ConvertTo(frameWM, mWritingMode, mContainerWidth - mMetrics.Width());
+      ConvertTo(frameWM, mWritingMode,
+                mContainerSize - mMetrics.PhysicalSize());
 
   // ApplyRelativePositioning in right-to-left writing modes needs to
   // know the updated frame width
   mFrame->SetSize(mWritingMode, mMetrics.Size(mWritingMode));
-  aReflowState.ApplyRelativePositioning(&logPos, mContainerWidth);
+  aReflowState.ApplyRelativePositioning(&logPos, mContainerSize);
 
   // Now place the frame and complete the reflow process
   nsContainerFrame::FinishReflowChild(mFrame, mPresContext, mMetrics,
                                       &aReflowState, frameWM, logPos,
-                                      mContainerWidth, 0);
+                                      mContainerSize, 0);
 
   aOverflowAreas = mMetrics.mOverflowAreas + mFrame->GetPosition();
 
   return true;
 }
--- a/layout/generic/nsBlockReflowContext.h
+++ b/layout/generic/nsBlockReflowContext.h
@@ -78,15 +78,16 @@ public:
 
 protected:
   nsPresContext* mPresContext;
   const nsHTMLReflowState& mOuterReflowState;
 
   nsIFrame* mFrame;
   mozilla::LogicalRect mSpace;
 
-  nscoord mICoord, mBCoord, mContainerWidth;
+  nscoord mICoord, mBCoord;
+  nsSize mContainerSize;
   mozilla::WritingMode mWritingMode;
   nsHTMLReflowMetrics mMetrics;
   nsCollapsingMargin mBStartMargin;
 };
 
 #endif /* nsBlockReflowContext_h___ */
--- a/layout/generic/nsBlockReflowState.cpp
+++ b/layout/generic/nsBlockReflowState.cpp
@@ -317,17 +317,17 @@ nsBlockReflowState::GetFloatAvailableSpa
                "bad coord system");
 #endif
 
   nscoord blockSize = (mContentArea.BSize(wm) == nscoord_MAX)
     ? nscoord_MAX : std::max(mContentArea.BEnd(wm) - aBCoord, 0);
   nsFlowAreaRect result =
     mFloatManager->GetFlowArea(wm, aBCoord, nsFloatManager::BAND_FROM_POINT,
                                blockSize, mContentArea, aState,
-                               ContainerWidth());
+                               ContainerSize());
   // Keep the inline size >= 0 for compatibility with nsSpaceManager.
   if (result.mRect.ISize(wm) < 0) {
     result.mRect.ISize(wm) = 0;
   }
 
 #ifdef DEBUG
   if (nsBlockFrame::gNoisyReflow) {
     nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
@@ -350,17 +350,17 @@ nsBlockReflowState::GetFloatAvailableSpa
   nscoord wI, wB;
   mFloatManager->GetTranslation(wI, wB);
 
   NS_ASSERTION((wI == mFloatManagerI) && (wB == mFloatManagerB),
                "bad coord system");
 #endif
   nsFlowAreaRect result =
     mFloatManager->GetFlowArea(wm, aBCoord, nsFloatManager::WIDTH_WITHIN_HEIGHT,
-                               aBSize, mContentArea, aState, ContainerWidth());
+                               aBSize, mContentArea, aState, ContainerSize());
   // Keep the width >= 0 for compatibility with nsSpaceManager.
   if (result.mRect.ISize(wm) < 0) {
     result.mRect.ISize(wm) = 0;
   }
 
 #ifdef DEBUG
   if (nsBlockFrame::gNoisyReflow) {
     nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
@@ -474,31 +474,31 @@ nsBlockReflowState::RecoverFloats(nsLine
       if (nsBlockFrame::gNoisyReflow || nsBlockFrame::gNoisyFloatManager) {
         nscoord tI, tB;
         mFloatManager->GetTranslation(tI, tB);
         nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
         printf("RecoverFloats: tIB=%d,%d (%d,%d) ",
                tI, tB, mFloatManagerI, mFloatManagerB);
         nsFrame::ListTag(stdout, floatFrame);
         LogicalRect region = nsFloatManager::GetRegionFor(wm, floatFrame,
-                                                          ContainerWidth());
+                                                          ContainerSize());
         printf(" aDeltaBCoord=%d region={%d,%d,%d,%d}\n",
                aDeltaBCoord, region.IStart(wm), region.BStart(wm),
                region.ISize(wm), region.BSize(wm));
       }
 #endif
       mFloatManager->AddFloat(floatFrame,
                               nsFloatManager::GetRegionFor(wm, floatFrame,
-                                                           ContainerWidth()),
-                              wm, ContainerWidth());
+                                                           ContainerSize()),
+                              wm, ContainerSize());
       fc = fc->Next();
     }
   } else if (aLine->IsBlock()) {
     nsBlockFrame::RecoverFloatsFor(aLine->mFirstChild, *mFloatManager, wm,
-                                   ContainerWidth());
+                                   ContainerSize());
   }
 }
 
 /**
  * Everything done in this function is done O(N) times for each pass of
  * reflow so it is O(N*M) where M is the number of incremental reflow
  * passes.  That's bad.  Don't do stuff here.
  *
@@ -695,17 +695,17 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
   // FIXME: Should give AutoRestore a getter for the value to avoid this.
   const nscoord saveBCoord = mBCoord;
 
   // Grab the float's display information
   const nsStyleDisplay* floatDisplay = aFloat->StyleDisplay();
 
   // The float's old region, so we can propagate damage.
   LogicalRect oldRegion = nsFloatManager::GetRegionFor(wm, aFloat,
-                                                       ContainerWidth());
+                                                       ContainerSize());
 
   // Enforce CSS2 9.5.1 rule [2], i.e., make sure that a float isn't
   // ``above'' another float that preceded it in the flow.
   mBCoord = std::max(mFloatManager->GetLowestFloatTop(), mBCoord);
 
   // See if the float should clear any preceding floats...
   // XXX We need to mark this float somehow so that it gets reflowed
   // when floats are inserted before it.
@@ -852,19 +852,20 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
   LogicalPoint floatPos(wm);
   bool leftFloat = NS_STYLE_FLOAT_LEFT == floatDisplay->mFloats;
 
   if (wm.IsVertical()) {
     // IStart and IEnd should use the ContainerHeight in vertical modes
     // with rtl direction. Since they don't yet (bug 1131451), we'll
     // just put left floats at the top of the line and right floats at
     // bottom.
-    floatPos.I(wm) = leftFloat
-                      ? floatAvailableSpace.mRect.Y(wm)
-                      : floatAvailableSpace.mRect.YMost(wm) - floatMarginISize;
+    floatPos.I(wm) =
+      leftFloat ? floatAvailableSpace.mRect.Y(wm, ContainerSize().height)
+                : floatAvailableSpace.mRect.YMost(wm, ContainerSize().height) -
+                  floatMarginISize;
   } else if (leftFloat == wm.IsBidiLTR()) {
     floatPos.I(wm) = floatAvailableSpace.mRect.IStart(wm);
   }
   else {
     if (!keepFloatOnSameLine) {
       floatPos.I(wm) = floatAvailableSpace.mRect.IEnd(wm) - floatMarginISize;
     }
     else {
@@ -930,49 +931,49 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
   // Calculate the actual origin of the float frame's border rect
   // relative to the parent block; the margin must be added in
   // to get the border rect
   LogicalPoint origin(wm, floatMargin.IStart(wm) + floatPos.I(wm),
                       floatMargin.BStart(wm) + floatPos.B(wm));
 
   // If float is relatively positioned, factor that in as well
   nsHTMLReflowState::ApplyRelativePositioning(aFloat, wm, floatOffsets,
-                                              &origin, ContainerWidth());
+                                              &origin, ContainerSize());
 
   // Position the float and make sure and views are properly
   // positioned. We need to explicitly position its child views as
   // well, since we're moving the float after flowing it.
-  bool moved = aFloat->GetLogicalPosition(wm, ContainerWidth()) != origin;
+  bool moved = aFloat->GetLogicalPosition(wm, ContainerSize()) != origin;
   if (moved) {
-    aFloat->SetPosition(wm, origin, ContainerWidth());
+    aFloat->SetPosition(wm, origin, ContainerSize());
     nsContainerFrame::PositionFrameView(aFloat);
     nsContainerFrame::PositionChildViews(aFloat);
   }
 
   // Update the float combined area state
   // XXX Floats should really just get invalidated here if necessary
   mFloatOverflowAreas.UnionWith(aFloat->GetOverflowAreas() +
                                 aFloat->GetPosition());
 
   // Place the float in the float manager
   // calculate region
   LogicalRect region =
     nsFloatManager::CalculateRegionFor(wm, aFloat, floatMargin,
-                                       ContainerWidth());
+                                       ContainerSize());
   // if the float split, then take up all of the vertical height
   if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus) &&
       (NS_UNCONSTRAINEDSIZE != ContentBSize())) {
     region.BSize(wm) = std::max(region.BSize(wm),
                                 ContentBSize() - floatPos.B(wm));
   }
   DebugOnly<nsresult> rv = mFloatManager->AddFloat(aFloat, region, wm,
-                                                   ContainerWidth());
+                                                   ContainerSize());
   MOZ_ASSERT(NS_SUCCEEDED(rv), "bad float placement");
   // store region
-  nsFloatManager::StoreRegionFor(wm, aFloat, region, ContainerWidth());
+  nsFloatManager::StoreRegionFor(wm, aFloat, region, ContainerSize());
 
   // If the float's dimensions have changed, note the damage in the
   // float manager.
   if (!region.IsEqualEdges(oldRegion)) {
     // XXXwaterson conservative: we could probably get away with noting
     // less damage; e.g., if only height has changed, then only note the
     // area into which the float has grown or from which the float has
     // shrunk.
--- a/layout/generic/nsBlockReflowState.h
+++ b/layout/generic/nsBlockReflowState.h
@@ -202,18 +202,17 @@ public:
   }
   mozilla::LogicalSize ContentSize(mozilla::WritingMode aWM) const {
     mozilla::WritingMode wm = mReflowState.GetWritingMode();
     return mContentArea.Size(wm).ConvertTo(aWM, wm);
   }
 
   // Physical size. Use only for physical <-> logical coordinate conversion.
   nsSize mContainerSize;
-  nscoord ContainerWidth() const { return mContainerSize.width; }
-  nscoord ContainerHeight() const { return mContainerSize.height; }
+  const nsSize& ContainerSize() const { return mContainerSize; }
 
   // Continuation out-of-flow float frames that need to move to our
   // next in flow are placed here during reflow.  It's a pointer to
   // a frame list stored in the block's property table.
   nsFrameList *mPushedFloats;
   // This method makes sure pushed floats are accessible to
   // StealFrame. Call it before adding any frames to mPushedFloats.
   void SetupPushedFloatList();
--- a/layout/generic/nsCanvasFrame.cpp
+++ b/layout/generic/nsCanvasFrame.cpp
@@ -660,30 +660,30 @@ nsCanvasFrame::Reflow(nsPresContext*    
         (kidFrame->GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_BSIZE)) {
       // Tell our kid it's being block-dir resized too.  Bit of a
       // hack for framesets.
       kidReflowState.SetBResize(true);
     }
 
     WritingMode wm = aReflowState.GetWritingMode();
     WritingMode kidWM = kidReflowState.GetWritingMode();
-    nscoord containerWidth = aReflowState.ComputedWidth();
+    nsSize containerSize = aReflowState.ComputedPhysicalSize();
 
     LogicalMargin margin = kidReflowState.ComputedLogicalMargin();
     LogicalPoint kidPt(kidWM, margin.IStart(kidWM), margin.BStart(kidWM));
 
-    kidReflowState.ApplyRelativePositioning(&kidPt, containerWidth);
+    kidReflowState.ApplyRelativePositioning(&kidPt, containerSize);
 
     // Reflow the frame
     ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState,
-                kidWM, kidPt, containerWidth, 0, aStatus);
+                kidWM, kidPt, containerSize, 0, aStatus);
 
     // Complete the reflow and position and size the child frame
     FinishReflowChild(kidFrame, aPresContext, kidDesiredSize, &kidReflowState,
-                      kidWM, kidPt, containerWidth, 0);
+                      kidWM, kidPt, containerSize, 0);
 
     if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
       nsIFrame* nextFrame = kidFrame->GetNextInFlow();
       NS_ASSERTION(nextFrame || aStatus & NS_FRAME_REFLOW_NEXTINFLOW,
         "If it's incomplete and has no nif yet, it must flag a nif reflow.");
       if (!nextFrame) {
         nextFrame = aPresContext->PresShell()->FrameConstructor()->
           CreateContinuingFrame(aPresContext, kidFrame, this);
--- a/layout/generic/nsColumnSetFrame.cpp
+++ b/layout/generic/nsColumnSetFrame.cpp
@@ -355,23 +355,23 @@ nsColumnSetFrame::ReflowColumns(nsHTMLRe
                               aConfig, aLastColumnUnbounded,
                               aCarriedOutBEndMargin, aColData);
   }
 
   return feasible;
 }
 
 static void MoveChildTo(nsIFrame* aChild, LogicalPoint aOrigin,
-                        WritingMode aWM, nscoord aContainerWidth)
+                        WritingMode aWM, const nsSize& aContainerSize)
 {
-  if (aChild->GetLogicalPosition(aWM, aContainerWidth) == aOrigin) {
+  if (aChild->GetLogicalPosition(aWM, aContainerSize) == aOrigin) {
     return;
   }
 
-  aChild->SetPosition(aWM, aOrigin, aContainerWidth);
+  aChild->SetPosition(aWM, aOrigin, aContainerSize);
   nsContainerFrame::PlaceFrameView(aChild);
 }
 
 nscoord
 nsColumnSetFrame::GetMinISize(nsRenderingContext *aRenderingContext)
 {
   nscoord iSize = 0;
   DISPLAY_MIN_WIDTH(this, iSize);
@@ -483,35 +483,37 @@ nsColumnSetFrame::ReflowChildren(nsHTMLR
   borderPadding.ApplySkipSides(GetLogicalSkipSides(&aReflowState));
 
   nsRect contentRect(0, 0, 0, 0);
   nsOverflowAreas overflowRects;
 
   nsIFrame* child = mFrames.FirstChild();
   LogicalPoint childOrigin(wm, borderPadding.IStart(wm),
                            borderPadding.BStart(wm));
-  // In vertical-rl mode we can't use the computed width as the
-  // container width because it may be NS_UNCONSTRAINEDSIZE, so we use 0
-  // for now and reposition the columns after reflowing them all.
-  nscoord containerWidth = wm.IsVerticalRL() ? 0 : aReflowState.ComputedWidth();
+  // In vertical-rl mode, columns will not be correctly placed if the
+  // reflowState's ComputedWidth() is UNCONSTRAINED (in which case we'll get
+  // a containerSize.width of zero here). In that case, the column positions
+  // will be adjusted later, after our correct contentSize is known.
+  nsSize containerSize = aReflowState.ComputedSizeAsContainerIfConstrained();
 
   // For RTL, since the columns might not fill the frame exactly, we
   // need to account for the slop. Otherwise we'll waste time moving the
   // columns by some tiny amount
 
   // XXX when all of layout is converted to logical coordinates, we
   //     probably won't need to do this hack any more. For now, we
   //     confine it to the legacy horizontal-rl case
   if (!isVertical && isRTL) {
     nscoord availISize = aReflowState.AvailableISize();
     if (aReflowState.ComputedISize() != NS_INTRINSICSIZE) {
       availISize = aReflowState.ComputedISize();
     }
     if (availISize != NS_INTRINSICSIZE) {
-      childOrigin.I(wm) = containerWidth - borderPadding.Left(wm) - availISize;
+      childOrigin.I(wm) = containerSize.width - borderPadding.Left(wm) -
+                          availISize;
 #ifdef DEBUG_roc
       printf("*** childOrigin.iCoord = %d\n", childOrigin.I(wm));
 #endif
     }
   }
 
   int columnCount = 0;
   int contentBEnd = 0;
@@ -562,17 +564,17 @@ nsColumnSetFrame::ReflowChildren(nsHTMLR
         NS_NOTREACHED("unknown block direction");
         break;
       }
     }
 
     nscoord childContentBEnd = 0;
     if (!reflowNext && (skipIncremental || skipResizeBSizeShrink)) {
       // This child does not need to be reflowed, but we may need to move it
-      MoveChildTo(child, childOrigin, wm, containerWidth);
+      MoveChildTo(child, childOrigin, wm, containerSize);
 
       // If this is the last frame then make sure we get the right status
       nsIFrame* kidNext = child->GetNextSibling();
       if (kidNext) {
         aStatus = (kidNext->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)
                   ? NS_FRAME_OVERFLOW_INCOMPLETE
                   : NS_FRAME_NOT_COMPLETE;
       } else {
@@ -629,32 +631,32 @@ nsColumnSetFrame::ReflowChildren(nsHTMLR
 
       // Reflow the frame
       LogicalPoint origin(wm,
                           childOrigin.I(wm) +
                           kidReflowState.ComputedLogicalMargin().IStart(wm),
                           childOrigin.B(wm) +
                           kidReflowState.ComputedLogicalMargin().BStart(wm));
       ReflowChild(child, PresContext(), kidDesiredSize, kidReflowState,
-                  wm, origin, containerWidth, 0, aStatus);
+                  wm, origin, containerSize, 0, aStatus);
 
       reflowNext = (aStatus & NS_FRAME_REFLOW_NEXTINFLOW) != 0;
 
 #ifdef DEBUG_roc
       printf("*** Reflowed child #%d %p: status = %d, desiredSize=%d,%d CarriedOutBEndMargin=%d\n",
              columnCount, (void*)child, aStatus, kidDesiredSize.Width(), kidDesiredSize.Height(),
              kidDesiredSize.mCarriedOutBEndMargin.get());
 #endif
 
       NS_FRAME_TRACE_REFLOW_OUT("Column::Reflow", aStatus);
 
       *aCarriedOutBEndMargin = kidDesiredSize.mCarriedOutBEndMargin;
 
       FinishReflowChild(child, PresContext(), kidDesiredSize,
-                        &kidReflowState, wm, childOrigin, containerWidth, 0);
+                        &kidReflowState, wm, childOrigin, containerSize, 0);
 
       childContentBEnd = nsLayoutUtils::CalculateContentBEnd(wm, child);
       if (childContentBEnd > aConfig.mColMaxBSize) {
         allFit = false;
       }
       if (childContentBEnd > availSize.BSize(wm)) {
         aColData.mMaxOverflowingBSize = std::max(childContentBEnd,
             aColData.mMaxOverflowingBSize);
@@ -796,27 +798,27 @@ nsColumnSetFrame::ReflowChildren(nsHTMLR
   }
 
   contentSize.ISize(wm) += borderPadding.IStartEnd(wm);
   contentSize.BSize(wm) += borderPadding.BStartEnd(wm);
   aDesiredSize.SetSize(wm, contentSize);
   aDesiredSize.mOverflowAreas = overflowRects;
   aDesiredSize.UnionOverflowAreasWithDesiredBounds();
 
-  // In vertical-rl mode, make a second pass to reposition the columns
-  // with the correct container width
-  if (wm.IsVerticalRL()) {
-    child = mFrames.FirstChild();
-    while (child) {
-      // Get the logical position as set before with containerWidth=0
-      // and reset with the correct container width (which is the block
-      // size in vertical modes).
-      child->SetPosition(wm, child->GetLogicalPosition(wm, 0),
-                         contentSize.BSize(wm));
-      child = child->GetNextSibling();
+  // In vertical-rl mode, make a second pass if necessary to reposition the
+  // columns with the correct container width. (In other writing modes,
+  // correct containerSize was not required for column positioning so we don't
+  // need this fixup.)
+  if (wm.IsVerticalRL() && containerSize.width != contentSize.Width(wm)) {
+    const nsSize finalContainerSize = aDesiredSize.PhysicalSize();
+    for (nsIFrame* child : mFrames) {
+      // Get the logical position as set previously using a provisional or
+      // dummy containerSize, and reset with the correct container size.
+      child->SetPosition(wm, child->GetLogicalPosition(wm, containerSize),
+                         finalContainerSize);
     }
   }
 
 #ifdef DEBUG_roc
   printf("*** DONE PASS feasible=%d\n", allFit && NS_FRAME_IS_FULLY_COMPLETE(aStatus)
          && !NS_FRAME_IS_TRUNCATED(aStatus));
 #endif
   return allFit && NS_FRAME_IS_FULLY_COMPLETE(aStatus)
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -969,30 +969,30 @@ nsContainerFrame::ComputeAutoSize(nsRend
 
 void
 nsContainerFrame::ReflowChild(nsIFrame*                aKidFrame,
                               nsPresContext*           aPresContext,
                               nsHTMLReflowMetrics&     aDesiredSize,
                               const nsHTMLReflowState& aReflowState,
                               const WritingMode&       aWM,
                               const LogicalPoint&      aPos,
-                              nscoord                  aContainerWidth,
+                              const nsSize&            aContainerSize,
                               uint32_t                 aFlags,
                               nsReflowStatus&          aStatus,
                               nsOverflowContinuationTracker* aTracker)
 {
   NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state");
   if (aWM.IsVerticalRL() || (!aWM.IsVertical() && !aWM.IsBidiLTR())) {
-    NS_ASSERTION(aContainerWidth != NS_UNCONSTRAINEDSIZE,
+    NS_ASSERTION(aContainerSize.width != NS_UNCONSTRAINEDSIZE,
                  "ReflowChild with unconstrained container width!");
   }
 
   // Position the child frame and its view if requested.
   if (NS_FRAME_NO_MOVE_FRAME != (aFlags & NS_FRAME_NO_MOVE_FRAME)) {
-    aKidFrame->SetPosition(aWM, aPos, aContainerWidth);
+    aKidFrame->SetPosition(aWM, aPos, aContainerSize);
   }
 
   if (0 == (aFlags & NS_FRAME_NO_MOVE_VIEW)) {
     PositionFrameView(aKidFrame);
   }
 
   // Reflow the child frame
   aKidFrame->Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
@@ -1109,32 +1109,32 @@ nsContainerFrame::PositionChildViews(nsI
  */
 void
 nsContainerFrame::FinishReflowChild(nsIFrame*                  aKidFrame,
                                     nsPresContext*             aPresContext,
                                     const nsHTMLReflowMetrics& aDesiredSize,
                                     const nsHTMLReflowState*   aReflowState,
                                     const WritingMode&         aWM,
                                     const LogicalPoint&        aPos,
-                                    nscoord                    aContainerWidth,
+                                    const nsSize&              aContainerSize,
                                     uint32_t                   aFlags)
 {
   if (aWM.IsVerticalRL() || (!aWM.IsVertical() && !aWM.IsBidiLTR())) {
-    NS_ASSERTION(aContainerWidth != NS_UNCONSTRAINEDSIZE,
+    NS_ASSERTION(aContainerSize.width != NS_UNCONSTRAINEDSIZE,
                  "FinishReflowChild with unconstrained container width!");
   }
 
   nsPoint curOrigin = aKidFrame->GetPosition();
   WritingMode outerWM = aDesiredSize.GetWritingMode();
   LogicalSize convertedSize = aDesiredSize.Size(outerWM).ConvertTo(aWM,
                                                                    outerWM);
 
   if (NS_FRAME_NO_MOVE_FRAME != (aFlags & NS_FRAME_NO_MOVE_FRAME)) {
     aKidFrame->SetRect(aWM, LogicalRect(aWM, aPos, convertedSize),
-                       aContainerWidth);
+                       aContainerSize);
   } else {
     aKidFrame->SetSize(aWM, convertedSize);
   }
 
   if (aKidFrame->HasView()) {
     nsView* view = aKidFrame->GetView();
     // Make sure the frame's view is properly sized and positioned and has
     // things like opacity correct
@@ -1256,35 +1256,35 @@ nsContainerFrame::ReflowOverflowContaine
     if (shouldReflowAllKids || NS_SUBTREE_DIRTY(frame)) {
       // Get prev-in-flow
       nsIFrame* prevInFlow = frame->GetPrevInFlow();
       NS_ASSERTION(prevInFlow,
                    "overflow container frame must have a prev-in-flow");
       NS_ASSERTION(frame->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER,
                    "overflow container frame must have overflow container bit set");
       WritingMode wm = frame->GetWritingMode();
-      nscoord containerWidth = aReflowState.AvailableSize(wm).Width(wm);
-      LogicalRect prevRect = prevInFlow->GetLogicalRect(wm, containerWidth);
+      nsSize containerSize = aReflowState.AvailableSize(wm).GetPhysicalSize(wm);
+      LogicalRect prevRect = prevInFlow->GetLogicalRect(wm, containerSize);
 
       // Initialize reflow params
       LogicalSize availSpace(wm, prevRect.ISize(wm),
                              aReflowState.AvailableSize(wm).BSize(wm));
       nsHTMLReflowMetrics desiredSize(aReflowState);
       nsHTMLReflowState frameState(aPresContext, aReflowState,
                                    frame, availSpace);
       nsReflowStatus frameStatus;
 
       // Reflow
       LogicalPoint pos(wm, prevRect.IStart(wm), 0);
       ReflowChild(frame, aPresContext, desiredSize, frameState,
-                  wm, pos, containerWidth, aFlags, frameStatus, &tracker);
+                  wm, pos, containerSize, aFlags, frameStatus, &tracker);
       //XXXfr Do we need to override any shrinkwrap effects here?
       // e.g. desiredSize.Width() = prevRect.width;
       FinishReflowChild(frame, aPresContext, desiredSize, &frameState,
-                        wm, pos, containerWidth, aFlags);
+                        wm, pos, containerSize, aFlags);
 
       // Handle continuations
       if (!NS_FRAME_IS_FULLY_COMPLETE(frameStatus)) {
         if (frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
           // Abspos frames can't cause their parent to be incomplete,
           // only overflow incomplete.
           NS_FRAME_SET_OVERFLOW_INCOMPLETE(frameStatus);
         }
@@ -1316,17 +1316,17 @@ nsContainerFrame::ReflowOverflowContaine
       // but we have some unsplittable frames that, when taller than
       // availableHeight will push zero-height content into a next-in-flow.
     }
     else {
       tracker.Skip(frame, aStatus);
       if (aReflowState.mFloatManager) {
         nsBlockFrame::RecoverFloatsFor(frame, *aReflowState.mFloatManager,
                                        aReflowState.GetWritingMode(),
-                                       aReflowState.ComputedWidth());
+                                       aReflowState.ComputedPhysicalSize());
       }
     }
     ConsiderChildOverflow(aOverflowRects, frame);
   }
 }
 
 void
 nsContainerFrame::DisplayOverflowContainers(nsDisplayListBuilder*   aBuilder,
--- a/layout/generic/nsContainerFrame.h
+++ b/layout/generic/nsContainerFrame.h
@@ -236,61 +236,61 @@ public:
                   const mozilla::LogicalSize& aPadding,
                   bool aShrinkWrap) override;
 
   /**
    * Positions aChildFrame and its view (if requested), and then calls Reflow().
    * If the reflow status after reflowing the child is FULLY_COMPLETE then any
    * next-in-flows are deleted using DeleteNextInFlowChild().
    *
-   * @param aContainerWidth  width of the border-box of the containing frame
+   * @param aContainerSize  size of the border-box of the containing frame
    *
    * Flags:
    * NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you
    *    don't want to automatically sync the frame and view
    * NS_FRAME_NO_MOVE_FRAME - don't move the frame. aPos is ignored in this
    *    case. Also implies NS_FRAME_NO_MOVE_VIEW
    */
   void ReflowChild(nsIFrame*                      aChildFrame,
                    nsPresContext*                 aPresContext,
                    nsHTMLReflowMetrics&           aDesiredSize,
                    const nsHTMLReflowState&       aReflowState,
                    const mozilla::WritingMode&    aWM,
                    const mozilla::LogicalPoint&   aPos,
-                   nscoord                        aContainerWidth,
+                   const nsSize&                  aContainerSize,
                    uint32_t                       aFlags,
                    nsReflowStatus&                aStatus,
                    nsOverflowContinuationTracker* aTracker = nullptr);
 
   /**
    * The second half of frame reflow. Does the following:
    * - sets the frame's bounds
    * - sizes and positions (if requested) the frame's view. If the frame's final
    *   position differs from the current position and the frame itself does not
    *   have a view, then any child frames with views are positioned so they stay
    *   in sync
    * - sets the view's visibility, opacity, content transparency, and clip
    * - invoked the DidReflow() function
    *
-   * @param aContainerWidth  width of the border-box of the containing frame
+   * @param aContainerSize  size of the border-box of the containing frame
    *
    * Flags:
    * NS_FRAME_NO_MOVE_FRAME - don't move the frame. aPos is ignored in this
    *    case. Also implies NS_FRAME_NO_MOVE_VIEW
    * NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you
    *    don't want to automatically sync the frame and view
    * NS_FRAME_NO_SIZE_VIEW - don't size the frame's view
    */
   static void FinishReflowChild(nsIFrame*                    aKidFrame,
                                 nsPresContext*               aPresContext,
                                 const nsHTMLReflowMetrics&   aDesiredSize,
                                 const nsHTMLReflowState*     aReflowState,
                                 const mozilla::WritingMode&  aWM,
                                 const mozilla::LogicalPoint& aPos,
-                                nscoord                      aContainerWidth,
+                                const nsSize&                aContainerSize,
                                 uint32_t                     aFlags);
 
   //XXX temporary: hold on to a copy of the old physical versions of
   //    ReflowChild and FinishReflowChild so that we can convert callers
   //    incrementally.
   void ReflowChild(nsIFrame*                      aKidFrame,
                    nsPresContext*                 aPresContext,
                    nsHTMLReflowMetrics&           aDesiredSize,
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -3819,19 +3819,21 @@ nsFlexContainerFrame::DoFlexLayout(nsPre
   const LogicalSides skipSides =
     GetLogicalSkipSides(&aReflowState) | LogicalSides(eLogicalSideBitsBEnd);
   containerBP.ApplySkipSides(skipSides);
 
   const LogicalPoint containerContentBoxOrigin(flexWM,
                                                containerBP.IStart(flexWM),
                                                containerBP.BStart(flexWM));
 
-  nscoord containerWidth = aAxisTracker.IsMainAxisHorizontal() ?
-                             aContentBoxMainSize : contentBoxCrossSize;
-  containerWidth += aReflowState.ComputedPhysicalBorderPadding().LeftRight();
+  nsSize containerSize;
+  containerSize.width = aAxisTracker.IsMainAxisHorizontal() ?
+                          aContentBoxMainSize : contentBoxCrossSize;
+  containerSize.width +=
+    aReflowState.ComputedPhysicalBorderPadding().LeftRight();
 
   // FINAL REFLOW: Give each child frame another chance to reflow, now that
   // we know its final size and position.
   for (const FlexLine* line = lines.getFirst(); line; line = line->getNext()) {
     for (const FlexItem* item = line->GetFirstItem(); item;
          item = item->getNext()) {
       LogicalPoint framePos = aAxisTracker.LogicalPointFromFlexRelativePoint(
                                item->GetMainPosition(),
@@ -3864,23 +3866,23 @@ nsFlexContainerFrame::DoFlexLayout(nsPre
           // relative bsize.
           if (!(item->Frame()->GetStateBits() &
                 NS_FRAME_CONTAINS_RELATIVE_BSIZE)) {
             // Item has the correct size (and its children don't care that
             // it's now "definite"). Let's just make sure it's at the right
             // position.
             itemNeedsReflow = false;
             MoveFlexItemToFinalPosition(aReflowState, *item, framePos,
-                                        containerWidth);
+                                        containerSize);
           }
         }
       }
       if (itemNeedsReflow) {
         ReflowFlexItem(aPresContext, aAxisTracker, aReflowState,
-                       *item, framePos, containerWidth);
+                       *item, framePos, containerSize);
       }
 
       // If this is our first child and we haven't established a baseline for
       // the container yet (i.e. if we don't have 'align-self: baseline' on any
       // children), then use this child's baseline as the container's baseline.
       if (item->Frame() == mFrames.FirstChild() &&
           flexContainerAscent == nscoord_MIN) {
         flexContainerAscent = itemNormalBPos + item->ResolvedAscent();
@@ -3955,44 +3957,44 @@ nsFlexContainerFrame::DoFlexLayout(nsPre
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize)
 }
 
 void
 nsFlexContainerFrame::MoveFlexItemToFinalPosition(
   const nsHTMLReflowState& aReflowState,
   const FlexItem& aItem,
   LogicalPoint& aFramePos,
-  nscoord aContainerWidth)
+  const nsSize& aContainerSize)
 {
   WritingMode outerWM = aReflowState.GetWritingMode();
 
   // If item is relpos, look up its offsets (cached from prev reflow)
   LogicalMargin logicalOffsets(outerWM);
   if (NS_STYLE_POSITION_RELATIVE == aItem.Frame()->StyleDisplay()->mPosition) {
     FrameProperties props = aItem.Frame()->Properties();
     nsMargin* cachedOffsets =
       static_cast<nsMargin*>(props.Get(nsIFrame::ComputedOffsetProperty()));
     MOZ_ASSERT(cachedOffsets,
                "relpos previously-reflowed frame should've cached its offsets");
     logicalOffsets = LogicalMargin(outerWM, *cachedOffsets);
   }
   nsHTMLReflowState::ApplyRelativePositioning(aItem.Frame(), outerWM,
                                               logicalOffsets, &aFramePos,
-                                              aContainerWidth);
-  aItem.Frame()->SetPosition(outerWM, aFramePos, aContainerWidth);
+                                              aContainerSize);
+  aItem.Frame()->SetPosition(outerWM, aFramePos, aContainerSize);
   PositionChildViews(aItem.Frame());
 }
 
 void
 nsFlexContainerFrame::ReflowFlexItem(nsPresContext* aPresContext,
                                      const FlexboxAxisTracker& aAxisTracker,
                                      const nsHTMLReflowState& aReflowState,
                                      const FlexItem& aItem,
                                      LogicalPoint& aFramePos,
-                                     nscoord aContainerWidth)
+                                     const nsSize& aContainerSize)
 {
   WritingMode outerWM = aReflowState.GetWritingMode();
   WritingMode wm = aItem.Frame()->GetWritingMode();
   LogicalSize availSize = aReflowState.ComputedSize(wm);
   availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
   nsHTMLReflowState childReflowState(aPresContext, aReflowState,
                                      aItem.Frame(), availSize);
 
@@ -4047,36 +4049,36 @@ nsFlexContainerFrame::ReflowFlexItem(nsP
   // NOTE: Be very careful about doing anything else with childReflowState
   // after this point, because some of its methods (e.g. SetComputedWidth)
   // internally call InitResizeFlags and stomp on mVResize & mHResize.
 
   nsHTMLReflowMetrics childDesiredSize(childReflowState);
   nsReflowStatus childReflowStatus;
   ReflowChild(aItem.Frame(), aPresContext,
               childDesiredSize, childReflowState,
-              outerWM, aFramePos, aContainerWidth,
+              outerWM, aFramePos, aContainerSize,
               0, childReflowStatus);
 
   // XXXdholbert Once we do pagination / splitting, we'll need to actually
   // handle incomplete childReflowStatuses. But for now, we give our kids
   // unconstrained available height, which means they should always
   // complete.
   MOZ_ASSERT(NS_FRAME_IS_COMPLETE(childReflowStatus),
              "We gave flex item unconstrained available height, so it "
              "should be complete");
 
   LogicalMargin offsets =
     childReflowState.ComputedLogicalOffsets().ConvertTo(outerWM, wm);
   nsHTMLReflowState::ApplyRelativePositioning(aItem.Frame(), outerWM,
                                               offsets, &aFramePos,
-                                              aContainerWidth);
+                                              aContainerSize);
 
   FinishReflowChild(aItem.Frame(), aPresContext,
                     childDesiredSize, &childReflowState,
-                    outerWM, aFramePos, aContainerWidth, 0);
+                    outerWM, aFramePos, aContainerSize, 0);
 
   // Save the first child's ascent; it may establish container's baseline.
   if (aItem.Frame() == mFrames.FirstChild()) {
     aItem.SetAscent(childDesiredSize.BlockStartAscent());
   }
 }
 
 /* virtual */ nscoord
--- a/layout/generic/nsFlexContainerFrame.h
+++ b/layout/generic/nsFlexContainerFrame.h
@@ -178,40 +178,40 @@ protected:
    * This can be used in cases where we've already done a "measuring reflow"
    * for the flex item at the correct size, and hence can skip its final reflow
    * (but still need to move it to the right final position).
    *
    * @param aReflowState    The flex container's reflow state.
    * @param aItem           The flex item whose frame should be moved.
    * @param aFramePos       The position where the flex item's frame should
    *                        be placed. (pre-relative positioning)
-   * @param aContainerWidth The flex container's width (required by some methods
+   * @param aContainerSize  The flex container's size (required by some methods
    *                        that we call, to interpret aFramePos correctly).
    */
   void MoveFlexItemToFinalPosition(const nsHTMLReflowState& aReflowState,
                                    const FlexItem& aItem,
                                    mozilla::LogicalPoint& aFramePos,
-                                   nscoord aContainerWidth);
+                                   const nsSize& aContainerSize);
   /**
    * Helper-function to reflow a child frame, at its final position determined
    * by flex layout.
    *
    * @param aPresContext    The presentation context being used in reflow.
    * @param aAxisTracker    A FlexboxAxisTracker with the flex container's axes.
    * @param aReflowState    The flex container's reflow state.
    * @param aItem           The flex item to be reflowed.
    * @param aFramePos       The position where the flex item's frame should
    *                        be placed. (pre-relative positioning)
-   * @param aContainerWidth The flex container's width (required by some methods
+   * @param aContainerSize  The flex container's size (required by some methods
    *                        that we call, to interpret aFramePos correctly).
    */
   void ReflowFlexItem(nsPresContext* aPresContext,
                       const FlexboxAxisTracker& aAxisTracker,
                       const nsHTMLReflowState& aReflowState,
                       const FlexItem& aItem,
                       mozilla::LogicalPoint& aFramePos,
-                      nscoord aContainerWidth);
+                      const nsSize& aContainerSize);
 
   bool mChildrenHaveBeenReordered; // Have we ever had to reorder our kids
                                    // to satisfy their 'order' values?
 };
 
 #endif /* nsFlexContainerFrame_h___ */
--- a/layout/generic/nsFloatManager.cpp
+++ b/layout/generic/nsFloatManager.cpp
@@ -117,17 +117,17 @@ void nsFloatManager::Shutdown()
 #define CHECK_BLOCK_DIR(aWM) \
   NS_ASSERTION(aWM.GetBlockDir() == mWritingMode.value.GetBlockDir(), \
   "incompatible writing modes")
 
 nsFlowAreaRect
 nsFloatManager::GetFlowArea(WritingMode aWM, nscoord aBOffset,
                             BandInfoType aInfoType, nscoord aBSize,
                             LogicalRect aContentArea, SavedState* aState,
-                            nscoord aContainerWidth) const
+                            const nsSize& aContainerSize) const
 {
   CHECK_BLOCK_DIR(aWM);
   NS_ASSERTION(aBSize >= 0, "unexpected max block size");
   NS_ASSERTION(aContentArea.ISize(aWM) >= 0,
                "unexpected content area inline size");
 
   nscoord blockStart = aBOffset + mBlockStart;
   if (blockStart < nscoord_MIN) {
@@ -164,18 +164,18 @@ nsFloatManager::GetFlowArea(WritingMode 
     blockEnd = nscoord_MAX;
   } else {
     blockEnd = blockStart + aBSize;
     if (blockEnd < blockStart || blockEnd > nscoord_MAX) {
       NS_WARNING("bad value");
       blockEnd = nscoord_MAX;
     }
   }
-  nscoord lineLeft = mLineLeft + aContentArea.LineLeft(aWM, aContainerWidth);
-  nscoord lineRight = mLineLeft + aContentArea.LineRight(aWM, aContainerWidth);
+  nscoord lineLeft = mLineLeft + aContentArea.LineLeft(aWM, aContainerSize);
+  nscoord lineRight = mLineLeft + aContentArea.LineRight(aWM, aContainerSize);
   if (lineRight < lineLeft) {
     NS_WARNING("bad value");
     lineRight = lineLeft;
   }
 
   // Walk backwards through the floats until we either hit the front of
   // the list or we're above |blockStart|.
   bool haveFloats = false;
@@ -238,33 +238,33 @@ nsFloatManager::GetFlowArea(WritingMode 
       }
     }
   }
 
   nscoord blockSize = (blockEnd == nscoord_MAX) ?
                        nscoord_MAX : (blockEnd - blockStart);
   // convert back from LineLeft/Right to IStart
   nscoord inlineStart = aWM.IsVertical() || aWM.IsBidiLTR()
-                         ? lineLeft - mLineLeft
-                         : mLineLeft + aContainerWidth - lineRight;
+                        ? lineLeft - mLineLeft
+                        : mLineLeft - lineRight + aContainerSize.width;
 
   return nsFlowAreaRect(aWM, inlineStart, blockStart - mBlockStart,
                         lineRight - lineLeft, blockSize, haveFloats);
 }
 
 nsresult
 nsFloatManager::AddFloat(nsIFrame* aFloatFrame, const LogicalRect& aMarginRect,
-                         WritingMode aWM, nscoord aContainerWidth)
+                         WritingMode aWM, const nsSize& aContainerSize)
 {
   CHECK_BLOCK_DIR(aWM);
   NS_ASSERTION(aMarginRect.ISize(aWM) >= 0, "negative inline size!");
   NS_ASSERTION(aMarginRect.BSize(aWM) >= 0, "negative block size!");
 
   FloatInfo info(aFloatFrame,
-                 aMarginRect.LineLeft(aWM, aContainerWidth) + mLineLeft,
+                 aMarginRect.LineLeft(aWM, aContainerSize) + mLineLeft,
                  aMarginRect.BStart(aWM) + mBlockStart,
                  aMarginRect.ISize(aWM),
                  aMarginRect.BSize(aWM));
 
   // Set mLeftBEnd and mRightBEnd.
   if (HasAnyFloats()) {
     FloatInfo &tail = mFloats[mFloats.Length() - 1];
     info.mLeftBEnd = tail.mLeftBEnd;
@@ -288,22 +288,22 @@ nsFloatManager::AddFloat(nsIFrame* aFloa
   return NS_OK;
 }
 
 // static
 LogicalRect
 nsFloatManager::CalculateRegionFor(WritingMode          aWM,
                                    nsIFrame*            aFloat,
                                    const LogicalMargin& aMargin,
-                                   nscoord              aContainerWidth)
+                                   const nsSize&        aContainerSize)
 {
   // We consider relatively positioned frames at their original position.
   LogicalRect region(aWM, nsRect(aFloat->GetNormalPosition(),
                                  aFloat->GetSize()),
-                     aContainerWidth);
+                     aContainerSize);
 
   // Float region includes its margin
   region.Inflate(aWM, aMargin);
 
   // Don't store rectangles with negative margin-box width or height in
   // the float manager; it can't deal with them.
   if (region.ISize(aWM) < 0) {
     // Preserve the right margin-edge for left floats and the left
@@ -319,33 +319,33 @@ nsFloatManager::CalculateRegionFor(Writi
   }
   return region;
 }
 
 NS_DECLARE_FRAME_PROPERTY(FloatRegionProperty, DeleteValue<nsMargin>)
 
 LogicalRect
 nsFloatManager::GetRegionFor(WritingMode aWM, nsIFrame* aFloat,
-                             nscoord aContainerWidth)
+                             const nsSize& aContainerSize)
 {
-  LogicalRect region = aFloat->GetLogicalRect(aWM, aContainerWidth);
+  LogicalRect region = aFloat->GetLogicalRect(aWM, aContainerSize);
   void* storedRegion = aFloat->Properties().Get(FloatRegionProperty());
   if (storedRegion) {
     nsMargin margin = *static_cast<nsMargin*>(storedRegion);
     region.Inflate(aWM, LogicalMargin(aWM, margin));
   }
   return region;
 }
 
 void
 nsFloatManager::StoreRegionFor(WritingMode aWM, nsIFrame* aFloat,
                                const LogicalRect& aRegion,
-                               nscoord aContainerWidth)
+                               const nsSize& aContainerSize)
 {
-  nsRect region = aRegion.GetPhysicalRect(aWM, aContainerWidth);
+  nsRect region = aRegion.GetPhysicalRect(aWM, aContainerSize);
   nsRect rect = aFloat->GetRect();
   FrameProperties props = aFloat->Properties();
   if (region.IsEqualEdges(rect)) {
     props.Delete(FloatRegionProperty());
   }
   else {
     nsMargin* storedMargin = static_cast<nsMargin*>
       (props.Get(FloatRegionProperty()));
--- a/layout/generic/nsFloatManager.h
+++ b/layout/generic/nsFloatManager.h
@@ -54,38 +54,38 @@ public:
 
   /**
    * Get float region stored on the frame. (Defaults to mRect if it's
    * not there.) The float region is the area impacted by this float;
    * the coordinates are relative to the containing block frame.
    */
   static mozilla::LogicalRect GetRegionFor(mozilla::WritingMode aWM,
                                            nsIFrame* aFloatFrame,
-                                           nscoord aContainerWidth);
+                                           const nsSize& aContainerSize);
   /**
    * Calculate the float region for this frame using aMargin and the
    * frame's mRect. The region includes the margins around the float,
    * but doesn't include the relative offsets.
    * Note that if the frame is or has a continuation, aMargin's top
    * and/or bottom must be zeroed by the caller.
    */
   static mozilla::LogicalRect CalculateRegionFor(
                                 mozilla::WritingMode aWM,
                                 nsIFrame* aFloatFrame,
                                 const mozilla::LogicalMargin& aMargin,
-                                nscoord aContainerWidth);
+                                const nsSize& aContainerSize);
   /**
    * Store the float region on the frame. The region is stored
    * as a delta against the mRect, so repositioning the frame will
    * also reposition the float region.
    */
   static void StoreRegionFor(mozilla::WritingMode aWM,
                              nsIFrame* aFloat,
                              const mozilla::LogicalRect& aRegion,
-                             nscoord aContainerWidth);
+                             const nsSize& aContainerSize);
 
   // Structure that stores the current state of a frame manager for
   // Save/Restore purposes.
   struct SavedState {
     explicit SavedState() {}
   private:
     uint32_t mFloatInfoCount;
     nscoord mLineLeft, mBlockStart;
@@ -157,29 +157,30 @@ public:
    *            inline size at all (because they are entirely in the margins)
    *
    * aBCoord and aAvailSpace are positioned relative to the current translation
    */
   enum BandInfoType { BAND_FROM_POINT, WIDTH_WITHIN_HEIGHT };
   nsFlowAreaRect GetFlowArea(mozilla::WritingMode aWM,
                              nscoord aBCoord, BandInfoType aInfoType,
                              nscoord aBSize, mozilla::LogicalRect aContentArea,
-                             SavedState* aState, nscoord mContainerWidth) const;
+                             SavedState* aState,
+                             const nsSize& aContainerSize) const;
 
   /**
    * Add a float that comes after all floats previously added.  Its
    * block start must be even with or below the top of all previous
    * floats.
    *
    * aMarginRect is relative to the current translation.  The caller
    * must ensure aMarginRect.height >= 0 and aMarginRect.width >= 0.
    */
   nsresult AddFloat(nsIFrame* aFloatFrame,
                     const mozilla::LogicalRect& aMarginRect,
-                    mozilla::WritingMode aWM, nscoord aContainerWidth);
+                    mozilla::WritingMode aWM, const nsSize& aContainerSize);
 
   /**
    * Notify that we tried to place a float that could not fit at all and
    * had to be pushed to the next page/column?  (If so, we can't place
    * any more floats in this page/column because of the rule that the
    * top of a float cannot be above the top of an earlier float.  It
    * also means that any clear needs to continue to the next column.)
    */
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -3550,29 +3550,29 @@ static FrameTarget GetSelectionClosestFr
 {
   nsIFrame *frame = aLine->mFirstChild;
   // Account for end of lines (any iterator from the block is valid)
   if (aLine == aParent->end_lines())
     return DrillDownToSelectionFrame(aParent, true, aFlags);
   nsIFrame *closestFromIStart = nullptr, *closestFromIEnd = nullptr;
   nscoord closestIStart = aLine->IStart(), closestIEnd = aLine->IEnd();
   WritingMode wm = aLine->mWritingMode;
-  LogicalPoint pt(wm, aPoint, aLine->mContainerWidth);
+  LogicalPoint pt(wm, aPoint, aLine->mContainerSize);
   bool canSkipBr = false;
   for (int32_t n = aLine->GetChildCount(); n;
        --n, frame = frame->GetNextSibling()) {
     // Skip brFrames. Can only skip if the line contains at least
     // one selectable and non-empty frame before
     if (!SelfIsSelectable(frame, aFlags) || frame->IsEmpty() ||
         (canSkipBr && frame->GetType() == nsGkAtoms::brFrame)) {
       continue;
     }
     canSkipBr = true;
     LogicalRect frameRect = LogicalRect(wm, frame->GetRect(),
-                                        aLine->mContainerWidth);
+                                        aLine->mContainerSize);
     if (pt.I(wm) >= frameRect.IStart(wm)) {
       if (pt.I(wm) < frameRect.IEnd(wm)) {
         return GetSelectionClosestFrameForChild(frame, aPoint, aFlags);
       }
       if (frameRect.IEnd(wm) >= closestIStart) {
         closestFromIStart = frame;
         closestIStart = frameRect.IEnd(wm);
       }
@@ -3620,17 +3620,17 @@ static FrameTarget GetSelectionClosestFr
       return FrameTarget(aFrame, false, false, true);
     }
     return FrameTarget::Null();
   }
   nsBlockFrame::line_iterator curLine = firstLine;
   nsBlockFrame::line_iterator closestLine = end;
   // Convert aPoint into a LogicalPoint in the writing-mode of this block
   WritingMode wm = curLine->mWritingMode;
-  LogicalPoint pt(wm, aPoint, curLine->mContainerWidth);
+  LogicalPoint pt(wm, aPoint, curLine->mContainerSize);
   while (curLine != end) {
     // Check to see if our point lies within the line's block-direction bounds
     nscoord BCoord = pt.B(wm) - curLine->BStart();
     nscoord BSize = curLine->BSize();
     if (BCoord >= 0 && BCoord < BSize) {
       closestLine = curLine;
       break; // We found the line; stop looking
     }
@@ -5676,24 +5676,26 @@ nsIFrame::ListGeneric(nsACString& aTo, c
                            wm.IsBidiLTR() ? "ltr" : "rtl",
                            ISize(), BSize());
   }
 
   nsIFrame* parent = GetParent();
   if (parent) {
     WritingMode pWM = parent->GetWritingMode();
     if (pWM.IsVertical() || !pWM.IsBidiLTR()) {
-      nscoord cw = parent->mRect.width;
-      LogicalRect lr(pWM, mRect, cw);
-      aTo += nsPrintfCString(" parent wm=%s-%s,width=%d,logicalRect={%d,%d,%d,%d}",
+      nsSize containerSize = parent->mRect.Size();
+      LogicalRect lr(pWM, mRect, containerSize);
+      aTo += nsPrintfCString(" parent wm=%s-%s, cs={%d,%d}, "
+                             " logicalRect={%d,%d,%d,%d}",
                              pWM.IsVertical() ? pWM.IsVerticalLR()
                                                 ? "vlr" : "vrl"
                                               : "htb",
                              wm.IsBidiLTR() ? "ltr" : "rtl",
-                             cw, lr.IStart(pWM), lr.BStart(pWM),
+                             containerSize.width, containerSize.height,
+                             lr.IStart(pWM), lr.BStart(pWM),
                              lr.ISize(pWM), lr.BSize(pWM));
     }
   }
   nsIFrame* f = const_cast<nsIFrame*>(this);
   if (f->HasOverflowAreas()) {
     nsRect vo = f->GetVisualOverflowRect();
     if (!vo.IsEqualEdges(mRect)) {
       aTo += nsPrintfCString(" vis-overflow=%d,%d,%d,%d", vo.x, vo.y, vo.width, vo.height);
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -509,33 +509,35 @@ nsHTMLScrollFrame::ReflowScrolledFrame(S
   // Temporarily set mHasHorizontalScrollbar/mHasVerticalScrollbar to
   // reflect our assumptions while we reflow the child.
   bool didHaveHorizontalScrollbar = mHelper.mHasHorizontalScrollbar;
   bool didHaveVerticalScrollbar = mHelper.mHasVerticalScrollbar;
   mHelper.mHasHorizontalScrollbar = aAssumeHScroll;
   mHelper.mHasVerticalScrollbar = aAssumeVScroll;
 
   nsReflowStatus status;
-  // No need to pass a container-width to ReflowChild or
+  // No need to pass a true container-size to ReflowChild or
   // FinishReflowChild, because it's only used there when positioning
   // the frame (i.e. if NS_FRAME_NO_MOVE_FRAME isn't set)
+  const nsSize dummyContainerSize;
   ReflowChild(mHelper.mScrolledFrame, presContext, *aMetrics,
-              kidReflowState, wm, LogicalPoint(wm), 0,
+              kidReflowState, wm, LogicalPoint(wm), dummyContainerSize,
               NS_FRAME_NO_MOVE_FRAME, status);
 
   mHelper.mHasHorizontalScrollbar = didHaveHorizontalScrollbar;
   mHelper.mHasVerticalScrollbar = didHaveVerticalScrollbar;
 
   // Don't resize or position the view (if any) because we're going to resize
   // it to the correct size anyway in PlaceScrollArea. Allowing it to
   // resize here would size it to the natural height of the frame,
   // which will usually be different from the scrollport height;
   // invalidating the difference will cause unnecessary repainting.
   FinishReflowChild(mHelper.mScrolledFrame, presContext,
-                    *aMetrics, &kidReflowState, wm, LogicalPoint(wm), 0,
+                    *aMetrics, &kidReflowState, wm, LogicalPoint(wm),
+                    dummyContainerSize,
                     NS_FRAME_NO_MOVE_FRAME | NS_FRAME_NO_SIZE_VIEW);
 
   // XXX Some frames (e.g., nsPluginFrame, nsFrameFrame, nsTextFrame) don't bother
   // setting their mOverflowArea. This is wrong because every frame should
   // always set mOverflowArea. In fact nsPluginFrame and nsFrameFrame don't
   // support the 'outline' property because of this. Rather than fix the world
   // right now, just fix up the overflow area if necessary. Note that we don't
   // check HasOverflowRect() because it could be set even though the
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -1241,18 +1241,19 @@ nsGridContainerFrame::ReflowChildren(Gri
                                      const nsTArray<TrackSize>& aColSizes,
                                      const nsTArray<TrackSize>& aRowSizes,
                                      nsHTMLReflowMetrics&       aDesiredSize,
                                      const nsHTMLReflowState&   aReflowState,
                                      nsReflowStatus&            aStatus)
 {
   WritingMode wm = aReflowState.GetWritingMode();
   const LogicalPoint gridOrigin(aContentArea.Origin(wm));
-  const nscoord containerWidth = aContentArea.Width(wm) +
-    aReflowState.ComputedPhysicalBorderPadding().LeftRight();
+  const nsSize containerSize =
+    (aContentArea.Size(wm) +
+     aReflowState.ComputedLogicalBorderPadding().Size(wm)).GetPhysicalSize(wm);
   nsPresContext* pc = PresContext();
   for (; !aIter.AtEnd(); aIter.Next()) {
     nsIFrame* child = *aIter;
     const bool isGridItem = child->GetType() != nsGkAtoms::placeholderFrame;
     LogicalRect cb(wm);
     if (MOZ_LIKELY(isGridItem)) {
       GridArea* area = GetGridAreaForChild(child);
       MOZ_ASSERT(area && area->IsDefinite());
@@ -1270,30 +1271,32 @@ nsGridContainerFrame::ReflowChildren(Gri
       // clamping though, and check the prop value is actually 'stretch'!
       LogicalMargin bp = childRS.ComputedLogicalBorderPadding();
       bp.ApplySkipSides(child->GetLogicalSkipSides());
       nscoord bSize = childCBSize.BSize(childWM) - bp.BStartEnd(childWM) -
                         margin.BStartEnd(childWM);
       childRS.SetComputedBSize(std::max(bSize, 0));
     }
     // We need the width of the child before we can correctly convert
-    // the writing-mode of its origin, so we reflow at (0, 0) and then
-    // pass the correct position to FinishReflowChild.
+    // the writing-mode of its origin, so we reflow at (0, 0) using a dummy
+    // containerSize, and then pass the correct position to FinishReflowChild.
     nsHTMLReflowMetrics childSize(childRS);
     nsReflowStatus childStatus;
+    const nsSize dummyContainerSize;
     ReflowChild(child, pc, childSize, childRS, childWM, LogicalPoint(childWM),
-                0, 0, childStatus);
+                dummyContainerSize, 0, childStatus);
     LogicalPoint childPos =
-      cb.Origin(wm).ConvertTo(childWM, wm, containerWidth - childSize.Width() -
-                                           margin.LeftRight(childWM));
+      cb.Origin(wm).ConvertTo(childWM, wm,
+                              containerSize - childSize.PhysicalSize() -
+                              margin.Size(childWM).GetPhysicalSize(childWM));
     childPos.I(childWM) += margin.IStart(childWM);
     childPos.B(childWM) += margin.BStart(childWM);
-    childRS.ApplyRelativePositioning(&childPos, containerWidth);
+    childRS.ApplyRelativePositioning(&childPos, containerSize);
     FinishReflowChild(child, pc, childSize, &childRS, childWM, childPos,
-                      containerWidth, 0);
+                      containerSize, 0);
     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, child);
     // XXX deal with 'childStatus' not being COMPLETE
   }
 
   if (IsAbsoluteContainer()) {
     nsFrameList children(GetChildList(GetAbsoluteListID()));
     if (!children.IsEmpty()) {
       LogicalMargin pad(aReflowState.ComputedLogicalPadding());
@@ -1313,17 +1316,17 @@ nsGridContainerFrame::ReflowChildren(Gri
                                                     gridOrigin, gridCB));
         // nsAbsoluteContainingBlock::Reflow uses physical coordinates.
         nsRect* cb = static_cast<nsRect*>(child->Properties().Get(
                        GridItemContainingBlockRect()));
         if (!cb) {
           cb = new nsRect;
           child->Properties().Set(GridItemContainingBlockRect(), cb);
         }
-        *cb = itemCB.GetPhysicalRect(wm, containerWidth);
+        *cb = itemCB.GetPhysicalRect(wm, containerSize);
       }
       // This rect isn't used at all for layout so we use it to optimize
       // away the virtual GetType() call in the callee in most cases.
       // @see nsAbsoluteContainingBlock::Reflow
       nsRect dummyRect(0, 0, VERY_LIKELY_A_GRID_CONTAINER, 0);
       GetAbsoluteContainingBlock()->Reflow(this, pc, aReflowState, aStatus,
                                            dummyRect, true,
                                            true, true, // XXX could be optimized
--- a/layout/generic/nsHTMLReflowMetrics.h
+++ b/layout/generic/nsHTMLReflowMetrics.h
@@ -267,16 +267,21 @@ public:
   nscoord BlockStartAscent() const
   {
     return mBlockStartAscent;
   }
 
   nscoord& Width() { return mWritingMode.IsVertical() ? mBSize : mISize; }
   nscoord& Height() { return mWritingMode.IsVertical() ? mISize : mBSize; }
 
+  nsSize PhysicalSize()
+  {
+    return Size(mWritingMode).GetPhysicalSize(mWritingMode);
+  }
+
   void SetBlockStartAscent(nscoord aAscent)
   {
     mBlockStartAscent = aAscent;
   }
 
   enum { ASK_FOR_BASELINE = nscoord_MAX };
 
   // Metrics that _exactly_ enclose the text to allow precise MathML placements.
--- a/layout/generic/nsHTMLReflowState.cpp
+++ b/layout/generic/nsHTMLReflowState.cpp
@@ -1260,53 +1260,57 @@ nsHTMLReflowState::CalculateHypothetical
     }
   }
 
   // Get the placeholder x-offset and y-offset in the coordinate
   // space of its containing block
   // XXXbz the placeholder is not fully reflowed yet if our containing block is
   // relatively positioned...
   WritingMode cbwm = cbrs->GetWritingMode();
-  nscoord containerWidth = containingBlock->GetStateBits() & NS_FRAME_IN_REFLOW
-    ? cbrs->ComputedSizeAsContainerIfConstrained().width
-    : containingBlock->GetSize().width;
+  nsSize containerSize = containingBlock->GetStateBits() & NS_FRAME_IN_REFLOW
+    ? cbrs->ComputedSizeAsContainerIfConstrained()
+    : containingBlock->GetSize();
   LogicalPoint placeholderOffset(wm, aPlaceholderFrame->GetOffsetTo(containingBlock),
-                                 containerWidth);
+                                 containerSize);
 
   // XXX hack to correct for lack of LogicalPoint bidi support in vertical mode
   if (wm.IsVertical() && !wm.IsBidiLTR()) {
     placeholderOffset.I(wm) = cbrs->ComputedHeight() +
       cbrs->ComputedLogicalBorderPadding().TopBottom(cbwm) -
       placeholderOffset.I(wm);
   }
 
   // First, determine the hypothetical box's mBStart.  We want to check the
   // content insertion frame of containingBlock for block-ness, but make
   // sure to compute all coordinates in the coordinate system of
   // containingBlock.
   nsBlockFrame* blockFrame =
     nsLayoutUtils::GetAsBlock(containingBlock->GetContentInsertionFrame());
   if (blockFrame) {
-    LogicalPoint blockOffset(wm, blockFrame->GetOffsetTo(containingBlock), 0);
+    // Use a null containerSize to convert a LogicalPoint functioning as a
+    // vector into a physical nsPoint vector.
+    const nsSize nullContainerSize;
+    LogicalPoint blockOffset(wm, blockFrame->GetOffsetTo(containingBlock),
+                             nullContainerSize);
     bool isValid;
     nsBlockInFlowLineIterator iter(blockFrame, aPlaceholderFrame, &isValid);
     if (!isValid) {
       // Give up.  We're probably dealing with somebody using
       // position:absolute inside native-anonymous content anyway.
       aHypotheticalBox.mBStart = placeholderOffset.B(wm);
     } else {
       NS_ASSERTION(iter.GetContainer() == blockFrame,
                    "Found placeholder in wrong block!");
       nsBlockFrame::line_iterator lineBox = iter.GetLine();
 
       // How we determine the hypothetical box depends on whether the element
       // would have been inline-level or block-level
       LogicalRect lineBounds =
         lineBox->GetBounds().ConvertTo(wm, lineBox->mWritingMode,
-                                       lineBox->mContainerWidth);
+                                       lineBox->mContainerSize);
       if (mStyleDisplay->IsOriginalDisplayInlineOutsideStyle()) {
         // Use the block-start of the inline box which the placeholder lives in
         // as the hypothetical box's block-start.
         aHypotheticalBox.mBStart = lineBounds.BStart(wm) + blockOffset.B(wm);
       } else {
         // The element would have been block-level which means it would
         // be below the line containing the placeholder frame, unless
         // all the frames before it are empty.  In that case, it would
@@ -1409,19 +1413,20 @@ nsHTMLReflowState::CalculateHypothetical
     } while (containingBlock != cbrs->frame);
   } else {
     // XXXldb We need to either ignore scrolling for the absolute
     // positioning case too (and take the incompatibility) or figure out
     // how to make these positioned elements actually *move* when we
     // scroll, and thus avoid the resulting incremental reflow bugs.
     cbOffset = containingBlock->GetOffsetTo(cbrs->frame);
   }
-  nscoord cbrsWidth = cbrs->ComputedWidth() +
-                        cbrs->ComputedLogicalBorderPadding().LeftRight(cbwm);
-  LogicalPoint logCBOffs(wm, cbOffset, cbrsWidth - containerWidth);
+  nsSize cbrsSize =
+    cbrs->ComputedPhysicalSize() +
+    cbrs->ComputedLogicalBorderPadding().Size(cbwm).GetPhysicalSize(cbwm);
+  LogicalPoint logCBOffs(wm, cbOffset, cbrsSize - containerSize);
   aHypotheticalBox.mIStart += logCBOffs.I(wm);
   aHypotheticalBox.mIEnd += logCBOffs.I(wm);
   aHypotheticalBox.mBStart += logCBOffs.B(wm);
 
   // The specified offsets are relative to the absolute containing block's
   // padding edge and our current values are relative to the border edge, so
   // translate.
   LogicalMargin border =
--- a/layout/generic/nsHTMLReflowState.h
+++ b/layout/generic/nsHTMLReflowState.h
@@ -431,16 +431,21 @@ struct nsHTMLReflowState : public nsCSSO
   }
 
   mozilla::LogicalSize
   ComputedSizeWithMarginBorderPadding(mozilla::WritingMode aWM) const {
     return ComputedSizeWithMarginBorderPadding().ConvertTo(aWM,
                                                            GetWritingMode());
   }
 
+  nsSize
+  ComputedPhysicalSize() const {
+    return nsSize(ComputedWidth(), ComputedHeight());
+  }
+
   // XXX this will need to change when we make mComputedOffsets logical;
   // we won't be able to return a reference for the physical offsets
   const nsMargin& ComputedPhysicalOffsets() const { return mComputedOffsets; }
   nsMargin& ComputedPhysicalOffsets() { return mComputedOffsets; }
 
   const LogicalMargin ComputedLogicalOffsets() const
     { return LogicalMargin(mWritingMode, mComputedOffsets); }
 
@@ -845,37 +850,37 @@ public:
     ApplyRelativePositioning(frame, ComputedPhysicalOffsets(), aPosition);
   }
 
   static void
   ApplyRelativePositioning(nsIFrame* aFrame,
                            mozilla::WritingMode aWritingMode,
                            const mozilla::LogicalMargin& aComputedOffsets,
                            mozilla::LogicalPoint* aPosition,
-                           nscoord aContainerWidth) {
-    // Subtract the width of the frame from the container width that we
+                           const nsSize& aContainerSize) {
+    // Subtract the size of the frame from the container size that we
     // use for converting between the logical and physical origins of
     // the frame. This accounts for the fact that logical origins in RTL
     // coordinate systems are at the top right of the frame instead of
     // the top left.
-    nscoord frameWidth = aFrame->GetSize().width;
+    nsSize frameSize = aFrame->GetSize();
     nsPoint pos = aPosition->GetPhysicalPoint(aWritingMode,
-                                              aContainerWidth - frameWidth);
+                                              aContainerSize - frameSize);
     ApplyRelativePositioning(aFrame,
                              aComputedOffsets.GetPhysicalMargin(aWritingMode),
                              &pos);
     *aPosition = mozilla::LogicalPoint(aWritingMode, pos,
-                                       aContainerWidth - frameWidth);
+                                       aContainerSize - frameSize);
   }
 
   void ApplyRelativePositioning(mozilla::LogicalPoint* aPosition,
-                                nscoord aContainerWidth) const {
+                                const nsSize& aContainerSize) const {
     ApplyRelativePositioning(frame, mWritingMode,
                              ComputedLogicalOffsets(), aPosition,
-                             aContainerWidth);
+                             aContainerSize);
   }
 
 #ifdef DEBUG
   // Reflow trace methods.  Defined in nsFrame.cpp so they have access
   // to the display-reflow infrastructure.
   static void* DisplayInitConstraintsEnter(nsIFrame* aFrame,
                                            nsHTMLReflowState* aState,
                                            nscoord aCBISize,
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -654,49 +654,49 @@ public:
   nsSize GetSize() const { return mRect.Size(); }
   nsRect GetRectRelativeToSelf() const {
     return nsRect(nsPoint(0, 0), mRect.Size());
   }
   /**
    * Dimensions and position in logical coordinates in the frame's writing mode
    *  or another writing mode
    */
-  mozilla::LogicalRect GetLogicalRect(nscoord aContainerWidth) const {
-    return GetLogicalRect(GetWritingMode(), aContainerWidth);
+  mozilla::LogicalRect GetLogicalRect(const nsSize& aContainerSize) const {
+    return GetLogicalRect(GetWritingMode(), aContainerSize);
   }
-  mozilla::LogicalPoint GetLogicalPosition(nscoord aContainerWidth) const {
-    return GetLogicalPosition(GetWritingMode(), aContainerWidth);
+  mozilla::LogicalPoint GetLogicalPosition(const nsSize& aContainerSize) const {
+    return GetLogicalPosition(GetWritingMode(), aContainerSize);
   }
   mozilla::LogicalSize GetLogicalSize() const {
     return GetLogicalSize(GetWritingMode());
   }
   mozilla::LogicalRect GetLogicalRect(mozilla::WritingMode aWritingMode,
-                                      nscoord aContainerWidth) const {
-    return mozilla::LogicalRect(aWritingMode, GetRect(), aContainerWidth);
+                                      const nsSize& aContainerSize) const {
+    return mozilla::LogicalRect(aWritingMode, GetRect(), aContainerSize);
   }
   mozilla::LogicalPoint GetLogicalPosition(mozilla::WritingMode aWritingMode,
-                                           nscoord aContainerWidth) const {
-    return GetLogicalRect(aWritingMode, aContainerWidth).Origin(aWritingMode);
+                                           const nsSize& aContainerSize) const {
+    return GetLogicalRect(aWritingMode, aContainerSize).Origin(aWritingMode);
   }
   mozilla::LogicalSize GetLogicalSize(mozilla::WritingMode aWritingMode) const {
     return mozilla::LogicalSize(aWritingMode, GetSize());
   }
-  nscoord IStart(nscoord aContainerWidth) const {
-    return IStart(GetWritingMode(), aContainerWidth);
+  nscoord IStart(const nsSize& aContainerSize) const {
+    return IStart(GetWritingMode(), aContainerSize);
   }
   nscoord IStart(mozilla::WritingMode aWritingMode,
-                 nscoord aContainerWidth) const {
-    return GetLogicalPosition(aWritingMode, aContainerWidth).I(aWritingMode);
+                 const nsSize& aContainerSize) const {
+    return GetLogicalPosition(aWritingMode, aContainerSize).I(aWritingMode);
   }
-  nscoord BStart(nscoord aContainerWidth) const {
-    return BStart(GetWritingMode(), aContainerWidth);
+  nscoord BStart(const nsSize& aContainerSize) const {
+    return BStart(GetWritingMode(), aContainerSize);
   }
   nscoord BStart(mozilla::WritingMode aWritingMode,
-                 nscoord aContainerWidth) const {
-    return GetLogicalPosition(aWritingMode, aContainerWidth).B(aWritingMode);
+                 const nsSize& aContainerSize) const {
+    return GetLogicalPosition(aWritingMode, aContainerSize).B(aWritingMode);
   }
   nscoord ISize() const { return ISize(GetWritingMode()); }
   nscoord ISize(mozilla::WritingMode aWritingMode) const {
     return GetLogicalSize(aWritingMode).ISize(aWritingMode);
   }
   nscoord BSize() const { return BSize(GetWritingMode()); }
   nscoord BSize(mozilla::WritingMode aWritingMode) const {
     return GetLogicalSize(aWritingMode).BSize(aWritingMode);
@@ -716,27 +716,28 @@ public:
       SetOverflowAreas(overflow);
     } else {
       mRect = aRect;
     }
   }
   /**
    * Set this frame's rect from a logical rect in its own writing direction
    */
-  void SetRect(const mozilla::LogicalRect& aRect, nscoord aContainerWidth) {
-    SetRect(GetWritingMode(), aRect, aContainerWidth);
+  void SetRect(const mozilla::LogicalRect& aRect,
+               const nsSize& aContainerSize) {
+    SetRect(GetWritingMode(), aRect, aContainerSize);
   }
   /**
    * Set this frame's rect from a logical rect in a different writing direction
    * (GetPhysicalRect will assert if the writing mode doesn't match)
    */
   void SetRect(mozilla::WritingMode aWritingMode,
                const mozilla::LogicalRect& aRect,
-               nscoord aContainerWidth) {
-    SetRect(aRect.GetPhysicalRect(aWritingMode, aContainerWidth));
+               const nsSize& aContainerSize) {
+    SetRect(aRect.GetPhysicalRect(aWritingMode, aContainerSize));
   }
 
   /**
    * Set this frame's size from a logical size in its own writing direction.
    * This leaves the frame's logical position unchanged, which means its
    * physical position may change (for right-to-left modes).
    */
   void SetSize(const mozilla::LogicalSize& aSize) {
@@ -766,22 +767,22 @@ public:
    */
   void SetSize(const nsSize& aSize) {
     SetRect(nsRect(mRect.TopLeft(), aSize));
   }
 
   void SetPosition(const nsPoint& aPt) { mRect.MoveTo(aPt); }
   void SetPosition(mozilla::WritingMode aWritingMode,
                    const mozilla::LogicalPoint& aPt,
-                   nscoord aContainerWidth) {
-    // We subtract mRect.width from the container width to account for
+                   const nsSize& aContainerSize) {
+    // We subtract mRect.Size() from the container size to account for
     // the fact that logical origins in RTL coordinate systems are at
     // the top right of the frame instead of the top left.
     mRect.MoveTo(aPt.GetPhysicalPoint(aWritingMode,
-                                      aContainerWidth - mRect.width));
+                                      aContainerSize - mRect.Size()));
   }
 
   /**
    * Move the frame, accounting for relative positioning. Use this when
    * adjusting the frame's position by a known amount, to properly update its
    * saved normal position (see GetNormalPosition below).
    *
    * This must be used only when moving a frame *after*
@@ -793,38 +794,43 @@ public:
   void MovePositionBy(const nsPoint& aTranslation);
 
   /**
    * As above, using a logical-point delta in a given writing mode.
    */
   void MovePositionBy(mozilla::WritingMode aWritingMode,
                       const mozilla::LogicalPoint& aTranslation)
   {
-    MovePositionBy(aTranslation.GetPhysicalPoint(aWritingMode, 0));
+    // The LogicalPoint represents a vector rather than a point within a
+    // rectangular coordinate space, so we use a null containerSize when
+    // converting logical to physical.
+    const nsSize nullContainerSize;
+    MovePositionBy(aTranslation.GetPhysicalPoint(aWritingMode,
+                                                 nullContainerSize));
   }
 
   /**
    * Return frame's rect without relative positioning
    */
   nsRect GetNormalRect() const;
 
   /**
    * Return frame's position without relative positioning
    */
   nsPoint GetNormalPosition() const;
   mozilla::LogicalPoint
   GetLogicalNormalPosition(mozilla::WritingMode aWritingMode,
-                           nscoord aContainerWidth) const
+                           const nsSize& aContainerSize) const
   {
-    // Subtract the width of this frame from the container width to get
+    // Subtract the size of this frame from the container size to get
     // the correct position in rtl frames where the origin is on the
     // right instead of the left
     return mozilla::LogicalPoint(aWritingMode,
                                  GetNormalPosition(),
-                                 aContainerWidth - mRect.width);
+                                 aContainerSize - mRect.Size());
   }
 
   virtual nsPoint GetPositionOfChildIgnoringScrolling(nsIFrame* aChild)
   { return aChild->GetPosition(); }
   
   nsPoint GetPositionIgnoringScrolling();
 
   static void DestroyContentArray(void* aPropertyValue);
--- a/layout/generic/nsLineBox.cpp
+++ b/layout/generic/nsLineBox.cpp
@@ -27,17 +27,17 @@ int32_t nsLineBox::GetCtorCount() { retu
 // static nsLineBox constant; initialized in the header file.
 const uint32_t nsLineBox::kMinChildCountForHashtable;
 #endif
 
 using namespace mozilla;
 
 nsLineBox::nsLineBox(nsIFrame* aFrame, int32_t aCount, bool aIsBlock)
   : mFirstChild(aFrame)
-  , mContainerWidth(-1)
+  , mContainerSize(-1, -1)
   , mBounds(WritingMode()) // mBounds will be initialized with the correct
                            // writing mode when it is set
 // NOTE: memory is already zeroed since we allocate with AllocateByObjectID.
 {
   MOZ_COUNT_CTOR(nsLineBox);
 #ifdef DEBUG
   ++ctorCount;
   NS_ASSERTION(!aIsBlock || aCount == 1, "Blocks must have exactly one child");
@@ -75,17 +75,17 @@ NS_NewLineBox(nsIPresShell* aPresShell, 
 }
 
 nsLineBox*
 NS_NewLineBox(nsIPresShell* aPresShell, nsLineBox* aFromLine,
               nsIFrame* aFrame, int32_t aCount)
 {
   nsLineBox* newLine = new (aPresShell) nsLineBox(aFrame, aCount, false);
   newLine->NoteFramesMovedFrom(aFromLine);
-  newLine->mContainerWidth = aFromLine->mContainerWidth;
+  newLine->mContainerSize = aFromLine->mContainerSize;
   return newLine;
 }
 
 void
 nsLineBox::StealHashTableFrom(nsLineBox* aFromLine, uint32_t aFromLineNewCount)
 {
   MOZ_ASSERT(!mFlags.mHasHashedFrames);
   MOZ_ASSERT(GetChildCount() >= int32_t(aFromLineNewCount));
@@ -244,23 +244,23 @@ nsLineBox::List(FILE* out, const char* a
           StateToString(cbuf, sizeof(cbuf)));
   if (IsBlock() && !GetCarriedOutBEndMargin().IsZero()) {
     str += nsPrintfCString("bm=%d ", GetCarriedOutBEndMargin().get());
   }
   nsRect bounds = GetPhysicalBounds();
   str += nsPrintfCString("{%d,%d,%d,%d} ",
           bounds.x, bounds.y, bounds.width, bounds.height);
   if (mWritingMode.IsVertical() || !mWritingMode.IsBidiLTR()) {
-    str += nsPrintfCString("{%s-%s: %d,%d,%d,%d; cw=%d} ",
+    str += nsPrintfCString("{%s-%s: %d,%d,%d,%d; cs=%d,%d} ",
                            mWritingMode.IsVertical()
                              ? mWritingMode.IsVerticalLR() ? "vlr" : "vrl"
                              : "htb",
                            mWritingMode.IsBidiLTR() ? "ltr" : "rtl",
                            IStart(), BStart(), ISize(), BSize(),
-                           mContainerWidth);
+                           mContainerSize.width, mContainerSize.height);
   }
   if (mData &&
       (!mData->mOverflowAreas.VisualOverflow().IsEqualEdges(bounds) ||
        !mData->mOverflowAreas.ScrollableOverflow().IsEqualEdges(bounds))) {
     str += nsPrintfCString("vis-overflow=%d,%d,%d,%d scr-overflow=%d,%d,%d,%d ",
             mData->mOverflowAreas.VisualOverflow().x,
             mData->mOverflowAreas.VisualOverflow().y,
             mData->mOverflowAreas.VisualOverflow().width,
@@ -732,37 +732,39 @@ nsLineIterator::FindFrameAt(int32_t aLin
   if (line->ISize() == 0 && line->BSize() == 0)
     return NS_ERROR_FAILURE;
 
   nsIFrame* frame = line->mFirstChild;
   nsIFrame* closestFromStart = nullptr;
   nsIFrame* closestFromEnd = nullptr;
 
   WritingMode wm = line->mWritingMode;
-  nscoord cw = line->mContainerWidth;
+  nsSize containerSize = line->mContainerSize;
 
-  LogicalPoint pos(wm, aPos, cw);
+  LogicalPoint pos(wm, aPos, containerSize);
 
   int32_t n = line->GetChildCount();
   while (n--) {
-    LogicalRect rect = frame->GetLogicalRect(wm, cw);
+    LogicalRect rect = frame->GetLogicalRect(wm, containerSize);
     if (rect.ISize(wm) > 0) {
       // If pos.I() is inside this frame - this is it
       if (rect.IStart(wm) <= pos.I(wm) && rect.IEnd(wm) > pos.I(wm)) {
         closestFromStart = closestFromEnd = frame;
         break;
       }
       if (rect.IStart(wm) < pos.I(wm)) {
         if (!closestFromStart || 
-            rect.IEnd(wm) > closestFromStart->GetLogicalRect(wm, cw).IEnd(wm))
+            rect.IEnd(wm) > closestFromStart->
+                              GetLogicalRect(wm, containerSize).IEnd(wm))
           closestFromStart = frame;
       }
       else {
         if (!closestFromEnd ||
-            rect.IStart(wm) < closestFromEnd->GetLogicalRect(wm, cw).IStart(wm))
+            rect.IStart(wm) < closestFromEnd->
+                                GetLogicalRect(wm, containerSize).IStart(wm))
           closestFromEnd = frame;
       }
     }
     frame = frame->GetNextSibling();
   }
   if (!closestFromStart && !closestFromEnd) {
     // All frames were zero-width. Just take the first one.
     closestFromStart = closestFromEnd = line->mFirstChild;
@@ -774,22 +776,25 @@ nsLineIterator::FindFrameAt(int32_t aLin
   }
   else if (!closestFromStart) {
     *aFrameFound = closestFromEnd;
   }
   else if (!closestFromEnd) {
     *aFrameFound = closestFromStart;
   }
   else { // we're between two frames
-    nscoord delta = closestFromEnd->GetLogicalRect(wm, cw).IStart(wm) -
-                    closestFromStart->GetLogicalRect(wm, cw).IEnd(wm);
-    if (pos.I(wm) < closestFromStart->GetLogicalRect(wm, cw).IEnd(wm) + delta/2)
+    nscoord delta =
+      closestFromEnd->GetLogicalRect(wm, containerSize).IStart(wm) -
+      closestFromStart->GetLogicalRect(wm, containerSize).IEnd(wm);
+    if (pos.I(wm) < closestFromStart->
+                      GetLogicalRect(wm, containerSize).IEnd(wm) + delta/2) {
       *aFrameFound = closestFromStart;
-    else
+    } else {
       *aFrameFound = closestFromEnd;
+    }
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsLineIterator::GetNextSiblingOnLine(nsIFrame*& aFrame, int32_t aLineNumber)
 {
   aFrame = aFrame->GetNextSibling();
--- a/layout/generic/nsLineBox.h
+++ b/layout/generic/nsLineBox.h
@@ -443,80 +443,85 @@ public:
 
   // Combined area is the area of the line that should influence the
   // overflow area of its parent block.  The combined area should be
   // used for painting-related things, but should never be used for
   // layout (except for handling of 'overflow').
   void SetOverflowAreas(const nsOverflowAreas& aOverflowAreas);
   mozilla::LogicalRect GetOverflowArea(nsOverflowType aType,
                                        mozilla::WritingMode aWM,
-                                       nscoord aContainerWidth)
+                                       const nsSize& aContainerSize)
   {
-    return mozilla::LogicalRect(aWM, GetOverflowArea(aType), aContainerWidth);
+    return mozilla::LogicalRect(aWM, GetOverflowArea(aType), aContainerSize);
   }
   nsRect GetOverflowArea(nsOverflowType aType) {
     return mData ? mData->mOverflowAreas.Overflow(aType) : GetPhysicalBounds();
   }
   nsOverflowAreas GetOverflowAreas() {
     if (mData) {
       return mData->mOverflowAreas;
     }
     nsRect bounds = GetPhysicalBounds();
     return nsOverflowAreas(bounds, bounds);
   }
   nsRect GetVisualOverflowArea()
     { return GetOverflowArea(eVisualOverflow); }
   nsRect GetScrollableOverflowArea()
     { return GetOverflowArea(eScrollableOverflow); }
 
-  void SlideBy(nscoord aDBCoord, nscoord aContainerWidth) {
-    NS_ASSERTION(aContainerWidth == mContainerWidth || mContainerWidth == -1,
-                 "container width doesn't match");
-    mContainerWidth = aContainerWidth;
+  void SlideBy(nscoord aDBCoord, const nsSize& aContainerSize) {
+    NS_ASSERTION(aContainerSize == mContainerSize ||
+                 mContainerSize == nsSize(-1, -1),
+                 "container size doesn't match");
+    mContainerSize = aContainerSize;
     mBounds.BStart(mWritingMode) += aDBCoord;
     if (mData) {
-      nsPoint physicalDelta = mozilla::LogicalPoint(mWritingMode, 0, aDBCoord).
-                                         GetPhysicalPoint(mWritingMode, 0);
+      // Use a null containerSize to convert vector from logical to physical.
+      const nsSize nullContainerSize;
+      nsPoint physicalDelta =
+        mozilla::LogicalPoint(mWritingMode, 0, aDBCoord).
+          GetPhysicalPoint(mWritingMode, nullContainerSize);
       NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
         mData->mOverflowAreas.Overflow(otype) += physicalDelta;
       }
     }
   }
 
-  // Container-width for the line is changing (and therefore if writing mode
+  // Container-size for the line is changing (and therefore if writing mode
   // was vertical-rl, the line will move physically; this is like SlideBy,
-  // but it is the container width instead of the line's own logical coord
+  // but it is the container size instead of the line's own logical coord
   // that is changing.
-  nscoord UpdateContainerWidth(nscoord aNewContainerWidth)
+  nsSize UpdateContainerSize(const nsSize aNewContainerSize)
   {
-    NS_ASSERTION(mContainerWidth != -1, "container width not set");
-    nscoord delta = mContainerWidth - aNewContainerWidth;
-    mContainerWidth = aNewContainerWidth;
+    NS_ASSERTION(mContainerSize != nsSize(-1, -1), "container size not set");
+    nsSize delta = mContainerSize - aNewContainerSize;
+    mContainerSize = aNewContainerSize;
     // this has a physical-coordinate effect only in vertical-rl mode
     if (mWritingMode.IsVerticalRL() && mData) {
-      nsPoint physicalDelta = mozilla::LogicalPoint(mWritingMode, 0, delta).
-                                         GetPhysicalPoint(mWritingMode, 0);
+      nsPoint physicalDelta(-delta.width, 0);
       NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
         mData->mOverflowAreas.Overflow(otype) += physicalDelta;
       }
     }
     return delta;
   }
 
-  void IndentBy(nscoord aDICoord, nscoord aContainerWidth) {
-    NS_ASSERTION(aContainerWidth == mContainerWidth || mContainerWidth == -1,
-                 "container width doesn't match");
-    mContainerWidth = aContainerWidth;
+  void IndentBy(nscoord aDICoord, const nsSize& aContainerSize) {
+    NS_ASSERTION(aContainerSize == mContainerSize ||
+                 mContainerSize == nsSize(-1, -1),
+                 "container size doesn't match");
+    mContainerSize = aContainerSize;
     mBounds.IStart(mWritingMode) += aDICoord;
   }
 
-  void ExpandBy(nscoord aDISize, nscoord aContainerWidth) {
-    NS_ASSERTION(aContainerWidth == mContainerWidth || mContainerWidth == -1,
-                 "container width doesn't match");
-    mContainerWidth = aContainerWidth;
+  void ExpandBy(nscoord aDISize, const nsSize& aContainerSize) {
+    NS_ASSERTION(aContainerSize == mContainerSize ||
+                 mContainerSize == nsSize(-1, -1),
+                 "container size doesn't match");
+    mContainerSize = aContainerSize;
     mBounds.ISize(mWritingMode) += aDISize;
   }
 
   /**
    * The logical ascent (distance from block-start to baseline) of the
    * linebox is the logical ascent of the anonymous inline box (for
    * which we don't actually create a frame) that wraps all the
    * consecutive inline children of a block.
@@ -603,49 +608,50 @@ public:
 #ifdef DEBUG
   static int32_t GetCtorCount();
 #endif
 
   nsIFrame* mFirstChild;
 
   mozilla::WritingMode mWritingMode;
 
-  // Physical width. Use only for physical <-> logical coordinate conversion.
-  nscoord mContainerWidth;
+  // Physical size. Use only for physical <-> logical coordinate conversion.
+  nsSize mContainerSize;
 
  private:
   mozilla::LogicalRect mBounds;
 
  public:
   const mozilla::LogicalRect& GetBounds() { return mBounds; }
   nsRect GetPhysicalBounds() const
   {
     if (mBounds.IsAllZero()) {
       return nsRect(0, 0, 0, 0);
     }
 
-    NS_ASSERTION(mContainerWidth != -1, "mContainerWidth not initialized");
-    return mBounds.GetPhysicalRect(mWritingMode, mContainerWidth);
+    NS_ASSERTION(mContainerSize != nsSize(-1, -1),
+                 "mContainerSize not initialized");
+    return mBounds.GetPhysicalRect(mWritingMode, mContainerSize);
   }
   void SetBounds(mozilla::WritingMode aWritingMode,
                  nscoord aIStart, nscoord aBStart,
                  nscoord aISize, nscoord aBSize,
-                 nscoord aContainerWidth)
+                 const nsSize& aContainerSize)
   {
     mWritingMode = aWritingMode;
-    mContainerWidth = aContainerWidth;
+    mContainerSize = aContainerSize;
     mBounds = mozilla::LogicalRect(aWritingMode, aIStart, aBStart,
                                    aISize, aBSize);
   }
   void SetBounds(mozilla::WritingMode aWritingMode,
-                 nsRect aRect, nscoord aContainerWidth)
+                 nsRect aRect, const nsSize& aContainerSize)
   {
     mWritingMode = aWritingMode;
-    mContainerWidth = aContainerWidth;
-    mBounds = mozilla::LogicalRect(aWritingMode, aRect, aContainerWidth);
+    mContainerSize = aContainerSize;
+    mBounds = mozilla::LogicalRect(aWritingMode, aRect, aContainerSize);
   }
 
   // mFlags.mHasHashedFrames says which one to use
   union {
     nsTHashtable< nsPtrHashKey<nsIFrame> >* mFrames;
     uint32_t mChildCount;
   };
 
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -311,17 +311,17 @@ void
 nsLineLayout::UpdateBand(WritingMode aWM,
                          const LogicalRect& aNewAvailSpace,
                          nsIFrame* aFloatFrame)
 {
   WritingMode lineWM = mRootSpan->mWritingMode;
   // need to convert to our writing mode, because we might have a different
   // mode from the caller due to dir: auto
   LogicalRect availSpace = aNewAvailSpace.ConvertTo(lineWM, aWM,
-                                                    ContainerWidth());
+                                                    ContainerSize());
 #ifdef REALLY_NOISY_REFLOW
   printf("nsLL::UpdateBand %d, %d, %d, %d, (converted to %d, %d, %d, %d); frame=%p\n  will set mImpacted to true\n",
          aNewAvailSpace.x, aNewAvailSpace.y,
          aNewAvailSpace.width, aNewAvailSpace.height,
          availSpace.IStart(lineWM), availSpace.BStart(lineWM),
          availSpace.ISize(lineWM), availSpace.BSize(lineWM),
          aFloatFrame);
 #endif
@@ -937,17 +937,17 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
   // going to end up moving it when we do the block-direction alignment.
 
   // Adjust spacemanager coordinate system for the frame.
   nsHTMLReflowMetrics metrics(lineWM);
 #ifdef DEBUG
   metrics.ISize(lineWM) = nscoord(0xdeadbeef);
   metrics.BSize(lineWM) = nscoord(0xdeadbeef);
 #endif
-  nscoord tI = pfd->mBounds.LineLeft(lineWM, ContainerWidth());
+  nscoord tI = pfd->mBounds.LineLeft(lineWM, ContainerSize());
   nscoord tB = pfd->mBounds.BStart(lineWM);
   mFloatManager->Translate(tI, tB);
 
   int32_t savedOptionalBreakOffset;
   gfxBreakPriority savedOptionalBreakPriority;
   nsIFrame* savedOptionalBreakFrame =
     GetLastOptionalBreakPosition(&savedOptionalBreakOffset,
                                  &savedOptionalBreakPriority);
@@ -1066,17 +1066,17 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
   // just the union of the bounds of any absolute children. That is
   // added in later by nsLineLayout::ReflowInlineFrames.
   pfd->mOverflowAreas = metrics.mOverflowAreas;
 
   pfd->mBounds.ISize(lineWM) = metrics.ISize(lineWM);
   pfd->mBounds.BSize(lineWM) = metrics.BSize(lineWM);
 
   // Size the frame, but |RelativePositionFrames| will size the view.
-  aFrame->SetRect(lineWM, pfd->mBounds, ContainerWidthForSpan(psd));
+  aFrame->SetRect(lineWM, pfd->mBounds, ContainerSizeForSpan(psd));
 
   // Tell the frame that we're done reflowing it
   aFrame->DidReflow(mPresContext,
                     isText ? nullptr : reflowStateHolder.ptr(),
                     nsDidReflowStatus::FINISHED);
 
   if (aMetrics) {
     *aMetrics = metrics;
@@ -1245,23 +1245,26 @@ nsLineLayout::SyncAnnotationBounds(PerFr
   MOZ_ASSERT(aRubyFrame->mSpan);
 
   PerSpanData* span = aRubyFrame->mSpan;
   WritingMode lineWM = mRootSpan->mWritingMode;
   for (PerFrameData* pfd = span->mFirstFrame; pfd; pfd = pfd->mNext) {
     for (PerFrameData* rtc = pfd->mNextAnnotation;
          rtc; rtc = rtc->mNextAnnotation) {
       // When the annotation container is reflowed, the width of the
-      // ruby container is unknown, hence zero should be used here
-      // as container width to get the correct logical rect.
-      LogicalRect rtcBounds(lineWM, rtc->mFrame->GetRect(), 0);
+      // ruby container is unknown so we use a dummy container size;
+      // in the case of RTL block direction, the final position will be
+      // fixed up later.
+      const nsSize dummyContainerSize;
+      LogicalRect rtcBounds(lineWM, rtc->mFrame->GetRect(),
+                            dummyContainerSize);
       rtc->mBounds = rtcBounds;
-      nscoord rtcWidth = rtcBounds.Width(lineWM);
+      nsSize rtcSize = rtcBounds.Size(lineWM).GetPhysicalSize(lineWM);
       for (PerFrameData* rt = rtc->mSpan->mFirstFrame; rt; rt = rt->mNext) {
-        LogicalRect rtBounds = rt->mFrame->GetLogicalRect(lineWM, rtcWidth);
+        LogicalRect rtBounds = rt->mFrame->GetLogicalRect(lineWM, rtcSize);
         MOZ_ASSERT(rt->mBounds.Size(lineWM) == rtBounds.Size(lineWM),
                    "Size of the annotation should not have been changed");
         rt->mBounds.SetOrigin(lineWM, rtBounds.Origin(lineWM));
       }
     }
   }
 }
 
@@ -1493,33 +1496,33 @@ nsLineLayout::AddBulletFrame(nsIFrame* a
   pfd->mIsBullet = true;
   if (aMetrics.BlockStartAscent() == nsHTMLReflowMetrics::ASK_FOR_BASELINE) {
     pfd->mAscent = aFrame->GetLogicalBaseline(lineWM);
   } else {
     pfd->mAscent = aMetrics.BlockStartAscent();
   }
 
   // Note: block-coord value will be updated during block-direction alignment
-  pfd->mBounds = LogicalRect(lineWM, aFrame->GetRect(), ContainerWidth());
+  pfd->mBounds = LogicalRect(lineWM, aFrame->GetRect(), ContainerSize());
   pfd->mOverflowAreas = aMetrics.mOverflowAreas;
 }
 
 #ifdef DEBUG
 void
 nsLineLayout::DumpPerSpanData(PerSpanData* psd, int32_t aIndent)
 {
   nsFrame::IndentBy(stdout, aIndent);
   printf("%p: left=%d x=%d right=%d\n", static_cast<void*>(psd),
          psd->mIStart, psd->mICoord, psd->mIEnd);
   PerFrameData* pfd = psd->mFirstFrame;
   while (nullptr != pfd) {
     nsFrame::IndentBy(stdout, aIndent+1);
     nsFrame::ListTag(stdout, pfd->mFrame);
     nsRect rect = pfd->mBounds.GetPhysicalRect(psd->mWritingMode,
-                                               ContainerWidth());
+                                               ContainerSize());
     printf(" %d,%d,%d,%d\n", rect.x, rect.y, rect.width, rect.height);
     if (pfd->mSpan) {
       DumpPerSpanData(pfd->mSpan, aIndent + 1);
     }
     pfd = pfd->mNext;
   }
 }
 #endif
@@ -1598,28 +1601,28 @@ nsLineLayout::VerticalAlignLine()
   // recurse over the child spans and place any frames we find with
   // vertical-align: top or bottom.
   // XXX PERFORMANCE: set a bit per-span to avoid the extra work
   // (propagate it upward too)
   WritingMode lineWM = psd->mWritingMode;
   for (PerFrameData* pfd = psd->mFirstFrame; pfd; pfd = pfd->mNext) {
     if (pfd->mBlockDirAlign == VALIGN_OTHER) {
       pfd->mBounds.BStart(lineWM) += baselineBCoord;
-      pfd->mFrame->SetRect(lineWM, pfd->mBounds, ContainerWidth());
+      pfd->mFrame->SetRect(lineWM, pfd->mBounds, ContainerSize());
     }
   }
   PlaceTopBottomFrames(psd, -mBStartEdge, lineBSize);
 
   mFinalLineBSize = lineBSize;
   if (mGotLineBox) {
     // Fill in returned line-box and max-element-width data
     mLineBox->SetBounds(lineWM,
                         psd->mIStart, mBStartEdge,
                         psd->mICoord - psd->mIStart, lineBSize,
-                        ContainerWidth());
+                        ContainerSize());
 
     mLineBox->SetLogicalAscent(baselineBCoord - mBStartEdge);
 #ifdef NOISY_BLOCKDIR_ALIGN
     printf(
       "  [line]==> bounds{x,y,w,h}={%d,%d,%d,%d} lh=%d a=%d\n",
       mLineBox->GetBounds().IStart(lineWM), mLineBox->GetBounds().BStart(lineWM),
       mLineBox->GetBounds().ISize(lineWM), mLineBox->GetBounds().BSize(lineWM),
       mFinalLineBSize, mLineBox->GetLogicalAscent());
@@ -1634,27 +1637,27 @@ nsLineLayout::PlaceTopBottomFrames(PerSp
                                    nscoord aLineBSize)
 {
   for (PerFrameData* pfd = psd->mFirstFrame; pfd; pfd = pfd->mNext) {
     PerSpanData* span = pfd->mSpan;
 #ifdef DEBUG
     NS_ASSERTION(0xFF != pfd->mBlockDirAlign, "umr");
 #endif
     WritingMode lineWM = mRootSpan->mWritingMode;
-    nscoord containerWidth = ContainerWidthForSpan(psd);
+    nsSize containerSize = ContainerSizeForSpan(psd);
     switch (pfd->mBlockDirAlign) {
       case VALIGN_TOP:
         if (span) {
           pfd->mBounds.BStart(lineWM) = -aDistanceFromStart - span->mMinBCoord;
         }
         else {
           pfd->mBounds.BStart(lineWM) =
             -aDistanceFromStart + pfd->mMargin.BStart(lineWM);
         }
-        pfd->mFrame->SetRect(lineWM, pfd->mBounds, containerWidth);
+        pfd->mFrame->SetRect(lineWM, pfd->mBounds, containerSize);
 #ifdef NOISY_BLOCKDIR_ALIGN
         printf("    ");
         nsFrame::ListTag(stdout, pfd->mFrame);
         printf(": y=%d dTop=%d [bp.top=%d topLeading=%d]\n",
                pfd->mBounds.BStart(lineWM), aDistanceFromStart,
                span ? pfd->mBorderPadding.BStart(lineWM) : 0,
                span ? span->mBStartLeading : 0);
 #endif
@@ -1664,17 +1667,17 @@ nsLineLayout::PlaceTopBottomFrames(PerSp
           // Compute bottom leading
           pfd->mBounds.BStart(lineWM) =
             -aDistanceFromStart + aLineBSize - span->mMaxBCoord;
         }
         else {
           pfd->mBounds.BStart(lineWM) = -aDistanceFromStart + aLineBSize -
             pfd->mMargin.BEnd(lineWM) - pfd->mBounds.BSize(lineWM);
         }
-        pfd->mFrame->SetRect(lineWM, pfd->mBounds, containerWidth);
+        pfd->mFrame->SetRect(lineWM, pfd->mBounds, containerSize);
 #ifdef NOISY_BLOCKDIR_ALIGN
         printf("    ");
         nsFrame::ListTag(stdout, pfd->mFrame);
         printf(": y=%d\n", pfd->mBounds.BStart(lineWM));
 #endif
         break;
     }
     if (span) {
@@ -2242,17 +2245,17 @@ nsLineLayout::VerticalAlignFrames(PerSpa
                pfd->mBorderPadding.Top(lineWM),
                pfd->mBorderPadding.Bottom(lineWM),
                logicalBSize,
                frameSpan ? frameSpan->mBStartLeading : 0,
                pfd->mBounds.BStart(lineWM), minBCoord, maxBCoord);
 #endif
       }
       if (psd != mRootSpan) {
-        frame->SetRect(lineWM, pfd->mBounds, ContainerWidthForSpan(psd));
+        frame->SetRect(lineWM, pfd->mBounds, ContainerSizeForSpan(psd));
       }
     }
     pfd = pfd->mNext;
   }
 
   // Factor in the minimum line block-size when handling the root-span for
   // the block.
   if (psd == mRootSpan) {
@@ -2405,17 +2408,17 @@ nsLineLayout::VerticalAlignFrames(PerSpa
       spanFramePFD->mBounds.BSize(lineWM) -= minBCoord; // move the block end up
       psd->mBStartLeading += minBCoord;
       *psd->mBaseline -= minBCoord;
 
       pfd = psd->mFirstFrame;
       while (nullptr != pfd) {
         pfd->mBounds.BStart(lineWM) -= minBCoord; // move all the children
                                                   // back up
-        pfd->mFrame->SetRect(lineWM, pfd->mBounds, ContainerWidthForSpan(psd));
+        pfd->mFrame->SetRect(lineWM, pfd->mBounds, ContainerSizeForSpan(psd));
         pfd = pfd->mNext;
       }
       maxBCoord -= minBCoord; // since minBCoord is in the frame's own
                               // coordinate system
       minBCoord = 0;
     }
     if (maxBCoord < spanFramePFD->mBounds.BSize(lineWM)) {
       nscoord adjust = spanFramePFD->mBounds.BSize(lineWM) - maxBCoord;
@@ -2483,21 +2486,21 @@ nsLineLayout::TrimTrailingWhiteSpaceIn(P
           pfd->mBounds.ISize(lineWM) -= deltaISize;
           if (psd != mRootSpan) {
             // When the child span is not a direct child of the block
             // we need to update the child spans frame rectangle
             // because it most likely will not be done again. Spans
             // that are direct children of the block will be updated
             // later, however, because the VerticalAlignFrames method
             // will be run after this method.
-            nscoord containerWidth = ContainerWidthForSpan(childSpan);
+            nsSize containerSize = ContainerSizeForSpan(childSpan);
             nsIFrame* f = pfd->mFrame;
-            LogicalRect r(lineWM, f->GetRect(), containerWidth);
+            LogicalRect r(lineWM, f->GetRect(), containerSize);
             r.ISize(lineWM) -= deltaISize;
-            f->SetRect(lineWM, r, containerWidth);
+            f->SetRect(lineWM, r, containerSize);
           }
 
           // Adjust the inline end edge of the span that contains the child span
           psd->mICoord -= deltaISize;
 
           // Slide any frames that follow the child span over by the
           // correct amount. The only thing that can follow the child
           // span is empty stuff, so we are just making things
@@ -2551,17 +2554,17 @@ nsLineLayout::TrimTrailingWhiteSpaceIn(P
         // generated by the space should be removed as well.
         pfd->mJustificationInfo.CancelOpportunityForTrimmedSpace();
 
         // See if the text frame has already been placed in its parent
         if (psd != mRootSpan) {
           // The frame was already placed during psd's
           // reflow. Update the frames rectangle now.
           pfd->mFrame->SetRect(lineWM, pfd->mBounds,
-                               ContainerWidthForSpan(psd));
+                               ContainerSizeForSpan(psd));
         }
 
         // Adjust containing span's right edge
         psd->mICoord -= trimOutput.mDeltaWidth;
 
         // Slide any frames that follow the text frame over by the
         // right amount. The only thing that can follow the text
         // frame is empty stuff, so we are just making things
@@ -2767,17 +2770,17 @@ nsLineLayout::ComputeFrameJustification(
     }
   }
 
   return outerOpportunities;
 }
 
 void
 nsLineLayout::AdvanceAnnotationInlineBounds(PerFrameData* aPFD,
-                                            nscoord aContainerWidth,
+                                            const nsSize& aContainerSize,
                                             nscoord aDeltaICoord,
                                             nscoord aDeltaISize)
 {
   nsIFrame* frame = aPFD->mFrame;
   nsIAtom* frameType = frame->GetType();
   MOZ_ASSERT(frameType == nsGkAtoms::rubyTextFrame ||
              frameType == nsGkAtoms::rubyTextContainerFrame);
   MOZ_ASSERT(aPFD->mSpan, "rt and rtc should have span.");
@@ -2805,44 +2808,44 @@ nsLineLayout::AdvanceAnnotationInlineBou
       nscoord reservedISize = RubyUtils::GetReservedISize(frame);
       RubyUtils::SetReservedISize(frame, reservedISize + aDeltaISize);
     }
   } else {
     // It is a normal ruby text container. Its children will expand
     // themselves properly. We only need to expand its own size here.
     aPFD->mBounds.ISize(lineWM) += aDeltaISize;
   }
-  aPFD->mFrame->SetRect(lineWM, aPFD->mBounds, aContainerWidth);
+  aPFD->mFrame->SetRect(lineWM, aPFD->mBounds, aContainerSize);
 }
 
 /**
  * This function applies the changes of icoord and isize caused by
  * justification to annotations of the given frame.
  */
 void
 nsLineLayout::ApplyLineJustificationToAnnotations(PerFrameData* aPFD,
                                                   nscoord aDeltaICoord,
                                                   nscoord aDeltaISize)
 {
   PerFrameData* pfd = aPFD->mNextAnnotation;
   while (pfd) {
-    nscoord containerWidth = pfd->mFrame->GetParent()->GetRect().Width();
-    AdvanceAnnotationInlineBounds(pfd, containerWidth,
+    nsSize containerSize = pfd->mFrame->GetParent()->GetSize();
+    AdvanceAnnotationInlineBounds(pfd, containerSize,
                                   aDeltaICoord, aDeltaISize);
 
     // There are two cases where an annotation frame has siblings which
     // do not attached to a ruby base-level frame:
     // 1. there's an intra-annotation whitespace which has no intra-base
     //    white-space to pair with;
     // 2. there are not enough ruby bases to be paired with annotations.
     // In these cases, their size should not be affected, but we still
     // need to move them so that they won't overlap other frames.
     PerFrameData* sibling = pfd->mNext;
     while (sibling && !sibling->mIsLinkedToBase) {
-      AdvanceAnnotationInlineBounds(sibling, containerWidth,
+      AdvanceAnnotationInlineBounds(sibling, containerSize,
                                     aDeltaICoord + aDeltaISize, 0);
       sibling = sibling->mNext;
     }
 
     pfd = pfd->mNextAnnotation;
   }
 }
 
@@ -2890,17 +2893,17 @@ nsLineLayout::ApplyFrameJustification(Pe
         dw += gapsAtEnd;
       }
       pfd->mBounds.IStart(lineWM) += deltaICoord;
 
       // The gaps added to the end of the frame should also be
       // excluded from the isize added to the annotation.
       ApplyLineJustificationToAnnotations(pfd, deltaICoord, dw - gapsAtEnd);
       deltaICoord += dw;
-      pfd->mFrame->SetRect(lineWM, pfd->mBounds, ContainerWidthForSpan(aPSD));
+      pfd->mFrame->SetRect(lineWM, pfd->mBounds, ContainerSizeForSpan(aPSD));
     }
   }
   return deltaICoord;
 }
 
 static nsIFrame*
 FindNearestRubyBaseAncestor(nsIFrame* aFrame)
 {
@@ -2915,17 +2918,17 @@ FindNearestRubyBaseAncestor(nsIFrame* aF
   return aFrame;
 }
 
 /**
  * This method expands the given frame by the given reserved isize.
  */
 void
 nsLineLayout::ExpandRubyBox(PerFrameData* aFrame, nscoord aReservedISize,
-                            nscoord aContainerWidth)
+                            const nsSize& aContainerSize)
 {
   WritingMode lineWM = mRootSpan->mWritingMode;
   auto rubyAlign = aFrame->mFrame->StyleText()->mRubyAlign;
   switch (rubyAlign) {
     case NS_STYLE_RUBY_ALIGN_START:
       // do nothing for start
       break;
     case NS_STYLE_RUBY_ALIGN_SPACE_BETWEEN:
@@ -2947,39 +2950,39 @@ nsLineLayout::ExpandRubyBox(PerFrameData
       // If there are no justification opportunities for space-between,
       // fall-through to center per spec.
     }
     case NS_STYLE_RUBY_ALIGN_CENTER:
       // Indent all children by half of the reserved inline size.
       for (PerFrameData* child = aFrame->mSpan->mFirstFrame;
            child; child = child->mNext) {
         child->mBounds.IStart(lineWM) += aReservedISize / 2;
-        child->mFrame->SetRect(lineWM, child->mBounds, aContainerWidth);
+        child->mFrame->SetRect(lineWM, child->mBounds, aContainerSize);
       }
       break;
     default:
       MOZ_ASSERT_UNREACHABLE("Unknown ruby-align value");
   }
 
   aFrame->mBounds.ISize(lineWM) += aReservedISize;
-  aFrame->mFrame->SetRect(lineWM, aFrame->mBounds, aContainerWidth);
+  aFrame->mFrame->SetRect(lineWM, aFrame->mBounds, aContainerSize);
 }
 
 /**
  * This method expands the given frame by the reserved inline size.
  * It also expands its annotations if they are expandable and have
  * reserved isize larger than zero.
  */
 void
 nsLineLayout::ExpandRubyBoxWithAnnotations(PerFrameData* aFrame,
-                                           nscoord aContainerWidth)
+                                           const nsSize& aContainerSize)
 {
   nscoord reservedISize = RubyUtils::GetReservedISize(aFrame->mFrame);
   if (reservedISize) {
-    ExpandRubyBox(aFrame, reservedISize, aContainerWidth);
+    ExpandRubyBox(aFrame, reservedISize, aContainerSize);
   }
 
   WritingMode lineWM = mRootSpan->mWritingMode;
   bool isLevelContainer =
     aFrame->mFrame->GetType() == nsGkAtoms::rubyBaseContainerFrame;
   for (PerFrameData* annotation = aFrame->mNextAnnotation;
        annotation; annotation = annotation->mNextAnnotation) {
     if (isLevelContainer) {
@@ -2987,17 +2990,17 @@ nsLineLayout::ExpandRubyBoxWithAnnotatio
       MOZ_ASSERT(rtcFrame->GetType() == nsGkAtoms::rubyTextContainerFrame);
       // It is necessary to set the rect again because the container
       // width was unknown, and zero was used instead when we reflow
       // them. The corresponding base containers were repositioned in
       // VerticalAlignFrames and PlaceTopBottomFrames.
       MOZ_ASSERT(
         rtcFrame->GetLogicalSize(lineWM) == annotation->mBounds.Size(lineWM));
       rtcFrame->SetPosition(lineWM, annotation->mBounds.Origin(lineWM),
-                            aContainerWidth);
+                            aContainerSize);
     }
 
     nscoord reservedISize = RubyUtils::GetReservedISize(annotation->mFrame);
     if (!reservedISize) {
       continue;
     }
 
     MOZ_ASSERT(annotation->mSpan);
@@ -3007,38 +3010,38 @@ nsLineLayout::ExpandRubyBoxWithAnnotatio
       continue;
     }
     if (IsRubyAlignSpaceAround(annotation->mFrame)) {
       // Add one gap at each side of this annotation.
       computeState.mFirstParticipant->mJustificationAssignment.mGapsAtStart = 1;
       computeState.mLastParticipant->mJustificationAssignment.mGapsAtEnd = 1;
     }
     nsIFrame* parentFrame = annotation->mFrame->GetParent();
-    nscoord containerWidth = parentFrame->GetRect().Width();
-    MOZ_ASSERT(containerWidth == aContainerWidth ||
+    nsSize containerSize = parentFrame->GetSize();
+    MOZ_ASSERT(containerSize == aContainerSize ||
                parentFrame->GetType() == nsGkAtoms::rubyTextContainerFrame,
                "Container width should only be different when the current "
                "annotation is a ruby text frame, whose parent is not same "
                "as its base frame.");
-    ExpandRubyBox(annotation, reservedISize, containerWidth);
+    ExpandRubyBox(annotation, reservedISize, containerSize);
     ExpandInlineRubyBoxes(annotation->mSpan);
   }
 }
 
 /**
  * This method looks for all expandable ruby box in the given span, and
  * calls ExpandRubyBox to expand them in depth-first preorder.
  */
 void
 nsLineLayout::ExpandInlineRubyBoxes(PerSpanData* aSpan)
 {
-  nscoord containerWidth = ContainerWidthForSpan(aSpan);
+  nsSize containerSize = ContainerSizeForSpan(aSpan);
   for (PerFrameData* pfd = aSpan->mFirstFrame; pfd; pfd = pfd->mNext) {
     if (RubyUtils::IsExpandableRubyBox(pfd->mFrame)) {
-      ExpandRubyBoxWithAnnotations(pfd, containerWidth);
+      ExpandRubyBoxWithAnnotations(pfd, containerSize);
     }
     if (pfd->mSpan) {
       ExpandInlineRubyBoxes(pfd->mSpan);
     }
   }
 }
 
 // Align inline frames within the line according to the CSS text-align
@@ -3122,17 +3125,17 @@ nsLineLayout::TextAlignLine(nsLineBox* a
           psd->mFrame->mJustificationInfo.mInnerOpportunities;
         if (opportunities > 0) {
           int32_t gaps = opportunities * 2 + additionalGaps;
           JustificationApplicationState applyState(gaps, remainingISize);
 
           // Apply the justification, and make sure to update our linebox
           // width to account for it.
           aLine->ExpandBy(ApplyFrameJustification(psd, applyState),
-                          ContainerWidthForSpan(psd));
+                          ContainerSizeForSpan(psd));
 
           MOZ_ASSERT(applyState.mGaps.mHandled == applyState.mGaps.mCount,
                      "Unprocessed justification gaps");
           MOZ_ASSERT(applyState.mWidth.mConsumed == applyState.mWidth.mAvailable,
                      "Unprocessed justification width");
           break;
         }
         // Fall through to the default case if we could not justify to fill
@@ -3174,44 +3177,44 @@ nsLineLayout::TextAlignLine(nsLineBox* a
 
   if (mPresContext->BidiEnabled() &&
       (!mPresContext->IsVisualMode() || !lineWM.IsBidiLTR())) {
     nsBidiPresUtils::ReorderFrames(psd->mFirstFrame->mFrame,
                                    aLine->GetChildCount(),
                                    lineWM, mContainerSize,
                                    psd->mIStart + mTextIndent + dx);
     if (dx) {
-      aLine->IndentBy(dx, ContainerWidth());
+      aLine->IndentBy(dx, ContainerSize());
     }
   } else if (dx) {
     for (PerFrameData* pfd = psd->mFirstFrame; pfd; pfd = pfd->mNext) {
       pfd->mBounds.IStart(lineWM) += dx;
-      pfd->mFrame->SetRect(lineWM, pfd->mBounds, ContainerWidthForSpan(psd));
+      pfd->mFrame->SetRect(lineWM, pfd->mBounds, ContainerSizeForSpan(psd));
     }
-    aLine->IndentBy(dx, ContainerWidth());
+    aLine->IndentBy(dx, ContainerSize());
   }
 }
 
 // This method applies any relative positioning to the given frame.
 void
 nsLineLayout::ApplyRelativePositioning(PerFrameData* aPFD)
 {
   if (!aPFD->mRelativePos) {
     return;
   }
 
   nsIFrame* frame = aPFD->mFrame;
   WritingMode frameWM = frame->GetWritingMode();
-  LogicalPoint origin = frame->GetLogicalPosition(ContainerWidth());
+  LogicalPoint origin = frame->GetLogicalPosition(ContainerSize());
   // right and bottom are handled by
   // nsHTMLReflowState::ComputeRelativeOffsets
   nsHTMLReflowState::ApplyRelativePositioning(frame, frameWM,
                                               aPFD->mOffsets, &origin,
-                                              ContainerWidth());
-  frame->SetPosition(frameWM, origin, ContainerWidth());
+                                              ContainerSize());
+  frame->SetPosition(frameWM, origin, ContainerSize());
 }
 
 // This method do relative positioning for ruby annotations.
 void
 nsLineLayout::RelativePositionAnnotations(PerSpanData* aRubyPSD,
                                           nsOverflowAreas& aOverflowAreas)
 {
   MOZ_ASSERT(aRubyPSD->mFrame->mFrame->GetType() == nsGkAtoms::rubyFrame);
@@ -3254,17 +3257,17 @@ nsLineLayout::RelativePositionFrames(Per
   }
   else {
     LogicalRect rect(wm, psd->mIStart, mBStartEdge,
                      psd->mICoord - psd->mIStart, mFinalLineBSize);
     // The minimum combined area for the frames that are direct
     // children of the block starts at the upper left corner of the
     // line and is sized to match the size of the line's bounding box
     // (the same size as the values returned from VerticalAlignFrames)
-    overflowAreas.VisualOverflow() = rect.GetPhysicalRect(wm, ContainerWidth());
+    overflowAreas.VisualOverflow() = rect.GetPhysicalRect(wm, ContainerSize());
     overflowAreas.ScrollableOverflow() = overflowAreas.VisualOverflow();
   }
 
   for (PerFrameData* pfd = psd->mFirstFrame; pfd; pfd = pfd->mNext) {
     nsIFrame* frame = pfd->mFrame;
 
     // Adjust the origin of the frame
     ApplyRelativePositioning(pfd);
--- a/layout/generic/nsLineLayout.h
+++ b/layout/generic/nsLineLayout.h
@@ -539,24 +539,25 @@ protected:
       }
       mLastFrame = pfd;
     }
   };
   PerSpanData* mSpanFreeList;
   PerSpanData* mRootSpan;
   PerSpanData* mCurrentSpan;
 
-  // The container width to use when converting between logical and
+  // The container size to use when converting between logical and
   // physical coordinates for frames in this span. For the root span
-  // this is the width of the block cached in mContainerSize.width; for
-  // child spans it's the width of the root span
-  nscoord ContainerWidthForSpan(PerSpanData* aPSD) {
+  // this is the size of the block cached in mContainerSize; for
+  // child spans it's the size of the root span.
+  nsSize ContainerSizeForSpan(PerSpanData* aPSD) {
     return (aPSD == mRootSpan)
-      ? ContainerWidth()
-      : aPSD->mFrame->mBounds.Width(mRootSpan->mWritingMode);
+      ? mContainerSize
+      : aPSD->mFrame->mBounds.Size(mRootSpan->mWritingMode).
+        GetPhysicalSize(mRootSpan->mWritingMode);
   }
 
   gfxBreakPriority mLastOptionalBreakPriority;
   int32_t     mLastOptionalBreakFrameOffset;
   int32_t     mForceBreakFrameOffset;
 
   nscoord mMinLineBSize;
   
@@ -582,18 +583,17 @@ protected:
   nscoord mFinalLineBSize;
   
   // Amount of trimmable whitespace inline size for the trailing text
   // frame, if any
   nscoord mTrimmableISize;
 
   // Physical size. Use only for physical <-> logical coordinate conversion.
   nsSize mContainerSize;
-  nscoord ContainerWidth() const { return mContainerSize.width; }
-  nscoord ContainerHeight() const { return mContainerSize.height; }
+  const nsSize& ContainerSize() const { return mContainerSize; }
 
   bool mFirstLetterStyleOK      : 1;
   bool mIsTopOfPage             : 1;
   bool mImpactedByFloats        : 1;
   bool mLastFloatWasLetterFrame : 1;
   bool mLineIsEmpty             : 1;
   bool mLineEndsInBR            : 1;
   bool mNeedBackup              : 1;
@@ -681,34 +681,34 @@ protected:
 
   static int AssignInterframeJustificationGaps(
     PerFrameData* aFrame, JustificationComputationState& aState);
 
   int32_t ComputeFrameJustification(PerSpanData* psd,
                                     JustificationComputationState& aState);
 
   void AdvanceAnnotationInlineBounds(PerFrameData* aPFD,
-                                     nscoord aContainerWidth,
+                                     const nsSize& aContainerSize,
                                      nscoord aDeltaICoord,
                                      nscoord aDeltaISize);
 
   void ApplyLineJustificationToAnnotations(PerFrameData* aPFD,
                                            nscoord aDeltaICoord,
                                            nscoord aDeltaISize);
 
   // Apply justification.  The return value is the amount by which the width of
   // the span corresponding to aPSD got increased due to justification.
   nscoord ApplyFrameJustification(
       PerSpanData* aPSD, mozilla::JustificationApplicationState& aState);
 
   void ExpandRubyBox(PerFrameData* aFrame, nscoord aReservedISize,
-                     nscoord aContainerWidth);
+                     const nsSize& aContainerSize);
 
   void ExpandRubyBoxWithAnnotations(PerFrameData* aFrame,
-                                    nscoord aContainerWidth);
+                                    const nsSize& aContainerSize);
 
   void ExpandInlineRubyBoxes(PerSpanData* aSpan);
 
   void AttachFrameToBaseLineLayout(PerFrameData* aFrame);
 
 #ifdef DEBUG
   void DumpPerSpanData(PerSpanData* psd, int32_t aIndent);
 #endif
--- a/layout/generic/nsRubyFrame.cpp
+++ b/layout/generic/nsRubyFrame.cpp
@@ -248,17 +248,19 @@ nsRubyFrame::ReflowSegment(nsPresContext
       nsIFrame* nextRTC = textContainers[i]->GetNextInFlow();
       if (nextRTC) {
         nextRTC->GetParent()->DeleteNextInFlowChild(nextRTC, true);
       }
     }
   }
 
   nscoord segmentISize = baseMetrics.ISize(lineWM);
-  LogicalRect baseRect = aBaseContainer->GetLogicalRect(lineWM, 0);
+  const nsSize dummyContainerSize;
+  LogicalRect baseRect =
+    aBaseContainer->GetLogicalRect(lineWM, dummyContainerSize);
   // We need to position our rtc frames on one side or the other of the
   // base container's rect, using a coordinate space that's relative to
   // the ruby frame. Right now, the base container's rect's block-axis
   // position is relative to the block container frame containing the
   // lines, so we use 0 instead. (i.e. we assume that the base container
   // is adjacent to the ruby frame's block-start edge.)
   // XXX We may need to add border/padding here. See bug 1055667.
   baseRect.BStart(lineWM) = 0;
@@ -313,20 +315,21 @@ nsRubyFrame::ReflowSegment(nsPresContext
       } else if (side.value() == eLogicalSideBEnd) {
         position = offsetRect.Origin(lineWM) +
           LogicalPoint(lineWM, 0, offsetRect.BSize(lineWM));
         offsetRect.BSize(lineWM) += size.BSize(lineWM);
       } else {
         MOZ_ASSERT_UNREACHABLE("???");
       }
     }
-    // Container width is set to zero here. We will fix it in
-    // nsLineLayout after the whole line get reflowed.
+    // Using a dummy container-size here, so child positioning may not be
+    // correct. We will fix it in nsLineLayout after the whole line is
+    // reflowed.
     FinishReflowChild(textContainer, aPresContext, textMetrics,
-                      &textReflowState, lineWM, position, 0, 0);
+                      &textReflowState, lineWM, position, dummyContainerSize, 0);
   }
   MOZ_ASSERT(baseRect.ISize(lineWM) == offsetRect.ISize(lineWM),
              "Annotations should only be placed on the block directions");
 
   nscoord deltaISize = segmentISize - baseMetrics.ISize(lineWM);
   if (deltaISize <= 0) {
     RubyUtils::ClearReservedISize(aBaseContainer);
   } else {
--- a/layout/generic/nsRubyTextContainerFrame.cpp
+++ b/layout/generic/nsRubyTextContainerFrame.cpp
@@ -130,46 +130,49 @@ nsRubyTextContainerFrame::Reflow(nsPresC
   // NS_FRAME_COMPLETE here is still safe, since its parent, ruby frame,
   // ignores the status, and continuations of the ruby base container
   // will take care of our continuations.
   aStatus = NS_FRAME_COMPLETE;
   WritingMode lineWM = aReflowState.mLineLayout->GetWritingMode();
 
   nscoord minBCoord = nscoord_MAX;
   nscoord maxBCoord = nscoord_MIN;
+  // The container size is not yet known, so we use a dummy (0, 0) size.
+  // The block-dir position will be corrected below after containerSize
+  // is finalized.
+  const nsSize dummyContainerSize;
   for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) {
     nsIFrame* child = e.get();
     MOZ_ASSERT(child->GetType() == nsGkAtoms::rubyTextFrame);
-    // The container width is still unknown yet.
-    LogicalRect rect = child->GetLogicalRect(lineWM, 0);
+    LogicalRect rect = child->GetLogicalRect(lineWM, dummyContainerSize);
     LogicalMargin margin = child->GetLogicalUsedMargin(lineWM);
     nscoord blockStart = rect.BStart(lineWM) - margin.BStart(lineWM);
     minBCoord = std::min(minBCoord, blockStart);
     nscoord blockEnd = rect.BEnd(lineWM) + margin.BEnd(lineWM);
     maxBCoord = std::max(maxBCoord, blockEnd);
   }
 
   LogicalSize size(lineWM, mISize, 0);
   if (!mFrames.IsEmpty()) {
     if (MOZ_UNLIKELY(minBCoord > maxBCoord)) {
       // XXX When bug 765861 gets fixed, this warning should be upgraded.
       NS_WARNING("bad block coord");
       minBCoord = maxBCoord = 0;
     }
     size.BSize(lineWM) = maxBCoord - minBCoord;
-    nscoord containerWidth = size.Width(lineWM);
+    nsSize containerSize = size.GetPhysicalSize(lineWM);
     for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) {
       nsIFrame* child = e.get();
-      // We reflowed the child with container width 0, as the true width
+      // We reflowed the child with a dummy container size, as the true size
       // was not yet known at that time.
-      LogicalPoint pos = child->GetLogicalPosition(lineWM, 0);
+      LogicalPoint pos = child->GetLogicalPosition(lineWM, dummyContainerSize);
       // Adjust block position to account for minBCoord,
       // then reposition child based on the true container width.
       pos.B(lineWM) -= minBCoord;
       // Relative positioning hasn't happened yet.
       // So MovePositionBy should not be used here.
-      child->SetPosition(lineWM, pos, containerWidth);
+      child->SetPosition(lineWM, pos, containerSize);
       nsContainerFrame::PlaceFrameView(child);
     }
   }
 
   aDesiredSize.SetSize(lineWM, size);
 }
--- a/layout/mathml/nsMathMLmtableFrame.cpp
+++ b/layout/mathml/nsMathMLmtableFrame.cpp
@@ -815,20 +815,21 @@ nsMathMLmtableOuterFrame::Reflow(nsPresC
   WritingMode wm = aDesiredSize.GetWritingMode();
   nscoord blockSize = aDesiredSize.BSize(wm);
   nsIFrame* rowFrame = nullptr;
   if (rowIndex) {
     rowFrame = GetRowFrameAt(aPresContext, rowIndex);
     if (rowFrame) {
       // translate the coordinates to be relative to us and in our writing mode
       nsIFrame* frame = rowFrame;
-      LogicalRect frameRect(wm, frame->GetRect(), aReflowState.ComputedWidth());
-      blockSize = frameRect.BSize(wm);
+      LogicalRect rect(wm, frame->GetRect(),
+                       aReflowState.ComputedSizeAsContainerIfConstrained());
+      blockSize = rect.BSize(wm);
       do {
-        dy += frameRect.BStart(wm);
+        dy += rect.BStart(wm);
         frame = frame->GetParent();
       } while (frame != this);
     }
   }
   switch (tableAlign) {
     case eAlign_top:
       aDesiredSize.SetBlockStartAscent(dy);
       break;
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -591,20 +591,20 @@ void nsTableCellFrame::BlockDirAlignChil
 
   nscoord bStartInset = borderPadding.BStart(aWM);
   nscoord bEndInset = borderPadding.BEnd(aWM);
 
   uint8_t verticalAlignFlags = GetVerticalAlign();
 
   nscoord bSize = BSize(aWM);
   nsIFrame* firstKid = mFrames.FirstChild();
-  nscoord containerWidth = mRect.width;
+  nsSize containerSize = mRect.Size();
   NS_ASSERTION(firstKid, "Frame construction error, a table cell always has "
                          "an inner cell frame");
-  LogicalRect kidRect = firstKid->GetLogicalRect(aWM, containerWidth);
+  LogicalRect kidRect = firstKid->GetLogicalRect(aWM, containerSize);
   nscoord childBSize = kidRect.BSize(aWM);
 
   // Vertically align the child
   nscoord kidBStart = 0;
   switch (verticalAlignFlags)
   {
     case NS_STYLE_VERTICAL_ALIGN_BASELINE:
       // Align the baselines of the child frame with the baselines of
@@ -631,17 +631,17 @@ void nsTableCellFrame::BlockDirAlignChil
   kidBStart = std::max(0, kidBStart);
 
   if (kidBStart != kidRect.BStart(aWM)) {
     // Invalidate at the old position first
     firstKid->InvalidateFrameSubtree();
   }
 
   firstKid->SetPosition(aWM, LogicalPoint(aWM, kidRect.IStart(aWM),
-                                          kidBStart), containerWidth);
+                                          kidBStart), containerSize);
   nsHTMLReflowMetrics desiredSize(aWM);
   desiredSize.SetSize(aWM, GetLogicalSize(aWM));
 
   nsRect overflow(nsPoint(0,0), GetSize());
   overflow.Inflate(GetBorderOverflow());
   desiredSize.mOverflowAreas.SetAllTo(overflow);
   ConsiderChildOverflow(desiredSize.mOverflowAreas, firstKid);
   FinishAndStoreOverflow(&desiredSize);
@@ -939,27 +939,27 @@ nsTableCellFrame::Reflow(nsPresContext* 
   if (aReflowState.mFlags.mSpecialBSizeReflow ||
       FirstInFlow()->HasAnyStateBits(NS_TABLE_CELL_HAD_SPECIAL_REFLOW)) {
     // We need to force the kid to have mBResize set if we've had a
     // special reflow in the past, since the non-special reflow needs to
     // resize back to what it was without the special bsize reflow.
     kidReflowState.SetBResize(true);
   }
 
-  nscoord containerWidth =
-    aReflowState.ComputedSizeAsContainerIfConstrained().width;
+  nsSize containerSize =
+    aReflowState.ComputedSizeAsContainerIfConstrained();
 
   LogicalPoint kidOrigin(wm, borderPadding.IStart(wm),
                          borderPadding.BStart(wm));
   nsRect origRect = firstKid->GetRect();
   nsRect origVisualOverflow = firstKid->GetVisualOverflowRect();
   bool firstReflow = firstKid->HasAnyStateBits(NS_FRAME_FIRST_REFLOW);
 
   ReflowChild(firstKid, aPresContext, kidSize, kidReflowState,
-              wm, kidOrigin, containerWidth, 0, aStatus);
+              wm, kidOrigin, containerSize, 0, aStatus);
   if (NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus)) {
     // Don't pass OVERFLOW_INCOMPLETE through tables until they can actually handle it
     //XXX should paginate overflow as overflow, but not in this patch (bug 379349)
     NS_FRAME_SET_INCOMPLETE(aStatus);
     printf("Set table cell incomplete %p\n", static_cast<void*>(this));
   }
 
   // XXXbz is this invalidate actually needed, really?
@@ -979,17 +979,17 @@ nsTableCellFrame::Reflow(nsPresContext* 
     isEmpty = static_cast<nsTableCellFrame*>(prevInFlow)->GetContentEmpty();
   } else {
     isEmpty = !CellHasVisibleContent(kidSize.Height(), tableFrame, firstKid);
   }
   SetContentEmpty(isEmpty);
 
   // Place the child
   FinishReflowChild(firstKid, aPresContext, kidSize, &kidReflowState,
-                    wm, kidOrigin, containerWidth, 0);
+                    wm, kidOrigin, containerSize, 0);
 
   nsTableFrame::InvalidateTableFrame(firstKid, origRect, origVisualOverflow,
                                      firstReflow);
 
   // first, compute the bsize which can be set w/o being restricted by
   // available bsize
   LogicalSize cellSize(wm);
   cellSize.BSize(wm) = kidSize.BSize(wm);
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -1417,17 +1417,17 @@ nsTableFrame::GetLogicalSkipSides(const 
     skip |= eLogicalSideBitsBEnd;
   }
   return skip;
 }
 
 void
 nsTableFrame::SetColumnDimensions(nscoord aBSize, WritingMode aWM,
                                   const LogicalMargin& aBorderPadding,
-                                  nscoord aContainerWidth)
+                                  const nsSize& aContainerSize)
 {
   const nscoord colBSize = aBSize - (aBorderPadding.BStartEnd(aWM) +
                            GetRowSpacing(-1) + GetRowSpacing(GetRowCount()));
   int32_t colIdx = 0;
   LogicalPoint colGroupOrigin(aWM,
                               aBorderPadding.IStart(aWM) + GetColSpacing(-1),
                               aBorderPadding.BStart(aWM) + GetRowSpacing(-1));
   nsTableFrame* fif = static_cast<nsTableFrame*>(FirstInFlow());
@@ -1449,29 +1449,29 @@ nsTableFrame::SetColumnDimensions(nscoor
       }
     }
     if (colGroupISize) {
       colGroupISize -= cellSpacingI;
     }
 
     LogicalRect colGroupRect(aWM, colGroupOrigin.I(aWM), colGroupOrigin.B(aWM),
                              colGroupISize, colBSize);
-    colGroupFrame->SetRect(aWM, colGroupRect, aContainerWidth);
-    nscoord colGroupWidth = colGroupFrame->GetSize().width;
+    colGroupFrame->SetRect(aWM, colGroupRect, aContainerSize);
+    nsSize colGroupSize = colGroupFrame->GetSize();
 
     // then we can place the columns correctly within the group
     colIdx = groupFirstCol;
     LogicalPoint colOrigin(aWM);
     for (nsIFrame* colFrame : columnList) {
       if (NS_STYLE_DISPLAY_TABLE_COLUMN ==
           colFrame->StyleDisplay()->mDisplay) {
         nscoord colISize = fif->GetColumnISizeFromFirstInFlow(colIdx);
         LogicalRect colRect(aWM, colOrigin.I(aWM), colOrigin.B(aWM),
                             colISize, colBSize);
-        colFrame->SetRect(aWM, colRect, colGroupWidth);
+        colFrame->SetRect(aWM, colRect, colGroupSize);
         cellSpacingI = GetColSpacing(colIdx);
         colOrigin.I(aWM) += colISize + cellSpacingI;
         ++colIdx;
       }
     }
 
     colGroupOrigin.I(aWM) += colGroupISize + cellSpacingI;
   }
@@ -1874,18 +1874,18 @@ nsTableFrame::Reflow(nsPresContext*     
     // bsize of the reflow before that
     nscoord availBSize = needToInitiateSpecialReflow
                          ? NS_UNCONSTRAINEDSIZE
                          : aReflowState.AvailableBSize();
 
     ReflowTable(aDesiredSize, aReflowState, availBSize,
                 lastChildReflowed, aStatus);
     // If ComputedWidth is unconstrained, we may need to fix child positions
-    // later (in vertical-rl mode) due to use of 0 as a fake containerWidth
-    // during ReflowChildren.
+    // later (in vertical-rl mode) due to use of 0 as a dummy
+    // containerSize.width during ReflowChildren.
     fixupKidPositions = wm.IsVerticalRL() &&
       aReflowState.ComputedWidth() == NS_UNCONSTRAINEDSIZE;
 
     // reevaluate special bsize reflow conditions
     if (HasAnyStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE)) {
       needToInitiateSpecialReflow = true;
     }
 
@@ -1922,17 +1922,17 @@ nsTableFrame::Reflow(nsPresContext*     
   if (!haveDesiredBSize) {
     CalcDesiredBSize(aReflowState, aDesiredSize);
   }
   if (IsRowInserted()) {
     ProcessRowInserted(aDesiredSize.BSize(wm));
   }
 
   if (fixupKidPositions) {
-    // If we didn't already know the containerWidth (and so used zero during
+    // If we didn't already know the containerSize (and so used zero during
     // ReflowChildren), then we need to update the block-position of our kids.
     for (nsIFrame* kid : mFrames) {
       kid->MovePositionBy(nsPoint(aDesiredSize.Width(), 0));
       RePositionViews(kid);
     }
   }
 
   // Calculate the overflow area contribution from our children. We couldn't
@@ -1940,17 +1940,17 @@ nsTableFrame::Reflow(nsPresContext*     
   // with unconstrained width, we weren't placing them in their final positions
   // until the fixupKidPositions loop just above.
   for (nsIFrame* kid : mFrames) {
     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, kid);
   }
 
   LogicalMargin borderPadding = GetChildAreaOffset(wm, &aReflowState);
   SetColumnDimensions(aDesiredSize.BSize(wm), wm, borderPadding,
-                      aDesiredSize.Width());
+                      aDesiredSize.PhysicalSize());
   if (NeedToCollapse() &&
       (NS_UNCONSTRAINEDSIZE != aReflowState.AvailableISize())) {
     AdjustForCollapsingRowsCols(aDesiredSize, wm, borderPadding);
   }
 
   // If there are any relatively-positioned table parts, we need to reflow their
   // absolutely-positioned descendants now that their dimensions are final.
   FixupPositionedTableParts(aPresContext, aDesiredSize, aReflowState);
@@ -2892,49 +2892,49 @@ nsTableFrame::SetupHeaderFooterChild(con
 {
   nsPresContext* presContext = PresContext();
   nscoord pageHeight = presContext->GetPageSize().height;
 
   // Reflow the child with unconstrained height
   WritingMode wm = aFrame->GetWritingMode();
   LogicalSize availSize = aReflowState.reflowState.AvailableSize(wm);
 
-  nscoord containerWidth = availSize.Width(wm);
-  // XXX check for containerWidth == NS_UNCONSTRAINEDSIZE
+  nsSize containerSize = availSize.GetPhysicalSize(wm);
+  // XXX check for containerSize.* == NS_UNCONSTRAINEDSIZE
 
   availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
   nsHTMLReflowState kidReflowState(presContext, aReflowState.reflowState,
                                    aFrame, availSize, nullptr,
                                    nsHTMLReflowState::CALLER_WILL_INIT);
   InitChildReflowState(kidReflowState);
   kidReflowState.mFlags.mIsTopOfPage = true;
   nsHTMLReflowMetrics desiredSize(aReflowState.reflowState);
   desiredSize.ClearSize();
   nsReflowStatus status;
   ReflowChild(aFrame, presContext, desiredSize, kidReflowState,
               wm, LogicalPoint(wm, aReflowState.iCoord, aReflowState.bCoord),
-              containerWidth, 0, status);
+              containerSize, 0, status);
   // The child will be reflowed again "for real" so no need to place it now
 
   aFrame->SetRepeatable(IsRepeatable(desiredSize.Height(), pageHeight));
   *aDesiredHeight = desiredSize.Height();
   return NS_OK;
 }
 
 void
 nsTableFrame::PlaceRepeatedFooter(nsTableReflowState& aReflowState,
                                   nsTableRowGroupFrame *aTfoot,
                                   nscoord aFooterHeight)
 {
   nsPresContext* presContext = PresContext();
   WritingMode wm = aTfoot->GetWritingMode();
   LogicalSize kidAvailSize = aReflowState.availSize;
 
-  nscoord containerWidth = kidAvailSize.Width(wm);
-  // XXX check for containerWidth == NS_UNCONSTRAINEDSIZE
+  nsSize containerSize = kidAvailSize.GetPhysicalSize(wm);
+  // XXX check for containerSize.* == NS_UNCONSTRAINEDSIZE
 
   kidAvailSize.BSize(wm) = aFooterHeight;
   nsHTMLReflowState footerReflowState(presContext,
                                       aReflowState.reflowState,
                                       aTfoot, kidAvailSize,
                                       nullptr,
                                       nsHTMLReflowState::CALLER_WILL_INIT);
   InitChildReflowState(footerReflowState);
@@ -2943,25 +2943,26 @@ nsTableFrame::PlaceRepeatedFooter(nsTabl
   nsRect origTfootRect = aTfoot->GetRect();
   nsRect origTfootVisualOverflow = aTfoot->GetVisualOverflowRect();
 
   nsReflowStatus footerStatus;
   nsHTMLReflowMetrics desiredSize(aReflowState.reflowState);
   desiredSize.ClearSize();
   LogicalPoint kidPosition(wm, aReflowState.iCoord, aReflowState.bCoord);
   ReflowChild(aTfoot, presContext, desiredSize, footerReflowState,
-              wm, kidPosition, containerWidth, 0, footerStatus);
-  footerReflowState.ApplyRelativePositioning(&kidPosition, containerWidth);
+              wm, kidPosition, containerSize, 0, footerStatus);
+  footerReflowState.ApplyRelativePositioning(&kidPosition, containerSize);
 
   PlaceChild(aReflowState, aTfoot,
-             // We subtract desiredSize.Width() from containerWidth here
+             // We subtract desiredSize.PhysicalSize() from containerSize here
              // to account for the fact that in RTL modes, the origin is
              // on the right-hand side so we're not simply converting a
              // point, we're also swapping the child's origin side.
-             kidPosition.GetPhysicalPoint(wm, containerWidth - desiredSize.Width()),
+             kidPosition.GetPhysicalPoint(wm, containerSize -
+                                              desiredSize.PhysicalSize()),
              desiredSize, origTfootRect, origTfootVisualOverflow);
 }
 
 // Reflow the children based on the avail size and reason in aReflowState
 // update aReflowMetrics a aStatus
 void
 nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
                              nsReflowStatus&     aStatus,
@@ -2971,18 +2972,18 @@ nsTableFrame::ReflowChildren(nsTableRefl
   aStatus = NS_FRAME_COMPLETE;
   aLastChildReflowed = nullptr;
 
   nsIFrame* prevKidFrame = nullptr;
   WritingMode wm = aReflowState.reflowState.GetWritingMode();
   NS_WARN_IF_FALSE(wm.IsVertical() || NS_UNCONSTRAINEDSIZE !=
                                       aReflowState.reflowState.ComputedWidth(),
                    "shouldn't have unconstrained width in horizontal mode");
-  nscoord containerWidth =
-    aReflowState.reflowState.ComputedSizeAsContainerIfConstrained().width;
+  nsSize containerSize =
+    aReflowState.reflowState.ComputedSizeAsContainerIfConstrained();
 
   nsPresContext* presContext = PresContext();
   // XXXldb Should we be checking constrained height instead?
   // tables are not able to pull back children from its next inflow, so even
   // under paginated contexts tables are should not paginate if they are inside
   // column set
   bool isPaginated = presContext->IsPaginated() &&
                        NS_UNCONSTRAINEDSIZE != aReflowState.availSize.BSize(wm) &&
@@ -3091,18 +3092,18 @@ nsTableFrame::ReflowChildren(nsTableRefl
       // record the presence of a next in flow, it might get destroyed so we
       // need to reorder the row group array
       bool reorder = false;
       if (kidFrame->GetNextInFlow())
         reorder = true;
 
       LogicalPoint kidPosition(wm, aReflowState.iCoord, aReflowState.bCoord);
       ReflowChild(kidFrame, presContext, desiredSize, kidReflowState,
-                  wm, kidPosition, containerWidth, 0, aStatus);
-      kidReflowState.ApplyRelativePositioning(&kidPosition, containerWidth);
+                  wm, kidPosition, containerSize, 0, aStatus);
+      kidReflowState.ApplyRelativePositioning(&kidPosition, containerSize);
 
       if (reorder) {
         // reorder row groups the reflow may have changed the nextinflows
         OrderRowGroups(rowGroups, &thead, &tfoot);
         childX = rowGroups.IndexOf(kidFrame);
         if (childX == RowGroupArray::NoIndex) {
           // XXXbz can this happen?
           childX = rowGroups.Length();
@@ -3125,18 +3126,18 @@ nsTableFrame::ReflowChildren(nsTableRefl
           break;
         }
         // if we are on top of the page place with dataloss
         if (kidReflowState.mFlags.mIsTopOfPage) {
           if (childX+1 < rowGroups.Length()) {
             nsIFrame* nextRowGroupFrame = rowGroups[childX + 1];
             if (nextRowGroupFrame) {
               PlaceChild(aReflowState, kidFrame,
-                         kidPosition.GetPhysicalPoint(wm, containerWidth -
-                                                          desiredSize.Width()),
+                         kidPosition.GetPhysicalPoint(wm,
+                           containerSize - desiredSize.PhysicalSize()),
                          desiredSize, oldKidRect, oldKidVisualOverflow);
               if (allowRepeatedFooter) {
                 PlaceRepeatedFooter(aReflowState, tfoot, footerHeight);
               }
               else if (tfoot && tfoot->IsRepeatable()) {
                 tfoot->SetRepeatable(false);
               }
               aStatus = NS_FRAME_NOT_COMPLETE;
@@ -3156,18 +3157,18 @@ nsTableFrame::ReflowChildren(nsTableRefl
             }
             aStatus = NS_FRAME_NOT_COMPLETE;
             PushChildren(rowGroups, childX);
             aLastChildReflowed = prevKidFrame;
             break;
           }
           else { // we can't push so lets make clear how much space we need
             PlaceChild(aReflowState, kidFrame,
-                       kidPosition.GetPhysicalPoint(wm, containerWidth -
-                                                        desiredSize.Width()),
+                       kidPosition.GetPhysicalPoint(wm,
+                         containerSize - desiredSize.PhysicalSize()),
                        desiredSize, oldKidRect, oldKidVisualOverflow);
             aLastChildReflowed = kidFrame;
             if (allowRepeatedFooter) {
               PlaceRepeatedFooter(aReflowState, tfoot, footerHeight);
               aLastChildReflowed = tfoot;
             }
             break;
           }
@@ -3182,18 +3183,18 @@ nsTableFrame::ReflowChildren(nsTableRefl
           (NS_UNCONSTRAINEDSIZE != kidReflowState.AvailableHeight())) {
         nsIFrame* nextKid =
           (childX + 1 < rowGroups.Length()) ? rowGroups[childX + 1] : nullptr;
         pageBreak = PageBreakAfter(kidFrame, nextKid);
       }
 
       // Place the child
       PlaceChild(aReflowState, kidFrame,
-                 kidPosition.GetPhysicalPoint(wm, containerWidth -
-                                                  desiredSize.Width()),
+                 kidPosition.GetPhysicalPoint(wm, containerSize -
+                                                  desiredSize.PhysicalSize()),
                  desiredSize, oldKidRect, oldKidVisualOverflow);
 
       // Remember where we just were in case we end up pushing children
       prevKidFrame = kidFrame;
 
       // Special handling for incomplete children
       if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
         nsIFrame* kidNextInFlow = kidFrame->GetNextInFlow();
@@ -3230,17 +3231,17 @@ nsTableFrame::ReflowChildren(nsTableRefl
         if (nextSibling) {
           PushChildren(rowGroups, childX + 1);
         }
         break;
       }
     }
     else { // it isn't being reflowed
       aReflowState.bCoord += cellSpacingB;
-      LogicalRect kidRect(wm, kidFrame->GetNormalRect(), containerWidth);
+      LogicalRect kidRect(wm, kidFrame->GetNormalRect(), containerSize);
       if (kidRect.BStart(wm) != aReflowState.bCoord) {
         // invalidate the old position
         kidFrame->InvalidateFrameSubtree();
         // move to the new position
         kidFrame->MovePositionBy(wm, LogicalPoint(wm, 0, aReflowState.bCoord -
                                                          kidRect.BStart(wm)));
         RePositionViews(kidFrame);
         // invalidate the new position
@@ -3375,42 +3376,44 @@ void ResizeCells(nsTableFrame& aTableFra
 
 void
 nsTableFrame::DistributeBSizeToRows(const nsHTMLReflowState& aReflowState,
                                     nscoord                  aAmount)
 {
   WritingMode wm = aReflowState.GetWritingMode();
   LogicalMargin borderPadding = GetChildAreaOffset(wm, &aReflowState);
 
-  nscoord containerWidth =
-    aReflowState.ComputedSizeAsContainerIfConstrained().width;
+  nsSize containerSize =
+    aReflowState.ComputedSizeAsContainerIfConstrained();
 
   RowGroupArray rowGroups;
   OrderRowGroups(rowGroups);
 
   nscoord amountUsed = 0;
   // distribute space to each pct bsize row whose row group doesn't have a computed
   // bsize, and base the pct on the table bsize. If the row group had a computed
   // bsize, then this was already done in nsTableRowGroupFrame::CalculateRowBSizes
   nscoord pctBasis = aReflowState.ComputedBSize() - GetRowSpacing(-1, GetRowCount());
   nscoord bOriginRG = borderPadding.BStart(wm) + GetRowSpacing(0);
   nscoord bEndRG = bOriginRG;
   uint32_t rgIdx;
   for (rgIdx = 0; rgIdx < rowGroups.Length(); rgIdx++) {
     nsTableRowGroupFrame* rgFrame = rowGroups[rgIdx];
     nscoord amountUsedByRG = 0;
     nscoord bOriginRow = 0;
-    LogicalRect rgNormalRect(wm, rgFrame->GetNormalRect(), containerWidth);
+    LogicalRect rgNormalRect(wm, rgFrame->GetNormalRect(), containerSize);
     if (!rgFrame->HasStyleBSize()) {
       nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
       while (rowFrame) {
-        // We don't know the final width of the rowGroupFrame yet, so use zero
-        // as a "fake" containerWidth here; we'll adjust the row positions at
+        // We don't know the final width of the rowGroupFrame yet, so use 0,0
+        // as a dummy containerSize here; we'll adjust the row positions at
         // the end, after the rowGroup size is finalized.
-        LogicalRect rowNormalRect(wm, rowFrame->GetNormalRect(), 0);
+        const nsSize dummyContainerSize;
+        LogicalRect rowNormalRect(wm, rowFrame->GetNormalRect(),
+                                  dummyContainerSize);
         nscoord cellSpacingB = GetRowSpacing(rowFrame->GetRowIndex());
         if ((amountUsed < aAmount) && rowFrame->HasPctBSize()) {
           nscoord pctBSize = rowFrame->GetInitialBSize(pctBasis);
           nscoord amountForRow = std::min(aAmount - amountUsed,
                                           pctBSize - rowNormalRect.BSize(wm));
           if (amountForRow > 0) {
             // XXXbz we don't need to move the row's b-position to bOriginRow?
             nsRect origRowRect = rowFrame->GetRect();
@@ -3537,24 +3540,29 @@ nsTableFrame::DistributeBSizeToRows(cons
   // allocate the extra bsize to the unstyled row groups and rows
   nscoord bSizeToDistribute = aAmount - amountUsed;
   bOriginRG = borderPadding.BStart(wm) + GetRowSpacing(-1);
   bEndRG = bOriginRG;
   for (rgIdx = 0; rgIdx < rowGroups.Length(); rgIdx++) {
     nsTableRowGroupFrame* rgFrame = rowGroups[rgIdx];
     nscoord amountUsedByRG = 0;
     nscoord bOriginRow = 0;
-    LogicalRect rgNormalRect(wm, rgFrame->GetNormalRect(), containerWidth);
+    LogicalRect rgNormalRect(wm, rgFrame->GetNormalRect(), containerSize);
     nsRect rgVisualOverflow = rgFrame->GetVisualOverflowRect();
     // see if there is an eligible row group or we distribute to all rows
     if (!firstUnStyledRG || !rgFrame->HasStyleBSize() || !eligibleRows) {
       for (nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
            rowFrame; rowFrame = rowFrame->GetNextRow()) {
         nscoord cellSpacingB = GetRowSpacing(rowFrame->GetRowIndex());
-        LogicalRect rowNormalRect(wm, rowFrame->GetNormalRect(), 0);
+        // We don't know the final width of the rowGroupFrame yet, so use 0,0
+        // as a dummy containerSize here; we'll adjust the row positions at
+        // the end, after the rowGroup size is finalized.
+        const nsSize dummyContainerSize;
+        LogicalRect rowNormalRect(wm, rowFrame->GetNormalRect(),
+                                  dummyContainerSize);
         nsRect rowVisualOverflow = rowFrame->GetVisualOverflowRect();
         // see if there is an eligible row or we distribute to all rows
         if (!firstUnStyledRow || !rowFrame->HasStyleBSize() || !eligibleRows) {
           float ratio;
           if (eligibleRows) {
             if (!expandEmptyRows) {
               // The amount of additional space each row gets is proportional
               // to its bsize
@@ -3626,21 +3634,21 @@ nsTableFrame::DistributeBSizeToRows(cons
 
         nsTableFrame::InvalidateTableFrame(rgFrame, origRgNormalRect,
                                            rgVisualOverflow, false);
       }
 
       // For vertical-rl mode, we needed to position the rows relative to the
       // right-hand (block-start) side of the group; but we couldn't do that
       // above, as we didn't know the rowGroupFrame's final block size yet.
-      // So we used a containerWidth of zero earlier, placing the rows to the
-      // left of the rowGroupFrame's (physical) origin. Now we move them all
-      // rightwards by its final width.
+      // So we used a dummyContainerSize of 0,0 earlier, placing the rows to
+      // the left of the rowGroupFrame's (physical) origin. Now we move them
+      // all rightwards by its final width.
       if (wm.IsVerticalRL()) {
-        nscoord rgWidth = rgFrame->GetRect().width;
+        nscoord rgWidth = rgFrame->GetSize().width;
         for (nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
              rowFrame; rowFrame = rowFrame->GetNextRow()) {
           rowFrame->InvalidateFrameSubtree();
           rowFrame->MovePositionBy(nsPoint(rgWidth, 0));
           nsTableFrame::RePositionViews(rowFrame);
           rowFrame->InvalidateFrameSubtree();
         }
       }
@@ -3741,28 +3749,28 @@ nsTableFrame::GetRowSpacing(int32_t aSta
 
 /* virtual */ nscoord
 nsTableFrame::GetLogicalBaseline(WritingMode aWritingMode) const
 {
   nscoord ascent = 0;
   RowGroupArray orderedRowGroups;
   OrderRowGroups(orderedRowGroups);
   nsTableRowFrame* firstRow = nullptr;
-  // XXX not sure if this should be the width of the containing block instead.
-  nscoord containerWidth = mRect.width;
+  // XXX not sure if this should be the size of the containing block instead.
+  nsSize containerSize = mRect.Size();
   for (uint32_t rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
     nsTableRowGroupFrame* rgFrame = orderedRowGroups[rgIndex];
     if (rgFrame->GetRowCount()) {
       firstRow = rgFrame->GetFirstRow();
 
       nscoord rgNormalBStart =
-        LogicalRect(aWritingMode, rgFrame->GetNormalRect(), containerWidth)
+        LogicalRect(aWritingMode, rgFrame->GetNormalRect(), containerSize)
         .Origin(aWritingMode).B(aWritingMode);
       nscoord firstRowNormalBStart =
-        LogicalRect(aWritingMode, firstRow->GetNormalRect(), containerWidth)
+        LogicalRect(aWritingMode, firstRow->GetNormalRect(), containerSize)
         .Origin(aWritingMode).B(aWritingMode);
 
       ascent = rgNormalBStart + firstRowNormalBStart +
                firstRow->GetRowBaseline(aWritingMode);
       break;
     }
   }
   if (!firstRow)
@@ -6402,18 +6410,18 @@ BCPaintBorderIterator::BCPaintBorderIter
   nsIFrame* bgFrame =
     nsCSSRendering::FindNonTransparentBackgroundFrame(aTable);
   mTableBgColor = bgFrame->StyleBackground();
 }
 
 bool
 BCPaintBorderIterator::SetDamageArea(const nsRect& aDirtyRect)
 {
-  nscoord containerWidth = mTable->GetRect().width;
-  LogicalRect dirtyRect(mTableWM, aDirtyRect, containerWidth);
+  nsSize containerSize = mTable->GetSize();
+  LogicalRect dirtyRect(mTableWM, aDirtyRect, containerSize);
   uint32_t startRowIndex, endRowIndex, startColIndex, endColIndex;
   startRowIndex = endRowIndex = startColIndex = endColIndex = 0;
   bool done = false;
   bool haveIntersect = false;
   // find startRowIndex, endRowIndex
   nscoord rowB = mInitialOffsetB;
   for (uint32_t rgIdx = 0; rgIdx < mRowGroups.Length() && !done; rgIdx++) {
     nsTableRowGroupFrame* rgFrame = mRowGroups[rgIdx];
@@ -6979,17 +6987,17 @@ BCBlockDirSeg::Paint(BCPaintBorderIterat
   nscoord bEndBevelOffset = (mIsBEndBevel) ?
                   nsPresContext::CSSPixelsToAppUnits(mBEndInlineSegBSize) : 0;
   LogicalSide bEndBevelSide =
     (aInlineSegBSize > 0) ? eLogicalSideIEnd : eLogicalSideIStart;
 
   // Convert logical to physical sides/coordinates for DrawTableBorderSegment.
 
   nsRect physicalRect = segRect.GetPhysicalRect(aIter.mTableWM,
-                                                aIter.mTable->GetSize().width);
+                                                aIter.mTable->GetSize());
   // XXX For reversed vertical writing-modes (with direction:rtl), we need to
   // invert physicalRect's y-position here, with respect to the table.
   // However, it's not worth fixing the border positions here until the
   // ordering of the table columns themselves is also fixed (bug 1180528).
 
   uint8_t startBevelSide = aIter.mTableWM.PhysicalSide(mBStartBevelSide);
   uint8_t endBevelSide = aIter.mTableWM.PhysicalSide(bEndBevelSide);
   nscoord startBevelOffset = mBStartBevelOffset;
@@ -7186,17 +7194,17 @@ BCInlineDirSeg::Paint(BCPaintBorderItera
   DivideBCBorderSize(mWidth, smallHalf, largeHalf);
   LogicalRect segRect(aIter.mTableWM, mOffsetI,
                       mOffsetB - nsPresContext::CSSPixelsToAppUnits(largeHalf),
                       mLength,
                       nsPresContext::CSSPixelsToAppUnits(mWidth));
 
   // Convert logical to physical sides/coordinates for DrawTableBorderSegment.
   nsRect physicalRect = segRect.GetPhysicalRect(aIter.mTableWM,
-                                                aIter.mTable->GetSize().width);
+                                                aIter.mTable->GetSize());
   uint8_t startBevelSide = aIter.mTableWM.PhysicalSide(mIStartBevelSide);
   uint8_t endBevelSide = aIter.mTableWM.PhysicalSide(mIEndBevelSide);
   nscoord startBevelOffset =
     nsPresContext::CSSPixelsToAppUnits(mIStartBevelOffset);
   nscoord endBevelOffset = mIEndBevelOffset;
   // With inline-RTL directionality, the 'start' and 'end' of the inline-dir
   // border segment need to be swapped because DrawTableBorderSegment will
   // apply the 'start' bevel physically at the left or top edge, and 'end' at
--- a/layout/tables/nsTableFrame.h
+++ b/layout/tables/nsTableFrame.h
@@ -809,17 +809,17 @@ protected:
   BCPropertyData* GetBCProperty(bool aCreateIfNecessary = false) const;
   void SetFullBCDamageArea();
   void CalcBCBorders();
 
   void ExpandBCDamageArea(mozilla::TableArea& aRect) const;
 
   void SetColumnDimensions(nscoord aHeight, WritingMode aWM,
                            const LogicalMargin& aBorderPadding,
-                           nscoord aContainerWidth);
+                           const nsSize& aContainerSize);
 
   int32_t CollectRows(nsIFrame*                   aFrame,
                       nsTArray<nsTableRowFrame*>& aCollection);
 
 public: /* ----- Cell Map public methods ----- */
 
   int32_t GetStartRowIndex(nsTableRowGroupFrame* aRowGroupFrame);
 
--- a/layout/tables/nsTableOuterFrame.cpp
+++ b/layout/tables/nsTableOuterFrame.cpp
@@ -34,17 +34,17 @@ nsTableOuterFrame::GetLogicalBaseline(Wr
 {
   nsIFrame* kid = mFrames.FirstChild();
   if (!kid) {
     NS_NOTREACHED("no inner table");
     return nsContainerFrame::GetLogicalBaseline(aWritingMode);
   }
 
   return kid->GetLogicalBaseline(aWritingMode) +
-         kid->BStart(aWritingMode, mRect.width);
+         kid->BStart(aWritingMode, mRect.Size());
 }
 
 nsTableOuterFrame::nsTableOuterFrame(nsStyleContext* aContext):
   nsContainerFrame(aContext)
 {
 }
 
 nsTableOuterFrame::~nsTableOuterFrame()
@@ -781,38 +781,38 @@ nsTableOuterFrame::OuterBeginReflowChild
 
 void
 nsTableOuterFrame::OuterDoReflowChild(nsPresContext*             aPresContext,
                                       nsIFrame*                  aChildFrame,
                                       const nsHTMLReflowState&   aChildRS,
                                       nsHTMLReflowMetrics&       aMetrics,
                                       nsReflowStatus&            aStatus)
 {
-  // Using zero as containerWidth here because we want consistency between
+  // Using zero as containerSize here because we want consistency between
   // the GetLogicalPosition and ReflowChild calls, to avoid unnecessarily
   // changing the frame's coordinates; but we don't yet know its final
   // position anyway so the actual value is unimportant.
-  const nscoord zeroCWidth = 0;
+  const nsSize zeroCSize;
   WritingMode wm = aChildRS.GetWritingMode();
 
   // Use the current position as a best guess for placement.
-  LogicalPoint childPt = aChildFrame->GetLogicalPosition(wm, zeroCWidth);
+  LogicalPoint childPt = aChildFrame->GetLogicalPosition(wm, zeroCSize);
   uint32_t flags = NS_FRAME_NO_MOVE_FRAME;
 
   // We don't want to delete our next-in-flow's child if it's an inner table
   // frame, because outer table frames always assume that their inner table
   // frames don't go away. If an outer table frame is removed because it is
   // a next-in-flow of an already complete outer table frame, then it will
   // take care of removing it's inner table frame.
   if (aChildFrame == InnerTableFrame()) {
     flags |= NS_FRAME_NO_DELETE_NEXT_IN_FLOW_CHILD;
   }
 
   ReflowChild(aChildFrame, aPresContext, aMetrics, aChildRS,
-              wm, childPt, zeroCWidth, flags, aStatus);
+              wm, childPt, zeroCSize, flags, aStatus);
 }
 
 void 
 nsTableOuterFrame::UpdateOverflowAreas(nsHTMLReflowMetrics& aMet)
 {
   aMet.SetOverflowAreasToDesiredBounds();
   ConsiderChildOverflow(aMet.mOverflowAreas, InnerTableFrame());
   if (mCaptionFrames.NotEmpty()) {
@@ -955,44 +955,43 @@ nsTableOuterFrame::Reflow(nsPresContext*
   LogicalSize containSize(wm, GetContainingBlockSize(aOuterRS));
 
   // Now that we've reflowed both we can place them.
   // XXXldb Most of the input variables here are now uninitialized!
 
   // XXX Need to recompute inner table's auto margins for the case of side
   // captions.  (Caption's are broken too, but that should be fixed earlier.)
 
-  // Compute the desiredSize so that we can use its Width() as containerWidth
+  // Compute the desiredSize so that we can use it as the containerSize
   // for the FinishReflowChild calls below.
   LogicalSize desiredSize(wm);
   SetDesiredSize(captionSide, innerSize, captionSize,
                  innerMargin, captionMargin,
                  desiredSize.ISize(wm), desiredSize.BSize(wm), wm);
   aDesiredSize.SetSize(wm, desiredSize);
-  nscoord containerWidth = aDesiredSize.Width();
+  nsSize containerSize = aDesiredSize.PhysicalSize();
   // XXX It's possible for this to be NS_UNCONSTRAINEDSIZE, which will result
   // in assertions from FinishReflowChild.
 
   if (mCaptionFrames.NotEmpty()) {
     LogicalPoint captionOrigin(wm);
     GetCaptionOrigin(captionSide, containSize, innerSize, innerMargin,
                      captionSize, captionMargin, captionOrigin, wm);
     FinishReflowChild(mCaptionFrames.FirstChild(), aPresContext, *captionMet,
-                      captionRS.ptr(), wm, captionOrigin, containerWidth,
-                      0);
+                      captionRS.ptr(), wm, captionOrigin, containerSize, 0);
     captionRS.reset();
   }
   // XXX If the bsize is constrained then we need to check whether
   // everything still fits...
 
   LogicalPoint innerOrigin(wm);
   GetInnerOrigin(captionSide, containSize, captionSize, captionMargin,
                  innerSize, innerMargin, innerOrigin, wm);
   FinishReflowChild(InnerTableFrame(), aPresContext, innerMet, innerRS.ptr(),
-                    wm, innerOrigin, containerWidth, 0);
+                    wm, innerOrigin, containerSize, 0);
   innerRS.reset();
 
   nsTableFrame::InvalidateTableFrame(InnerTableFrame(), origInnerRect,
                                      origInnerVisualOverflow,
                                      innerFirstReflow);
   if (mCaptionFrames.NotEmpty()) {
     nsTableFrame::InvalidateTableFrame(mCaptionFrames.FirstChild(),
                                        origCaptionRect,
--- a/layout/tables/nsTableRowFrame.cpp
+++ b/layout/tables/nsTableRowFrame.cpp
@@ -321,58 +321,58 @@ nsTableRowFrame::DidResize()
   // Resize and re-align the cell frames based on our row bsize
   nsTableFrame* tableFrame = GetTableFrame();
 
   WritingMode wm = GetWritingMode();
   nsHTMLReflowMetrics desiredSize(wm);
   desiredSize.SetSize(wm, GetLogicalSize(wm));
   desiredSize.SetOverflowAreasToDesiredBounds();
 
-  nscoord containerWidth = mRect.width;
+  nsSize containerSize = mRect.Size();
 
   for (nsIFrame* childFrame : mFrames) {
     nsTableCellFrame *cellFrame = do_QueryFrame(childFrame);
     if (cellFrame) {
       nscoord cellBSize = BSize(wm) +
         GetBSizeOfRowsSpannedBelowFirst(*cellFrame, *tableFrame, wm);
 
       // If the bsize for the cell has changed, we need to reset it;
       // and in vertical-rl mode, we need to update the cell's block position
-      // to account for the containerWidth, which may not have been known
+      // to account for the containerSize, which may not have been known
       // earlier, so we always apply it here.
       LogicalSize cellSize = cellFrame->GetLogicalSize(wm);
       if (cellSize.BSize(wm) != cellBSize || wm.IsVerticalRL()) {
         nsRect cellOldRect = cellFrame->GetRect();
         nsRect cellVisualOverflow = cellFrame->GetVisualOverflowRect();
 
         if (wm.IsVerticalRL()) {
           // Get the old position of the cell, as we want to preserve its
           // inline coordinate.
           LogicalPoint oldPos =
-            cellFrame->GetLogicalPosition(wm, containerWidth);
+            cellFrame->GetLogicalPosition(wm, containerSize);
 
           // The cell should normally be aligned with the row's block-start,
           // so set the B component of the position to zero:
           LogicalPoint newPos(wm, oldPos.I(wm), 0);
 
           // ...unless relative positioning is in effect, in which case the
           // cell may have been moved away from the row's block-start
           if (cellFrame->IsRelativelyPositioned()) {
             // Find out where the cell would have been without relative
             // positioning.
             LogicalPoint oldNormalPos =
-              cellFrame->GetLogicalNormalPosition(wm, containerWidth);
+              cellFrame->GetLogicalNormalPosition(wm, containerSize);
             // The difference (if any) between oldPos and oldNormalPos reflects
             // relative positioning that was applied to the cell, and which we
             // need to incorporate when resetting the position.
             newPos.B(wm) = oldPos.B(wm) - oldNormalPos.B(wm);
           }
 
           if (oldPos != newPos) {
-            cellFrame->SetPosition(wm, newPos, containerWidth);
+            cellFrame->SetPosition(wm, newPos, containerSize);
             nsTableFrame::RePositionViews(cellFrame);
           }
         }
 
         cellSize.BSize(wm) = cellBSize;
         cellFrame->SetSize(wm, cellSize);
         nsTableFrame::InvalidateTableFrame(cellFrame, cellOldRect,
                                            cellVisualOverflow,
@@ -427,23 +427,23 @@ nscoord nsTableRowFrame::GetRowBaseline(
   // bpx            xpb
   // bpxxxxxxxxxxxxxxpb  base line
   // bp              pb
   // bp              pb
   // bppppppppppppppppb
   // bbbbbbbbbbbbbbbbbb
 
   nscoord ascent = 0;
-  nscoord containerWidth = GetRect().width;
+  nsSize containerSize = GetSize();
   for (nsIFrame* childFrame : mFrames) {
     if (IS_TABLE_CELL(childFrame->GetType())) {
       nsIFrame* firstKid = childFrame->GetFirstPrincipalChild();
       ascent = std::max(ascent,
                         LogicalRect(aWM, firstKid->GetNormalRect(),
-                                    containerWidth).BEnd(aWM));
+                                    containerSize).BEnd(aWM));
     }
   }
   return ascent;
 }
 
 nscoord
 nsTableRowFrame::GetInitialBSize(nscoord aPctBasis) const
 {
@@ -812,18 +812,18 @@ nsTableRowFrame::ReflowChildren(nsPresCo
   int32_t prevColIndex = -1;
   nscoord iCoord = 0; // running total of children inline-coord offset
 
   // This computes the max of all cell bsizes
   nscoord cellMaxBSize = 0;
 
   // Reflow each of our existing cell frames
   WritingMode wm = aReflowState.GetWritingMode();
-  nscoord containerWidth =
-    aReflowState.ComputedSizeAsContainerIfConstrained().width;
+  nsSize containerSize =
+    aReflowState.ComputedSizeAsContainerIfConstrained();
 
   for (nsIFrame* kidFrame : mFrames) {
     nsTableCellFrame *cellFrame = do_QueryFrame(kidFrame);
     if (!cellFrame) {
       // XXXldb nsCSSFrameConstructor needs to enforce this!
       NS_NOTREACHED("yikes, a non-row child");
 
       // it's an unknown frame type, give it a generic reflow and ignore the results
@@ -873,21 +873,21 @@ nsTableRowFrame::ReflowChildren(nsPresCo
     }
 
     // remember the rightmost (ltr) or leftmost (rtl) column this cell spans into
     prevColIndex = cellColIndex + (cellColSpan - 1);
 
     // Reflow the child frame
     nsRect kidRect = kidFrame->GetRect();
     LogicalPoint origKidNormalPosition =
-      kidFrame->GetLogicalNormalPosition(wm, containerWidth);
+      kidFrame->GetLogicalNormalPosition(wm, containerSize);
     // All cells' no-relative-positioning position should be snapped to the
     // row's bstart edge.
     // This doesn't hold in vertical-rl mode, where we don't yet know the
-    // correct containerWidth for the row frame. In that case, we'll have to
+    // correct containerSize for the row frame. In that case, we'll have to
     // fix up child positions later, after determining our desiredSize.
     NS_ASSERTION(origKidNormalPosition.B(wm) == 0 || wm.IsVerticalRL(),
                  "unexpected kid position");
 
     nsRect kidVisualOverflow = kidFrame->GetVisualOverflowRect();
     LogicalPoint kidPosition(wm, iCoord, 0);
     bool firstReflow = kidFrame->HasAnyStateBits(NS_FRAME_FIRST_REFLOW);
 
@@ -924,17 +924,17 @@ nsTableRowFrame::ReflowChildren(nsPresCo
         kidReflowState.emplace(aPresContext, aReflowState, kidFrame,
                                kidAvailSize,
                                nsHTMLReflowState::CALLER_WILL_INIT);
         InitChildReflowState(*aPresContext, kidAvailSize, borderCollapse,
                              *kidReflowState);
 
         nsReflowStatus status;
         ReflowChild(kidFrame, aPresContext, desiredSize, *kidReflowState,
-                    wm, kidPosition, containerWidth, 0, status);
+                    wm, kidPosition, containerSize, 0, status);
 
         // allow the table to determine if/how the table needs to be rebalanced
         // If any of the cells are not complete, then we're not complete
         if (NS_FRAME_IS_NOT_COMPLETE(status)) {
           aStatus = NS_FRAME_NOT_COMPLETE;
         }
       } else {
         if (iCoord != origKidNormalPosition.I(wm)) {
@@ -977,38 +977,32 @@ nsTableRowFrame::ReflowChildren(nsPresCo
         }
       }
 
       // Place the child
       desiredSize.ISize(wm) = availCellISize;
 
       if (kidReflowState) {
         // We reflowed. Apply relative positioning in the normal way.
-        kidReflowState->ApplyRelativePositioning(&kidPosition, containerWidth);
+        kidReflowState->ApplyRelativePositioning(&kidPosition, containerSize);
       } else if (kidFrame->IsRelativelyPositioned()) {
         // We didn't reflow.  Do the positioning part of what
         // MovePositionBy does internally.  (This codepath should really
         // be merged into the else below if we can.)
         LogicalMargin computedOffsets(wm, *static_cast<nsMargin*>
           (kidFrame->Properties().Get(nsIFrame::ComputedOffsetProperty())));
         nsHTMLReflowState::ApplyRelativePositioning(kidFrame, wm, computedOffsets,
-                                                    &kidPosition, containerWidth);
+                                                    &kidPosition, containerSize);
       }
 
-      // In vertical-rl writing mode, we are likely to have containerWidth 0
-      // because ComputedWidth() was NS_UNCONSTRAINEDSIZE. The true value
-      // we need is the row's bsize, but we don't know that yet. So we'll use
-      // the kid's (cell's) desiredSize.Width() value for now.
+      // In vertical-rl mode, we are likely to have containerSize.width = 0
+      // because ComputedWidth() was NS_UNCONSTRAINEDSIZE.
       // For cases where that's wrong, we will fix up the position later.
       FinishReflowChild(kidFrame, aPresContext, desiredSize, nullptr,
-                        wm, kidPosition,
-                        wm.IsVerticalRL() && containerWidth == 0
-                          ? desiredSize.Width()
-                          : containerWidth,
-                        0);
+                        wm, kidPosition, containerSize, 0);
 
       nsTableFrame::InvalidateTableFrame(kidFrame, kidRect, kidVisualOverflow,
                                          firstReflow);
 
       iCoord += desiredSize.ISize(wm);
     } else {
       if (iCoord != origKidNormalPosition.I(wm)) {
         // Invalidate the old position
@@ -1153,18 +1147,18 @@ nsTableRowFrame::ReflowCellFrame(nsPresC
                                  bool                     aIsTopOfPage,
                                  nsTableCellFrame*        aCellFrame,
                                  nscoord                  aAvailableBSize,
                                  nsReflowStatus&          aStatus)
 {
   WritingMode wm = aReflowState.GetWritingMode();
 
   // Reflow the cell frame with the specified height. Use the existing width
-  nscoord containerWidth = aCellFrame->GetSize().width;
-  LogicalRect cellRect = aCellFrame->GetLogicalRect(wm, containerWidth);
+  nsSize containerSize = aCellFrame->GetSize();
+  LogicalRect cellRect = aCellFrame->GetLogicalRect(wm, containerSize);
   nsRect cellVisualOverflow = aCellFrame->GetVisualOverflowRect();
 
   LogicalSize cellSize = cellRect.Size(wm);
   LogicalSize availSize(wm, cellRect.ISize(wm), aAvailableBSize);
   bool borderCollapse = GetTableFrame()->IsBorderCollapse();
   NS_ASSERTION(aCellFrame->GetWritingMode() == wm,
                "expected consistent writing-mode within table");
   nsTableCellReflowState
@@ -1187,17 +1181,17 @@ nsTableRowFrame::ReflowCellFrame(nsPresC
   // Note: BlockDirAlignChild can affect the overflow rect.
   // XXX What happens if this cell has 'vertical-align: baseline' ?
   // XXX Why is it assumed that the cell's ascent hasn't changed ?
   if (fullyComplete) {
     aCellFrame->BlockDirAlignChild(wm, mMaxCellAscent);
   }
 
   nsTableFrame::InvalidateTableFrame(aCellFrame,
-                                     cellRect.GetPhysicalRect(wm, containerWidth),
+                                     cellRect.GetPhysicalRect(wm, containerSize),
                                      cellVisualOverflow,
                                      aCellFrame->
                                        HasAnyStateBits(NS_FRAME_FIRST_REFLOW));
 
   aCellFrame->DidReflow(aPresContext, nullptr, nsDidReflowStatus::FINISHED);
 
   return desiredSize.BSize(wm);
 }
@@ -1218,46 +1212,46 @@ nsTableRowFrame::CollapseRowIfNecessary(
 
   if (aRowOffset != 0) {
     // We're moving, so invalidate our old position
     InvalidateFrameSubtree();
   }
 
   WritingMode wm = GetWritingMode();
 
-  nscoord parentWidth = GetParent()->GetRect().width;
-  LogicalRect rowRect = GetLogicalRect(wm, parentWidth);
+  nsSize parentSize = GetParent()->GetSize();
+  LogicalRect rowRect = GetLogicalRect(wm, parentSize);
   nsRect oldRect = mRect;
   nsRect oldVisualOverflow = GetVisualOverflowRect();
 
   rowRect.BStart(wm) -= aRowOffset;
   rowRect.ISize(wm)  = aISize;
   nsOverflowAreas overflow;
   nscoord shift = 0;
-  nscoord containerWidth = mRect.width;
+  nsSize containerSize = mRect.Size();
 
   if (aCollapseGroup || collapseRow) {
     aDidCollapse = true;
     shift = rowRect.BSize(wm);
     nsTableCellFrame* cellFrame = GetFirstCell();
     if (cellFrame) {
       int32_t rowIndex;
       cellFrame->GetRowIndex(rowIndex);
       shift += tableFrame->GetRowSpacing(rowIndex);
       while (cellFrame) {
-        LogicalRect cRect = cellFrame->GetLogicalRect(wm, containerWidth);
+        LogicalRect cRect = cellFrame->GetLogicalRect(wm, containerSize);
         // If aRowOffset != 0, there's no point in invalidating the cells, since
         // we've already invalidated our overflow area.  Note that we _do_ still
         // need to invalidate if our row is not moving, because the cell might
         // span out of this row, so invalidating our row rect won't do enough.
         if (aRowOffset == 0) {
           InvalidateFrame();
         }
         cRect.BSize(wm) = 0;
-        cellFrame->SetRect(wm, cRect, containerWidth);
+        cellFrame->SetRect(wm, cRect, containerSize);
         cellFrame = cellFrame->GetNextCell();
       }
     } else {
       shift += tableFrame->GetRowSpacing(GetRowIndex());
     }
     rowRect.BSize(wm) = 0;
   }
   else { // row is not collapsed
@@ -1321,58 +1315,58 @@ nsTableRowFrame::CollapseRowIfNecessary(
         int32_t actualRowSpan = tableFrame->GetEffectiveRowSpan(*cellFrame);
         nsTableRowFrame* rowFrame = GetNextRow();
         for (actualRowSpan--; actualRowSpan > 0 && rowFrame; actualRowSpan--) {
           const nsStyleVisibility* nextRowVis = rowFrame->StyleVisibility();
           bool collapseNextRow = (NS_STYLE_VISIBILITY_COLLAPSE ==
                                     nextRowVis->mVisible);
           if (!collapseNextRow) {
             LogicalRect nextRect = rowFrame->GetLogicalRect(wm,
-                                                            containerWidth);
+                                                            containerSize);
             cRect.BSize(wm) +=
               nextRect.BSize(wm) +
               tableFrame->GetRowSpacing(rowFrame->GetRowIndex());
           }
           rowFrame = rowFrame->GetNextRow();
         }
 
         nsRect oldCellRect = cellFrame->GetRect();
         LogicalPoint oldCellNormalPos =
-          cellFrame->GetLogicalNormalPosition(wm, containerWidth);
+          cellFrame->GetLogicalNormalPosition(wm, containerSize);
 
         nsRect oldCellVisualOverflow = cellFrame->GetVisualOverflowRect();
 
         if (aRowOffset == 0 && cRect.Origin(wm) != oldCellNormalPos) {
           // We're moving the cell.  Invalidate the old overflow area
           cellFrame->InvalidateFrameSubtree();
         }
 
         cellFrame->MovePositionBy(wm, cRect.Origin(wm) - oldCellNormalPos);
         cellFrame->SetSize(wm, cRect.Size(wm));
 
         // XXXbz This looks completely bogus in the cases when we didn't
         // collapse the cell!
         LogicalRect cellBounds(wm, 0, 0, cRect.ISize(wm), cRect.BSize(wm));
         nsRect cellPhysicalBounds =
-          cellBounds.GetPhysicalRect(wm, containerWidth);
+          cellBounds.GetPhysicalRect(wm, containerSize);
         nsOverflowAreas cellOverflow(cellPhysicalBounds, cellPhysicalBounds);
         cellFrame->FinishAndStoreOverflow(cellOverflow,
                                           cRect.Size(wm).GetPhysicalSize(wm));
         nsTableFrame::RePositionViews(cellFrame);
         ConsiderChildOverflow(overflow, cellFrame);
 
         if (aRowOffset == 0) {
           nsTableFrame::InvalidateTableFrame(cellFrame, oldCellRect,
                                              oldCellVisualOverflow, false);
         }
       }
     }
   }
 
-  SetRect(wm, rowRect, containerWidth);
+  SetRect(wm, rowRect, containerSize);
   overflow.UnionAllWith(nsRect(0, 0, rowRect.Width(wm), rowRect.Height(wm)));
   FinishAndStoreOverflow(overflow, rowRect.Size(wm).GetPhysicalSize(wm));
 
   nsTableFrame::RePositionViews(this);
   nsTableFrame::InvalidateTableFrame(this, oldRect, oldVisualOverflow, false);
   return shift;
 }
 
--- a/layout/tables/nsTableRowGroupFrame.cpp
+++ b/layout/tables/nsTableRowGroupFrame.cpp
@@ -256,26 +256,26 @@ nsTableRowGroupFrame::GetLogicalSkipSide
 
 // Position and size aKidFrame and update our reflow state.
 void
 nsTableRowGroupFrame::PlaceChild(nsPresContext*         aPresContext,
                                  nsRowGroupReflowState& aReflowState,
                                  nsIFrame*              aKidFrame,
                                  WritingMode            aWM,
                                  const LogicalPoint&    aKidPosition,
-                                 nscoord                aContainerWidth,
+                                 const nsSize&          aContainerSize,
                                  nsHTMLReflowMetrics&   aDesiredSize,
                                  const nsRect&          aOriginalKidRect,
                                  const nsRect&          aOriginalKidVisualOverflow)
 {
   bool isFirstReflow = aKidFrame->HasAnyStateBits(NS_FRAME_FIRST_REFLOW);
 
   // Place and size the child
   FinishReflowChild(aKidFrame, aPresContext, aDesiredSize, nullptr,
-                    aWM, aKidPosition, aContainerWidth, 0);
+                    aWM, aKidPosition, aContainerSize, 0);
 
   nsTableFrame::InvalidateTableFrame(aKidFrame, aOriginalKidRect,
                                      aOriginalKidVisualOverflow, isFirstReflow);
 
   // Adjust the running block-offset
   aReflowState.bCoord += aDesiredSize.BSize(aWM);
 
   // If our block-size is constrained then update the available bsize
@@ -338,21 +338,21 @@ nsTableRowGroupFrame::ReflowChildren(nsP
   bool isPaginated = aPresContext->IsPaginated() &&
                      NS_UNCONSTRAINEDSIZE != aReflowState.availSize.BSize(wm);
 
   bool haveRow = false;
   bool reflowAllKids = aReflowState.reflowState.ShouldReflowAllKids() ||
                          tableFrame->IsGeometryDirty();
 
   // in vertical-rl mode, we always need the row bsizes in order to
-  // get the necessary containerWidth for placing our kids
+  // get the necessary containerSize for placing our kids
   bool needToCalcRowBSizes = reflowAllKids || wm.IsVerticalRL();
 
-  nscoord containerWidth =
-    aReflowState.reflowState.ComputedSizeAsContainerIfConstrained().width;
+  nsSize containerSize =
+    aReflowState.reflowState.ComputedSizeAsContainerIfConstrained();
 
   nsIFrame *prevKidFrame = nullptr;
   for (nsIFrame* kidFrame = mFrames.FirstChild(); kidFrame;
        prevKidFrame = kidFrame, kidFrame = kidFrame->GetNextSibling()) {
     nsTableRowFrame *rowFrame = do_QueryFrame(kidFrame);
     if (!rowFrame) {
       // XXXldb nsCSSFrameConstructor needs to enforce this!
       NS_NOTREACHED("yikes, a non-row child");
@@ -362,17 +362,17 @@ nsTableRowGroupFrame::ReflowChildren(nsP
     haveRow = true;
 
     // Reflow the row frame
     if (reflowAllKids ||
         NS_SUBTREE_DIRTY(kidFrame) ||
         (aReflowState.reflowState.mFlags.mSpecialBSizeReflow &&
          (isPaginated ||
           kidFrame->HasAnyStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE)))) {
-      LogicalRect oldKidRect = kidFrame->GetLogicalRect(wm, containerWidth);
+      LogicalRect oldKidRect = kidFrame->GetLogicalRect(wm, containerSize);
       nsRect oldKidVisualOverflow = kidFrame->GetVisualOverflowRect();
 
       // XXXldb We used to only pass aDesiredSize.mFlags through for the
       // incremental reflow codepath.
       nsHTMLReflowMetrics desiredSize(aReflowState.reflowState,
                                       aDesiredSize.mFlags);
       desiredSize.ClearSize();
 
@@ -397,23 +397,23 @@ nsTableRowGroupFrame::ReflowChildren(nsP
                    "previous sibling...");
       // If prev row has nonzero YMost, then we can't be at the top of the page
       if (prevKidFrame && prevKidFrame->GetNormalRect().YMost() > 0) {
         kidReflowState.mFlags.mIsTopOfPage = false;
       }
 
       LogicalPoint kidPosition(wm, 0, aReflowState.bCoord);
       ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState,
-                  wm, kidPosition, containerWidth, 0, aStatus);
-      kidReflowState.ApplyRelativePositioning(&kidPosition, containerWidth);
+                  wm, kidPosition, containerSize, 0, aStatus);
+      kidReflowState.ApplyRelativePositioning(&kidPosition, containerSize);
 
       // Place the child
       PlaceChild(aPresContext, aReflowState, kidFrame,
-                 wm, kidPosition, containerWidth,
-                 desiredSize, oldKidRect.GetPhysicalRect(wm, containerWidth),
+                 wm, kidPosition, containerSize,
+                 desiredSize, oldKidRect.GetPhysicalRect(wm, containerSize),
                  oldKidVisualOverflow);
       aReflowState.bCoord += cellSpacingB;
 
       if (!reflowAllKids) {
         if (IsSimpleRowFrame(aReflowState.tableFrame, rowFrame)) {
           // Inform the row of its new bsize.
           rowFrame->DidResize();
           // the overflow area may have changed inflate the overflow area
@@ -547,20 +547,20 @@ nsTableRowGroupFrame::CalculateRowBSizes
 
   if (!startRowFrame) {
     return;
   }
 
   // The current row group block-size is the block-origin of the 1st row
   // we are about to calculate a block-size for.
   WritingMode wm = aReflowState.GetWritingMode();
-  nscoord containerWidth = 0; // actual value is unimportant as we're initially
-                              // computing sizes, not physical positions
+  nsSize containerSize; // actual value is unimportant as we're initially
+                        // computing sizes, not physical positions
   nscoord startRowGroupBSize =
-    startRowFrame->GetLogicalNormalPosition(wm, containerWidth).B(wm);
+    startRowFrame->GetLogicalNormalPosition(wm, containerSize).B(wm);
 
   int32_t numRows = GetRowCount() - (startRowFrame->GetRowIndex() - GetStartRowIndex());
   // Collect the current bsize of each row.
   if (numRows <= 0)
     return;
 
   nsTArray<RowInfo> rowInfo;
   if (!rowInfo.AppendElements(numRows)) {
@@ -776,30 +776,30 @@ nsTableRowGroupFrame::CalculateRowBSizes
           }
         }
       }
     }
     rowGroupBSize = aReflowState.ComputedBSize();
   }
 
   if (wm.IsVertical()) {
-    // we need the correct containerWidth below for block positioning in
+    // we need the correct containerSize below for block positioning in
     // vertical-rl writing mode
-    containerWidth = rowGroupBSize;
+    containerSize.width = rowGroupBSize;
   }
 
   nscoord bOrigin = startRowGroupBSize;
   // update the rows with their (potentially) new bsizes
   for (rowFrame = startRowFrame, rowIndex = 0; rowFrame;
        rowFrame = rowFrame->GetNextRow(), rowIndex++) {
     nsRect rowBounds = rowFrame->GetRect();
     LogicalSize rowBoundsSize(wm, rowBounds.Size());
     nsRect rowVisualOverflow = rowFrame->GetVisualOverflowRect();
     nscoord deltaB =
-      bOrigin - rowFrame->GetLogicalNormalPosition(wm, containerWidth).B(wm);
+      bOrigin - rowFrame->GetLogicalNormalPosition(wm, containerSize).B(wm);
 
     nscoord rowBSize = (rowInfo[rowIndex].bSize > 0) ? rowInfo[rowIndex].bSize : 0;
 
     if (deltaB != 0 || (rowBSize != rowBoundsSize.BSize(wm))) {
       // Resize/move the row to its final size and position
       if (deltaB != 0) {
         rowFrame->InvalidateFrameSubtree();
       }
@@ -830,17 +830,17 @@ nsTableRowGroupFrame::CalculateRowBSizes
 }
 
 nscoord
 nsTableRowGroupFrame::CollapseRowGroupIfNecessary(nscoord aBTotalOffset,
                                                   nscoord aISize,
                                                   WritingMode aWM)
 {
   nsTableFrame* tableFrame = GetTableFrame();
-  nscoord containerWidth = tableFrame->GetRect().width;
+  nsSize containerSize = tableFrame->GetSize();
   const nsStyleVisibility* groupVis = StyleVisibility();
   bool collapseGroup = (NS_STYLE_VISIBILITY_COLLAPSE == groupVis->mVisible);
   if (collapseGroup) {
     tableFrame->SetNeedToCollapse(true);
   }
 
   nsOverflowAreas overflow;
 
@@ -850,17 +850,17 @@ nsTableRowGroupFrame::CollapseRowGroupIf
   while (rowFrame) {
     bGroupOffset += rowFrame->CollapseRowIfNecessary(bGroupOffset,
                                                      aISize, collapseGroup,
                                                      didCollapse);
     ConsiderChildOverflow(overflow, rowFrame);
     rowFrame = rowFrame->GetNextRow();
   }
 
-  LogicalRect groupRect = GetLogicalRect(aWM, containerWidth);
+  LogicalRect groupRect = GetLogicalRect(aWM, containerSize);
   nsRect oldGroupRect = GetRect();
   nsRect oldGroupVisualOverflow = GetVisualOverflowRect();
 
   groupRect.BSize(aWM) -= bGroupOffset;
   if (didCollapse) {
     // add back the cellspacing between rowgroups
     groupRect.BSize(aWM) += tableFrame->GetRowSpacing(GetStartRowIndex() +
                                                       GetRowCount());
@@ -868,41 +868,45 @@ nsTableRowGroupFrame::CollapseRowGroupIf
 
   groupRect.BStart(aWM) -= aBTotalOffset;
   groupRect.ISize(aWM) = aISize;
 
   if (aBTotalOffset != 0) {
     InvalidateFrameSubtree();
   }
 
-  SetRect(aWM, groupRect, containerWidth);
+  SetRect(aWM, groupRect, containerSize);
   overflow.UnionAllWith(nsRect(0, 0, groupRect.Width(aWM),
                                groupRect.Height(aWM)));
   FinishAndStoreOverflow(overflow, groupRect.Size(aWM).GetPhysicalSize(aWM));
   nsTableFrame::RePositionViews(this);
   nsTableFrame::InvalidateTableFrame(this, oldGroupRect, oldGroupVisualOverflow,
                                      false);
 
   return bGroupOffset;
 }
 
 // Move a child that was skipped during a reflow.
 void
 nsTableRowGroupFrame::SlideChild(nsRowGroupReflowState& aReflowState,
                                  nsIFrame*              aKidFrame)
 {
-  // Move the frame if we need to
+  // Move the frame if we need to.
   WritingMode wm = aReflowState.reflowState.GetWritingMode();
-  LogicalPoint oldPosition = aKidFrame->GetLogicalNormalPosition(wm, 0);
+  const nsSize containerSize =
+    aReflowState.reflowState.ComputedSizeAsContainerIfConstrained();
+  LogicalPoint oldPosition =
+    aKidFrame->GetLogicalNormalPosition(wm, containerSize);
   LogicalPoint newPosition = oldPosition;
   newPosition.B(wm) = aReflowState.bCoord;
   if (oldPosition.B(wm) != newPosition.B(wm)) {
     aKidFrame->InvalidateFrameSubtree();
-    aReflowState.reflowState.ApplyRelativePositioning(&newPosition, 0);
-    aKidFrame->SetPosition(wm, newPosition, 0);
+    aReflowState.reflowState.ApplyRelativePositioning(&newPosition,
+                                                      containerSize);
+    aKidFrame->SetPosition(wm, newPosition, containerSize);
     nsTableFrame::RePositionViews(aKidFrame);
     aKidFrame->InvalidateFrameSubtree();
   }
 }
 
 // Create a continuing frame, add it to the child list, and then push it
 // and the frames that follow
 void
@@ -1757,18 +1761,18 @@ nsTableRowGroupFrame::FindFrameAt(int32_
                                   nsIFrame** aFrameFound,
                                   bool*    aPosIsBeforeFirstFrame,
                                   bool*    aPosIsAfterLastFrame)
 {
   nsTableFrame* table = GetTableFrame();
   nsTableCellMap* cellMap = table->GetCellMap();
 
   WritingMode wm = table->GetWritingMode();
-  nscoord cw = table->GetRect().width;
-  LogicalPoint pos(wm, aPos, cw);
+  nsSize containerSize = table->GetSize();
+  LogicalPoint pos(wm, aPos, containerSize);
 
   *aFrameFound = nullptr;
   *aPosIsBeforeFirstFrame = true;
   *aPosIsAfterLastFrame = false;
 
   aLineNumber += GetStartRowIndex();
   int32_t numCells = cellMap->GetNumCellsOriginatingInRow(aLineNumber);
   if (numCells == 0) {
@@ -1788,31 +1792,33 @@ nsTableRowGroupFrame::FindFrameAt(int32_
   bool isRTL = (NS_STYLE_DIRECTION_RTL ==
                   table->StyleVisibility()->mDirection);
 
   nsIFrame* closestFromStart = nullptr;
   nsIFrame* closestFromEnd = nullptr;
   int32_t n = numCells;
   nsIFrame* firstFrame = frame;
   while (n--) {
-    LogicalRect rect = frame->GetLogicalRect(wm, cw);
+    LogicalRect rect = frame->GetLogicalRect(wm, containerSize);
     if (rect.ISize(wm) > 0) {
       // If pos.I() is inside this frame - this is it
       if (rect.IStart(wm) <= pos.I(wm) && rect.IEnd(wm) > pos.I(wm)) {
         closestFromStart = closestFromEnd = frame;
         break;
       }
       if (rect.IStart(wm) < pos.I(wm)) {
         if (!closestFromStart ||
-            rect.IEnd(wm) > closestFromStart->GetLogicalRect(wm, cw).IEnd(wm))
+            rect.IEnd(wm) > closestFromStart->
+                              GetLogicalRect(wm, containerSize).IEnd(wm))
           closestFromStart = frame;
       }
       else {
         if (!closestFromEnd ||
-            rect.IStart(wm) < closestFromEnd->GetLogicalRect(wm, cw).IStart(wm))
+            rect.IStart(wm) < closestFromEnd->
+                                GetLogicalRect(wm, containerSize).IStart(wm))
           closestFromEnd = frame;
       }
     }
     frame = frame->GetNextSibling();
   }
   if (!closestFromStart && !closestFromEnd) {
     // All frames were zero-width. Just take the first one.
     closestFromStart = closestFromEnd = firstFrame;
@@ -1824,19 +1830,21 @@ nsTableRowGroupFrame::FindFrameAt(int32_
   }
   else if (!closestFromStart) {
     *aFrameFound = closestFromEnd;
   }
   else if (!closestFromEnd) {
     *aFrameFound = closestFromStart;
   }
   else { // we're between two frames
-    nscoord delta = closestFromEnd->GetLogicalRect(wm, cw).IStart(wm) -
-                    closestFromStart->GetLogicalRect(wm, cw).IEnd(wm);
-    if (pos.I(wm) < closestFromStart->GetLogicalRect(wm, cw).IEnd(wm) + delta/2) {
+    nscoord delta =
+      closestFromEnd->GetLogicalRect(wm, containerSize).IStart(wm) -
+      closestFromStart->GetLogicalRect(wm, containerSize).IEnd(wm);
+    if (pos.I(wm) < closestFromStart->
+                      GetLogicalRect(wm, containerSize).IEnd(wm) + delta/2) {
       *aFrameFound = closestFromStart;
     } else {
       *aFrameFound = closestFromEnd;
     }
   }
   return NS_OK;
 }
 
--- a/layout/tables/nsTableRowGroupFrame.h
+++ b/layout/tables/nsTableRowGroupFrame.h
@@ -350,17 +350,17 @@ protected:
 
   virtual LogicalSides GetLogicalSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const override;
 
   void PlaceChild(nsPresContext*         aPresContext,
                   nsRowGroupReflowState& aReflowState,
                   nsIFrame*              aKidFrame,
                   mozilla::WritingMode   aWM,
                   const mozilla::LogicalPoint& aKidPosition,
-                  nscoord                aContainerWidth,
+                  const nsSize&          aContainerSize,
                   nsHTMLReflowMetrics&   aDesiredSize,
                   const nsRect&          aOriginalKidRect,
                   const nsRect&          aOriginalKidVisualOverflow);
 
   void CalculateRowBSizes(nsPresContext*           aPresContext,
                           nsHTMLReflowMetrics&     aDesiredSize,
                           const nsHTMLReflowState& aReflowState);
 
--- a/layout/xul/nsTextBoxFrame.cpp
+++ b/layout/xul/nsTextBoxFrame.cpp
@@ -960,25 +960,25 @@ nsTextBoxFrame::DoLayout(nsBoxLayoutStat
     nsRefPtr<nsFontMetrics> fontMet;
     nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet));
     nsBoundingMetrics metrics = 
       fontMet->GetInkBoundsForVisualOverflow(mCroppedTitle.get(),
                                              mCroppedTitle.Length(),
                                              aBoxLayoutState.GetRenderingContext());
 
     WritingMode wm = GetWritingMode();
-    LogicalRect tr(wm, textRect, GetSize().width);
+    LogicalRect tr(wm, textRect, GetSize());
 
     tr.IStart(wm) -= metrics.leftBearing;
     tr.ISize(wm) = metrics.width;
     // In DrawText() we always draw with the baseline at MaxAscent() (relative to mTextDrawRect), 
     tr.BStart(wm) += fontMet->MaxAscent() - metrics.ascent;
     tr.BSize(wm) = metrics.ascent + metrics.descent;
 
-    textRect = tr.GetPhysicalRect(wm, GetSize().width);
+    textRect = tr.GetPhysicalRect(wm, GetSize());
 
     // Our scrollable overflow is our bounds; our visual overflow may
     // extend beyond that.
     nsRect visualBounds;
     visualBounds.UnionRect(scrollBounds, textRect);
     nsOverflowAreas overflow(visualBounds, scrollBounds);
 
     if (textStyle->mTextShadow) {
@@ -1091,17 +1091,17 @@ nsTextBoxFrame::CalcDrawRect(nsRendering
     } else if (textStyle->mTextAlign == NS_STYLE_TEXT_ALIGN_END ||
              (textStyle->mTextAlign == NS_STYLE_TEXT_ALIGN_LEFT &&
               !wm.IsBidiLTR()) ||
              (textStyle->mTextAlign == NS_STYLE_TEXT_ALIGN_RIGHT &&
               wm.IsBidiLTR())) {
       textRect.IStart(wm) += (outerISize - textRect.ISize(wm));
     }
 
-    mTextDrawRect = textRect.GetPhysicalRect(wm, GetSize().width);
+    mTextDrawRect = textRect.GetPhysicalRect(wm, GetSize());
 }
 
 /**
  * Ok return our dimensions
  */
 nsSize
 nsTextBoxFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState)
 {