forked from mirrors/gecko-dev
		
	 265e672179
			
		
	
	
		265e672179
		
	
	
	
	
		
			
			# ignore-this-changeset --HG-- extra : amend_source : 4d301d3b0b8711c4692392aa76088ba7fd7d1022
		
			
				
	
	
		
			505 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			505 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| #include "nsFrameList.h"
 | |
| 
 | |
| #include "mozilla/ArenaObjectID.h"
 | |
| #include "nsBidiPresUtils.h"
 | |
| #include "nsContainerFrame.h"
 | |
| #include "nsGkAtoms.h"
 | |
| #include "nsILineIterator.h"
 | |
| #include "nsIPresShell.h"
 | |
| #include "nsLayoutUtils.h"
 | |
| #include "nsPresContext.h"
 | |
| 
 | |
| using namespace mozilla;
 | |
| 
 | |
| namespace mozilla {
 | |
| namespace layout {
 | |
| namespace detail {
 | |
| const AlignedFrameListBytes gEmptyFrameListBytes = {0};
 | |
| }  // namespace detail
 | |
| }  // namespace layout
 | |
| }  // namespace mozilla
 | |
| 
 | |
| void* nsFrameList::operator new(size_t sz, nsIPresShell* aPresShell) {
 | |
|   return aPresShell->AllocateByObjectID(eArenaObjectID_nsFrameList, sz);
 | |
| }
 | |
| 
 | |
| void nsFrameList::Delete(nsIPresShell* aPresShell) {
 | |
|   MOZ_ASSERT(this != &EmptyList(), "Shouldn't Delete() this list");
 | |
|   NS_ASSERTION(IsEmpty(), "Shouldn't Delete() a non-empty list");
 | |
| 
 | |
|   aPresShell->FreeByObjectID(eArenaObjectID_nsFrameList, this);
 | |
| }
 | |
| 
 | |
| void nsFrameList::DestroyFrames() {
 | |
|   while (nsIFrame* frame = RemoveFirstChild()) {
 | |
|     frame->Destroy();
 | |
|   }
 | |
|   mLastChild = nullptr;
 | |
| }
 | |
| 
 | |
| void nsFrameList::DestroyFramesFrom(
 | |
|     nsIFrame* aDestructRoot, layout::PostFrameDestroyData& aPostDestroyData) {
 | |
|   MOZ_ASSERT(aDestructRoot, "Missing destruct root");
 | |
| 
 | |
|   while (nsIFrame* frame = RemoveFirstChild()) {
 | |
|     frame->DestroyFrom(aDestructRoot, aPostDestroyData);
 | |
|   }
 | |
|   mLastChild = nullptr;
 | |
| }
 | |
| 
 | |
| void nsFrameList::SetFrames(nsIFrame* aFrameList) {
 | |
|   MOZ_ASSERT(!mFirstChild, "Losing frames");
 | |
| 
 | |
|   mFirstChild = aFrameList;
 | |
|   mLastChild = nsLayoutUtils::GetLastSibling(mFirstChild);
 | |
| }
 | |
| 
 | |
| void nsFrameList::RemoveFrame(nsIFrame* aFrame) {
 | |
|   MOZ_ASSERT(aFrame, "null ptr");
 | |
| #ifdef DEBUG_FRAME_LIST
 | |
|   // ContainsFrame is O(N)
 | |
|   MOZ_ASSERT(ContainsFrame(aFrame), "wrong list");
 | |
| #endif
 | |
| 
 | |
|   nsIFrame* nextFrame = aFrame->GetNextSibling();
 | |
|   if (aFrame == mFirstChild) {
 | |
|     mFirstChild = nextFrame;
 | |
|     aFrame->SetNextSibling(nullptr);
 | |
|     if (!nextFrame) {
 | |
|       mLastChild = nullptr;
 | |
|     }
 | |
|   } else {
 | |
|     nsIFrame* prevSibling = aFrame->GetPrevSibling();
 | |
|     NS_ASSERTION(prevSibling && prevSibling->GetNextSibling() == aFrame,
 | |
|                  "Broken frame linkage");
 | |
|     prevSibling->SetNextSibling(nextFrame);
 | |
|     aFrame->SetNextSibling(nullptr);
 | |
|     if (!nextFrame) {
 | |
|       mLastChild = prevSibling;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| nsFrameList nsFrameList::RemoveFramesAfter(nsIFrame* aAfterFrame) {
 | |
|   if (!aAfterFrame) {
 | |
|     nsFrameList result;
 | |
|     result.InsertFrames(nullptr, nullptr, *this);
 | |
|     return result;
 | |
|   }
 | |
| 
 | |
|   MOZ_ASSERT(NotEmpty(), "illegal operation on empty list");
 | |
| #ifdef DEBUG_FRAME_LIST
 | |
|   MOZ_ASSERT(ContainsFrame(aAfterFrame), "wrong list");
 | |
| #endif
 | |
| 
 | |
|   nsIFrame* tail = aAfterFrame->GetNextSibling();
 | |
|   // if (!tail) return EmptyList();  -- worth optimizing this case?
 | |
|   nsIFrame* oldLastChild = mLastChild;
 | |
|   mLastChild = aAfterFrame;
 | |
|   aAfterFrame->SetNextSibling(nullptr);
 | |
|   return nsFrameList(tail, tail ? oldLastChild : nullptr);
 | |
| }
 | |
| 
 | |
| nsIFrame* nsFrameList::RemoveFirstChild() {
 | |
|   if (mFirstChild) {
 | |
|     nsIFrame* firstChild = mFirstChild;
 | |
|     RemoveFrame(firstChild);
 | |
|     return firstChild;
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| void nsFrameList::DestroyFrame(nsIFrame* aFrame) {
 | |
|   MOZ_ASSERT(aFrame, "null ptr");
 | |
|   RemoveFrame(aFrame);
 | |
|   aFrame->Destroy();
 | |
| }
 | |
| 
 | |
| nsFrameList::Slice nsFrameList::InsertFrames(nsContainerFrame* aParent,
 | |
|                                              nsIFrame* aPrevSibling,
 | |
|                                              nsFrameList& aFrameList) {
 | |
|   MOZ_ASSERT(aFrameList.NotEmpty(), "Unexpected empty list");
 | |
| 
 | |
|   if (aParent) {
 | |
|     aFrameList.ApplySetParent(aParent);
 | |
|   }
 | |
| 
 | |
|   NS_ASSERTION(IsEmpty() || FirstChild()->GetParent() ==
 | |
|                                 aFrameList.FirstChild()->GetParent(),
 | |
|                "frame to add has different parent");
 | |
|   NS_ASSERTION(!aPrevSibling || aPrevSibling->GetParent() ==
 | |
|                                     aFrameList.FirstChild()->GetParent(),
 | |
|                "prev sibling has different parent");
 | |
| #ifdef DEBUG_FRAME_LIST
 | |
|   // ContainsFrame is O(N)
 | |
|   NS_ASSERTION(!aPrevSibling || ContainsFrame(aPrevSibling),
 | |
|                "prev sibling is not on this list");
 | |
| #endif
 | |
| 
 | |
|   nsIFrame* firstNewFrame = aFrameList.FirstChild();
 | |
|   nsIFrame* nextSibling;
 | |
|   if (aPrevSibling) {
 | |
|     nextSibling = aPrevSibling->GetNextSibling();
 | |
|     aPrevSibling->SetNextSibling(firstNewFrame);
 | |
|   } else {
 | |
|     nextSibling = mFirstChild;
 | |
|     mFirstChild = firstNewFrame;
 | |
|   }
 | |
| 
 | |
|   nsIFrame* lastNewFrame = aFrameList.LastChild();
 | |
|   lastNewFrame->SetNextSibling(nextSibling);
 | |
|   if (!nextSibling) {
 | |
|     mLastChild = lastNewFrame;
 | |
|   }
 | |
| 
 | |
|   VerifyList();
 | |
| 
 | |
|   aFrameList.Clear();
 | |
|   return Slice(*this, firstNewFrame, nextSibling);
 | |
| }
 | |
| 
 | |
| nsFrameList nsFrameList::ExtractHead(FrameLinkEnumerator& aLink) {
 | |
|   MOZ_ASSERT(&aLink.List() == this, "Unexpected list");
 | |
|   MOZ_ASSERT(!aLink.PrevFrame() ||
 | |
|                  aLink.PrevFrame()->GetNextSibling() == aLink.NextFrame(),
 | |
|              "Unexpected PrevFrame()");
 | |
|   MOZ_ASSERT(aLink.PrevFrame() || aLink.NextFrame() == FirstChild(),
 | |
|              "Unexpected NextFrame()");
 | |
|   MOZ_ASSERT(!aLink.PrevFrame() || aLink.NextFrame() != FirstChild(),
 | |
|              "Unexpected NextFrame()");
 | |
|   MOZ_ASSERT(aLink.mEnd == nullptr,
 | |
|              "Unexpected mEnd for frame link enumerator");
 | |
| 
 | |
|   nsIFrame* prev = aLink.PrevFrame();
 | |
|   nsIFrame* newFirstFrame = nullptr;
 | |
|   if (prev) {
 | |
|     // Truncate the list after |prev| and hand the first part to our new list.
 | |
|     prev->SetNextSibling(nullptr);
 | |
|     newFirstFrame = mFirstChild;
 | |
|     mFirstChild = aLink.NextFrame();
 | |
|     if (!mFirstChild) {  // we handed over the whole list
 | |
|       mLastChild = nullptr;
 | |
|     }
 | |
| 
 | |
|     // Now make sure aLink doesn't point to a frame we no longer have.
 | |
|     aLink.mPrev = nullptr;
 | |
|   }
 | |
|   // else aLink is pointing to before our first frame.  Nothing to do.
 | |
| 
 | |
|   return nsFrameList(newFirstFrame, prev);
 | |
| }
 | |
| 
 | |
| nsFrameList nsFrameList::ExtractTail(FrameLinkEnumerator& aLink) {
 | |
|   MOZ_ASSERT(&aLink.List() == this, "Unexpected list");
 | |
|   MOZ_ASSERT(!aLink.PrevFrame() ||
 | |
|                  aLink.PrevFrame()->GetNextSibling() == aLink.NextFrame(),
 | |
|              "Unexpected PrevFrame()");
 | |
|   MOZ_ASSERT(aLink.PrevFrame() || aLink.NextFrame() == FirstChild(),
 | |
|              "Unexpected NextFrame()");
 | |
|   MOZ_ASSERT(!aLink.PrevFrame() || aLink.NextFrame() != FirstChild(),
 | |
|              "Unexpected NextFrame()");
 | |
|   MOZ_ASSERT(aLink.mEnd == nullptr,
 | |
|              "Unexpected mEnd for frame link enumerator");
 | |
| 
 | |
|   nsIFrame* prev = aLink.PrevFrame();
 | |
|   nsIFrame* newFirstFrame;
 | |
|   nsIFrame* newLastFrame;
 | |
|   if (prev) {
 | |
|     // Truncate the list after |prev| and hand the second part to our new list
 | |
|     prev->SetNextSibling(nullptr);
 | |
|     newFirstFrame = aLink.NextFrame();
 | |
|     newLastFrame = newFirstFrame ? mLastChild : nullptr;
 | |
|     mLastChild = prev;
 | |
|   } else {
 | |
|     // Hand the whole list over to our new list
 | |
|     newFirstFrame = mFirstChild;
 | |
|     newLastFrame = mLastChild;
 | |
|     Clear();
 | |
|   }
 | |
| 
 | |
|   // Now make sure aLink doesn't point to a frame we no longer have.
 | |
|   aLink.mFrame = nullptr;
 | |
| 
 | |
|   MOZ_ASSERT(aLink.AtEnd(), "What's going on here?");
 | |
| 
 | |
|   return nsFrameList(newFirstFrame, newLastFrame);
 | |
| }
 | |
| 
 | |
| nsIFrame* nsFrameList::FrameAt(int32_t aIndex) const {
 | |
|   MOZ_ASSERT(aIndex >= 0, "invalid arg");
 | |
|   if (aIndex < 0) return nullptr;
 | |
|   nsIFrame* frame = mFirstChild;
 | |
|   while ((aIndex-- > 0) && frame) {
 | |
|     frame = frame->GetNextSibling();
 | |
|   }
 | |
|   return frame;
 | |
| }
 | |
| 
 | |
| int32_t nsFrameList::IndexOf(nsIFrame* aFrame) const {
 | |
|   int32_t count = 0;
 | |
|   for (nsIFrame* f = mFirstChild; f; f = f->GetNextSibling()) {
 | |
|     if (f == aFrame) return count;
 | |
|     ++count;
 | |
|   }
 | |
|   return -1;
 | |
| }
 | |
| 
 | |
| bool nsFrameList::ContainsFrame(const nsIFrame* aFrame) const {
 | |
|   MOZ_ASSERT(aFrame, "null ptr");
 | |
| 
 | |
|   nsIFrame* frame = mFirstChild;
 | |
|   while (frame) {
 | |
|     if (frame == aFrame) {
 | |
|       return true;
 | |
|     }
 | |
|     frame = frame->GetNextSibling();
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| int32_t nsFrameList::GetLength() const {
 | |
|   int32_t count = 0;
 | |
|   nsIFrame* frame = mFirstChild;
 | |
|   while (frame) {
 | |
|     count++;
 | |
|     frame = frame->GetNextSibling();
 | |
|   }
 | |
|   return count;
 | |
| }
 | |
| 
 | |
| void nsFrameList::ApplySetParent(nsContainerFrame* aParent) const {
 | |
|   NS_ASSERTION(aParent, "null ptr");
 | |
| 
 | |
|   for (nsIFrame* f = FirstChild(); f; f = f->GetNextSibling()) {
 | |
|     f->SetParent(aParent);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /* static */ void nsFrameList::UnhookFrameFromSiblings(nsIFrame* aFrame) {
 | |
|   MOZ_ASSERT(aFrame->GetPrevSibling() && aFrame->GetNextSibling());
 | |
|   nsIFrame* const nextSibling = aFrame->GetNextSibling();
 | |
|   nsIFrame* const prevSibling = aFrame->GetPrevSibling();
 | |
|   aFrame->SetNextSibling(nullptr);
 | |
|   prevSibling->SetNextSibling(nextSibling);
 | |
|   MOZ_ASSERT(!aFrame->GetPrevSibling() && !aFrame->GetNextSibling());
 | |
| }
 | |
| 
 | |
| #ifdef DEBUG_FRAME_DUMP
 | |
| void nsFrameList::List(FILE* out) const {
 | |
|   fprintf_stderr(out, "<\n");
 | |
|   for (nsIFrame* frame = mFirstChild; frame; frame = frame->GetNextSibling()) {
 | |
|     frame->List(out, "  ");
 | |
|   }
 | |
|   fprintf_stderr(out, ">\n");
 | |
| }
 | |
| #endif
 | |
| 
 | |
| nsIFrame* nsFrameList::GetPrevVisualFor(nsIFrame* aFrame) const {
 | |
|   if (!mFirstChild) return nullptr;
 | |
| 
 | |
|   nsIFrame* parent = mFirstChild->GetParent();
 | |
|   if (!parent) return aFrame ? aFrame->GetPrevSibling() : LastChild();
 | |
| 
 | |
|   nsBidiDirection paraDir = nsBidiPresUtils::ParagraphDirection(mFirstChild);
 | |
| 
 | |
|   nsAutoLineIterator iter = parent->GetLineIterator();
 | |
|   if (!iter) {
 | |
|     // Parent is not a block Frame
 | |
|     if (parent->IsLineFrame()) {
 | |
|       // Line frames are not bidi-splittable, so need to consider bidi
 | |
|       // reordering
 | |
|       if (paraDir == NSBIDI_LTR) {
 | |
|         return nsBidiPresUtils::GetFrameToLeftOf(aFrame, mFirstChild, -1);
 | |
|       } else {  // RTL
 | |
|         return nsBidiPresUtils::GetFrameToRightOf(aFrame, mFirstChild, -1);
 | |
|       }
 | |
|     } else {
 | |
|       // Just get the next or prev sibling, depending on block and frame
 | |
|       // direction.
 | |
|       if (nsBidiPresUtils::IsFrameInParagraphDirection(mFirstChild)) {
 | |
|         return aFrame ? aFrame->GetPrevSibling() : LastChild();
 | |
|       } else {
 | |
|         return aFrame ? aFrame->GetNextSibling() : mFirstChild;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Parent is a block frame, so use the LineIterator to find the previous
 | |
|   // visual sibling on this line, or the last one on the previous line.
 | |
| 
 | |
|   int32_t thisLine;
 | |
|   if (aFrame) {
 | |
|     thisLine = iter->FindLineContaining(aFrame);
 | |
|     if (thisLine < 0) return nullptr;
 | |
|   } else {
 | |
|     thisLine = iter->GetNumLines();
 | |
|   }
 | |
| 
 | |
|   nsIFrame* frame = nullptr;
 | |
|   nsIFrame* firstFrameOnLine;
 | |
|   int32_t numFramesOnLine;
 | |
|   nsRect lineBounds;
 | |
| 
 | |
|   if (aFrame) {
 | |
|     iter->GetLine(thisLine, &firstFrameOnLine, &numFramesOnLine, lineBounds);
 | |
| 
 | |
|     if (paraDir == NSBIDI_LTR) {
 | |
|       frame = nsBidiPresUtils::GetFrameToLeftOf(aFrame, firstFrameOnLine,
 | |
|                                                 numFramesOnLine);
 | |
|     } else {  // RTL
 | |
|       frame = nsBidiPresUtils::GetFrameToRightOf(aFrame, firstFrameOnLine,
 | |
|                                                  numFramesOnLine);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (!frame && thisLine > 0) {
 | |
|     // Get the last frame of the previous line
 | |
|     iter->GetLine(thisLine - 1, &firstFrameOnLine, &numFramesOnLine,
 | |
|                   lineBounds);
 | |
| 
 | |
|     if (paraDir == NSBIDI_LTR) {
 | |
|       frame = nsBidiPresUtils::GetFrameToLeftOf(nullptr, firstFrameOnLine,
 | |
|                                                 numFramesOnLine);
 | |
|     } else {  // RTL
 | |
|       frame = nsBidiPresUtils::GetFrameToRightOf(nullptr, firstFrameOnLine,
 | |
|                                                  numFramesOnLine);
 | |
|     }
 | |
|   }
 | |
|   return frame;
 | |
| }
 | |
| 
 | |
| nsIFrame* nsFrameList::GetNextVisualFor(nsIFrame* aFrame) const {
 | |
|   if (!mFirstChild) return nullptr;
 | |
| 
 | |
|   nsIFrame* parent = mFirstChild->GetParent();
 | |
|   if (!parent) return aFrame ? aFrame->GetPrevSibling() : mFirstChild;
 | |
| 
 | |
|   nsBidiDirection paraDir = nsBidiPresUtils::ParagraphDirection(mFirstChild);
 | |
| 
 | |
|   nsAutoLineIterator iter = parent->GetLineIterator();
 | |
|   if (!iter) {
 | |
|     // Parent is not a block Frame
 | |
|     if (parent->IsLineFrame()) {
 | |
|       // Line frames are not bidi-splittable, so need to consider bidi
 | |
|       // reordering
 | |
|       if (paraDir == NSBIDI_LTR) {
 | |
|         return nsBidiPresUtils::GetFrameToRightOf(aFrame, mFirstChild, -1);
 | |
|       } else {  // RTL
 | |
|         return nsBidiPresUtils::GetFrameToLeftOf(aFrame, mFirstChild, -1);
 | |
|       }
 | |
|     } else {
 | |
|       // Just get the next or prev sibling, depending on block and frame
 | |
|       // direction.
 | |
|       if (nsBidiPresUtils::IsFrameInParagraphDirection(mFirstChild)) {
 | |
|         return aFrame ? aFrame->GetNextSibling() : mFirstChild;
 | |
|       } else {
 | |
|         return aFrame ? aFrame->GetPrevSibling() : LastChild();
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Parent is a block frame, so use the LineIterator to find the next visual
 | |
|   // sibling on this line, or the first one on the next line.
 | |
| 
 | |
|   int32_t thisLine;
 | |
|   if (aFrame) {
 | |
|     thisLine = iter->FindLineContaining(aFrame);
 | |
|     if (thisLine < 0) return nullptr;
 | |
|   } else {
 | |
|     thisLine = -1;
 | |
|   }
 | |
| 
 | |
|   nsIFrame* frame = nullptr;
 | |
|   nsIFrame* firstFrameOnLine;
 | |
|   int32_t numFramesOnLine;
 | |
|   nsRect lineBounds;
 | |
| 
 | |
|   if (aFrame) {
 | |
|     iter->GetLine(thisLine, &firstFrameOnLine, &numFramesOnLine, lineBounds);
 | |
| 
 | |
|     if (paraDir == NSBIDI_LTR) {
 | |
|       frame = nsBidiPresUtils::GetFrameToRightOf(aFrame, firstFrameOnLine,
 | |
|                                                  numFramesOnLine);
 | |
|     } else {  // RTL
 | |
|       frame = nsBidiPresUtils::GetFrameToLeftOf(aFrame, firstFrameOnLine,
 | |
|                                                 numFramesOnLine);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   int32_t numLines = iter->GetNumLines();
 | |
|   if (!frame && thisLine < numLines - 1) {
 | |
|     // Get the first frame of the next line
 | |
|     iter->GetLine(thisLine + 1, &firstFrameOnLine, &numFramesOnLine,
 | |
|                   lineBounds);
 | |
| 
 | |
|     if (paraDir == NSBIDI_LTR) {
 | |
|       frame = nsBidiPresUtils::GetFrameToRightOf(nullptr, firstFrameOnLine,
 | |
|                                                  numFramesOnLine);
 | |
|     } else {  // RTL
 | |
|       frame = nsBidiPresUtils::GetFrameToLeftOf(nullptr, firstFrameOnLine,
 | |
|                                                 numFramesOnLine);
 | |
|     }
 | |
|   }
 | |
|   return frame;
 | |
| }
 | |
| 
 | |
| #ifdef DEBUG_FRAME_LIST
 | |
| void nsFrameList::VerifyList() const {
 | |
|   NS_ASSERTION((mFirstChild == nullptr) == (mLastChild == nullptr),
 | |
|                "bad list state");
 | |
| 
 | |
|   if (IsEmpty()) {
 | |
|     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
 | |
|   NS_ASSERTION(!mFirstChild->GetPrevSibling(), "bad prev sibling pointer");
 | |
|   nsIFrame *first = mFirstChild, *second = mFirstChild;
 | |
|   for (;;) {
 | |
|     first = first->GetNextSibling();
 | |
|     second = second->GetNextSibling();
 | |
|     if (!second) {
 | |
|       break;
 | |
|     }
 | |
|     NS_ASSERTION(second->GetPrevSibling()->GetNextSibling() == second,
 | |
|                  "bad prev sibling pointer");
 | |
|     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.");
 | |
|       return;
 | |
|     }
 | |
|     if (!second) {
 | |
|       break;
 | |
|     }
 | |
|     NS_ASSERTION(second->GetPrevSibling()->GetNextSibling() == second,
 | |
|                  "bad prev sibling pointer");
 | |
|   }
 | |
| 
 | |
|   NS_ASSERTION(mLastChild == nsLayoutUtils::GetLastSibling(mFirstChild),
 | |
|                "bogus mLastChild");
 | |
|   // XXX we should also assert that all GetParent() are either null or
 | |
|   // the same non-null value, but nsCSSFrameConstructor::nsFrameItems
 | |
|   // prevents that, e.g. table captions.
 | |
| }
 | |
| #endif
 | |
| 
 | |
| namespace mozilla {
 | |
| namespace layout {
 | |
| 
 | |
| AutoFrameListPtr::~AutoFrameListPtr() {
 | |
|   if (mFrameList) {
 | |
|     mFrameList->Delete(mPresContext->PresShell());
 | |
|   }
 | |
| }
 | |
| 
 | |
| }  // namespace layout
 | |
| }  // namespace mozilla
 |