Bug 1459937 - In DEBUG mode, verify that reparenting direction is correct - r=dbaron
MozReview-Commit-ID: JPfg9YtBm6M
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -618,44 +618,70 @@ ReparentFrameInternal(nsIFrame* aFrame,
}
// When pushing and pulling frames we need to check for whether any
// views need to be reparented
nsContainerFrame::ReparentFrameView(aFrame, aOldParent, aNewParent);
}
static bool
-ShouldMarkReparentedFramesDirty(nsIFrame* aNewParent,
- ReparentingDirection aDirection)
-{
+ShouldMarkReparentedFramesDirty(
+#ifdef DEBUG
+ nsContainerFrame* aOldParent,
+#endif
+ nsIFrame* aNewParent,
+ ReparentingDirection aDirection)
+{
+#ifdef DEBUG
+ MOZ_ASSERT(aOldParent->FirstInFlow() == aNewParent->FirstInFlow(),
+ "Reparenting should be between continuations of the same frame");
+ if (aDirection != ReparentingDirection::Variable &&
+ aOldParent->FirstInFlow() == aNewParent->FirstInFlow()) {
+ auto IndexInFlow =
+ [](const nsIFrame* f) {
+ int i = 0; while ((f = f->GetPrevInFlow())) { ++i; } return i;
+ };
+ MOZ_ASSERT((IndexInFlow(aOldParent) < IndexInFlow(aNewParent)) ==
+ (aDirection == ReparentingDirection::Forwards),
+ "Parents not in expected order");
+ }
+#endif
// Frames going forward must have already been reflowed, or at least marked
// dirty. Otherwise frames going backwards (or direction is unknown) may not
// be marked dirty yet.
return (aDirection != ReparentingDirection::Forwards) &&
(aNewParent->GetStateBits() & NS_FRAME_IS_DIRTY);
}
// Because a frame with NS_FRAME_IS_DIRTY marks all of its children dirty at
// the start of its reflow, when we move a frame from a later frame backwards to
// an earlier frame, and the earlier frame has NS_FRAME_IS_DIRTY (though that
// should corresponded with the later frame having NS_FRAME_IS_DIRTY), we need
// to add NS_FRAME_IS_DIRTY to the reparented frame.
static void
ReparentFrame(nsIFrame* aFrame, nsContainerFrame* aOldParent,
nsContainerFrame* aNewParent, ReparentingDirection aDirection)
{
- const bool markDirty = ShouldMarkReparentedFramesDirty(aNewParent, aDirection);
+ const bool markDirty = ShouldMarkReparentedFramesDirty(
+#ifdef DEBUG
+ aOldParent,
+#endif
+ aNewParent, aDirection);
ReparentFrameInternal(aFrame, aOldParent, aNewParent, markDirty);
}
static void
ReparentFrames(nsFrameList& aFrameList, nsContainerFrame* aOldParent,
nsContainerFrame* aNewParent, ReparentingDirection aDirection)
{
- const bool markDirty = ShouldMarkReparentedFramesDirty(aNewParent, aDirection);
+ const bool markDirty = ShouldMarkReparentedFramesDirty(
+#ifdef DEBUG
+ aOldParent,
+#endif
+ aNewParent, aDirection);
for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
ReparentFrameInternal(e.get(), aOldParent, aNewParent, markDirty);
}
}
/**
* Remove the first line from aFromLines and adjust the associated frame list
* aFromFrames accordingly. The removed line is assigned to *aOutLine and