Bug 1890428 - Add serialization support for Declarative Shadow DOM. r=webidl,smaug

Differential Revision: https://phabricator.services.mozilla.com/D206955
This commit is contained in:
Adam Vandolder 2024-05-14 16:43:28 +00:00
parent c72e6da172
commit 133a24fad6
18 changed files with 211 additions and 10973 deletions

View File

@ -1286,12 +1286,14 @@ already_AddRefed<ShadowRoot> Element::AttachShadow(const ShadowRootInit& aInit,
return AttachShadowWithoutNameChecks(
aInit.mMode, DelegatesFocus(aInit.mDelegatesFocus), aInit.mSlotAssignment,
ShadowRootClonable(aInit.mClonable));
ShadowRootClonable(aInit.mClonable),
ShadowRootSerializable(aInit.mSerializable));
}
already_AddRefed<ShadowRoot> Element::AttachShadowWithoutNameChecks(
ShadowRootMode aMode, DelegatesFocus aDelegatesFocus,
SlotAssignmentMode aSlotAssignment, ShadowRootClonable aClonable) {
SlotAssignmentMode aSlotAssignment, ShadowRootClonable aClonable,
ShadowRootSerializable aSerializable) {
nsAutoScriptBlocker scriptBlocker;
auto* nim = mNodeInfo->NodeInfoManager();
@ -1317,7 +1319,7 @@ already_AddRefed<ShadowRoot> Element::AttachShadowWithoutNameChecks(
*/
RefPtr<ShadowRoot> shadowRoot = new (nim)
ShadowRoot(this, aMode, aDelegatesFocus, aSlotAssignment, aClonable,
ShadowRootDeclarative::No, nodeInfo.forget());
aSerializable, ShadowRootDeclarative::No, nodeInfo.forget());
if (NodeOrAncestorHasDirAuto()) {
shadowRoot->SetAncestorHasDirAuto();
@ -5061,6 +5063,18 @@ void Element::SetHTML(const nsAString& aInnerHTML,
oldChildCount);
}
void Element::GetHTML(const GetHTMLOptions& aOptions, nsAString& aResult) {
if (aOptions.mSerializableShadowRoots || !aOptions.mShadowRoots.IsEmpty()) {
nsContentUtils::SerializeNodeToMarkup<SerializeShadowRoots::Yes>(
this, true, aResult, aOptions.mSerializableShadowRoots,
aOptions.mShadowRoots);
} else {
nsContentUtils::SerializeNodeToMarkup<SerializeShadowRoots::No>(
this, true, aResult, aOptions.mSerializableShadowRoots,
aOptions.mShadowRoots);
}
}
bool Element::Translate() const {
if (const auto* parent = Element::FromNodeOrNull(mParent)) {
return parent->Translate();

View File

@ -120,6 +120,7 @@ namespace dom {
struct CheckVisibilityOptions;
struct CustomElementData;
struct SetHTMLOptions;
struct GetHTMLOptions;
struct GetAnimationsOptions;
struct ScrollIntoViewOptions;
struct ScrollToOptions;
@ -1359,11 +1360,13 @@ class Element : public FragmentOrElement {
enum class DelegatesFocus : bool { No, Yes };
enum class ShadowRootClonable : bool { No, Yes };
enum class ShadowRootSerializable : bool { No, Yes };
already_AddRefed<ShadowRoot> AttachShadowWithoutNameChecks(
ShadowRootMode aMode, DelegatesFocus = DelegatesFocus::No,
SlotAssignmentMode aSlotAssignmentMode = SlotAssignmentMode::Named,
ShadowRootClonable aClonable = ShadowRootClonable::No);
ShadowRootClonable aClonable = ShadowRootClonable::No,
ShadowRootSerializable aSerializable = ShadowRootSerializable::No);
// Attach UA Shadow Root if it is not attached.
enum class NotifyUAWidgetSetup : bool { No, Yes };
@ -1543,6 +1546,7 @@ class Element : public FragmentOrElement {
void SetHTML(const nsAString& aInnerHTML, const SetHTMLOptions& aOptions,
ErrorResult& aError);
void GetHTML(const GetHTMLOptions& aOptions, nsAString& aResult);
//----------------------------------------

View File

@ -1870,7 +1870,8 @@ void FragmentOrElement::GetMarkup(bool aIncludeSelf, nsAString& aMarkup) {
Document* doc = OwnerDoc();
if (IsInHTMLDocument()) {
nsContentUtils::SerializeNodeToMarkup(this, !aIncludeSelf, aMarkup);
nsContentUtils::SerializeNodeToMarkup(this, !aIncludeSelf, aMarkup, false,
{});
return;
}

View File

@ -13,6 +13,7 @@
#include "nsWindowSizes.h"
#include "mozilla/dom/DirectionalityUtils.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ElementBinding.h"
#include "mozilla/dom/HTMLDetailsElement.h"
#include "mozilla/dom/HTMLSlotElement.h"
#include "mozilla/dom/HTMLSummaryElement.h"
@ -52,7 +53,8 @@ NS_IMPL_RELEASE_INHERITED(ShadowRoot, DocumentFragment)
ShadowRoot::ShadowRoot(Element* aElement, ShadowRootMode aMode,
Element::DelegatesFocus aDelegatesFocus,
SlotAssignmentMode aSlotAssignment,
IsClonable aIsClonable, Declarative aDeclarative,
IsClonable aIsClonable, IsSerializable aIsSerializable,
Declarative aDeclarative,
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
: DocumentFragment(std::move(aNodeInfo)),
DocumentOrShadowRoot(this),
@ -62,7 +64,8 @@ ShadowRoot::ShadowRoot(Element* aElement, ShadowRootMode aMode,
mIsDetailsShadowTree(aElement->IsHTMLElement(nsGkAtoms::details)),
mIsAvailableToElementInternals(false),
mIsDeclarative(aDeclarative),
mIsClonable(aIsClonable) {
mIsClonable(aIsClonable),
mIsSerializable(aIsSerializable) {
// nsINode.h relies on this.
MOZ_ASSERT(static_cast<nsINode*>(this) == reinterpret_cast<nsINode*>(this));
MOZ_ASSERT(static_cast<nsIContent*>(this) ==
@ -885,3 +888,9 @@ void ShadowRoot::SetHTMLUnsafe(const nsAString& aHTML) {
RefPtr<Element> host = GetHost();
nsContentUtils::SetHTMLUnsafe(this, host, aHTML);
}
void ShadowRoot::GetHTML(const GetHTMLOptions& aOptions, nsAString& aResult) {
nsContentUtils::SerializeNodeToMarkup<SerializeShadowRoots::Yes>(
this, true, aResult, aOptions.mSerializableShadowRoots,
aOptions.mShadowRoots);
}

View File

@ -44,6 +44,7 @@ class ShadowRoot final : public DocumentFragment, public DocumentOrShadowRoot {
using Declarative = Element::ShadowRootDeclarative;
using IsClonable = Element::ShadowRootClonable;
using IsSerializable = Element::ShadowRootSerializable;
public:
NS_IMPL_FROMNODE_HELPER(ShadowRoot, IsShadowRoot());
@ -54,7 +55,7 @@ class ShadowRoot final : public DocumentFragment, public DocumentOrShadowRoot {
ShadowRoot(Element* aElement, ShadowRootMode aMode,
Element::DelegatesFocus aDelegatesFocus,
SlotAssignmentMode aSlotAssignment, IsClonable aClonable,
Declarative aDeclarative,
IsSerializable aIsSerializable, Declarative aDeclarative,
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
void AddSizeOfExcludingThis(nsWindowSizes&, size_t* aNodeSize) const final;
@ -83,6 +84,7 @@ class ShadowRoot final : public DocumentFragment, public DocumentOrShadowRoot {
SlotAssignmentMode SlotAssignment() const { return mSlotAssignment; }
bool Clonable() const { return mIsClonable == IsClonable::Yes; }
bool IsClosed() const { return mMode == ShadowRootMode::Closed; }
bool Serializable() const { return mIsSerializable == IsSerializable::Yes; }
void RemoveSheetFromStyles(StyleSheet&);
void RuleAdded(StyleSheet&, css::Rule&);
@ -247,6 +249,8 @@ class ShadowRoot final : public DocumentFragment, public DocumentOrShadowRoot {
MOZ_CAN_RUN_SCRIPT
void SetHTMLUnsafe(const nsAString& aHTML);
void GetHTML(const GetHTMLOptions& aOptions, nsAString& aResult);
protected:
// FIXME(emilio): This will need to become more fine-grained.
void ApplicableRulesChanged();
@ -290,6 +294,9 @@ class ShadowRoot final : public DocumentFragment, public DocumentOrShadowRoot {
// https://dom.spec.whatwg.org/#shadowroot-clonable
const IsClonable mIsClonable;
// https://dom.spec.whatwg.org/#shadowroot-serializable
const IsSerializable mIsSerializable;
nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
};

View File

@ -178,6 +178,7 @@
#include "mozilla/dom/HTMLFormElement.h"
#include "mozilla/dom/HTMLImageElement.h"
#include "mozilla/dom/HTMLInputElement.h"
#include "mozilla/dom/HTMLTemplateElement.h"
#include "mozilla/dom/HTMLTextAreaElement.h"
#include "mozilla/dom/IPCBlob.h"
#include "mozilla/dom/IPCBlobUtils.h"
@ -9547,27 +9548,63 @@ static inline bool IsVoidTag(Element* aElement) {
return FragmentOrElement::IsHTMLVoid(aElement->NodeInfo()->NameAtom());
}
bool nsContentUtils::SerializeNodeToMarkup(nsINode* aRoot,
bool aDescendantsOnly,
nsAString& aOut) {
// If you pass in a DOCUMENT_NODE, you must pass aDescendentsOnly as true
MOZ_ASSERT(aDescendantsOnly || aRoot->NodeType() != nsINode::DOCUMENT_NODE);
nsINode* current =
aDescendantsOnly ? aRoot->GetFirstChildOfTemplateOrNode() : aRoot;
if (!current) {
return true;
static bool StartSerializingShadowDOM(
nsINode* aNode, StringBuilder& aBuilder, bool aSerializableShadowRoots,
const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) {
ShadowRoot* shadow = aNode->GetShadowRoot();
if (!shadow || ((!aSerializableShadowRoots || !shadow->Serializable()) &&
!aShadowRoots.Contains(shadow))) {
return false;
}
aBuilder.Append(u"<template shadowrootmode=\"");
if (shadow->IsClosed()) {
aBuilder.Append(u"closed\"");
} else {
aBuilder.Append(u"open\"");
}
if (shadow->DelegatesFocus()) {
aBuilder.Append(u" shadowrootdelegatesfocus=\"\"");
}
if (shadow->Serializable()) {
aBuilder.Append(u" shadowrootserializable=\"\"");
}
if (shadow->Clonable()) {
aBuilder.Append(u" shadowrootclonable=\"\"");
}
aBuilder.Append(u">");
return true;
}
template <SerializeShadowRoots ShouldSerializeShadowRoots>
static void SerializeNodeToMarkupInternal(
nsINode* aRoot, bool aDescendantsOnly, StringBuilder& aBuilder,
bool aSerializableShadowRoots,
const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) {
nsINode* current =
aDescendantsOnly ? aRoot->GetFirstChildOfTemplateOrNode() : aRoot;
if (!current) {
return;
}
StringBuilder builder;
nsIContent* next;
while (true) {
bool isVoid = false;
switch (current->NodeType()) {
case nsINode::ELEMENT_NODE: {
Element* elem = current->AsElement();
StartElement(elem, builder);
StartElement(elem, aBuilder);
if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) {
if (StartSerializingShadowDOM(
current, aBuilder, aSerializableShadowRoots, aShadowRoots)) {
current = current->GetShadowRoot()->GetFirstChild();
continue;
}
}
isVoid = IsVoidTag(elem);
if (!isVoid && (next = current->GetFirstChildOfTemplateOrNode())) {
current = next;
@ -9581,53 +9618,53 @@ bool nsContentUtils::SerializeNodeToMarkup(nsINode* aRoot,
const nsTextFragment* text = &current->AsText()->TextFragment();
nsIContent* parent = current->GetParent();
if (ShouldEscape(parent)) {
AppendEncodedCharacters(text, builder);
AppendEncodedCharacters(text, aBuilder);
} else {
builder.Append(text);
aBuilder.Append(text);
}
break;
}
case nsINode::COMMENT_NODE: {
builder.Append(u"<!--");
builder.Append(static_cast<nsIContent*>(current)->GetText());
builder.Append(u"-->");
aBuilder.Append(u"<!--");
aBuilder.Append(static_cast<nsIContent*>(current)->GetText());
aBuilder.Append(u"-->");
break;
}
case nsINode::DOCUMENT_TYPE_NODE: {
builder.Append(u"<!DOCTYPE ");
builder.Append(nsString(current->NodeName()));
builder.Append(u">");
aBuilder.Append(u"<!DOCTYPE ");
aBuilder.Append(nsString(current->NodeName()));
aBuilder.Append(u">");
break;
}
case nsINode::PROCESSING_INSTRUCTION_NODE: {
builder.Append(u"<?");
builder.Append(nsString(current->NodeName()));
builder.Append(u" ");
builder.Append(static_cast<nsIContent*>(current)->GetText());
builder.Append(u">");
aBuilder.Append(u"<?");
aBuilder.Append(nsString(current->NodeName()));
aBuilder.Append(u" ");
aBuilder.Append(static_cast<nsIContent*>(current)->GetText());
aBuilder.Append(u">");
break;
}
}
while (true) {
if (!isVoid && current->NodeType() == nsINode::ELEMENT_NODE) {
builder.Append(u"</");
aBuilder.Append(u"</");
nsIContent* elem = static_cast<nsIContent*>(current);
if (elem->IsHTMLElement() || elem->IsSVGElement() ||
elem->IsMathMLElement()) {
builder.Append(elem->NodeInfo()->NameAtom());
aBuilder.Append(elem->NodeInfo()->NameAtom());
} else {
builder.Append(nsString(current->NodeName()));
aBuilder.Append(nsString(current->NodeName()));
}
builder.Append(u">");
aBuilder.Append(u">");
}
isVoid = false;
if (current == aRoot) {
return builder.ToString(aOut);
return;
}
if ((next = current->GetNextSibling())) {
@ -9635,6 +9672,23 @@ bool nsContentUtils::SerializeNodeToMarkup(nsINode* aRoot,
break;
}
if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) {
// If the current node is a shadow root, then we must go to its host.
// Since shadow DOMs are serialized declaratively as template elements,
// we serialize the end tag of the template before going back to
// serializing the shadow host.
if (current->IsShadowRoot()) {
current = current->GetContainingShadowHost();
aBuilder.Append(u"</template>");
if (current->HasChildren()) {
current = current->GetFirstChildOfTemplateOrNode();
break;
}
continue;
}
}
current = current->GetParentNode();
// Handle template element. If the parent is a template's content,
@ -9649,12 +9703,48 @@ bool nsContentUtils::SerializeNodeToMarkup(nsINode* aRoot,
}
if (aDescendantsOnly && current == aRoot) {
return builder.ToString(aOut);
return;
}
}
}
}
template <SerializeShadowRoots ShouldSerializeShadowRoots>
bool nsContentUtils::SerializeNodeToMarkup(
nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
bool aSerializableShadowRoots,
const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) {
// If you pass in a DOCUMENT_NODE, you must pass aDescendentsOnly as true
MOZ_ASSERT(aDescendantsOnly || aRoot->NodeType() != nsINode::DOCUMENT_NODE);
StringBuilder builder;
if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) {
if (aDescendantsOnly &&
StartSerializingShadowDOM(aRoot, builder, aSerializableShadowRoots,
aShadowRoots)) {
SerializeNodeToMarkupInternal<SerializeShadowRoots::Yes>(
aRoot->GetShadowRoot()->GetFirstChild(), false, builder,
aSerializableShadowRoots, aShadowRoots);
// The template tag is opened in StartSerializingShadowDOM, so we need
// to close it here before serializing any children of aRoot.
builder.Append(u"</template>");
}
}
SerializeNodeToMarkupInternal<ShouldSerializeShadowRoots>(
aRoot, aDescendantsOnly, builder, aSerializableShadowRoots, aShadowRoots);
return builder.ToString(aOut);
}
template bool nsContentUtils::SerializeNodeToMarkup<SerializeShadowRoots::No>(
nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
bool aSerializableShadowRoots,
const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots);
template bool nsContentUtils::SerializeNodeToMarkup<SerializeShadowRoots::Yes>(
nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
bool aSerializableShadowRoots,
const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots);
bool nsContentUtils::IsSpecificAboutPage(JSObject* aGlobal, const char* aUri) {
// aUri must start with about: or this isn't the right function to be using.
MOZ_ASSERT(strncmp(aUri, "about:", 6) == 0);
@ -11437,6 +11527,7 @@ int32_t nsContentUtils::CompareTreePosition(const nsINode* aNode1,
nsIContent* nsContentUtils::AttachDeclarativeShadowRoot(nsIContent* aHost,
ShadowRootMode aMode,
bool aIsClonable,
bool aIsSerializable,
bool aDelegatesFocus) {
RefPtr<Element> host = mozilla::dom::Element::FromNodeOrNull(aHost);
if (!host || host->GetShadowRoot()) {
@ -11449,6 +11540,7 @@ nsIContent* nsContentUtils::AttachDeclarativeShadowRoot(nsIContent* aHost,
init.mDelegatesFocus = aDelegatesFocus;
init.mSlotAssignment = SlotAssignmentMode::Named;
init.mClonable = aIsClonable;
init.mSerializable = aIsSerializable;
RefPtr shadowRoot = host->AttachShadow(init, IgnoreErrors());
if (shadowRoot) {

View File

@ -190,6 +190,7 @@ class NodeInfo;
class OwningFileOrUSVStringOrFormData;
class Selection;
enum class ShadowRootMode : uint8_t;
class ShadowRoot;
struct StructuredSerializeOptions;
class WorkerPrivate;
enum class ElementCallbackType;
@ -232,6 +233,8 @@ enum EventNameType {
enum class TreeKind : uint8_t { DOM, Flat };
enum class SerializeShadowRoots : uint8_t { Yes, No };
struct EventNameMapping {
// This holds pointers to nsGkAtoms members, and is therefore safe as a
// non-owning reference.
@ -3108,8 +3111,13 @@ class nsContentUtils {
/*
* Serializes a HTML nsINode into its markup representation.
*/
static bool SerializeNodeToMarkup(nsINode* aRoot, bool aDescendentsOnly,
nsAString& aOut);
template <SerializeShadowRoots ShouldSerializeShadowRoots =
SerializeShadowRoots::No>
static bool SerializeNodeToMarkup(
nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
bool aSerializableShadowRoots,
const mozilla::dom::Sequence<
mozilla::OwningNonNull<mozilla::dom::ShadowRoot>>& aShadowRoots);
/*
* Returns true iff the provided JSObject is a global, and its URI matches
@ -3543,7 +3551,7 @@ class nsContentUtils {
MOZ_CAN_RUN_SCRIPT_BOUNDARY
static nsIContent* AttachDeclarativeShadowRoot(
nsIContent* aHost, mozilla::dom::ShadowRootMode aMode, bool aIsClonable,
bool aDelegatesFocus);
bool aIsSerializable, bool aDelegatesFocus);
private:
static bool InitializeEventTable();

View File

@ -7,6 +7,7 @@
#include "BodyExtractor.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FormData.h"
#include "mozilla/dom/ShadowRoot.h"
#include "mozilla/dom/TypedArray.h"
#include "mozilla/dom/URLSearchParams.h"
#include "mozilla/dom/XMLHttpRequest.h"
@ -87,7 +88,8 @@ nsresult BodyExtractor<Document>::GetAsStream(
aContentTypeWithCharset.AssignLiteral("text/html;charset=UTF-8");
nsString serialized;
if (!nsContentUtils::SerializeNodeToMarkup(mBody, true, serialized)) {
if (!nsContentUtils::SerializeNodeToMarkup(mBody, true, serialized, false,
{})) {
return NS_ERROR_OUT_OF_MEMORY;
}

View File

@ -65,6 +65,13 @@ class HTMLTemplateElement final : public nsGenericHTMLElement {
SetHTMLBoolAttr(nsGkAtoms::shadowrootclonable, aValue, aRv);
}
bool ShadowRootSerializable() const {
return GetBoolAttr(nsGkAtoms::shadowrootserializable);
}
void SetShadowRootSerializable(bool aValue, ErrorResult& aRv) {
SetHTMLBoolAttr(nsGkAtoms::shadowrootserializable, aValue, aRv);
}
MOZ_CAN_RUN_SCRIPT
void SetHTMLUnsafe(const nsAString& aHTML) final;

View File

@ -276,6 +276,8 @@ dictionary ShadowRootInit {
SlotAssignmentMode slotAssignment = "named";
[Pref="dom.webcomponents.shadowdom.declarative.enabled"]
boolean clonable = false;
[Pref="dom.webcomponents.shadowdom.declarative.enabled"]
boolean serializable = false;
};
// https://dom.spec.whatwg.org/#element
@ -403,8 +405,15 @@ partial interface Element {
undefined setHTML(DOMString aInnerHTML, optional SetHTMLOptions options = {});
};
dictionary GetHTMLOptions {
boolean serializableShadowRoots = false;
sequence<ShadowRoot> shadowRoots = [];
};
partial interface Element {
// https://html.spec.whatwg.org/#dom-element-sethtmlunsafe
[Pref="dom.webcomponents.shadowdom.declarative.enabled"]
undefined setHTMLUnsafe(DOMString html);
[Pref="dom.webcomponents.shadowdom.declarative.enabled"]
DOMString getHTML(optional GetHTMLOptions options = {});
};

View File

@ -20,4 +20,6 @@ interface HTMLTemplateElement : HTMLElement {
attribute boolean shadowRootDelegatesFocus;
[CEReactions, SetterThrows, Pref="dom.webcomponents.shadowdom.declarative.enabled"]
attribute boolean shadowRootClonable;
[CEReactions, SetterThrows, Pref="dom.webcomponents.shadowdom.declarative.enabled"]
attribute boolean shadowRootSerializable;
};

View File

@ -29,6 +29,8 @@ interface ShadowRoot : DocumentFragment
readonly attribute SlotAssignmentMode slotAssignment;
[Pref="dom.webcomponents.shadowdom.declarative.enabled"]
readonly attribute boolean clonable;
[Pref="dom.webcomponents.shadowdom.declarative.enabled"]
readonly attribute boolean serializable;
readonly attribute Element host;
attribute EventHandler onslotchange;
@ -62,6 +64,8 @@ partial interface ShadowRoot {
// https://html.spec.whatwg.org/#dom-shadowroot-sethtmlunsafe
[Pref="dom.webcomponents.shadowdom.declarative.enabled"]
undefined setHTMLUnsafe(DOMString html);
[Pref="dom.webcomponents.shadowdom.declarative.enabled"]
DOMString getHTML(optional GetHTMLOptions options = {});
};
ShadowRoot includes DocumentOrShadowRoot;

View File

@ -1722,7 +1722,7 @@ nsIContentHandle* nsHtml5TreeBuilder::getShadowRootFromHost(
if (mBuilder) {
nsIContent* root = nsContentUtils::AttachDeclarativeShadowRoot(
static_cast<nsIContent*>(aHost), mode, aShadowRootIsClonable,
aShadowRootDelegatesFocus);
aShadowRootIsSerializable, aShadowRootDelegatesFocus);
if (!root) {
nsContentUtils::LogSimpleConsoleError(
u"Failed to attach Declarative Shadow DOM."_ns, "DOM"_ns,
@ -1738,9 +1738,9 @@ nsIContentHandle* nsHtml5TreeBuilder::getShadowRootFromHost(
return nullptr;
}
nsIContentHandle* fragHandle = AllocateContentHandle();
opGetShadowRootFromHost operation(aHost, fragHandle, aTemplateNode, mode,
aShadowRootIsClonable,
aShadowRootDelegatesFocus);
opGetShadowRootFromHost operation(
aHost, fragHandle, aTemplateNode, mode, aShadowRootIsClonable,
aShadowRootIsSerializable, aShadowRootDelegatesFocus);
treeOp->Init(mozilla::AsVariant(operation));
return fragHandle;
}

View File

@ -934,6 +934,7 @@ nsresult nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder,
nsIContent* root = nsContentUtils::AttachDeclarativeShadowRoot(
*aOperation.mHost, aOperation.mShadowRootMode,
aOperation.mShadowRootIsClonable,
aOperation.mShadowRootIsSerializable,
aOperation.mShadowRootDelegatesFocus);
if (root) {
*aOperation.mFragHandle = root;

View File

@ -282,6 +282,7 @@ struct opGetShadowRootFromHost {
nsIContent** mTemplateNode;
mozilla::dom::ShadowRootMode mShadowRootMode;
bool mShadowRootIsClonable;
bool mShadowRootIsSerializable;
bool mShadowRootDelegatesFocus;
explicit opGetShadowRootFromHost(nsIContentHandle* aHost,
@ -289,12 +290,14 @@ struct opGetShadowRootFromHost {
nsIContentHandle* aTemplateNode,
mozilla::dom::ShadowRootMode aShadowRootMode,
bool aShadowRootIsClonable,
bool aShadowRootIsSerializable,
bool aShadowRootDelegatesFocus) {
mHost = static_cast<nsIContent**>(aHost);
mFragHandle = static_cast<nsIContent**>(aFragHandle);
mTemplateNode = static_cast<nsIContent**>(aTemplateNode);
mShadowRootMode = aShadowRootMode;
mShadowRootIsClonable = aShadowRootIsClonable;
mShadowRootIsSerializable = aShadowRootIsSerializable;
mShadowRootDelegatesFocus = aShadowRootDelegatesFocus;
}
};

View File

@ -1,3 +0,0 @@
[declarative-shadow-dom-repeats.html]
[Calling attachShadow() on declarative shadow root must match all parameters]
expected: FAIL

View File

@ -1,2 +0,0 @@
[gethtml-ordering.html]
expected: ERROR