Bug 1663722: Make nsPageSequenceFrame gracefully handle SizeToContent calls. r=emilio

nsPageSequenceFrame does a thing where it grows its desired size to fit the
AvailableISize and ComputedBSize (under the assumption that those are the
actual dimensions of our scrollport, which it wants to make maximal use of).

This behavior causes trouble when it's reflowed under the privileged
'sizeToContent' JS API.  That API makes us reflow with nscoord_MAX as the
viewport's ComputedBSize(), and this nscoord_MAX value gets passed down to be
the nsPageSequenceFrame's ComputedBSize as well.  When we reach the code in
question, we dutifully grow the desired size to that bogus huge value, which is
clearly wrong.

This patch addresses this issue by simply declining to grow the desired size in
the scenario where ComputedBSize() is unconstrained.  This leaves us with
reasonable values for our desired size (which are actually based on the
content, which makes it the right thing to do for the purpose of a
SizeToContent() call).

Differential Revision: https://phabricator.services.mozilla.com/D135762
This commit is contained in:
Daniel Holbert 2022-01-13 06:08:51 +00:00
Родитель 288e47841c
Коммит 080e18fa47
3 изменённых файлов: 28 добавлений и 2 удалений

Просмотреть файл

@ -190,10 +190,21 @@ void nsPageSequenceFrame::PopulateReflowOutput(
nscoord iSize = wm.IsVertical() ? mSize.Height() : mSize.Width();
nscoord bSize = wm.IsVertical() ? mSize.Width() : mSize.Height();
nscoord availableISize = aReflowInput.AvailableISize();
nscoord computedBSize = aReflowInput.ComputedBSize();
if (MOZ_UNLIKELY(computedBSize == NS_UNCONSTRAINEDSIZE)) {
// We have unconstrained BSize, which should only happen if someone calls
// SizeToContent() on our window (which we don't expect to happen for
// actual user flows, but is possible for fuzzers to trigger). We just nerf
// the ReflowInput's contributions to the std::max() expressions below,
// which does indeed make us "size to content", via letting std::max()
// choose the scaled iSize/bSize expressions.
availableISize = computedBSize = 0;
}
aReflowOutput.ISize(wm) =
std::max(NSToCoordFloor(iSize * scale), aReflowInput.AvailableISize());
std::max(NSToCoordFloor(iSize * scale), availableISize);
aReflowOutput.BSize(wm) =
std::max(NSToCoordFloor(bSize * scale), aReflowInput.ComputedBSize());
std::max(NSToCoordFloor(bSize * scale), computedBSize);
aReflowOutput.SetOverflowAreasToDesiredBounds();
}
@ -275,6 +286,9 @@ void nsPageSequenceFrame::Reflow(nsPresContext* aPresContext,
// When we're displayed on-screen, the computed size that we're given is
// the size of our scrollport. We need to save this for use in
// GetPrintPreviewScale.
// (NOTE: It's possible but unlikely that we have an unconstrained BSize
// here, if we're being sized to content. GetPrintPreviewScale() checks
// for and handles this, when making use of this member-var.)
mScrollportSize = aReflowInput.ComputedSize();
}

Просмотреть файл

@ -0,0 +1,11 @@
<html class="reftest-wait">
<head>
<script>
document.addEventListener("DOMContentLoaded", () => {
const proxy = SpecialPowers.wrap(self).printPreview();
proxy.sizeToContent();
document.documentElement.className = "";
})
</script>
</head>
</html>

Просмотреть файл

@ -3,4 +3,5 @@ load 509839-2.html
load 576878.xhtml
asserts-if(Android,0-1) load 793844.html
skip-if(Android) load 1662259.html
skip-if(Android) load 1663722.html
skip-if(Android) load 1671503.html