Bug 1324983 - Don't persist styles on elements not in the document. r?emilio draft
authorCameron McCormack <cam@mcc.id.au>
Thu, 29 Dec 2016 15:04:32 +0800
changeset 454385 34562a53079525f3dec755ebc861068e1838e9c2
parent 454384 1e23bded92169ae78de2d07ac7278cb1067b039b
child 454386 c410308ed8a51649f8ecca8c085ff778a128c129
push id39910
push userbmo:cam@mcc.id.au
push dateThu, 29 Dec 2016 07:06:54 +0000
reviewersemilio
bugs1324983
milestone53.0a1
Bug 1324983 - Don't persist styles on elements not in the document. r?emilio MozReview-Commit-ID: 4Z8IxPS6rfE
dom/xbl/nsXBLService.cpp
layout/style/ServoBindings.cpp
layout/style/ServoBindings.h
--- a/dom/xbl/nsXBLService.cpp
+++ b/dom/xbl/nsXBLService.cpp
@@ -407,28 +407,39 @@ nsXBLService::IsChromeOrResourceURI(nsIU
   return false;
 }
 
 // RAII class to invoke StyleNewChildren for Elements in Servo-backed documents
 // on destruction.
 class MOZ_STACK_CLASS AutoStyleNewChildren
 {
 public:
-  explicit AutoStyleNewChildren(Element* aElement) : mElement(aElement) { MOZ_ASSERT(mElement); }
+  explicit AutoStyleNewChildren(Element* aElement, bool aDoIt)
+    : mElement(aElement)
+    , mDoIt(aDoIt)
+  {
+    MOZ_ASSERT(mElement);
+  }
+
   ~AutoStyleNewChildren()
   {
+    if (!mDoIt) {
+      return;
+    }
+
     nsIPresShell* presShell = mElement->OwnerDoc()->GetShell();
     ServoStyleSet* servoSet = presShell ? presShell->StyleSet()->GetAsServo() : nullptr;
     if (servoSet) {
       servoSet->StyleNewChildren(mElement);
     }
   }
 
 private:
   Element* mElement;
+  bool mDoIt;
 };
 
 // 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)
@@ -457,17 +468,22 @@ nsXBLService::LoadBindings(nsIContent* a
 
   // 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());
+  //
+  // However, we skip this styling if aContent is not in the document, since we
+  // should keep such elements unstyled.  (There are some odd cases where we do
+  // apply bindings to elements not in the document.)
+  AutoStyleNewChildren styleNewChildren(aContent->AsElement(),
+                                        aContent->IsInComposedDoc());
 
   nsXBLBinding *binding = aContent->GetXBLBinding();
   if (binding) {
     if (binding->MarkedForDeath()) {
       FlushStyleBindings(aContent);
       binding = nullptr;
     }
     else {
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -54,16 +54,22 @@ Gecko_ChildrenCount(RawGeckoNodeBorrowed
 }
 
 bool
 Gecko_NodeIsElement(RawGeckoNodeBorrowed aNode)
 {
   return aNode->IsElement();
 }
 
+bool
+Gecko_IsInDocument(RawGeckoNodeBorrowed aNode)
+{
+  return aNode->IsInComposedDoc();
+}
+
 RawGeckoNodeBorrowedOrNull
 Gecko_GetParentNode(RawGeckoNodeBorrowed aNode)
 {
   return aNode->GetFlattenedTreeParentNodeForStyle();
 }
 
 RawGeckoNodeBorrowedOrNull
 Gecko_GetFirstChild(RawGeckoNodeBorrowed aNode)
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -78,16 +78,17 @@ extern "C" {
 
 // Object refcounting.
 NS_DECL_HOLDER_FFI_REFCOUNTING(nsIPrincipal, Principal)
 NS_DECL_HOLDER_FFI_REFCOUNTING(nsIURI, URI)
 
 // DOM Traversal.
 uint32_t Gecko_ChildrenCount(RawGeckoNodeBorrowed node);
 bool Gecko_NodeIsElement(RawGeckoNodeBorrowed node);
+bool Gecko_IsInDocument(RawGeckoNodeBorrowed node);
 RawGeckoNodeBorrowedOrNull Gecko_GetParentNode(RawGeckoNodeBorrowed node);
 RawGeckoNodeBorrowedOrNull Gecko_GetFirstChild(RawGeckoNodeBorrowed node);
 RawGeckoNodeBorrowedOrNull Gecko_GetLastChild(RawGeckoNodeBorrowed node);
 RawGeckoNodeBorrowedOrNull Gecko_GetPrevSibling(RawGeckoNodeBorrowed node);
 RawGeckoNodeBorrowedOrNull Gecko_GetNextSibling(RawGeckoNodeBorrowed node);
 RawGeckoElementBorrowedOrNull Gecko_GetParentElement(RawGeckoElementBorrowed element);
 RawGeckoElementBorrowedOrNull Gecko_GetFirstChildElement(RawGeckoElementBorrowed element);
 RawGeckoElementBorrowedOrNull Gecko_GetLastChildElement(RawGeckoElementBorrowed element);