From 015148fcc37225f93dd0bd0d5913ec3e5acff2db Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Sat, 4 Mar 2023 19:17:22 +0800 Subject: [PATCH] Issue #2135 - Bug 1425864: Ensure printing documents which have shadow DOM works --- dom/base/ShadowRoot.cpp | 17 +++++++++++++++++ dom/base/ShadowRoot.h | 5 +++++ dom/base/nsNodeUtils.cpp | 27 +++++++++++++++++++++++++-- 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/dom/base/ShadowRoot.cpp b/dom/base/ShadowRoot.cpp index 39859da4cf..e31b97262c 100644 --- a/dom/base/ShadowRoot.cpp +++ b/dom/base/ShadowRoot.cpp @@ -101,6 +101,23 @@ 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 && sheet->IsApplicable()) { + // TODO: Remove AsGecko() call once Stylo is removed. + RefPtr clonedSheet = + sheet->AsGecko()->Clone(nullptr, nullptr, nullptr, nullptr); + if (clonedSheet) { + AppendStyleSheet(*clonedSheet); + } + } + } +} + ShadowRoot* ShadowRoot::FromNode(nsINode* aNode) { diff --git a/dom/base/ShadowRoot.h b/dom/base/ShadowRoot.h index 580099875d..e122a65ef1 100644 --- a/dom/base/ShadowRoot.h +++ b/dom/base/ShadowRoot.h @@ -64,6 +64,11 @@ public: return &DocumentOrShadowRoot::EnsureDOMStyleSheets(); } + /** + * Clones internal state, for example stylesheets, of aOther to 'this'. + */ + void CloneInternalDataFrom(ShadowRoot* aOther); + /** * Distributes all the explicit children of the pool host to the content * insertion points in this ShadowRoot. diff --git a/dom/base/nsNodeUtils.cpp b/dom/base/nsNodeUtils.cpp index f1be693d2e..80a0f93247 100644 --- a/dom/base/nsNodeUtils.cpp +++ b/dom/base/nsNodeUtils.cpp @@ -653,8 +653,31 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep, } } - if (aDeep && !aClone && aNode->IsElement()) { - if (ShadowRoot* shadowRoot = aNode->AsElement()->GetShadowRoot()) { + if (aDeep && aNode->IsElement()) { + ShadowRoot* shadowRoot = aNode->AsElement()->GetShadowRoot(); + if (!shadowRoot) { + // Nothing to do here. + } else if (aClone && clone->OwnerDoc()->IsStaticDocument()) { + ShadowRootInit init; + init.mMode = shadowRoot->Mode(); + RefPtr newShadowRoot = + clone->AsElement()->AttachShadow(init, aError); + if (NS_WARN_IF(aError.Failed())) { + return nullptr; + } + + newShadowRoot->CloneInternalDataFrom(shadowRoot); + for (nsIContent* originalChild = shadowRoot->GetFirstChild(); + originalChild; + originalChild = originalChild->GetNextSibling()) { + nsCOMPtr child = CloneAndAdopt(originalChild, aClone, aDeep, nodeInfoManager, + aReparentScope, aNodesWithProperties, newShadowRoot, + aError); + if (NS_WARN_IF(aError.Failed())) { + return nullptr; + } + } + } else if (!aClone) { nsCOMPtr child = CloneAndAdopt(shadowRoot, aClone, aDeep, nodeInfoManager, aReparentScope, aNodesWithProperties, clone, aError);