Commit 87107bc5 authored by ojan@chromium.org's avatar ojan@chromium.org

Fix infinite recursion in computePreferredLogicalWidths.

RenderReplaced::computeReplacedLogicalWidth walks up to it's
containingBlock in some cases and asks for the containingBlock's
width. If the containingBlock's width itself depends on the
RenderReplaced's width, then we infinite loop. Avoid the
infinite loop by making sure that width/min-width/max-width
are all specified on the containingBlock, which will keep
the width from depending on it's children.

Added FIXMEs. I think we should delete all this containingBlock
walking code, but it needs to be done carefully to make sure
percentage widths on <svg> keep working. The spec actually
considered this undefined behavior, but suggests doing the
crazy that we do here.

BUG=344647

Review URL: https://codereview.chromium.org/186913003

git-svn-id: svn://svn.chromium.org/blink/trunk@168511 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 6ed44dfd
<!DOCTYPE html>
<style>
object {
width: 300px;
}
</style>
<object type="image/svg+xml" data="resources/intrinsic-ratio.svg"></object>
<!DOCTYPE html>
<style>
p {
width: 300px;
display: table-cell;
min-width: -webkit-min-content;
}
</style>
<p><object type="image/svg+xml" data="resources/intrinsic-ratio.svg"></object></p>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.0"
viewBox="0 0 1000 250" preserveAspectRatio="xMinYMin meet"
xmlns="http://www.w3.org/2000/svg">
<!-- This rectangle goes from (0,0) to (1500,1000) in user space.
Because of the viewBox attribute above,
the rectangle will end up filling the entire area
reserved for the SVG content. -->
<rect x="0" y="0" width="1000" height="250"
fill="lime" stroke="green" stroke-width="12" />
<!-- A large, red triangle -->
<path fill="green" d="M 500,50 L 150,200 L 850,200 z"/>
</svg>
\ No newline at end of file
......@@ -225,7 +225,9 @@ static inline RenderBlock* firstContainingBlockWithLogicalWidth(const RenderRepl
return 0;
for (; !containingBlock->isRenderView() && !containingBlock->isBody(); containingBlock = containingBlock->containingBlock()) {
if (containingBlock->style()->logicalWidth().isSpecified())
if (containingBlock->style()->logicalWidth().isSpecified()
&& containingBlock->style()->logicalMinWidth().isSpecified()
&& (containingBlock->style()->logicalMaxWidth().isSpecified() || containingBlock->style()->logicalMaxWidth().isUndefined()))
return containingBlock;
}
......@@ -418,10 +420,19 @@ LayoutUnit RenderReplaced::computeReplacedLogicalWidth(ShouldComputePreferred sh
// The aforementioned 'constraint equation' used for block-level, non-replaced elements in normal flow:
// 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block
LayoutUnit logicalWidth;
if (RenderBlock* blockWithWidth = firstContainingBlockWithLogicalWidth(this))
// FIXME: This walking up the containgBlock chain to find the first one with a specified width is bonkers.
// If nothing else, it requires making sure that computeReplacedLogicalWidthRespectingMinMaxWidth cannot
// depend on the width of the replaced element or we infinite loop. Right now we do that in
// firstContainingBlockWithLogicalWidth by checking that width/min-width/max-width are all specified.
//
// Firefox 27 seems to only do this if the <svg> has a viewbox.
if (RenderBlock* blockWithWidth = firstContainingBlockWithLogicalWidth(this)) {
logicalWidth = blockWithWidth->computeReplacedLogicalWidthRespectingMinMaxWidth(blockWithWidth->computeReplacedLogicalWidthUsing(blockWithWidth->style()->logicalWidth()), shouldComputePreferred);
else
} else {
// FIXME: If shouldComputePreferred == ComputePreferred, then we're reading this during preferred width
// computation, at which point this is reading stale data from a previous layout.
logicalWidth = containingBlock()->availableLogicalWidth();
}
// This solves above equation for 'width' (== logicalWidth).
LayoutUnit marginStart = minimumValueForLength(style()->marginStart(), logicalWidth);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment