From: L. David Baron Bug 1110277 patch 5 - Pass the aAllowLazyConstruction parameter through to ReframeContainingBlock so that we don't do lazy reconstruction when it is forbidden. Note that this presumes that lazy reconstruction is forbidden inside ContentRemoved, which matches the caller to RecreateFramesForContent already in ContentRemoved, but which is perhaps suboptimal and should be passed to ContentRemoved explicitly. (Then again, maybe it *should* always be false?) This patch alone fixes the bug by making transitions still start correctly when the reframe occurs. (We explicitly suppress lazy frame construction in RestyleManager::ProcessRestyledFrames; one of the reasons we do so is so that we can start transitions correctly on elements that are being reframed.) diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -8041,17 +8041,17 @@ nsCSSFrameConstructor::ContentRemoved(ns } if (childFrame) { InvalidateCanvasIfNeeded(mPresShell, aChild); // See whether we need to remove more than just childFrame LAYOUT_PHASE_TEMP_EXIT(); nsIContent* container; - if (MaybeRecreateContainerForFrameRemoval(childFrame, aFlags, &rv, &container)) { + if (MaybeRecreateContainerForFrameRemoval(childFrame, aFlags, &rv, &container, false)) { LAYOUT_PHASE_TEMP_REENTER(); MOZ_ASSERT(container); *aDidReconstruct = true; if (aDestroyedFramesFor) { *aDestroyedFramesFor = container; } return rv; } @@ -8996,17 +8996,18 @@ FindPreviousNonWhitespaceSibling(nsIFram f->GetContent()->TextIsOnlyWhitespace()); return f; } bool nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame, RemoveFlags aFlags, nsresult* aResult, - nsIContent** aDestroyedFramesFor) + nsIContent** aDestroyedFramesFor, + bool aAllowLazyConstruction) { NS_PRECONDITION(aFrame, "Must have a frame"); NS_PRECONDITION(aFrame->GetParent(), "Frame shouldn't be root"); NS_PRECONDITION(aResult, "Null out param?"); NS_PRECONDITION(aFrame == aFrame->FirstContinuation(), "aFrame not the result of GetPrimaryFrame()?"); *aDestroyedFramesFor = nullptr; @@ -9018,17 +9019,18 @@ nsCSSFrameConstructor::MaybeRecreateCont if (gNoisyContentUpdates) { printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: " "frame="); nsFrame::ListTag(stdout, aFrame); printf(" is ib-split\n"); } #endif - *aResult = ReframeContainingBlock(aFrame, aFlags, aDestroyedFramesFor); + *aResult = ReframeContainingBlock(aFrame, aFlags, aDestroyedFramesFor, + aAllowLazyConstruction); return true; } nsContainerFrame* insertionFrame = aFrame->GetContentInsertionFrame(); if (insertionFrame && insertionFrame->GetType() == nsGkAtoms::legendFrame && aFrame->GetParent()->GetType() == nsGkAtoms::fieldSetFrame) { // When we remove the legend for a fieldset, we should reframe // the fieldset to ensure another legend is used, if there is one @@ -9180,17 +9182,18 @@ nsCSSFrameConstructor::MaybeRecreateCont if (gNoisyContentUpdates) { printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: " "frame="); nsFrame::ListTag(stdout, parent); printf(" is ib-split\n"); } #endif - *aResult = ReframeContainingBlock(parent, aFlags, aDestroyedFramesFor); + *aResult = ReframeContainingBlock(parent, aFlags, aDestroyedFramesFor, + aAllowLazyConstruction); return true; } nsresult nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent, bool aAsyncInsert, RemoveFlags aFlags, nsIContent** aDestroyedFramesFor) @@ -9264,17 +9267,18 @@ nsCSSFrameConstructor::RecreateFramesFor return RecreateFramesForContent(parentContent, aAsyncInsert, aFlags, aDestroyedFramesFor); } } nsresult rv = NS_OK; nsIContent* container; if (frame && MaybeRecreateContainerForFrameRemoval(frame, aFlags, &rv, - &container)) { + &container, + aAsyncInsert)) { MOZ_ASSERT(container); if (aDestroyedFramesFor) { *aDestroyedFramesFor = container; } return rv; } nsINode* containerNode = aContent->GetParentNode(); @@ -11893,17 +11897,18 @@ nsCSSFrameConstructor::WipeContainingBlo RecreateFramesForContent(blockContent, aAllowLazyConstruction, REMOVE_FOR_RECONSTRUCTION, nullptr); return true; } nsresult nsCSSFrameConstructor::ReframeContainingBlock(nsIFrame* aFrame, RemoveFlags aFlags, - nsIContent** aDestroyedFramesFor) + nsIContent** aDestroyedFramesFor, + bool aAllowLazyConstruction) { #ifdef DEBUG // ReframeContainingBlock is a NASTY routine, it causes terrible performance problems // so I want to see when it is happening! Unfortunately, it is happening way to often because // so much content on the web causes block-in-inline frame situations and we handle them // very poorly if (gNoisyContentUpdates) { @@ -11936,23 +11941,24 @@ nsCSSFrameConstructor::ReframeContaining // And get the containingBlock's content nsCOMPtr blockContent = containingBlock->GetContent(); if (blockContent) { #ifdef DEBUG if (gNoisyContentUpdates) { printf(" ==> blockContent=%p\n", static_cast(blockContent)); } #endif - return RecreateFramesForContent(blockContent, true, aFlags, aDestroyedFramesFor); + return RecreateFramesForContent(blockContent, aAllowLazyConstruction, + aFlags, aDestroyedFramesFor); } } // If we get here, we're screwed! return RecreateFramesForContent(mPresShell->GetDocument()->GetRootElement(), - true, aFlags, nullptr); + aAllowLazyConstruction, aFlags, nullptr); } nsresult nsCSSFrameConstructor::GenerateChildFrames(nsContainerFrame* aFrame) { { nsAutoScriptBlocker scriptBlocker; BeginUpdate(); diff --git a/layout/base/nsCSSFrameConstructor.h b/layout/base/nsCSSFrameConstructor.h --- a/layout/base/nsCSSFrameConstructor.h +++ b/layout/base/nsCSSFrameConstructor.h @@ -1604,17 +1604,18 @@ private: // this method returns false, the value of *aResult is not affected. aFrame // and aResult must not be null. aFrame must be the result of a // GetPrimaryFrame() call on a content node (which means its parent is also // not null). If this method returns true, aDestroyedFramesFor contains the // content that was reframed. bool MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame, RemoveFlags aFlags, nsresult* aResult, - nsIContent** aDestroyedFramesFor); + nsIContent** aDestroyedFramesFor, + bool aAllowLazyConstruction); nsIFrame* CreateContinuingOuterTableFrame(nsIPresShell* aPresShell, nsPresContext* aPresContext, nsIFrame* aFrame, nsContainerFrame* aParentFrame, nsIContent* aContent, nsStyleContext* aStyleContext); @@ -1733,17 +1734,18 @@ private: nsIFrame* aFrame, FrameConstructionItemList& aItems, bool aIsAppend, nsIFrame* aPrevSibling, bool aAllowLazyConstruction); nsresult ReframeContainingBlock(nsIFrame* aFrame, RemoveFlags aFlags, - nsIContent** aReframeContent); + nsIContent** aReframeContent, + bool aAllowLazyConstruction); //---------------------------------------- // Methods support :first-letter style void CreateFloatingLetterFrame(nsFrameConstructorState& aState, nsContainerFrame* aBlockFrame, nsIContent* aTextContent,