Bug 1429961: Make sure to remove all the continuations with the same PostDestroyData. r?mats draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Mon, 15 Jan 2018 16:40:26 +0100
changeset 720419 68e09413d4b6c25f4af9f95503297c358b247ab3
parent 720417 226d891924cd581a709cb5759b4be19355137b5b
child 720610 e2e2717b1c58b5ff31e391b5fb21065d07067b81
child 720620 623dc3b0ade6cda9bdd9a2ec6cc9b57c67d37f29
push id95546
push userbmo:emilio@crisal.io
push dateMon, 15 Jan 2018 15:44:57 +0000
reviewersmats
bugs1429961
milestone59.0a1
Bug 1429961: Make sure to remove all the continuations with the same PostDestroyData. r?mats If we remove the first continuation of the ::after content before the last, before this patch unbind the generated content ASAP. Part of the generated content (the second counter) in the test-case ends up in a continuation of that frame. That text node would already be unbound from the tree when destroying its frame. MozReview-Commit-ID: 4VtVRSoGxCT
layout/generic/nsContainerFrame.cpp
layout/generic/nsIFrame.h
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -156,24 +156,25 @@ nsContainerFrame::RemoveFrame(ChildListI
   // Request a reflow on the parent frames involved unless we were explicitly
   // told not to (kNoReflowPrincipalList).
   bool generateReflowCommand = true;
   if (kNoReflowPrincipalList == aListID) {
     generateReflowCommand = false;
   }
   nsIPresShell* shell = PresShell();
   nsContainerFrame* lastParent = nullptr;
+  AutoPostDestroyData data(PresContext());
   while (aOldFrame) {
     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);
-    aOldFrame->Destroy();
+    aOldFrame->Destroy(data.mData);
     aOldFrame = oldFrameNextContinuation;
     if (parent != lastParent && generateReflowCommand) {
       shell->FrameNeedsReflow(parent, nsIPresShell::eTreeChange,
                               NS_FRAME_HAS_DIRTY_CHILDREN);
       lastParent = parent;
     }
   }
 }
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -679,17 +679,25 @@ public:
    * Destroy() for each child). If this frame is a first-continuation, this
    * also removes the frame from the primary frame map and clears undisplayed
    * content for its content node.
    * If the frame is a placeholder, it also ensures the out-of-flow frame's
    * removal and destruction.
    */
   void Destroy() {
     AutoPostDestroyData data(PresContext());
-    DestroyFrom(this, data.mData);
+    Destroy(data.mData);
+    // Note that |this| is deleted at this point.
+  }
+
+  /**
+   * Pretty much like Destroy() but with a provided PostDestroyData.
+   */
+  void Destroy(PostDestroyData& aPostDestroyData) {
+    DestroyFrom(this, aPostDestroyData);
     // Note that |this| is deleted at this point.
   }
 
   /** Flags for PeekOffsetCharacter, PeekOffsetNoAmount, PeekOffsetWord return values.
     */
   enum FrameSearchResult {
     // Peek found a appropriate offset within frame.
     FOUND = 0x00,