From 3faf40c8972c3e3674f38adfc5ce39fa2c1be865 Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Sun, 4 Mar 2018 19:41:13 +0900 Subject: [PATCH] Bug 1425864 - Ensure printing documents which have ShadowDOM works, r=mrbkap,emilio --- dom/base/ShadowRoot.cpp | 18 ++++++++++++++++ dom/base/ShadowRoot.h | 4 ++++ dom/base/nsNodeUtils.cpp | 44 ++++++++++++++++++++++++++++++++-------- 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/dom/base/ShadowRoot.cpp b/dom/base/ShadowRoot.cpp index 639b5e130597..72a7a2bf928e 100644 --- a/dom/base/ShadowRoot.cpp +++ b/dom/base/ShadowRoot.cpp @@ -94,6 +94,24 @@ ShadowRoot::WrapObject(JSContext* aCx, JS::Handle 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 clonedSheet = + sheet->Clone(nullptr, nullptr, nullptr, nullptr); + if (clonedSheet) { + AppendStyleSheet(*clonedSheet.get()); + Servo_AuthorStyles_AppendStyleSheet(mServoStyles.get(), + clonedSheet->AsServo()); + } + } + } +} + void ShadowRoot::AddSlot(HTMLSlotElement* aSlot) { diff --git a/dom/base/ShadowRoot.h b/dom/base/ShadowRoot.h index 19473c65d9a5..7791e0b6570d 100644 --- a/dom/base/ShadowRoot.h +++ b/dom/base/ShadowRoot.h @@ -89,6 +89,10 @@ public: return &DocumentOrShadowRoot::EnsureDOMStyleSheets(); } + /** + * Clones internal state, for example stylesheets, of aOther to 'this'. + */ + void CloneInternalDataFrom(ShadowRoot* aOther); private: /** diff --git a/dom/base/nsNodeUtils.cpp b/dom/base/nsNodeUtils.cpp index 625a6b2e573c..3595d01c7ec9 100644 --- a/dom/base/nsNodeUtils.cpp +++ b/dom/base/nsNodeUtils.cpp @@ -657,14 +657,42 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep, } } - if (aDeep && !aClone && aNode->IsElement()) { - if (ShadowRoot* shadowRoot = aNode->AsElement()->GetShadowRoot()) { - nsCOMPtr 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 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 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 child = + CloneAndAdopt(shadowRoot, aClone, aDeep, nodeInfoManager, + aReparentScope, aNodesWithProperties, clone, + aError); + if (NS_WARN_IF(aError.Failed())) { + return nullptr; + } } } }