Bug 939901 part 4: Make the flexbox reflow code loop over the FlexLines, rather than just working with one FlexLine. r=mats
authorDaniel Holbert <dholbert@cs.stanford.edu>
Thu, 05 Dec 2013 10:57:51 -0800
changeset 174724 79a76a1dce4ec13dcd45f6b63dfcb08f4ec74140
parent 174723 7ffb0aa5121f477c712b18387c9daeaefc096b69
child 174725 47901ad6d20b5183a62ee9d7df2dce4b4b69df78
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmats
bugs939901
milestone28.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 939901 part 4: Make the flexbox reflow code loop over the FlexLines, rather than just working with one FlexLine. r=mats
layout/generic/nsFlexContainerFrame.cpp
layout/generic/nsFlexContainerFrame.h
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -2098,24 +2098,38 @@ nsFlexContainerFrame::GetMainSizeFromRef
     // Horizontal case is easy -- our main size is our computed width
     // (which is already resolved).
     return aReflowState.ComputedWidth();
   }
 
   return GetEffectiveComputedHeight(aReflowState);
 }
 
+// Returns the largest outer hypothetical main-size of any line in |aLines|.
+// (i.e. the hypothetical main-size of the largest line)
+static nscoord
+GetLargestLineMainSize(const nsTArray<FlexLine>& aLines)
+{
+  nscoord largestLineOuterSize = 0;
+  for (uint32_t lineIdx = 0; lineIdx < aLines.Length(); lineIdx++) {
+    largestLineOuterSize =
+      std::max(largestLineOuterSize,
+               aLines[lineIdx].GetTotalOuterHypotheticalMainSize());
+  }
+  return largestLineOuterSize;
+}
+
 // Returns the content-box main-size of our flex container, based on the
 // available height (if appropriate) and the main-sizes of the flex items.
 static nscoord
 ClampFlexContainerMainSize(const nsHTMLReflowState& aReflowState,
                            const FlexboxAxisTracker& aAxisTracker,
                            nscoord aUnclampedMainSize,
                            nscoord aAvailableHeightForContent,
-                           const FlexLine& aLine,
+                           const nsTArray<FlexLine>& aLines,
                            nsReflowStatus& aStatus)
 {
   if (IsAxisHorizontal(aAxisTracker.GetMainAxis())) {
     // Horizontal case is easy -- our main size should already be resolved
     // before we get a call to Reflow. We don't have to worry about doing
     // page-breaking or shrinkwrapping in the horizontal axis.
     return aUnclampedMainSize;
   }
@@ -2134,39 +2148,50 @@ ClampFlexContainerMainSize(const nsHTMLR
     // Fragmenting *and* our fixed height is too tall for available height:
     // Mark incomplete so we get a next-in-flow, and take up all of the
     // available height (or the amount of height required by our children, if
     // that's larger; but of course not more than our own computed height).
     // XXXdholbert For now, we don't support pushing children to our next
     // continuation or splitting children, so "amount of height required by
     // our children" is just the sum of our children's heights.
     NS_FRAME_SET_INCOMPLETE(aStatus);
-    nscoord sumOfChildHeights = aLine.GetTotalOuterHypotheticalMainSize();
-    if (sumOfChildHeights <= aAvailableHeightForContent) {
+    nscoord largestLineOuterSize = GetLargestLineMainSize(aLines);
+
+    if (largestLineOuterSize <= aAvailableHeightForContent) {
       return aAvailableHeightForContent;
     }
-    return std::min(aUnclampedMainSize, sumOfChildHeights);
+    return std::min(aUnclampedMainSize, largestLineOuterSize);
   }
 
   // Vertical case, with auto-height:
-  // Resolve auto-height to the sum of our items' hypothetical outer main
-  // sizes (their outer heights), clamped to our computed min/max main-size
-  // properties (min-height & max-height).
+  // Resolve auto-height to the largest FlexLine-length, clamped to our
+  // computed min/max main-size properties (min-height & max-height).
   // XXXdholbert Handle constrained-aAvailableHeightForContent case here.
-  nscoord sumOfChildHeights = aLine.GetTotalOuterHypotheticalMainSize();
-  return NS_CSS_MINMAX(sumOfChildHeights,
+  nscoord largestLineOuterSize = GetLargestLineMainSize(aLines);
+  return NS_CSS_MINMAX(largestLineOuterSize,
                        aReflowState.mComputedMinHeight,
                        aReflowState.mComputedMaxHeight);
 }
 
+// Returns the sum of the cross sizes of all the lines in |aLines|
+static nscoord
+SumLineCrossSizes(const nsTArray<FlexLine>& aLines)
+{
+  nscoord sum = 0;
+  for (uint32_t lineIdx = 0; lineIdx < aLines.Length(); lineIdx++) {
+    sum += aLines[lineIdx].GetLineCrossSize();
+  }
+  return sum;
+}
+
 nscoord
 nsFlexContainerFrame::ComputeFlexContainerCrossSize(
   const nsHTMLReflowState& aReflowState,
   const FlexboxAxisTracker& aAxisTracker,
-  nscoord aLineCrossSize,
+  const nsTArray<FlexLine>& aLines,
   nscoord aAvailableHeightForContent,
   bool* aIsDefinite,
   nsReflowStatus& aStatus)
 {
   MOZ_ASSERT(aIsDefinite, "outparam pointer must be non-null"); 
 
   if (IsAxisHorizontal(aAxisTracker.GetCrossAxis())) {
     // Cross axis is horizontal: our cross size is our computed width
@@ -2191,27 +2216,28 @@ nsFlexContainerFrame::ComputeFlexContain
     // Fragmenting *and* our fixed height is too tall for available height:
     // Mark incomplete so we get a next-in-flow, and take up all of the
     // available height (or the amount of height required by our children, if
     // that's larger; but of course not more than our own computed height).
     // XXXdholbert For now, we don't support pushing children to our next
     // continuation or splitting children, so "amount of height required by
     // our children" is just our line-height.
     NS_FRAME_SET_INCOMPLETE(aStatus);
-    if (aLineCrossSize <= aAvailableHeightForContent) {
+    nscoord sumOfLineCrossSizes = SumLineCrossSizes(aLines);
+    if (sumOfLineCrossSizes <= aAvailableHeightForContent) {
       return aAvailableHeightForContent;
     }
-    return std::min(effectiveComputedHeight, aLineCrossSize);
+    return std::min(effectiveComputedHeight, sumOfLineCrossSizes);
   }
 
   // Cross axis is vertical and we have auto-height: shrink-wrap our line(s),
   // subject to our min-size / max-size constraints in that (vertical) axis.
   // XXXdholbert Handle constrained-aAvailableHeightForContent case here.
   *aIsDefinite = false;
-  return NS_CSS_MINMAX(aLineCrossSize,
+  return NS_CSS_MINMAX(SumLineCrossSizes(aLines),
                        aReflowState.mComputedMinHeight,
                        aReflowState.mComputedMaxHeight);
 }
 
 void
 FlexLine::PositionItemsInMainAxis(uint8_t aJustifyContent,
                                   nscoord aContentBoxMainSize,
                                   const FlexboxAxisTracker& aAxisTracker)
@@ -2445,217 +2471,231 @@ nsFlexContainerFrame::Reflow(nsPresConte
 
   // Generate an array of our flex items (already sorted), in a FlexLine.
   nsAutoTArray<FlexLine, 1> lines;
   nsresult rv = GenerateFlexLines(aPresContext, aReflowState,
                                   contentBoxMainSize, availableHeightForContent,
                                   axisTracker, lines);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  FlexLine& line = lines[0]; // XXXdholbert Temporary; a later patch will
-                             // rewrite the relevant code to loop over |lines|
-                             // where appropriate.
   contentBoxMainSize =
     ClampFlexContainerMainSize(aReflowState, axisTracker,
                                contentBoxMainSize, availableHeightForContent,
-                               line, aStatus);
-
-  line.ResolveFlexibleLengths(contentBoxMainSize);
+                               lines, aStatus);
+
+  for (uint32_t i = 0; i < lines.Length(); i++) {
+    lines[i].ResolveFlexibleLengths(contentBoxMainSize);
+  }
 
   // Cross Size Determination - Flexbox spec section 9.4
   // ===================================================
   // Calculate the hypothetical cross size of each item:
-  for (uint32_t i = 0; i < line.mItems.Length(); ++i) {
-    FlexItem& curItem = line.mItems[i];
-
-    // (If the item's already been stretched, then it already knows its
-    // cross size.  Don't bother trying to recalculate it.)
-    if (!curItem.IsStretched()) {
-      nsHTMLReflowState childReflowState(aPresContext, aReflowState,
-                                         curItem.Frame(),
-                                         nsSize(aReflowState.ComputedWidth(),
-                                                NS_UNCONSTRAINEDSIZE));
-      // Override computed main-size
-      if (IsAxisHorizontal(axisTracker.GetMainAxis())) {
-        childReflowState.SetComputedWidth(curItem.GetMainSize());
-      } else {
-        childReflowState.SetComputedHeight(curItem.GetMainSize());
+  for (uint32_t lineIdx = 0; lineIdx < lines.Length(); ++lineIdx) {
+    FlexLine& line = lines[lineIdx];
+    for (uint32_t i = 0; i < line.mItems.Length(); ++i) {
+      FlexItem& curItem = line.mItems[i];
+
+      // (If the item's already been stretched, then it already knows its
+      // cross size.  Don't bother trying to recalculate it.)
+      if (!curItem.IsStretched()) {
+        nsHTMLReflowState childReflowState(aPresContext, aReflowState,
+                                           curItem.Frame(),
+                                           nsSize(aReflowState.ComputedWidth(),
+                                                  NS_UNCONSTRAINEDSIZE));
+        // Override computed main-size
+        if (IsAxisHorizontal(axisTracker.GetMainAxis())) {
+          childReflowState.SetComputedWidth(curItem.GetMainSize());
+        } else {
+          childReflowState.SetComputedHeight(curItem.GetMainSize());
+        }
+
+        nsresult rv = SizeItemInCrossAxis(aPresContext, axisTracker,
+                                          childReflowState, curItem);
+        NS_ENSURE_SUCCESS(rv, rv);
       }
-
-      nsresult rv = SizeItemInCrossAxis(aPresContext, axisTracker,
-                                        childReflowState, curItem);
-      NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
   // Calculate the cross size and (if necessary) baseline-alignment position
-  // for our (single) flex line:
-  line.ComputeCrossSizeAndBaseline(axisTracker);
+  // for each of our flex lines:
+  for (uint32_t lineIdx = 0; lineIdx < lines.Length(); ++lineIdx) {
+    lines[lineIdx].ComputeCrossSizeAndBaseline(axisTracker);
+  }
 
   // Set up state for cross-axis alignment, at a high level (outside the
   // scope of a particular flex line)
   CrossAxisPositionTracker
     crossAxisPosnTracker(this, axisTracker, aReflowState);
 
   // XXXdholbert Once we've got multi-line flexbox support: here, after we've
   // computed the cross size of all lines, we need to check if if
   // 'align-content' is 'stretch' -- if it is, we need to give each line an
   // additional share of our flex container's desired cross-size. (if it's
   // not NS_AUTOHEIGHT and there's any cross-size left over to distribute)
   bool isCrossSizeDefinite;
   const nscoord contentBoxCrossSize =
     ComputeFlexContainerCrossSize(aReflowState, axisTracker,
-                                  line.GetLineCrossSize(), // XXXdholbert this should take |lines|
+                                  lines,
                                   availableHeightForContent,
                                   &isCrossSizeDefinite, aStatus);
 
   if (isCrossSizeDefinite) {
-    // XXXdholbert When we support multi-line flex containers, we should
-    // distribute any extra space among or between our lines here according
-    // to 'align-content'. For now, we do the single-line special behavior:
-    // "If the flex container has only a single line (even if it's a multi-line
-    // flex container) and has a definite cross size, the cross size of the
-    // flex line is the flex container's inner cross size."
-    line.SetLineCrossSize(contentBoxCrossSize);
+    if (lines.Length() == 1) {
+      // "If the flex container has only a single line (even if it's a multi-line
+      // flex container) and has a definite cross size, the cross size of the
+      // flex line is the flex container's inner cross size."
+      lines[0].SetLineCrossSize(contentBoxCrossSize);
+    } else {
+      // XXXdholbert Distribute contentBoxCrossSize among (or around) lines,
+      // depending on 'align-content' value. (This will be handled in the later
+      // patch about honoring "align-content".)
+    }
   }
 
-  // Set the flex container's baseline, from its baseline-aligned items.
+  // Set the flex container's baseline, from its first line's baseline-aligned items.
   // (This might give us nscoord_MIN if we don't have any baseline-aligned
   // flex items.  That's OK, we'll update it below.)
   nscoord flexContainerAscent =
-    line.GetBaselineOffsetFromCrossStart();
+    lines[0].GetBaselineOffsetFromCrossStart();
   if (flexContainerAscent != nscoord_MIN) {
     // Add top borderpadding, so our ascent is w.r.t. border-box
     flexContainerAscent += aReflowState.mComputedBorderPadding.top;
   }
 
-  // Main-Axis Alignment - Flexbox spec section 9.5
-  // ==============================================
-  line.PositionItemsInMainAxis(aReflowState.mStylePosition->mJustifyContent,
-                               contentBoxMainSize,
-                               axisTracker);
-
-  // Cross-Axis Alignment - Flexbox spec section 9.6
-  // ===============================================
-  line.PositionItemsInCrossAxis(crossAxisPosnTracker.GetPosition(),
-                                axisTracker);
+  for (uint32_t lineIdx = 0; lineIdx < lines.Length(); ++lineIdx) {
+    FlexLine& line = lines[lineIdx];
+
+    // Main-Axis Alignment - Flexbox spec section 9.5
+    // ==============================================
+    line.PositionItemsInMainAxis(aReflowState.mStylePosition->mJustifyContent,
+                                 contentBoxMainSize,
+                                 axisTracker);
+
+    // Cross-Axis Alignment - Flexbox spec section 9.6
+    // ===============================================
+    line.PositionItemsInCrossAxis(crossAxisPosnTracker.GetPosition(),
+                                  axisTracker);
+  }
 
   // Before giving each child a final reflow, calculate the origin of the
   // flex container's content box (with respect to its border-box), so that
   // we can compute our flex item's final positions.
   nsMargin containerBorderPadding(aReflowState.mComputedBorderPadding);
   ApplySkipSides(containerBorderPadding, &aReflowState);
   const nsPoint containerContentBoxOrigin(containerBorderPadding.left,
                                           containerBorderPadding.top);
 
   // FINAL REFLOW: Give each child frame another chance to reflow, now that
   // we know its final size and position.
-  for (uint32_t i = 0; i < line.mItems.Length(); ++i) {
-    FlexItem& curItem = line.mItems[i];
-
-    nsPoint physicalPosn = axisTracker.PhysicalPositionFromLogicalPosition(
-                             curItem.GetMainPosition(),
-                             curItem.GetCrossPosition(),
-                             contentBoxMainSize,
-                             contentBoxCrossSize);
-    // Adjust physicalPosn to be relative to the container's border-box
-    // (i.e. its frame rect), instead of the container's content-box:
-    physicalPosn += containerContentBoxOrigin;
-
-    nsHTMLReflowState childReflowState(aPresContext, aReflowState,
-                                       curItem.Frame(),
-                                       nsSize(aReflowState.ComputedWidth(),
-                                              NS_UNCONSTRAINEDSIZE));
-
-    // Keep track of whether we've overriden the child's computed height
-    // and/or width, so we can set its resize flags accordingly.
-    bool didOverrideComputedWidth = false;
-    bool didOverrideComputedHeight = false;
-
-    // Override computed main-size
-    if (IsAxisHorizontal(axisTracker.GetMainAxis())) {
-      childReflowState.SetComputedWidth(curItem.GetMainSize());
-      didOverrideComputedWidth = true;
-    } else {
-      childReflowState.SetComputedHeight(curItem.GetMainSize());
-      didOverrideComputedHeight = true;
-    }
-
-    // Override reflow state's computed cross-size, for stretched items.
-    if (curItem.IsStretched()) {
-      MOZ_ASSERT(curItem.GetAlignSelf() == NS_STYLE_ALIGN_ITEMS_STRETCH,
-                 "stretched item w/o 'align-self: stretch'?");
-      if (IsAxisHorizontal(axisTracker.GetCrossAxis())) {
-        childReflowState.SetComputedWidth(curItem.GetCrossSize());
+  for (uint32_t lineIdx = 0; lineIdx < lines.Length(); ++lineIdx) {
+    FlexLine& line = lines[lineIdx];
+    for (uint32_t i = 0; i < line.mItems.Length(); ++i) {
+      FlexItem& curItem = line.mItems[i];
+
+      nsPoint physicalPosn = axisTracker.PhysicalPositionFromLogicalPosition(
+                               curItem.GetMainPosition(),
+                               curItem.GetCrossPosition(),
+                               contentBoxMainSize,
+                               contentBoxCrossSize);
+      // Adjust physicalPosn to be relative to the container's border-box
+      // (i.e. its frame rect), instead of the container's content-box:
+      physicalPosn += containerContentBoxOrigin;
+
+      nsHTMLReflowState childReflowState(aPresContext, aReflowState,
+                                         curItem.Frame(),
+                                         nsSize(aReflowState.ComputedWidth(),
+                                                NS_UNCONSTRAINEDSIZE));
+
+      // Keep track of whether we've overriden the child's computed height
+      // and/or width, so we can set its resize flags accordingly.
+      bool didOverrideComputedWidth = false;
+      bool didOverrideComputedHeight = false;
+
+      // Override computed main-size
+      if (IsAxisHorizontal(axisTracker.GetMainAxis())) {
+        childReflowState.SetComputedWidth(curItem.GetMainSize());
         didOverrideComputedWidth = true;
       } else {
-        // If this item's height is stretched, it's a relative height.
-        curItem.Frame()->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT);
-        childReflowState.SetComputedHeight(curItem.GetCrossSize());
+        childReflowState.SetComputedHeight(curItem.GetMainSize());
         didOverrideComputedHeight = true;
       }
-    }
-
-    // XXXdholbert Might need to actually set the correct margins in the
-    // reflow state at some point, so that they can be saved on the frame for
-    // UsedMarginProperty().  Maybe doesn't matter though...?
-
-    // If we're overriding the computed width or height, *and* we had an
-    // earlier "measuring" reflow, then this upcoming reflow needs to be
-    // treated as a resize.
-    if (curItem.HadMeasuringReflow()) {
-      if (didOverrideComputedWidth) {
-        // (This is somewhat redundant, since the reflow state already
-        // sets mHResize whenever our computed width has changed since the
-        // previous reflow. Still, it's nice for symmetry, and it may become
-        // necessary once we support orthogonal flows.)
-        childReflowState.mFlags.mHResize = true;
+
+      // Override reflow state's computed cross-size, for stretched items.
+      if (curItem.IsStretched()) {
+        MOZ_ASSERT(curItem.GetAlignSelf() == NS_STYLE_ALIGN_ITEMS_STRETCH,
+                   "stretched item w/o 'align-self: stretch'?");
+        if (IsAxisHorizontal(axisTracker.GetCrossAxis())) {
+          childReflowState.SetComputedWidth(curItem.GetCrossSize());
+          didOverrideComputedWidth = true;
+        } else {
+          // If this item's height is stretched, it's a relative height.
+          curItem.Frame()->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT);
+          childReflowState.SetComputedHeight(curItem.GetCrossSize());
+          didOverrideComputedHeight = true;
+        }
       }
-      if (didOverrideComputedHeight) {
-        childReflowState.mFlags.mVResize = true;
+
+      // XXXdholbert Might need to actually set the correct margins in the
+      // reflow state at some point, so that they can be saved on the frame for
+      // UsedMarginProperty().  Maybe doesn't matter though...?
+
+      // If we're overriding the computed width or height, *and* we had an
+      // earlier "measuring" reflow, then this upcoming reflow needs to be
+      // treated as a resize.
+      if (curItem.HadMeasuringReflow()) {
+        if (didOverrideComputedWidth) {
+          // (This is somewhat redundant, since the reflow state already
+          // sets mHResize whenever our computed width has changed since the
+          // previous reflow. Still, it's nice for symmetry, and it may become
+          // necessary once we support orthogonal flows.)
+          childReflowState.mFlags.mHResize = true;
+        }
+        if (didOverrideComputedHeight) {
+          childReflowState.mFlags.mVResize = true;
+        }
       }
-    }
-    // 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;
-    nsReflowStatus childReflowStatus;
-    nsresult rv = ReflowChild(curItem.Frame(), aPresContext,
-                              childDesiredSize, childReflowState,
-                              physicalPosn.x, physicalPosn.y,
-                              0, childReflowStatus);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    // 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");
-
-    childReflowState.ApplyRelativePositioning(&physicalPosn);
-
-    rv = FinishReflowChild(curItem.Frame(), aPresContext,
-                           &childReflowState, childDesiredSize,
-                           physicalPosn.x, physicalPosn.y, 0);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    // 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 (i == 0 && flexContainerAscent == nscoord_MIN) {
-      ResolveReflowedChildAscent(curItem.Frame(), childDesiredSize);
-
-      // (We use GetNormalPosition() instead of physicalPosn because we don't
-      // want relative positioning on the child to affect the baseline that we
-      // read from it).
-      flexContainerAscent = curItem.Frame()->GetNormalPosition().y +
-        childDesiredSize.ascent;
+      // 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;
+      nsReflowStatus childReflowStatus;
+      nsresult rv = ReflowChild(curItem.Frame(), aPresContext,
+                                childDesiredSize, childReflowState,
+                                physicalPosn.x, physicalPosn.y,
+                                0, childReflowStatus);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      // 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");
+
+      childReflowState.ApplyRelativePositioning(&physicalPosn);
+
+      rv = FinishReflowChild(curItem.Frame(), aPresContext,
+                             &childReflowState, childDesiredSize,
+                             physicalPosn.x, physicalPosn.y, 0);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      // 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 (lineIdx == 0 && i == 0 && flexContainerAscent == nscoord_MIN) {
+        ResolveReflowedChildAscent(curItem.Frame(), childDesiredSize);
+
+        // (We use GetNormalPosition() instead of physicalPosn because we don't
+        // want relative positioning on the child to affect the baseline that we
+        // read from it).
+        flexContainerAscent = curItem.Frame()->GetNormalPosition().y +
+          childDesiredSize.ascent;
+      }
     }
   }
 
   nsSize desiredContentBoxSize =
     axisTracker.PhysicalSizeFromLogicalSizes(contentBoxMainSize,
                                              contentBoxCrossSize);
 
   aDesiredSize.width = desiredContentBoxSize.width +
@@ -2664,17 +2704,17 @@ nsFlexContainerFrame::Reflow(nsPresConte
   aDesiredSize.height = desiredContentBoxSize.height +
     containerBorderPadding.top;
 
   if (flexContainerAscent == nscoord_MIN) {
     // Still don't have our baseline set -- this happens if we have no
     // children (or if our children are huge enough that they have nscoord_MIN
     // as their baseline... in which case, we'll use the wrong baseline, but no
     // big deal)
-    NS_WARN_IF_FALSE(line.mItems.IsEmpty(),
+    NS_WARN_IF_FALSE(lines[0].mItems.IsEmpty(),
                      "Have flex items but didn't get an ascent - that's odd "
                      "(or there are just gigantic sizes involved)");
     // Per spec, just use the bottom of content-box.
     flexContainerAscent = aDesiredSize.height;
   }
   aDesiredSize.ascent = flexContainerAscent;
 
   // Now: If we're complete, add bottom border/padding to desired height
--- a/layout/generic/nsFlexContainerFrame.h
+++ b/layout/generic/nsFlexContainerFrame.h
@@ -101,17 +101,17 @@ protected:
                              const FlexboxAxisTracker& aAxisTracker,
                              nsTArray<FlexLine>& aLines);
 
   nscoord GetMainSizeFromReflowState(const nsHTMLReflowState& aReflowState,
                                      const FlexboxAxisTracker& aAxisTracker);
 
   nscoord ComputeFlexContainerCrossSize(const nsHTMLReflowState& aReflowState,
                                         const FlexboxAxisTracker& aAxisTracker,
-                                        nscoord aLineCrossSize,
+                                        const nsTArray<FlexLine>& aLines,
                                         nscoord aAvailableHeightForContent,
                                         bool* aIsDefinite,
                                         nsReflowStatus& aStatus);
 
   nsresult SizeItemInCrossAxis(nsPresContext* aPresContext,
                                const FlexboxAxisTracker& aAxisTracker,
                                nsHTMLReflowState& aChildReflowState,
                                FlexItem& aItem);