зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1739260 - Force to advance next band if we cannot get a suitable float available space. r=dholbert
Without this patch, the test case, floats-aspect-ratio-001.html, hangs because: 1. The initial float available space is correct, and its size is 100px x 50px. And the bfc element is "width: auto; height: auto; aspect-ratio: 1/1;". So its width and height depend on the available space. 2. And then, we try to get a new available area based on the height of the bfc element (note: its size is 100px x 100px). However, we get an invalid zero-width float available area which is occupied by the element with float:right (i.e. the pink one), in the first band, and the size of float available space is 0px x 100px. This makes the size of bfc element become 0px x 0px when checking `FloatAvoidingBlockFitsInAvailSpace()`. So it always fits in this float available area. And because we get two different available areas in the first band (i.e. same `aBCoord`), so we don't go into the break condition, and contine to get a new `childReflowInput`, and then go to the next iteration. 3. In the 2nd loop, we try to get a new float available space by the height of the bfc element (note: its size is 0px x 0px now because the width of current float available space is 0px), so the new float available space is 100px x 0px, and the bfc element fits in this available area, but again, we have two different available areas, so we still don't go into the break condition. Instead, we use the new available area to compute the childReflowInput for the next iteration, and now the size of the bfc element becomes 100px x 100px. And then we go back to the state of (2). 4. So the bfc element enters a resize oscillation due to the invalid float available space together with the aspect-ratio and auto sizes (i.e. "widht: auto; height: auto;") I think. And the invalid float available space also let |AvailableSpaceShrunk()| be unexpected because we hit an assertion: "ASSERTION: available space should not grow on the start side and shrink on the end side". A possible way is to make sure we get a suitable float available area for `floatAvoidingBlock`, so this can avoid the bfc element from entering a resize oscillation. Note: 1. bfc means block-formatting-context, and its variable name is `floatAvoidingBlock` in nsBlockFrame.cpp. 2. We don't need to check zere or positive inline size for the float available space because `AvailableSpaceShrunk()` should make sure we leave the loop properly. See https://phabricator.services.mozilla.com/D145524#4766290 for the the example when the inline size is exactly zero. Besides, we also fix contain-inline-size-bfc-floats-001.html with this patch. Differential Revision: https://phabricator.services.mozilla.com/D145524
This commit is contained in:
Родитель
74d28327be
Коммит
1f362db13a
|
@ -274,6 +274,15 @@ bool BlockReflowState::FloatAvoidingBlockFitsInAvailSpace(
|
|||
// somewhat expensive.
|
||||
return true;
|
||||
}
|
||||
|
||||
// |aFloatAvailableSpace| was computed as having a negative size, which means
|
||||
// there are floats on both sides pushing inwards past each other, and
|
||||
// |aFloatAvoidingBlock| would necessarily intersect a float if we put it
|
||||
// here. So, it doesn't fit.
|
||||
if (aFloatAvailableSpace.ISizeIsActuallyNegative()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WritingMode wm = mReflowInput.GetWritingMode();
|
||||
nsBlockFrame::FloatAvoidingISizeToClear replacedISize =
|
||||
nsBlockFrame::ISizeToClearPastFloats(*this, aFloatAvailableSpace.mRect,
|
||||
|
|
|
@ -108,6 +108,14 @@ class BlockReflowState {
|
|||
*
|
||||
* Returns whether there are floats present at the given block-direction
|
||||
* coordinate and within the inline size of the content rect.
|
||||
*
|
||||
* Note: some codepaths clamp this structure's inline-size to be >=0 "for
|
||||
* compatibility with nsSpaceManager". So if you encounter a nsFlowAreaRect
|
||||
* which appears to have an ISize of 0, you can't necessarily assume that a
|
||||
* 0-ISize float-avoiding block would actually fit; you need to check the
|
||||
* InitialISizeIsNegative flag to see whether that 0 is actually a clamped
|
||||
* negative value (in which case a 0-ISize float-avoiding block *should not*
|
||||
* be considered as fitting, because it would intersect some float).
|
||||
*/
|
||||
nsFlowAreaRect GetFloatAvailableSpace() const {
|
||||
return GetFloatAvailableSpace(mBCoord);
|
||||
|
|
|
@ -250,6 +250,14 @@ nsFlowAreaRect nsFloatManager::GetFlowArea(
|
|||
(haveFloats ? nsFlowAreaRectFlags::HasFloats
|
||||
: nsFlowAreaRectFlags::NoFlags) |
|
||||
(mayWiden ? nsFlowAreaRectFlags::MayWiden : nsFlowAreaRectFlags::NoFlags);
|
||||
// Some callers clamp the inline size of nsFlowAreaRect to be nonnegative
|
||||
// "for compatibility with nsSpaceManager". So, we set a flag here to record
|
||||
// the fact that the ISize is actually negative, so that downstream code can
|
||||
// realize that there's no place here where we could put a float-avoiding
|
||||
// block (even one with ISize of 0).
|
||||
if (lineRight - lineLeft < 0) {
|
||||
flags |= nsFlowAreaRectFlags::ISizeIsActuallyNegative;
|
||||
}
|
||||
|
||||
return nsFlowAreaRect(aWM, inlineStart, blockStart - mBlockStart,
|
||||
lineRight - lineLeft, blockSize, flags);
|
||||
|
|
|
@ -29,7 +29,8 @@ class PresShell;
|
|||
enum class nsFlowAreaRectFlags : uint32_t {
|
||||
NoFlags = 0,
|
||||
HasFloats = 1 << 0,
|
||||
MayWiden = 1 << 1
|
||||
MayWiden = 1 << 1,
|
||||
ISizeIsActuallyNegative = 1 << 2,
|
||||
};
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsFlowAreaRectFlags)
|
||||
|
||||
|
@ -59,6 +60,9 @@ struct nsFlowAreaRect {
|
|||
bool MayWiden() const {
|
||||
return (bool)(mAreaFlags & nsFlowAreaRectFlags::MayWiden);
|
||||
}
|
||||
bool ISizeIsActuallyNegative() const {
|
||||
return (bool)(mAreaFlags & nsFlowAreaRectFlags::ISizeIsActuallyNegative);
|
||||
}
|
||||
};
|
||||
|
||||
#define NS_FLOAT_MANAGER_CACHE_SIZE 64
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
[contain-inline-size-bfc-floats-001.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS aspect-ratio reference: block formatting context with floats</title>
|
||||
|
||||
<div style="width: 200px; border: solid 1px; display: flow-root;">
|
||||
<div style="float: left; width: 50px; height: 50px; background: lime;"></div>
|
||||
<div style="float: right; width: 50px; height: 50px; background: hotpink;"></div>
|
||||
<div style="float: left; width: 160px; height: 50px; background: aqua;"></div>
|
||||
<div style="float: right; width: 40px; height: 40px; background: orange;"></div>
|
||||
</div>
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS aspect-ratio: block formatting context with floats</title>
|
||||
<link rel="author" title="Mozilla" href="https://www.mozilla.org/">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#aspect-ratio">
|
||||
<link rel="match" href="floats-aspect-ratio-001-ref.html" />
|
||||
|
||||
<div style="width: 200px; border: solid 1px; display: flow-root;">
|
||||
<div style="float: left; width: 50px; height: 50px; background: lime;"></div>
|
||||
<div style="float: right; width: 50px; height: 50px; background: hotpink;"></div>
|
||||
<div style="float: left; width: 160px; height: 50px; background: aqua;"></div>
|
||||
|
||||
<div style="aspect-ratio: 1/1; background: orange; display: flow-root;"></div>
|
||||
</div>
|
Загрузка…
Ссылка в новой задаче