Bug 600100, Part 1: Return a status of NS_FRAME_NOT_COMPLETE during reflow of nsBlockFrame if we have a next continuation with pushed floats to prevent crashing in columns. [r=dbaron]

This commit is contained in:
Scott Johnson
2013-03-19 09:05:05 -05:00
parent dc00523371
commit 5818c97afa
5 changed files with 51 additions and 1 deletions

View File

@@ -0,0 +1 @@
<html xmlns="http://www.w3.org/1999/xhtml"><head><style>*::first-line { } *::after { content: 'after text'; } *::before { content: 'before text'; } </style></head><body onload="document.documentElement.offsetHeight; document.getElementsByTagName('style')[0].appendChild(document.createTextNode(' '));" style="-moz-column-width: 0pt;"><div style="float: right;"><span style="overflow-y: auto; float: left;"></span></div></body></html>

View File

@@ -388,6 +388,7 @@ asserts(0-1) load 592118.html
load 594808-1.html
load 595435-1.xhtml
load 595740-1.html
load 600100.xhtml
load 603490-1.html
load 603510-1.html
load 604314-1.html

View File

@@ -1065,6 +1065,27 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
// Now reflow...
rv = ReflowDirtyLines(state);
// If we have a next-in-flow, and that next-in-flow has pushed floats from
// this frame from a previous iteration of reflow, then we should not return
// a status of NS_FRAME_COMPLETE, since we actually have overflow, it's just
// already been handled.
// NOTE: This really shouldn't happen, since we _should_ pull back our floats
// and reflow them, but just in case it does, this is a safety precaution so
// we don't end up with a placeholder pointing to frames that have already
// been deleted as part of removing our next-in-flow.
if (NS_FRAME_IS_COMPLETE(state.mReflowStatus)) {
nsBlockFrame* nif = static_cast<nsBlockFrame*>(GetNextInFlow());
while (nif) {
if (nif->HasPushedFloatsFromPrevContinuation()) {
NS_MergeReflowStatusInto(&state.mReflowStatus, NS_FRAME_NOT_COMPLETE);
}
nif = static_cast<nsBlockFrame*>(nif->GetNextInFlow());
}
}
NS_ASSERTION(NS_SUCCEEDED(rv), "reflow dirty lines failed");
if (NS_FAILED(rv)) return rv;

View File

@@ -470,6 +470,33 @@ public:
static void RecoverFloatsFor(nsIFrame* aFrame,
nsFloatManager& aFloatManager);
/**
* Determine if we have any pushed floats from a previous continuation.
*
* @returns true, if any of the floats at the beginning of our mFloats list
* have the NS_FRAME_IS_PUSHED_FLOAT bit set; false otherwise.
*/
bool HasPushedFloatsFromPrevContinuation() const {
if (!mFloats.IsEmpty()) {
// If we have pushed floats, then they should be at the beginning of our
// float list.
if (mFloats.FrameAt(0)->GetStateBits() & NS_FRAME_IS_PUSHED_FLOAT) {
return true;
}
}
#ifdef DEBUG
// Double-check the above assertion that pushed floats should be at the
// beginning of our floats list.
for (int32_t i = 0; i < mFloats.GetLength(); i++) {
NS_ASSERTION(!(mFloats.FrameAt(i)->GetStateBits() &
NS_FRAME_IS_PUSHED_FLOAT),
"pushed floats must be at the beginning of the float list");
}
#endif
return false;
}
protected:
/** grab overflow lines from this block's prevInFlow, and make them