Bug 253195. Fix a really nasty data corruption bug in nsBlockFrame::DoRemoveFrame, that only shows up when you need to delete inline continuations that are in a continuation of the current block --- probably doesn't happen today, but will happen with columns and page-layout editing. r+sr=dbaron

This commit is contained in:
roc+%cs.cmu.edu 2004-07-27 18:22:14 +00:00
Родитель 46045bea89
Коммит 45c94413a9
2 изменённых файлов: 42 добавлений и 22 удалений

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

@ -381,6 +381,12 @@ nsBlockFrame::List(nsIPresContext* aPresContext, FILE* out, PRInt32 aIndent) con
if (0 != mState) {
fprintf(out, " [state=%08x]", mState);
}
nsBlockFrame* f = NS_CONST_CAST(nsBlockFrame*, this);
nsRect* overflowArea = f->GetOverflowAreaProperty(PR_FALSE);
if (overflowArea) {
fprintf(out, " [overflow=%d,%d,%d,%d]", overflowArea->x, overflowArea->y,
overflowArea->width, overflowArea->height);
}
PRInt32 numInlineLines = 0;
PRInt32 numBlockLines = 0;
if (! mLines.empty()) {
@ -2140,7 +2146,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
aState.ReconstructMarginAbove(line);
// Update aState.mPrevChild as if we had reflowed all of the frames in
// this line. This is expensive in some cases, since it requires
// the last line. This is expensive in some cases, since it requires
// walking |GetNextSibling|.
aState.mPrevChild = line.prev()->LastChild();
}
@ -2156,6 +2162,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
nsBlockFrame* nextInFlow = aState.mNextInFlow;
line_iterator nifLine = nextInFlow->begin_lines();
if (nifLine == nextInFlow->end_lines()) {
NS_WARNING("Drained the life from next-in-flow!\n");
aState.mNextInFlow = (nsBlockFrame*) aState.mNextInFlow->mNextInFlow;
continue;
}
@ -2186,8 +2193,10 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
lastFrame->SetNextSibling(nsnull);
// Add line to our line list
if (aState.mPrevChild)
if (aState.mPrevChild) {
aState.mPrevChild->SetNextSibling(toMove->mFirstChild);
}
line = mLines.before_insert(end_lines(), toMove);
// If line contains floats, remove them from aState.mNextInFlow's
@ -2570,11 +2579,12 @@ nsBlockFrame::PullFrameFrom(nsBlockReflowState& aState,
if (aDamageDeletedLines) {
Invalidate(fromLine->mBounds);
}
if (aFromLine.next() != end_lines())
if (aFromLine.next() != aFromContainer.end())
aFromLine.next()->MarkPreviousMarginDirty();
Invalidate(fromLine->GetCombinedArea());
aFromContainer.erase(aFromLine);
// Note that aFromLine just got incremented, so don't use it again here!
aState.FreeLineBox(fromLine);
}
@ -2591,10 +2601,10 @@ nsBlockFrame::PullFrameFrom(nsBlockReflowState& aState,
// The frame is being pulled from a next-in-flow; therefore we
// need to add it to our sibling list.
frame->SetNextSibling(nsnull);
if (nsnull != aState.mPrevChild) {
aState.mPrevChild->SetNextSibling(frame);
}
frame->SetNextSibling(nsnull);
}
// Stop pulling because we found a frame to pull
@ -4729,9 +4739,9 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext,
// Find the line and the previous sibling that contains
// deletedFrame; we also find the pointer to the line.
nsBlockFrame* flow = this;
nsLineList& lines = flow->mLines;
nsLineList::iterator line = lines.begin(),
line_end = lines.end();
nsLineList* lines = &flow->mLines;
nsLineList::iterator line = lines->begin(),
line_end = lines->end();
nsIFrame* prevSibling = nsnull;
for ( ; line != line_end; ++line) {
nsIFrame* frame = line->mFirstChild;
@ -4807,7 +4817,7 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext,
// If line is empty, remove it now
if (0 == lineChildCount) {
nsLineBox *cur = line;
line = lines.erase(line);
line = lines->erase(line);
// Invalidate the space taken up by the line.
// XXX We need to do this if we're removing a frame as a result of
// a call to RemoveFrame(), but we may not need to do this in all
@ -4857,9 +4867,9 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext,
NS_ASSERTION(nsnull != flow, "whoops, continuation without a parent");
// add defensive pointer check for bug 56894
if (flow) {
lines = flow->mLines;
line = lines.begin();
line_end = lines.end();
lines = &flow->mLines;
line = lines->begin();
line_end = lines->end();
prevSibling = nsnull;
} else {
aDeletedFrame = nsnull;

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

@ -381,6 +381,12 @@ nsBlockFrame::List(nsIPresContext* aPresContext, FILE* out, PRInt32 aIndent) con
if (0 != mState) {
fprintf(out, " [state=%08x]", mState);
}
nsBlockFrame* f = NS_CONST_CAST(nsBlockFrame*, this);
nsRect* overflowArea = f->GetOverflowAreaProperty(PR_FALSE);
if (overflowArea) {
fprintf(out, " [overflow=%d,%d,%d,%d]", overflowArea->x, overflowArea->y,
overflowArea->width, overflowArea->height);
}
PRInt32 numInlineLines = 0;
PRInt32 numBlockLines = 0;
if (! mLines.empty()) {
@ -2140,7 +2146,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
aState.ReconstructMarginAbove(line);
// Update aState.mPrevChild as if we had reflowed all of the frames in
// this line. This is expensive in some cases, since it requires
// the last line. This is expensive in some cases, since it requires
// walking |GetNextSibling|.
aState.mPrevChild = line.prev()->LastChild();
}
@ -2156,6 +2162,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
nsBlockFrame* nextInFlow = aState.mNextInFlow;
line_iterator nifLine = nextInFlow->begin_lines();
if (nifLine == nextInFlow->end_lines()) {
NS_WARNING("Drained the life from next-in-flow!\n");
aState.mNextInFlow = (nsBlockFrame*) aState.mNextInFlow->mNextInFlow;
continue;
}
@ -2186,8 +2193,10 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
lastFrame->SetNextSibling(nsnull);
// Add line to our line list
if (aState.mPrevChild)
if (aState.mPrevChild) {
aState.mPrevChild->SetNextSibling(toMove->mFirstChild);
}
line = mLines.before_insert(end_lines(), toMove);
// If line contains floats, remove them from aState.mNextInFlow's
@ -2570,11 +2579,12 @@ nsBlockFrame::PullFrameFrom(nsBlockReflowState& aState,
if (aDamageDeletedLines) {
Invalidate(fromLine->mBounds);
}
if (aFromLine.next() != end_lines())
if (aFromLine.next() != aFromContainer.end())
aFromLine.next()->MarkPreviousMarginDirty();
Invalidate(fromLine->GetCombinedArea());
aFromContainer.erase(aFromLine);
// Note that aFromLine just got incremented, so don't use it again here!
aState.FreeLineBox(fromLine);
}
@ -2591,10 +2601,10 @@ nsBlockFrame::PullFrameFrom(nsBlockReflowState& aState,
// The frame is being pulled from a next-in-flow; therefore we
// need to add it to our sibling list.
frame->SetNextSibling(nsnull);
if (nsnull != aState.mPrevChild) {
aState.mPrevChild->SetNextSibling(frame);
}
frame->SetNextSibling(nsnull);
}
// Stop pulling because we found a frame to pull
@ -4729,9 +4739,9 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext,
// Find the line and the previous sibling that contains
// deletedFrame; we also find the pointer to the line.
nsBlockFrame* flow = this;
nsLineList& lines = flow->mLines;
nsLineList::iterator line = lines.begin(),
line_end = lines.end();
nsLineList* lines = &flow->mLines;
nsLineList::iterator line = lines->begin(),
line_end = lines->end();
nsIFrame* prevSibling = nsnull;
for ( ; line != line_end; ++line) {
nsIFrame* frame = line->mFirstChild;
@ -4807,7 +4817,7 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext,
// If line is empty, remove it now
if (0 == lineChildCount) {
nsLineBox *cur = line;
line = lines.erase(line);
line = lines->erase(line);
// Invalidate the space taken up by the line.
// XXX We need to do this if we're removing a frame as a result of
// a call to RemoveFrame(), but we may not need to do this in all
@ -4857,9 +4867,9 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext,
NS_ASSERTION(nsnull != flow, "whoops, continuation without a parent");
// add defensive pointer check for bug 56894
if (flow) {
lines = flow->mLines;
line = lines.begin();
line_end = lines.end();
lines = &flow->mLines;
line = lines->begin();
line_end = lines->end();
prevSibling = nsnull;
} else {
aDeletedFrame = nsnull;