Bug 1153478 part 1 - Add nsInlineFrame::StealFrame and make it deal with being called on the wrong parent for aChild (due to lazy reparenting). r=roc

This commit is contained in:
Mats Palmgren 2015-04-16 09:04:19 +00:00
parent d3c0c2098b
commit 6fe94a0e3d
3 changed files with 43 additions and 4 deletions

View File

@ -142,12 +142,11 @@ nsContainerFrame::RemoveFrame(ChildListID aListID,
nsIPresShell* shell = PresContext()->PresShell();
nsContainerFrame* lastParent = nullptr;
while (aOldFrame) {
//XXXfr probably should use StealFrame here. I'm not sure if we need to
// check the overflow lists atm, but we'll need a prescontext lookup
// for overflow containers once we can split abspos elements with
// inline containing blocks.
nsIFrame* oldFrameNextContinuation = aOldFrame->GetNextContinuation();
nsContainerFrame* parent = aOldFrame->GetParent();
// Please note that 'parent' may not actually be where 'aOldFrame' lives.
// We really MUST use StealFrame() and nothing else here.
// @see nsInlineFrame::StealFrame for details.
parent->StealFrame(aOldFrame, true);
aOldFrame->Destroy();
aOldFrame = oldFrameNextContinuation;

View File

@ -204,6 +204,45 @@ nsInlineFrame::DestroyFrom(nsIFrame* aDestructRoot)
nsContainerFrame::DestroyFrom(aDestructRoot);
}
nsresult
nsInlineFrame::StealFrame(nsIFrame* aChild,
bool aForceNormal)
{
if (aChild->HasAnyStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER) &&
!aForceNormal) {
return nsContainerFrame::StealFrame(aChild, aForceNormal);
}
nsInlineFrame* parent = this;
bool removed = false;
do {
removed = parent->mFrames.StartRemoveFrame(aChild);
if (removed) {
break;
}
// We didn't find the child in our principal child list.
// Maybe it's on the overflow list?
nsFrameList* frameList = parent->GetOverflowFrames();
if (frameList) {
removed = frameList->ContinueRemoveFrame(aChild);
if (frameList->IsEmpty()) {
parent->DestroyOverflowList();
}
if (removed) {
break;
}
}
// Due to our "lazy reparenting" optimization 'aChild' might not actually
// be on any of our child lists, but instead in one of our next-in-flows.
parent = static_cast<nsInlineFrame*>(parent->GetNextInFlow());
} while (parent);
MOZ_ASSERT(removed, "nsInlineFrame::StealFrame: can't find aChild");
return removed ? NS_OK : NS_ERROR_UNEXPECTED;
}
void
nsInlineFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,

View File

@ -64,6 +64,7 @@ public:
bool aRespectClusters = true) override;
virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
virtual nsresult StealFrame(nsIFrame* aChild, bool aForceNormal) override;
// nsIHTMLReflow overrides
virtual void AddInlineMinISize(nsRenderingContext *aRenderingContext,