зеркало из https://github.com/mozilla/pjs.git
Add assertions that the frame tree is safe to destroy (i.e., doesn't contain any first-in-flows or other things we should never destroy) when we call DeleteNextInFlowChild. (Bug 619021) r=roc a2.0=blocking
This commit is contained in:
Родитель
409c9ae8fc
Коммит
a6043f9061
|
@ -3811,6 +3811,49 @@ nsLayoutUtils::AssertNoDuplicateContinuations(nsIFrame* aContainer,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Is one of aFrame's ancestors a letter frame?
|
||||
static bool
|
||||
IsInLetterFrame(nsIFrame *aFrame)
|
||||
{
|
||||
for (nsIFrame *f = aFrame->GetParent(); f; f = f->GetParent()) {
|
||||
if (f->GetType() == nsGkAtoms::letterFrame) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsLayoutUtils::AssertTreeOnlyEmptyNextInFlows(nsIFrame *aSubtreeRoot)
|
||||
{
|
||||
NS_ASSERTION(aSubtreeRoot->GetPrevInFlow(),
|
||||
"frame tree not empty, but caller reported complete status");
|
||||
|
||||
// Also assert that text frames map no text.
|
||||
PRInt32 start, end;
|
||||
nsresult rv = aSubtreeRoot->GetOffsets(start, end);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "GetOffsets failed");
|
||||
// In some cases involving :first-letter, we'll partially unlink a
|
||||
// continuation in the middle of a continuation chain from its
|
||||
// previous and next continuations before destroying it, presumably so
|
||||
// that we don't also destroy the later continuations. Once we've
|
||||
// done this, GetOffsets returns incorrect values.
|
||||
// For examples, see list of tests in
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=619021#c29
|
||||
NS_ASSERTION(start == end || IsInLetterFrame(aSubtreeRoot),
|
||||
"frame tree not empty, but caller reported complete status");
|
||||
|
||||
PRInt32 listIndex = 0;
|
||||
nsIAtom* childList = nsnull;
|
||||
do {
|
||||
for (nsIFrame* child = aSubtreeRoot->GetFirstChild(childList); child;
|
||||
child = child->GetNextSibling()) {
|
||||
nsLayoutUtils::AssertTreeOnlyEmptyNextInFlows(child);
|
||||
}
|
||||
childList = aSubtreeRoot->GetAdditionalChildListName(listIndex++);
|
||||
} while (childList);
|
||||
}
|
||||
#endif
|
||||
|
||||
nsSetAttrRunnable::nsSetAttrRunnable(nsIContent* aContent, nsIAtom* aAttrName,
|
||||
|
|
|
@ -1273,6 +1273,13 @@ public:
|
|||
static void
|
||||
AssertNoDuplicateContinuations(nsIFrame* aContainer,
|
||||
const nsFrameList& aFrameList);
|
||||
|
||||
/**
|
||||
* Assert that the frame tree rooted at |aSubtreeRoot| is empty, i.e.,
|
||||
* that it contains no first-in-flows.
|
||||
*/
|
||||
static void
|
||||
AssertTreeOnlyEmptyNextInFlows(nsIFrame *aSubtreeRoot);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -5642,6 +5642,11 @@ nsBlockFrame::DeleteNextInFlowChild(nsPresContext* aPresContext,
|
|||
aNextInFlow, aDeletingEmptyFrames);
|
||||
}
|
||||
else {
|
||||
#ifdef DEBUG
|
||||
if (aDeletingEmptyFrames) {
|
||||
nsLayoutUtils::AssertTreeOnlyEmptyNextInFlows(aNextInFlow);
|
||||
}
|
||||
#endif
|
||||
DoRemoveFrame(aNextInFlow,
|
||||
aDeletingEmptyFrames ? FRAMES_ARE_EMPTY : 0);
|
||||
}
|
||||
|
|
|
@ -1140,6 +1140,12 @@ nsContainerFrame::DeleteNextInFlowChild(nsPresContext* aPresContext,
|
|||
StealFrame(aPresContext, aNextInFlow);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "StealFrame failure");
|
||||
|
||||
#ifdef DEBUG
|
||||
if (aDeletingEmptyFrames) {
|
||||
nsLayoutUtils::AssertTreeOnlyEmptyNextInFlows(aNextInFlow);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Delete the next-in-flow frame and its descendants. This will also
|
||||
// remove it from its next-in-flow/prev-in-flow chain.
|
||||
aNextInFlow->Destroy();
|
||||
|
|
Загрузка…
Ссылка в новой задаче