Bug 406137. Fix crashes on redhat.com etc by avoiding RecoverFloats traversing stale float caches. r+sr=dbaron

This commit is contained in:
roc+@cs.cmu.edu 2007-12-01 00:29:02 -08:00
Родитель cf314091fe
Коммит 0b47bce39d
1 изменённых файлов: 25 добавлений и 3 удалений

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

@ -1845,7 +1845,14 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// Now repair the line and update |aState.mY| by calling // Now repair the line and update |aState.mY| by calling
// |ReflowLine| or |SlideLine|. // |ReflowLine| or |SlideLine|.
if (line->IsDirty() && !willReflowAgain) { // If we're going to reflow everything again, then no need to reflow
// the dirty line ... unless the line has floats, in which case we'd
// better reflow it now to refresh its float cache, which may contain
// dangling frame pointers! Ugh! This reflow of the line may be
// incorrect because we skipped reflowing previous lines (e.g., floats
// may be placed incorrectly), but that's OK because we'll mark the
// line dirty below under "if (aState.mReflowState.mDiscoveredClearance..."
if (line->IsDirty() && (line->HasFloats() || !willReflowAgain)) {
lastLineMovedUp = PR_TRUE; lastLineMovedUp = PR_TRUE;
PRBool maybeReflowingForFirstTime = PRBool maybeReflowingForFirstTime =
@ -1867,6 +1874,9 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
*aState.mReflowState.mDiscoveredClearance) { *aState.mReflowState.mDiscoveredClearance) {
line->MarkDirty(); line->MarkDirty();
willReflowAgain = PR_TRUE; willReflowAgain = PR_TRUE;
// Note that once we've entered this state, every line that gets here
// (e.g. because it has floats) gets marked dirty and reflowed again.
// in the next pass. This is important, see above.
} }
if (line->HasFloats()) { if (line->HasFloats()) {
@ -1937,8 +1947,20 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
else else
repositionViews = PR_TRUE; repositionViews = PR_TRUE;
// XXX EVIL O(N^2) EVIL if (willReflowAgain) {
aState.RecoverStateFrom(line, deltaY); NS_ASSERTION(!line->HasFloats(), "Possibly stale float cache here!");
// If we're going to reflow everything again, and this line has no
// cached floats, then there is no need to recover float state. The line
// may be a block that contains other lines with floats, but in that
// case RecoverStateFrom would only add floats to the space manager.
// We don't need to do that because everything's going to get reflowed
// again "for real". Calling RecoverStateFrom in this situation could
// be lethal because the block's descendant lines may have float
// caches containing dangling frame pointers. Ugh!
} else {
// XXX EVIL O(N^2) EVIL
aState.RecoverStateFrom(line, deltaY);
}
// Keep mY up to date in case we're propagating reflow damage // Keep mY up to date in case we're propagating reflow damage
// and also because our final height may depend on it. If the // and also because our final height may depend on it. If the