Bug 1425864 - Ensure printing documents which have ShadowDOM works, r=mrbkap,emilio
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Sun, 04 Mar 2018 19:41:13 +0900
changeset 461514 7cc75e6db0ee34102119caef09af078af234f620
parent 461509 0df0223d1c9f81b07d4c7ac7744cb333281e0a80
child 461516 190b536928f8a8ca96e52101d2013c88a1a66384
child 461528 09894bd08b93467a61adab7e37c5920f775443f1
push id1683
push usersfraser@mozilla.com
push dateThu, 26 Apr 2018 16:43:40 +0000
treeherdermozilla-release@5af6cb21869d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap, emilio
bugs1425864
milestone60.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 1425864 - Ensure printing documents which have ShadowDOM works, r=mrbkap,emilio
dom/base/ShadowRoot.cpp
dom/base/ShadowRoot.h
dom/base/nsNodeUtils.cpp
--- a/dom/base/ShadowRoot.cpp
+++ b/dom/base/ShadowRoot.cpp
@@ -90,16 +90,34 @@ ShadowRoot::~ShadowRoot()
 
 JSObject*
 ShadowRoot::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return mozilla::dom::ShadowRootBinding::Wrap(aCx, this, aGivenProto);
 }
 
 void
+ShadowRoot::CloneInternalDataFrom(ShadowRoot* aOther)
+{
+  size_t sheetCount = aOther->SheetCount();
+  for (size_t i = 0; i < sheetCount; ++i) {
+    StyleSheet* sheet = aOther->SheetAt(i);
+    if (sheet->IsApplicable()) {
+      RefPtr<StyleSheet> clonedSheet =
+        sheet->Clone(nullptr, nullptr, nullptr, nullptr);
+      if (clonedSheet) {
+        AppendStyleSheet(*clonedSheet.get());
+        Servo_AuthorStyles_AppendStyleSheet(mServoStyles.get(),
+                                            clonedSheet->AsServo());
+      }
+    }
+  }
+}
+
+void
 ShadowRoot::AddSlot(HTMLSlotElement* aSlot)
 {
   MOZ_ASSERT(aSlot);
 
   // Note that if name attribute missing, the slot is a default slot.
   nsAutoString name;
   aSlot->GetName(name);
 
--- a/dom/base/ShadowRoot.h
+++ b/dom/base/ShadowRoot.h
@@ -84,16 +84,20 @@ public:
   // [deprecated] Shadow DOM v0
   void InsertSheet(StyleSheet* aSheet, nsIContent* aLinkingContent);
   void RemoveSheet(StyleSheet* aSheet);
   StyleSheetList* StyleSheets()
   {
     return &DocumentOrShadowRoot::EnsureDOMStyleSheets();
   }
 
+  /**
+   * Clones internal state, for example stylesheets, of aOther to 'this'.
+   */
+  void CloneInternalDataFrom(ShadowRoot* aOther);
 private:
 
   /**
    * Try to reassign an element to a slot and returns whether the assignment
    * changed.
    */
   bool MaybeReassignElement(Element* aElement, const nsAttrValue* aOldValue);
 
--- a/dom/base/nsNodeUtils.cpp
+++ b/dom/base/nsNodeUtils.cpp
@@ -652,24 +652,52 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNod
                       aReparentScope, aNodesWithProperties, clone,
                       aError);
       if (NS_WARN_IF(aError.Failed())) {
         return nullptr;
       }
     }
   }
 
-  if (aDeep && !aClone && aNode->IsElement()) {
-    if (ShadowRoot* shadowRoot = aNode->AsElement()->GetShadowRoot()) {
-      nsCOMPtr<nsINode> child =
-        CloneAndAdopt(shadowRoot, aClone, aDeep, nodeInfoManager,
-                      aReparentScope, aNodesWithProperties, clone,
-                      aError);
-      if (NS_WARN_IF(aError.Failed())) {
-        return nullptr;
+  if (aDeep && aNode->IsElement()) {
+    if (aClone) {
+      if (clone->OwnerDoc()->IsStaticDocument()) {
+        ShadowRoot* originalShadowRoot = aNode->AsElement()->GetShadowRoot();
+        if (originalShadowRoot) {
+          ShadowRootInit init;
+          init.mMode = originalShadowRoot->Mode();
+          RefPtr<ShadowRoot> newShadowRoot =
+            clone->AsElement()->AttachShadow(init, aError);
+          if (NS_WARN_IF(aError.Failed())) {
+            return nullptr;
+          }
+
+          newShadowRoot->CloneInternalDataFrom(originalShadowRoot);
+          for (nsIContent* origChild = originalShadowRoot->GetFirstChild();
+               origChild;
+               origChild = origChild->GetNextSibling()) {
+            nsCOMPtr<nsINode> child =
+              CloneAndAdopt(origChild, aClone, aDeep, nodeInfoManager,
+                            aReparentScope, aNodesWithProperties, newShadowRoot,
+                            aError);
+            if (NS_WARN_IF(aError.Failed())) {
+              return nullptr;
+            }
+          }
+        }
+      }
+    } else {
+      if (ShadowRoot* shadowRoot = aNode->AsElement()->GetShadowRoot()) {
+        nsCOMPtr<nsINode> child =
+          CloneAndAdopt(shadowRoot, aClone, aDeep, nodeInfoManager,
+                        aReparentScope, aNodesWithProperties, clone,
+                        aError);
+        if (NS_WARN_IF(aError.Failed())) {
+          return nullptr;
+        }
       }
     }
   }
 
   // Cloning template element.
   if (aDeep && aClone && IsTemplateElement(aNode)) {
     DocumentFragment* origContent =
       static_cast<HTMLTemplateElement*>(aNode)->Content();