mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 12:51:06 +00:00
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:
parent
c72e6da172
commit
133a24fad6
@ -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();
|
||||
|
@ -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);
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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 = ¤t->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) {
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 = {});
|
||||
};
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
@ -1,3 +0,0 @@
|
||||
[declarative-shadow-dom-repeats.html]
|
||||
[Calling attachShadow() on declarative shadow root must match all parameters]
|
||||
expected: FAIL
|
@ -1,2 +0,0 @@
|
||||
[gethtml-ordering.html]
|
||||
expected: ERROR
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user