Bug 1437790: No need to reframe synchronously on chrome-flush-skin-caches. r=xidorn draft
authorEmilio Cobos Alvarez <emilio@crisal.io>
Wed, 14 Feb 2018 10:52:20 +1100
changeset 754718 ed232dabe7ad0e50cb450aa5697bef1742924084
parent 754625 456c88c7b26e077e4503bc1aa8a751f73fae4cef
child 754719 6eac8c0b9ef66be18d57935bb9c9f84b98539609
child 754720 718ecaf384f0ac1569b65af79141a5499464d97b
push id98965
push userxquan@mozilla.com
push dateWed, 14 Feb 2018 00:22:00 +0000
reviewersxidorn
bugs1437790
milestone60.0a1
Bug 1437790: No need to reframe synchronously on chrome-flush-skin-caches. r=xidorn
layout/base/PresShell.cpp
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -9206,20 +9206,20 @@ PresShell::WindowSizeMoveDone()
 #ifdef MOZ_XUL
 /*
  * It's better to add stuff to the |DidSetStyleContext| method of the
  * relevant frames than adding it here.  These methods should (ideally,
  * anyway) go away.
  */
 
 // Return value says whether to walk children.
-typedef bool (* frameWalkerFn)(nsIFrame *aFrame, void *aClosure);
+typedef bool (* frameWalkerFn)(nsIFrame *aFrame);
 
 static bool
-ReResolveMenusAndTrees(nsIFrame *aFrame, void *aClosure)
+ReResolveMenusAndTrees(nsIFrame *aFrame)
 {
   // Trees have a special style cache that needs to be flushed when
   // the theme changes.
   nsTreeBodyFrame *treeBody = do_QueryFrame(aFrame);
   if (treeBody)
     treeBody->ClearStyleAndImageCaches();
 
   // We deliberately don't re-resolve style on a menu's popup
@@ -9228,46 +9228,47 @@ ReResolveMenusAndTrees(nsIFrame *aFrame,
   // popup frames just get destroyed completely.
   nsMenuFrame* menu = do_QueryFrame(aFrame);
   if (menu)
     menu->CloseMenu(true);
   return true;
 }
 
 static bool
-ReframeImageBoxes(nsIFrame *aFrame, void *aClosure)
-{
-  nsStyleChangeList *list = static_cast<nsStyleChangeList*>(aClosure);
+ReframeImageBoxes(nsIFrame* aFrame)
+{
   if (aFrame->IsImageBoxFrame()) {
-    list->AppendChange(aFrame, aFrame->GetContent(),
-                       nsChangeHint_ReconstructFrame);
+    aFrame->PresContext()->RestyleManager()->PostRestyleEvent(
+        aFrame->GetContent()->AsElement(),
+        nsRestyleHint(0),
+        nsChangeHint_ReconstructFrame);
     return false; // don't walk descendants
   }
   return true; // walk descendants
 }
 
 static void
-WalkFramesThroughPlaceholders(nsPresContext *aPresContext, nsIFrame *aFrame,
-                              frameWalkerFn aFunc, void *aClosure)
-{
-  bool walkChildren = (*aFunc)(aFrame, aClosure);
+WalkFramesThroughPlaceholders(nsPresContext* aPresContext, nsIFrame *aFrame,
+                              frameWalkerFn aFunc)
+{
+  bool walkChildren = (*aFunc)(aFrame);
   if (!walkChildren)
     return;
 
   nsIFrame::ChildListIterator lists(aFrame);
   for (; !lists.IsDone(); lists.Next()) {
     nsFrameList::Enumerator childFrames(lists.CurrentList());
     for (; !childFrames.AtEnd(); childFrames.Next()) {
       nsIFrame* child = childFrames.get();
       if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
         // only do frames that are in flow, and recur through the
         // out-of-flows of placeholders.
         WalkFramesThroughPlaceholders(aPresContext,
                                       nsPlaceholderFrame::GetRealFrameFor(child),
-                                      aFunc, aClosure);
+                                      aFunc);
       }
     }
   }
 }
 #endif
 
 NS_IMETHODIMP
 PresShell::Observe(nsISupports* aSubject,
@@ -9276,47 +9277,28 @@ PresShell::Observe(nsISupports* aSubject
 {
   if (mIsDestroying) {
     NS_WARNING("our observers should have been unregistered by now");
     return NS_OK;
   }
 
 #ifdef MOZ_XUL
   if (!nsCRT::strcmp(aTopic, "chrome-flush-skin-caches")) {
-    nsIFrame *rootFrame = mFrameConstructor->GetRootFrame();
     // Need to null-check because "chrome-flush-skin-caches" can happen
     // at interesting times during startup.
-    if (rootFrame) {
+    if (nsIFrame* rootFrame = mFrameConstructor->GetRootFrame()) {
       NS_ASSERTION(mViewManager, "View manager must exist");
 
-      AutoWeakFrame weakRoot(rootFrame);
-      // Have to make sure that the content notifications are flushed before we
-      // start messing with the frame model; otherwise we can get content doubling.
-      mDocument->FlushPendingNotifications(FlushType::ContentAndNotify);
-
-      if (weakRoot.IsAlive()) {
-        WalkFramesThroughPlaceholders(mPresContext, rootFrame,
-                                      &ReResolveMenusAndTrees, nullptr);
-
-        // Because "chrome:" URL equality is messy, reframe image box
-        // frames (hack!).
-        nsStyleChangeList changeList(mPresContext->StyleSet()->BackendType());
-        WalkFramesThroughPlaceholders(mPresContext, rootFrame,
-                                      ReframeImageBoxes, &changeList);
-        // Mark ourselves as not safe to flush while we're doing frame
-        // construction.
-        {
-          nsAutoScriptBlocker scriptBlocker;
-          ++mChangeNestCount;
-          RestyleManager* restyleManager = mPresContext->RestyleManager();
-          restyleManager->ProcessRestyledFrames(changeList);
-          restyleManager->FlushOverflowChangedTracker();
-          --mChangeNestCount;
-        }
-      }
+      WalkFramesThroughPlaceholders(
+          mPresContext, rootFrame, ReResolveMenusAndTrees);
+
+      // Because "chrome:" URL equality is messy, reframe image box
+      // frames (hack!).
+      WalkFramesThroughPlaceholders(
+          mPresContext, rootFrame, ReframeImageBoxes);
     }
     return NS_OK;
   }
 #endif
 
   if (!nsCRT::strcmp(aTopic, "memory-pressure")) {
     if (!AssumeAllFramesVisible() && mPresContext->IsRootContentDocument()) {
       DoUpdateApproximateFrameVisibility(/* aRemoveOnly = */ true);