зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1599159 - Break the child block frame reflow loop if there is a break-before. r=emilio
This patch is based on Mats Palmgren's idea bug 1599159 comment 0. When a child block frame reports inline-break-before status after being reflowed, its size in the returned reflow output shouldn't matter because the parent is expected to push it to the next page/column [1]. Here is the detail of the debug assertion if the workaround in fieldset frame is removed. In nsBlockReflowContext::ReflowBlock(), it sets mReflowOutput::BSize() to 0xdeadbeef, which is a negative number in 32-bits integer. Without the early break of the loop in nsBlockFrame::ReflowBlockFrame(), then later in the loop we are going to pass the negative block-size to BlockReflowState::GetFloatAvailableSpaceForBSize(), which triggers a `aBSize>=0` assertion further down in the callstack in nsFloatManager::GetFlowArea(). layout/reftests/pagination/fieldset-00G.html can trigger the above assertion after removing the workaround in fieldset frame. I don't expect this patch will change the behavior even if there are some float elements interacting with this block. Without the early breaking out of the loop, we still end up in [1]. [1] https://searchfox.org/mozilla-central/rev/ace2c59e6c56b2dcba25af1aa8903a5e7f9a5857/layout/generic/nsBlockFrame.cpp#4026-4035 Differential Revision: https://phabricator.services.mozilla.com/D148815
This commit is contained in:
Родитель
d2534adbc1
Коммит
f8731e5b3c
|
@ -481,14 +481,11 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
|
|||
// Propagate break-before from the legend to the fieldset.
|
||||
if (legend->StyleDisplay()->BreakBefore() ||
|
||||
aStatus.IsInlineBreakBefore()) {
|
||||
// XXX(mats) setting a desired size shouldn't be necessary: bug 1599159.
|
||||
aDesiredSize.SetSize(wm, LogicalSize(wm));
|
||||
aStatus.SetInlineLineBreakBeforeAndReset();
|
||||
return;
|
||||
}
|
||||
// Honor break-inside:avoid by breaking before instead.
|
||||
if (MOZ_UNLIKELY(avoidBreakInside) && !aStatus.IsFullyComplete()) {
|
||||
aDesiredSize.SetSize(wm, LogicalSize(wm));
|
||||
aStatus.SetInlineLineBreakBeforeAndReset();
|
||||
return;
|
||||
}
|
||||
|
@ -650,7 +647,6 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
|
|||
!aReflowInput.mFlags.mIsTopOfPage &&
|
||||
availSize.BSize(wm) != NS_UNCONSTRAINEDSIZE) {
|
||||
if (status.IsInlineBreakBefore() || !status.IsFullyComplete()) {
|
||||
aDesiredSize.SetSize(wm, LogicalSize(wm));
|
||||
aStatus.SetInlineLineBreakBeforeAndReset();
|
||||
return;
|
||||
}
|
||||
|
@ -775,7 +771,6 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
|
|||
border.BEnd(wm) > 0 && aReflowInput.AvailableBSize() > border.BEnd(wm)) {
|
||||
// Our end border doesn't fit but it should fit in the next column/page.
|
||||
if (MOZ_UNLIKELY(avoidBreakInside)) {
|
||||
aDesiredSize.SetSize(wm, LogicalSize(wm));
|
||||
aStatus.SetInlineLineBreakBeforeAndReset();
|
||||
return;
|
||||
} else {
|
||||
|
|
|
@ -3907,6 +3907,12 @@ void nsBlockFrame::ReflowBlockFrame(BlockReflowState& aState,
|
|||
clearance, aState.IsAdjacentWithTop(), aLine.get(),
|
||||
*childReflowInput, frameReflowStatus, aState);
|
||||
|
||||
if (frameReflowStatus.IsInlineBreakBefore()) {
|
||||
// No need to retry this loop if there is a break opportunity before the
|
||||
// child block.
|
||||
break;
|
||||
}
|
||||
|
||||
// Now the block has a height. Using that height, get the
|
||||
// available space again and call ComputeBlockAvailSpace again.
|
||||
// If ComputeBlockAvailSpace gives a different result, we need to
|
||||
|
|
Загрузка…
Ссылка в новой задаче