Bug 1374761 part 1. Properly restyle the viewport and its child anonymous box when we do a restyle. r=heycam
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 21 Jun 2017 11:45:12 -0400
changeset 365325 74d8ec6397ee08180e001cc516b34a59e68bcd9c
parent 365324 5c4c815e1ad575584c0c9dbf9350242406747d7d
child 365326 272a41ef0e3d64cc510424d0801142730302a0a4
push id91734
push userkwierso@gmail.com
push dateThu, 22 Jun 2017 01:05:37 +0000
treeherdermozilla-inbound@2576a0695305 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1374761
milestone56.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 1374761 part 1. Properly restyle the viewport and its child anonymous box when we do a restyle. r=heycam The child anon box may be an nsHTMLScrollFrame, a nsRootBoxFrame, or a nsSimplePageSequenceFrame. nsHTMLScrollFrame already knows how to deal with its anonymous box kids, nsRootBoxFrame doesn't have any, and the next changeset will deal with anon box kids of nsSimplePageSequenceFrame. MozReview-Commit-ID: 2ZV061EhRmc
layout/base/ServoRestyleManager.cpp
layout/base/nsCSSFrameConstructor.cpp
layout/generic/ViewportFrame.cpp
layout/generic/ViewportFrame.h
layout/generic/nsFrame.cpp
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ServoRestyleManager.h"
 
 #include "mozilla/DocumentStyleRootIterator.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/ServoStyleSet.h"
 #include "mozilla/Unused.h"
+#include "mozilla/ViewportFrame.h"
 #include "mozilla/dom/ChildIterator.h"
 #include "mozilla/dom/ElementInlines.h"
 #include "nsBlockFrame.h"
 #include "nsBulletFrame.h"
 #include "nsPlaceholderFrame.h"
 #include "nsContentUtils.h"
 #include "nsCSSFrameConstructor.h"
 #include "nsPrintfCString.h"
@@ -427,16 +428,25 @@ ServoRestyleManager::ProcessPostTraversa
       displayContentsNode->mStyle = newContext;
     }
 
     if (styleFrame) {
       styleFrame->UpdateStyleOfOwnedAnonBoxes(*aStyleSet, aChangeList, changeHint);
       UpdateFramePseudoElementStyles(styleFrame, *aStyleSet, aChangeList);
     }
 
+    if (!aElement->GetParent()) {
+      // This is the root.  Update styles on the viewport as needed.
+      ViewportFrame* viewport =
+        do_QueryFrame(mPresContext->PresShell()->GetRootFrame());
+      if (viewport) {
+        viewport->UpdateStyle(*aStyleSet, aChangeList);
+      }
+    }
+
     // Some changes to animations don't affect the computed style and yet still
     // require the layer to be updated. For example, pausing an animation via
     // the Web Animations API won't affect an element's style but still
     // requires to update the animation on the layer.
     //
     // We can sometimes reach this when the animated style is being removed.
     // Since AddLayerChangesForAnimation checks if |styleFrame| has a transform
     // style or not, we need to call it *after* setting |newContext| to
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -2756,16 +2756,18 @@ nsCSSFrameConstructor::ConstructRootFram
   ViewportFrame* viewportFrame =
     NS_NewViewportFrame(mPresShell, viewportPseudoStyle);
 
   // XXXbz do we _have_ to pass a null content pointer to that frame?
   // Would it really kill us to pass in the root element or something?
   // What would that break?
   viewportFrame->Init(nullptr, nullptr, nullptr);
 
+  viewportFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
+
   // Bind the viewport frame to the root view
   nsView* rootView = mPresShell->GetViewManager()->GetRootView();
   viewportFrame->SetView(rootView);
 
   viewportFrame->SyncFrameViewProperties(rootView);
   nsContainerFrame::SyncWindowProperties(mPresShell->GetPresContext(), viewportFrame,
                                          rootView, nullptr, nsContainerFrame::SET_ASYNC);
 
--- a/layout/generic/ViewportFrame.cpp
+++ b/layout/generic/ViewportFrame.cpp
@@ -410,15 +410,44 @@ ViewportFrame::ComputeCustomOverflow(nsO
     PresContext()->PresShell()->GetRootScrollFrameAsScrollable();
   if (rootScrollFrame && !rootScrollFrame->IsIgnoringViewportClipping()) {
     return false;
   }
 
   return nsContainerFrame::ComputeCustomOverflow(aOverflowAreas);
 }
 
+void
+ViewportFrame::UpdateStyle(ServoStyleSet& aStyleSet,
+                           nsStyleChangeList& aChangeList)
+{
+  nsStyleContext* oldContext = StyleContext();
+  nsIAtom* pseudo = oldContext->GetPseudo();
+  RefPtr<nsStyleContext> newContext =
+    aStyleSet.ResolveInheritingAnonymousBoxStyle(pseudo, nullptr);
+
+  // We're special because we have a null GetContent(), so don't call things
+  // like UpdateStyleOfOwnedChildFrame that try to append changes for the
+  // content to the change list.  Nor do we computed a changehint, since we have
+  // no way to apply it anyway.
+  newContext->EnsureSameStructsCached(oldContext);
+
+  MOZ_ASSERT(!GetNextContinuation(), "Viewport has continuations?");
+  SetStyleContext(newContext);
+
+  UpdateStyleOfOwnedAnonBoxes(aStyleSet, aChangeList, nsChangeHint_Empty);
+}
+
+void
+ViewportFrame::AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult)
+{
+  if (mFrames.NotEmpty()) {
+    aResult.AppendElement(mFrames.FirstChild());
+  }
+}
+
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 ViewportFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("Viewport"), aResult);
 }
 #endif
--- a/layout/generic/ViewportFrame.h
+++ b/layout/generic/ViewportFrame.h
@@ -67,16 +67,27 @@ public:
   /**
    * Adjust aReflowInput to account for scrollbars and pres shell
    * GetScrollPositionClampingScrollPortSizeSet and
    * GetContentDocumentFixedPositionMargins adjustments.
    * @return the rect to use as containing block rect
    */
   nsRect AdjustReflowInputAsContainingBlock(ReflowInput* aReflowInput) const;
 
+  /**
+   * Update our style (and recursively the styles of any anonymous boxes we
+   * might own)
+   */
+  void UpdateStyle(ServoStyleSet& aStyleSet, nsStyleChangeList& aChangeList);
+
+  /**
+   * Return our single anonymous box child.
+   */
+  void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override;
+
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
 protected:
   ViewportFrame(nsStyleContext* aContext, ClassID aID)
     : nsContainerFrame(aContext, aID)
     , mView(nullptr)
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -10203,17 +10203,18 @@ nsFrame::BoxMetrics() const
 void
 nsIFrame::UpdateStyleOfChildAnonBox(nsIFrame* aChildFrame,
                                     ServoStyleSet& aStyleSet,
                                     nsStyleChangeList& aChangeList,
                                     nsChangeHint aHintForThisFrame)
 {
   MOZ_ASSERT(aChildFrame->GetParent() == this,
              "This should only be used for children!");
-  MOZ_ASSERT(aChildFrame->GetContent() == GetContent(),
+  MOZ_ASSERT((!GetContent() && IsViewportFrame()) ||
+             aChildFrame->GetContent() == GetContent(),
              "What content node is it a frame for?");
   MOZ_ASSERT(!aChildFrame->GetPrevContinuation(),
              "Only first continuations should end up here");
 
   // We could force the caller to pass in the pseudo, since some callers know it
   // statically...  But this API is a bit nicer.
   nsIAtom* pseudo = aChildFrame->StyleContext()->GetPseudo();
   MOZ_ASSERT(nsCSSAnonBoxes::IsAnonBox(pseudo), "Child is not an anon box?");