Bug 1321284 - Part 5: Process document level NAC when restyling. r=bholley draft
authorCameron McCormack <cam@mcc.id.au>
Thu, 01 Dec 2016 16:19:50 +0800
changeset 447240 30d6f5b3b32c921ae15e69b29a9cc3d5372ad8bc
parent 447239 3e479a152c1cafabb2ee4c0d8941fd872274ba28
child 539004 bdf9ba5c13c701ca10119ee7bb94ecb69fa1493b
push id38026
push userbmo:cam@mcc.id.au
push dateSat, 03 Dec 2016 07:08:17 +0000
reviewersbholley
bugs1321284
milestone53.0a1
Bug 1321284 - Part 5: Process document level NAC when restyling. r=bholley MozReview-Commit-ID: GigSrTHXXte
layout/base/RestyleManagerHandleInlines.h
layout/base/ServoRestyleManager.cpp
layout/base/ServoRestyleManager.h
layout/base/ServoRestyleManagerInlines.h
layout/base/moz.build
layout/base/nsPresContext.cpp
layout/style/ServoStyleSet.cpp
--- a/layout/base/RestyleManagerHandleInlines.h
+++ b/layout/base/RestyleManagerHandleInlines.h
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_RestyleManagerHandleInlines_h
 #define mozilla_RestyleManagerHandleInlines_h
 
 #include "mozilla/RestyleManager.h"
 #include "mozilla/ServoRestyleManager.h"
+#include "mozilla/ServoRestyleManagerInlines.h"
 
 #define FORWARD_CONCRETE(method_, geckoargs_, servoargs_) \
   if (IsGecko()) { \
     return AsGecko()->method_ geckoargs_; \
   } else { \
     return AsServo()->method_ servoargs_; \
   }
 
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -1,16 +1,19 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * 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/ServoRestyleManagerInlines.h"
 #include "mozilla/ServoStyleSet.h"
 #include "mozilla/dom/ChildIterator.h"
 #include "nsContentUtils.h"
 #include "nsPrintfCString.h"
 #include "nsStyleChangeList.h"
 
 using namespace mozilla::dom;
 
@@ -284,37 +287,38 @@ ServoRestyleManager::ProcessPendingResty
   }
 
   if (!HasPendingRestyles()) {
     return;
   }
 
   ServoStyleSet* styleSet = StyleSet();
   nsIDocument* doc = PresContext()->Document();
-  Element* root = doc->GetRootElement();
 
   // XXXbholley: Should this be while() per bug 1316247?
   if (HasPendingRestyles()) {
-    MOZ_ASSERT(root);
     mInStyleRefresh = true;
     styleSet->StyleDocument();
 
     // First do any queued-up frame creation. (see bugs 827239 and 997506).
     //
     // XXXEmilio I'm calling this to avoid random behavior changes, since we
     // delay frame construction after styling we should re-check once our
     // model is more stable whether we can skip this call.
     //
     // Note this has to be *after* restyling, because otherwise frame
     // construction will find unstyled nodes, and that's not funny.
     PresContext()->FrameConstructor()->CreateNeededFrames();
 
     // Recreate style contexts and queue up change hints.
     nsStyleChangeList currentChanges;
-    RecreateStyleContexts(root, nullptr, styleSet, currentChanges);
+    DocumentStyleRootIterator iter(doc);
+    while (Element* root = iter.GetNextStyleRoot()) {
+      RecreateStyleContexts(root, nullptr, styleSet, currentChanges);
+    }
 
     // Process the change hints.
     //
     // Unfortunately, the frame constructor can generate new change hints while
     // processing existing ones. We redirect those into a secondary queue and
     // iterate until there's nothing left.
     ReentrantChangeList newChanges;
     mReentrantChanges = &newChanges;
--- a/layout/base/ServoRestyleManager.h
+++ b/layout/base/ServoRestyleManager.h
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_ServoRestyleManager_h
 #define mozilla_ServoRestyleManager_h
 
+#include "mozilla/DocumentStyleRootIterator.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/RestyleManagerBase.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/ServoElementSnapshot.h"
 #include "nsChangeHint.h"
 #include "nsHashKeys.h"
 #include "nsINode.h"
 #include "nsISupportsImpl.h"
@@ -73,21 +74,17 @@ public:
                            const nsAttrValue* aNewValue);
 
   void AttributeChanged(dom::Element* aElement, int32_t aNameSpaceID,
                         nsIAtom* aAttribute, int32_t aModType,
                         const nsAttrValue* aOldValue);
 
   nsresult ReparentStyleContext(nsIFrame* aFrame);
 
-  bool HasPendingRestyles()
-  {
-    Element* root = PresContext()->Document()->GetRootElement();
-    return root && root->HasDirtyDescendantsForServo();
-  }
+  inline bool HasPendingRestyles();
 
 
   /**
    * Gets the appropriate frame given a content and a pseudo-element tag.
    *
    * Right now only supports a null tag, before or after. If the pseudo-element
    * is not null, the content needs to be an element.
    */
new file mode 100644
--- /dev/null
+++ b/layout/base/ServoRestyleManagerInlines.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef ServoRestyleManagerInlines_h
+#define ServoRestyleManagerInlines_h
+
+#include "ServoRestyleManager.h"
+
+#include "mozilla/dom/ElementInlines.h"
+
+namespace mozilla {
+
+using namespace dom;
+
+inline bool
+ServoRestyleManager::HasPendingRestyles()
+{
+  nsIDocument* doc = PresContext()->Document();
+  DocumentStyleRootIterator iter(doc);
+  while (Element* root = iter.GetNextStyleRoot()) {
+    if (root->ShouldTraverseForServo()) {
+      return true;
+    }
+  }
+  return false;
+}
+
+} // namespace mozilla
+
+#endif // ServoRestyleManagerInlines_h
--- a/layout/base/moz.build
+++ b/layout/base/moz.build
@@ -72,16 +72,17 @@ EXPORTS.mozilla += [
     'GeometryUtils.h',
     'OverflowChangedTracker.h',
     'RestyleLogging.h',
     'RestyleManager.h',
     'RestyleManagerBase.h',
     'RestyleManagerHandle.h',
     'RestyleManagerHandleInlines.h',
     'ServoRestyleManager.h',
+    'ServoRestyleManagerInlines.h',
     'StaticPresData.h',
 ]
 
 UNIFIED_SOURCES += [
     'AccessibleCaret.cpp',
     'AccessibleCaretEventHub.cpp',
     'AccessibleCaretManager.cpp',
     'FramePropertyTable.cpp',
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -71,16 +71,17 @@
 #include "nsContentUtils.h"
 #include "nsPIWindowRoot.h"
 #include "mozilla/Preferences.h"
 #include "gfxTextRun.h"
 #include "nsFontFaceUtils.h"
 #include "nsLayoutStylesheetCache.h"
 #include "mozilla/StyleSheet.h"
 #include "mozilla/StyleSheetInlines.h"
+#include "mozilla/ServoRestyleManagerInlines.h"
 
 #if defined(MOZ_WIDGET_GTK)
 #include "gfxPlatformGtk.h" // xxx - for UseFcFontList
 #endif
 
 
 // Needed for Start/Stop of Image Animation
 #include "imgIContainer.h"
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ServoStyleSet.h"
 
+#include "mozilla/DocumentStyleRootIterator.h"
 #include "mozilla/ServoRestyleManager.h"
 #include "mozilla/dom/ChildIterator.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsCSSPseudoElements.h"
 #include "nsIDocumentInlines.h"
 #include "nsPrintfCString.h"
 #include "nsStyleContext.h"
 #include "nsStyleSet.h"
@@ -41,17 +42,18 @@ ServoStyleSet::BeginShutdown()
   // frame tree has been destroyed, but before the script runners that delete
   // native anonymous content (which also could be holding on the RuleNodes)
   // have run.  By clearing style here, before the frame tree is destroyed,
   // the AllChildrenIterator will find the anonymous content.
   //
   // Note that this is pretty bad for performance; we should find a way to
   // get by with the ServoNodeDatas being dropped as part of the document
   // going away.
-  if (Element* root = mPresContext->Document()->GetRootElement()) {
+  DocumentStyleRootIterator iter(mPresContext->Document());
+  while (Element* root = iter.GetNextStyleRoot()) {
     ServoRestyleManager::ClearServoDataFromSubtree(root);
   }
 }
 
 void
 ServoStyleSet::Shutdown()
 {
   mRawSet = nullptr;
@@ -443,23 +445,24 @@ ServoStyleSet::HasStateDependentStyle(do
 {
   NS_WARNING("stylo: HasStateDependentStyle always returns zero!");
   return nsRestyleHint(0);
 }
 
 void
 ServoStyleSet::StyleDocument()
 {
-  // Grab the root.
-  nsIDocument* doc = mPresContext->Document();
-  Element* root = doc->GetRootElement();
-  MOZ_ASSERT(root);
-
-  // Restyle the document.
-  Servo_TraverseSubtree(root, mRawSet.get(), SkipRootBehavior::DontSkip);
+  // Restyle the document from the root element and each of the document level
+  // NAC subtree roots.
+  DocumentStyleRootIterator iter(mPresContext->Document());
+  while (Element* root = iter.GetNextStyleRoot()) {
+    if (root->ShouldTraverseForServo()) {
+      Servo_TraverseSubtree(root, mRawSet.get(), SkipRootBehavior::DontSkip);
+    }
+  }
 }
 
 void
 ServoStyleSet::StyleNewSubtree(nsIContent* aContent)
 {
   if (aContent->IsElement()) {
     Servo_TraverseSubtree(aContent->AsElement(), mRawSet.get(), SkipRootBehavior::DontSkip);
   }