From: L. David Baron Bug 1110277 patch 3 - Look for the GenConPseudos() property on the first continuation/ib-split so that we can find it when looking for the ::after frame. The change to GetAfterFrameForContent prevents the reframe that is part of the chain of events leading to this bug, and thus fixes the bug on its own. The change to GetBeforeFrameForContent seems desirable for symmetry. This probably needs somewhat careful review. We should examine: (1) what the rules for calling nsLayoutUtils::GetBeforeFrame and nsLayoutUtils::GetAfterFrame are, and whether both (or neither) need to be patched. (2) What the rules for which frame the GenConProperty() lives on, and whether we should adjust nsIFrame::GetGenConPseudos() to either do something more intelligent, or assert about callers. (We should probably clean up some of these things in a followup bug.) diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -1166,17 +1166,20 @@ nsLayoutUtils::GetChildListNameFor(nsIFr return id; } /*static*/ nsIFrame* nsLayoutUtils::GetBeforeFrameForContent(nsIFrame* aFrame, nsIContent* aContent) { - nsContainerFrame* genConParentFrame = aFrame->GetContentInsertionFrame(); + // We need to call GetGenConPseudos() on the first continuation/ib-split. + // Find it, for symmetry with GetAfterFrameForContent. + nsContainerFrame* genConParentFrame = + FirstContinuationOrIBSplitSibling(aFrame)->GetContentInsertionFrame(); if (!genConParentFrame) { return nullptr; } nsTArray* prop = genConParentFrame->GetGenConPseudos(); if (prop) { const nsTArray& pseudos(*prop); for (uint32_t i = 0; i < pseudos.Length(); ++i) { if (pseudos[i]->GetParent() == aContent && @@ -1202,35 +1205,38 @@ nsLayoutUtils::GetBeforeFrame(nsIFrame* { return GetBeforeFrameForContent(aFrame, aFrame->GetContent()); } /*static*/ nsIFrame* nsLayoutUtils::GetAfterFrameForContent(nsIFrame* aFrame, nsIContent* aContent) { - nsContainerFrame* genConParentFrame = aFrame->GetContentInsertionFrame(); + // We need to call GetGenConPseudos() on the first continuation, + // but callers are likely to pass the last. + nsContainerFrame* genConParentFrame = + FirstContinuationOrIBSplitSibling(aFrame)->GetContentInsertionFrame(); if (!genConParentFrame) { return nullptr; } nsTArray* prop = genConParentFrame->GetGenConPseudos(); if (prop) { const nsTArray& pseudos(*prop); for (uint32_t i = 0; i < pseudos.Length(); ++i) { if (pseudos[i]->GetParent() == aContent && pseudos[i]->Tag() == nsGkAtoms::mozgeneratedcontentafter) { return pseudos[i]->GetPrimaryFrame(); } } } // If the last child frame is a pseudo-frame, then try that. // Note that the frame we create for the generated content is also a // pseudo-frame and so don't drill down in that case. - nsIFrame* lastParentContinuation = - nsLayoutUtils::LastContinuationWithChild(genConParentFrame); + nsIFrame* lastParentContinuation = LastContinuationWithChild( + LastContinuationOrIBSplitSibling(genConParentFrame)); nsIFrame* childFrame = lastParentContinuation->GetLastChild(nsIFrame::kPrincipalList); if (childFrame && childFrame->IsPseudoFrame(aContent) && !childFrame->IsGeneratedContentFrame()) { return GetAfterFrameForContent(childFrame->FirstContinuation(), aContent); } return nullptr;