Bug 1294572 - Drop Servo data in SetXBLInsertionParent, and call StyleNewSubtree after all bindings have been removed and applied. r=heycam
☠☠ backed out by dac601a343ca ☠ ☠
authorBobby Holley <bobbyholley@gmail.com>
Tue, 13 Dec 2016 19:11:28 -0800
changeset 325791 62ad968c5c5de657f732f8049baeddf0f93bffea
parent 325790 fd40189cf066ee07101a774c729e49b6b0d732e9
child 325792 dac601a343ca5591740aa77922f77313d9ec5a51
push id84799
push userbholley@mozilla.com
push dateWed, 14 Dec 2016 05:33:05 +0000
treeherdermozilla-inbound@62ad968c5c5d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1294572
milestone53.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 1294572 - Drop Servo data in SetXBLInsertionParent, and call StyleNewSubtree after all bindings have been removed and applied. r=heycam MozReview-Commit-ID: Iv7uyq4uQye
dom/base/FragmentOrElement.cpp
dom/xbl/nsXBLBinding.cpp
dom/xbl/nsXBLService.cpp
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -18,16 +18,17 @@
 #include "mozilla/dom/FragmentOrElement.h"
 
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/DeclarationBlockInlines.h"
 #include "mozilla/EffectSet.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStates.h"
+#include "mozilla/ServoRestyleManager.h"
 #include "mozilla/dom/Attr.h"
 #include "nsDOMAttributeMap.h"
 #include "nsIAtom.h"
 #include "mozilla/dom/NodeInfo.h"
 #include "mozilla/dom/Event.h"
 #include "nsIDocumentInlines.h"
 #include "nsIDocumentEncoder.h"
 #include "nsIDOMNodeList.h"
@@ -1107,16 +1108,22 @@ FragmentOrElement::SetXBLInsertionParent
     SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
     slots->mXBLInsertionParent = aContent;
   } else {
     nsDOMSlots *slots = GetExistingDOMSlots();
     if (slots) {
       slots->mXBLInsertionParent = nullptr;
     }
   }
+
+  // We just changed the flattened tree, so any Servo style data is now invalid.
+  // We rely on nsXBLService::LoadBindings to re-traverse the subtree afterwards.
+  if (IsElement() && AsElement()->HasServoData()) {
+    ServoRestyleManager::ClearServoDataFromSubtree(AsElement());
+  }
 }
 
 CustomElementData*
 FragmentOrElement::GetCustomElementData() const
 {
   nsDOMSlots *slots = GetExistingDOMSlots();
   if (slots) {
     return slots->mCustomElementData;
--- a/dom/xbl/nsXBLBinding.cpp
+++ b/dom/xbl/nsXBLBinding.cpp
@@ -53,17 +53,16 @@
 // Nasty hack.  Maybe we could move some of the classinfo utility methods
 // (e.g. WrapNative) over to nsContentUtils?
 #include "nsDOMClassInfo.h"
 
 #include "mozilla/DeferredFinalize.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/ShadowRoot.h"
-#include "mozilla/ServoStyleSet.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 // Helper classes
 
 /***********************************************************************/
 //
@@ -415,24 +414,16 @@ nsXBLBinding::GenerateAnonymousContent()
                                value2, false);
       }
     }
 
     // Conserve space by wiping the attributes off the clone.
     if (mContent)
       mContent->UnsetAttr(namespaceID, name, false);
   }
-
-  // Now that we've finished shuffling the tree around, go ahead and restyle it
-  // since frame construction is about to happen.
-  nsIPresShell* presShell = mBoundElement->OwnerDoc()->GetShell();
-  ServoStyleSet* servoSet = presShell->StyleSet()->GetAsServo();
-  if (servoSet) {
-    servoSet->StyleNewChildren(mBoundElement->AsElement());
-  }
 }
 
 nsIURI*
 nsXBLBinding::GetSourceDocURI()
 {
   nsIContent* targetContent =
     mPrototypeBinding->GetImmediateChild(nsGkAtoms::content);
   if (!targetContent) {
--- a/dom/xbl/nsXBLService.cpp
+++ b/dom/xbl/nsXBLService.cpp
@@ -48,16 +48,17 @@
 
 #ifdef MOZ_XUL
 #include "nsXULPrototypeCache.h"
 #endif
 #include "nsIDOMEventListener.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/ServoStyleSet.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/Element.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 #define NS_MAX_XBL_BINDING_RECURSION 20
 
@@ -401,16 +402,34 @@ nsXBLService::IsChromeOrResourceURI(nsIU
   bool isChrome = false;
   bool isResource = false;
   if (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) &&
       NS_SUCCEEDED(aURI->SchemeIs("resource", &isResource)))
       return (isChrome || isResource);
   return false;
 }
 
+// RAII class to invoke StyleNewChildren for Elements in Servo-backed documents
+// on destruction.
+class MOZ_STACK_CLASS AutoStyleNewChildren
+{
+public:
+  AutoStyleNewChildren(Element* aElement) : mElement(aElement) { MOZ_ASSERT(mElement); }
+  ~AutoStyleNewChildren()
+  {
+    nsIPresShell* presShell = mElement->OwnerDoc()->GetShell();
+    ServoStyleSet* servoSet = presShell ? presShell->StyleSet()->GetAsServo() : nullptr;
+    if (servoSet) {
+      servoSet->StyleNewChildren(mElement);
+    }
+  }
+
+private:
+  Element* mElement;
+};
 
 // This function loads a particular XBL file and installs all of the bindings
 // onto the element.
 nsresult
 nsXBLService::LoadBindings(nsIContent* aContent, nsIURI* aURL,
                            nsIPrincipal* aOriginPrincipal,
                            nsXBLBinding** aBinding, bool* aResolveStyle)
 {
@@ -431,16 +450,25 @@ nsXBLService::LoadBindings(nsIContent* a
   }
 
   if (ok) {
     // Block an attempt to load a binding that has special wrapper
     // automation needs.
     return NS_OK;
   }
 
+  // There are various places in this function where we shuffle content around
+  // the subtree and rebind things to and from insertion points. Once all that's
+  // done, we want to invoke StyleNewChildren to style any unstyled children
+  // that we may have after bindings have been removed and applied. This includes
+  // anonymous content created in this function, explicit children for which we
+  // defer styling until after XBL bindings are applied, and elements whose existing
+  // style was invalidated by a call to SetXBLInsertionParent.
+  AutoStyleNewChildren styleNewChildren(aContent->AsElement());
+
   nsXBLBinding *binding = aContent->GetXBLBinding();
   if (binding) {
     if (binding->MarkedForDeath()) {
       FlushStyleBindings(aContent);
       binding = nullptr;
     }
     else {
       // See if the URIs match.