Bug 1414397 - Make sure we properly invalidate the entire frame subtree when detecting a caret frame change. r=miko
authorMatt Woodrow <mwoodrow@mozilla.com>
Wed, 08 Nov 2017 15:33:34 +1300
changeset 390697 574db20bdf3e8b013b3575fc154621213a6aa8a6
parent 390696 7c87b438511359c8792273d261d3bed546c9b530
child 390698 c0e806b7a992dc9e8f608df3e6380bce574eb791
push id32839
push usernbeleuzu@mozilla.com
push dateWed, 08 Nov 2017 10:51:56 +0000
treeherdermozilla-central@f63559d7e6a5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmiko
bugs1414397
milestone58.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1414397 - Make sure we properly invalidate the entire frame subtree when detecting a caret frame change. r=miko
layout/generic/nsFrame.cpp
layout/generic/nsSubDocumentFrame.cpp
layout/painting/nsDisplayList.h
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2805,17 +2805,17 @@ nsIFrame::BuildDisplayListForStackingCon
       hasOverrideDirtyRect = true;
     }
   }
   // Always build the entire display list if we previously had a blend
   // container since a partial build might make us think we no longer
   // need the container even though the merged result will.
   if (aBuilder->IsRetainingDisplayList() && BuiltBlendContainer()) {
     dirtyRect = visibleRect;
-    aBuilder->MarkFrameModifiedDuringBuilding(this);
+    aBuilder->MarkCurrentFrameModifiedDuringBuilding();
   }
 
   bool usingFilter = StyleEffects()->HasFilters();
   bool usingMask = nsSVGIntegrationUtils::UsingMaskOrClipPathForFrame(this);
   bool usingSVGEffects = usingFilter || usingMask;
 
   nsRect visibleRectOutsideSVGEffects = visibleRect;
   nsDisplayList hoistedScrollInfoItemsStorage(aBuilder);
@@ -2968,17 +2968,17 @@ nsIFrame::BuildDisplayListForStackingCon
     // repeating display list building if it changed.
 
     // If we changed whether we're going to build a blend mode item,
     // then we need to make sure we're marked as invalid and we've built
     // the full display list.
     if (aBuilder->ContainsBlendMode() != BuiltBlendContainer() &&
         aBuilder->IsRetainingDisplayList()) {
       SetBuiltBlendContainer(aBuilder->ContainsBlendMode());
-      aBuilder->MarkFrameModifiedDuringBuilding(this);
+      aBuilder->MarkCurrentFrameModifiedDuringBuilding();
 
       // If we did a partial build then delete all the items we just built
       // and repeat building with the full area.
       if (!aBuilder->GetDirtyRect().Contains(aBuilder->GetVisibleRect())) {
         aBuilder->SetDirtyRect(aBuilder->GetVisibleRect());
         set.DeleteAll(aBuilder);
 
         if (eventRegions) {
--- a/layout/generic/nsSubDocumentFrame.cpp
+++ b/layout/generic/nsSubDocumentFrame.cpp
@@ -457,28 +457,28 @@ nsSubDocumentFrame::BuildDisplayList(nsD
     // The value of needsOwnLayer can change between builds without
     // an invalidation recorded for this frame (like if the root
     // scrollframe becomes active). If this happens,
     // then we need to notify the builder so that merging can
     // happen correctly.
     if (!mPreviouslyNeededLayer ||
         mPreviouslyNeededLayer.value() != needsOwnLayer) {
       dirty = visible;
-      aBuilder->MarkFrameModifiedDuringBuilding(this);
+      aBuilder->MarkCurrentFrameModifiedDuringBuilding();
     }
     mPreviouslyNeededLayer = Some(needsOwnLayer);
 
     // Caret frame changed, rebuild the entire subdoc.
     // We could just invalidate the old and new frame
     // areas and save some work here. RetainedDisplayListBuilder
     // does this, so we could teach it to find and check all
     // subdocs in advance.
     if (mPreviousCaret != aBuilder->GetCaretFrame()) {
       dirty = visible;
-      aBuilder->MarkFrameModifiedDuringBuilding(this);
+      aBuilder->MarkCurrentFrameModifiedDuringBuilding();
     }
     mPreviousCaret = aBuilder->GetCaretFrame();
   }
 
   nsDisplayList childItems(aBuilder);
 
   {
     DisplayListClipState::AutoSaveRestore nestedClipState(aBuilder);
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -1602,16 +1602,26 @@ public:
     mBuildingInvisibleItems = aBuildingInvisibleItems;
   }
 
   bool MarkFrameModifiedDuringBuilding(nsIFrame* aFrame)
   {
     if (!aFrame->IsFrameModified()) {
       mModifiedFramesDuringBuilding.AppendElement(aFrame);
       aFrame->SetFrameIsModified(true);
+      mInInvalidSubtree = true;
+      return true;
+    }
+    return false;
+  }
+
+  bool MarkCurrentFrameModifiedDuringBuilding()
+  {
+    if (MarkFrameModifiedDuringBuilding(const_cast<nsIFrame*>(mCurrentFrame))) {
+      mInInvalidSubtree = true;
       return true;
     }
     return false;
   }
 
   /**
    * This is a convenience function to ease the transition until AGRs and ASRs
    * are unified.