Add loop-detection to the various methods that can change an nsFrameList. This

will assert if a loop is detected.  Bug 266332, r+sr=roc
This commit is contained in:
bzbarsky%mit.edu 2004-10-30 18:35:53 +00:00
parent cf0cf99c31
commit 630c5022f7
4 changed files with 112 additions and 0 deletions

View File

@ -51,6 +51,9 @@ public:
nsFrameList(nsIFrame* aHead) {
mFirstChild = aHead;
#ifdef DEBUG
CheckForLoops();
#endif
}
~nsFrameList() {
@ -60,6 +63,9 @@ public:
void SetFrames(nsIFrame* aFrameList) {
mFirstChild = aFrameList;
#ifdef DEBUG
CheckForLoops();
#endif
}
void AppendFrames(nsIFrame* aParent, nsIFrame* aFrameList);
@ -156,6 +162,10 @@ private:
PRBool DoReplaceFrame(nsIFrame* aParent,
nsIFrame* aOldFrame,
nsIFrame* aNewFrame);
#ifdef DEBUG
void CheckForLoops();
#endif
protected:
nsIFrame* mFirstChild;

View File

@ -150,6 +150,9 @@ nsFrameList::AppendFrames(nsIFrame* aParent, nsIFrame* aFrameList)
}
}
}
#ifdef DEBUG
CheckForLoops();
#endif
}
void
@ -168,6 +171,9 @@ nsFrameList::AppendFrame(nsIFrame* aParent, nsIFrame* aFrame)
aFrame->SetParent(aParent);
}
}
#ifdef DEBUG
CheckForLoops();
#endif
}
PRBool
@ -236,6 +242,9 @@ nsFrameList::InsertFrame(nsIFrame* aParent,
aNewFrame->SetParent(aParent);
}
}
#ifdef DEBUG
CheckForLoops();
#endif
}
void
@ -271,6 +280,9 @@ nsFrameList::InsertFrames(nsIFrame* aParent,
lastNewFrame->SetNextSibling(nextFrame);
}
}
#ifdef DEBUG
CheckForLoops();
#endif
}
PRBool
@ -302,6 +314,9 @@ nsFrameList::DoReplaceFrame(nsIFrame* aParent,
if (aParent) {
aNewFrame->SetParent(aParent);
}
#ifdef DEBUG
CheckForLoops();
#endif
return PR_TRUE;
}
@ -364,6 +379,9 @@ nsFrameList::PullFrame(nsIFrame* aParent,
pulledFrame->SetParent(aParent);
}
}
#ifdef DEBUG
CheckForLoops();
#endif
return pulledFrame;
}
@ -593,3 +611,31 @@ nsFrameList::GetNextVisualFor(nsIFrame* aFrame) const
return nearestFrame;
}
#endif
#ifdef DEBUG
void
nsFrameList::CheckForLoops()
{
if (!mFirstChild) {
return;
}
// Simple algorithm to find a loop in a linked list -- advance pointers
// through it at speeds of 1 and 2, and if they ever get to be equal bail
nsIFrame *first = mFirstChild, *second = mFirstChild;
do {
first = first->GetNextSibling();
second = second->GetNextSibling();
if (!second) {
break;
}
second = second->GetNextSibling();
if (first == second) {
// Loop detected! Since second advances faster, they can't both be null;
// we would have broken out of the loop long ago.
NS_ERROR("loop in frame list. This will probably hang soon.");
break;
}
} while (first && second);
}
#endif

View File

@ -150,6 +150,9 @@ nsFrameList::AppendFrames(nsIFrame* aParent, nsIFrame* aFrameList)
}
}
}
#ifdef DEBUG
CheckForLoops();
#endif
}
void
@ -168,6 +171,9 @@ nsFrameList::AppendFrame(nsIFrame* aParent, nsIFrame* aFrame)
aFrame->SetParent(aParent);
}
}
#ifdef DEBUG
CheckForLoops();
#endif
}
PRBool
@ -236,6 +242,9 @@ nsFrameList::InsertFrame(nsIFrame* aParent,
aNewFrame->SetParent(aParent);
}
}
#ifdef DEBUG
CheckForLoops();
#endif
}
void
@ -271,6 +280,9 @@ nsFrameList::InsertFrames(nsIFrame* aParent,
lastNewFrame->SetNextSibling(nextFrame);
}
}
#ifdef DEBUG
CheckForLoops();
#endif
}
PRBool
@ -302,6 +314,9 @@ nsFrameList::DoReplaceFrame(nsIFrame* aParent,
if (aParent) {
aNewFrame->SetParent(aParent);
}
#ifdef DEBUG
CheckForLoops();
#endif
return PR_TRUE;
}
@ -364,6 +379,9 @@ nsFrameList::PullFrame(nsIFrame* aParent,
pulledFrame->SetParent(aParent);
}
}
#ifdef DEBUG
CheckForLoops();
#endif
return pulledFrame;
}
@ -593,3 +611,31 @@ nsFrameList::GetNextVisualFor(nsIFrame* aFrame) const
return nearestFrame;
}
#endif
#ifdef DEBUG
void
nsFrameList::CheckForLoops()
{
if (!mFirstChild) {
return;
}
// Simple algorithm to find a loop in a linked list -- advance pointers
// through it at speeds of 1 and 2, and if they ever get to be equal bail
nsIFrame *first = mFirstChild, *second = mFirstChild;
do {
first = first->GetNextSibling();
second = second->GetNextSibling();
if (!second) {
break;
}
second = second->GetNextSibling();
if (first == second) {
// Loop detected! Since second advances faster, they can't both be null;
// we would have broken out of the loop long ago.
NS_ERROR("loop in frame list. This will probably hang soon.");
break;
}
} while (first && second);
}
#endif

View File

@ -51,6 +51,9 @@ public:
nsFrameList(nsIFrame* aHead) {
mFirstChild = aHead;
#ifdef DEBUG
CheckForLoops();
#endif
}
~nsFrameList() {
@ -60,6 +63,9 @@ public:
void SetFrames(nsIFrame* aFrameList) {
mFirstChild = aFrameList;
#ifdef DEBUG
CheckForLoops();
#endif
}
void AppendFrames(nsIFrame* aParent, nsIFrame* aFrameList);
@ -156,6 +162,10 @@ private:
PRBool DoReplaceFrame(nsIFrame* aParent,
nsIFrame* aOldFrame,
nsIFrame* aNewFrame);
#ifdef DEBUG
void CheckForLoops();
#endif
protected:
nsIFrame* mFirstChild;