summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2020-04-17 07:10:54 -0400
committerMatt A. Tobin <email@mattatobin.com>2020-04-17 07:10:54 -0400
commite31ed5b07466d4a579fe4b025f97c971003fbc3f (patch)
treeabd621b87578770973591fd03608993334f6af64
parent8beb65dd501cbdcfd6a793027b5de2a1fdfc7149 (diff)
downloadUXP-e31ed5b07466d4a579fe4b025f97c971003fbc3f.tar
UXP-e31ed5b07466d4a579fe4b025f97c971003fbc3f.tar.gz
UXP-e31ed5b07466d4a579fe4b025f97c971003fbc3f.tar.lz
UXP-e31ed5b07466d4a579fe4b025f97c971003fbc3f.tar.xz
UXP-e31ed5b07466d4a579fe4b025f97c971003fbc3f.zip
Bug 1409975 - Implement node distribution for shadow tree slots
* Implementation for assignedNodes * Include slots in the flat tree * Fix event get-the-parent algorithm for a node * Update and add reftests for Shadow DOM v1 * Update web platform tests expectations Tag #1375
-rw-r--r--dom/base/ChildIterator.cpp67
-rw-r--r--dom/base/ChildIterator.h21
-rw-r--r--dom/base/FragmentOrElement.cpp72
-rw-r--r--dom/base/ShadowRoot.cpp240
-rw-r--r--dom/base/ShadowRoot.h33
-rw-r--r--dom/base/nsContentUtils.cpp8
-rw-r--r--dom/base/nsIContent.h6
-rw-r--r--dom/base/nsINode.h6
-rw-r--r--dom/events/EventDispatcher.h7
-rw-r--r--dom/html/HTMLSlotElement.cpp151
-rw-r--r--dom/html/HTMLSlotElement.h23
-rw-r--r--layout/reftests/webcomponents/basic-insertion-point-1-ref.html8
-rw-r--r--layout/reftests/webcomponents/basic-insertion-point-1.html21
-rw-r--r--layout/reftests/webcomponents/basic-insertion-point-2-ref.html11
-rw-r--r--layout/reftests/webcomponents/basic-insertion-point-2.html24
-rw-r--r--layout/reftests/webcomponents/basic-shadow-1.html2
-rw-r--r--layout/reftests/webcomponents/basic-shadow-2.html2
-rw-r--r--layout/reftests/webcomponents/basic-shadow-3.html2
-rw-r--r--layout/reftests/webcomponents/basic-shadow-4.html2
-rw-r--r--layout/reftests/webcomponents/basic-slot-1-ref.html11
-rw-r--r--layout/reftests/webcomponents/basic-slot-1.html6
-rw-r--r--layout/reftests/webcomponents/basic-slot-2-ref.html16
-rw-r--r--layout/reftests/webcomponents/basic-slot-2.html7
-rw-r--r--layout/reftests/webcomponents/basic-slot-3-ref.html8
-rw-r--r--layout/reftests/webcomponents/basic-slot-3.html18
-rw-r--r--layout/reftests/webcomponents/basic-slot-4.html20
-rw-r--r--layout/reftests/webcomponents/dynamic-insertion-point-distribution-1.html10
-rw-r--r--layout/reftests/webcomponents/dynamic-insertion-point-distribution-2.html8
-rw-r--r--layout/reftests/webcomponents/dynamic-shadow-element-1-ref.html10
-rw-r--r--layout/reftests/webcomponents/dynamic-shadow-element-1.html23
-rw-r--r--layout/reftests/webcomponents/fallback-content-1.html8
-rw-r--r--layout/reftests/webcomponents/input-transition-1.html18
-rw-r--r--layout/reftests/webcomponents/nested-insertion-point-1.html11
-rw-r--r--layout/reftests/webcomponents/reframe-shadow-child-1.html16
-rw-r--r--layout/reftests/webcomponents/reframe-shadow-child-2.html15
-rw-r--r--layout/reftests/webcomponents/reftest.list8
-rw-r--r--layout/reftests/webcomponents/remove-append-shadow-host-1.html2
-rw-r--r--layout/reftests/webcomponents/remove-insertion-point-1.html8
-rw-r--r--layout/reftests/webcomponents/style-sharing-across-shadow.html22
-rw-r--r--layout/reftests/webcomponents/style-sharing.html14
-rw-r--r--layout/reftests/webcomponents/update-dist-node-descendants-1.html17
-rw-r--r--layout/style/res/ua.css6
-rw-r--r--testing/web-platform/meta/html/dom/interfaces.html.ini17
-rw-r--r--testing/web-platform/meta/html/dom/reflection-misc.html.ini2
-rw-r--r--testing/web-platform/meta/shadow-dom/HTMLSlotElement-interface.html.ini44
-rw-r--r--testing/web-platform/meta/shadow-dom/Slotable-interface.html.ini12
-rw-r--r--testing/web-platform/meta/shadow-dom/event-inside-slotted-node.html.ini38
-rw-r--r--testing/web-platform/meta/shadow-dom/slots-fallback.html.ini32
-rw-r--r--testing/web-platform/meta/shadow-dom/slots.html.ini71
49 files changed, 775 insertions, 429 deletions
diff --git a/dom/base/ChildIterator.cpp b/dom/base/ChildIterator.cpp
index dc356fc01..ae5f4665d 100644
--- a/dom/base/ChildIterator.cpp
+++ b/dom/base/ChildIterator.cpp
@@ -6,6 +6,7 @@
#include "ChildIterator.h"
#include "nsContentUtils.h"
+#include "mozilla/dom/HTMLSlotElement.h"
#include "mozilla/dom/XBLChildrenElement.h"
#include "mozilla/dom/ShadowRoot.h"
#include "nsIAnonymousContentCreator.h"
@@ -57,15 +58,34 @@ GetMatchedNodesForPoint(nsIContent* aContent)
// XXX handle <slot> element?
}
+ExplicitChildIterator::ExplicitChildIterator(const nsIContent* aParent,
+ bool aStartAtBeginning)
+ : mParent(aParent),
+ mChild(nullptr),
+ mDefaultChild(nullptr),
+ mIsFirst(aStartAtBeginning),
+ mIndexInInserted(0)
+{
+ mParentAsSlot = HTMLSlotElement::FromContent(mParent);
+}
+
nsIContent*
ExplicitChildIterator::GetNextChild()
{
// If we're already in the inserted-children array, look there first
if (mIndexInInserted) {
MOZ_ASSERT(mChild);
- MOZ_ASSERT(nsContentUtils::IsContentInsertionPoint(mChild));
MOZ_ASSERT(!mDefaultChild);
+ if (mParentAsSlot) {
+ const nsTArray<RefPtr<nsINode>>& assignedNodes =
+ mParentAsSlot->AssignedNodes();
+
+ mChild = (mIndexInInserted < assignedNodes.Length()) ?
+ assignedNodes[mIndexInInserted++]->AsContent() : nullptr;
+ return mChild;
+ }
+
MatchedNodes assignedChildren = GetMatchedNodesForPoint(mChild);
if (mIndexInInserted < assignedChildren.Length()) {
return assignedChildren[mIndexInInserted++];
@@ -84,6 +104,19 @@ ExplicitChildIterator::GetNextChild()
mChild = mChild->GetNextSibling();
} else if (mIsFirst) { // at the beginning of the child list
+ // For slot parent, iterate over assigned nodes if not empty, otherwise
+ // fall through and iterate over direct children (fallback content).
+ if (mParentAsSlot) {
+ const nsTArray<RefPtr<nsINode>>& assignedNodes =
+ mParentAsSlot->AssignedNodes();
+ if (!assignedNodes.IsEmpty()) {
+ mIndexInInserted = 1;
+ mChild = assignedNodes[0]->AsContent();
+ mIsFirst = false;
+ return mChild;
+ }
+ }
+
mChild = mParent->GetFirstChild();
mIsFirst = false;
} else if (mChild) { // in the middle of the child list
@@ -185,6 +218,12 @@ ExplicitChildIterator::Get() const
{
MOZ_ASSERT(!mIsFirst);
+ // When mParentAsSlot is set, mChild is always set to the current child. It
+ // does not matter whether mChild is an assigned node or a fallback content.
+ if (mParentAsSlot) {
+ return mChild;
+ }
+
if (mIndexInInserted) {
MatchedNodes assignedChildren = GetMatchedNodesForPoint(mChild);
return assignedChildren[mIndexInInserted - 1];
@@ -198,6 +237,20 @@ ExplicitChildIterator::GetPreviousChild()
{
// If we're already in the inserted-children array, look there first
if (mIndexInInserted) {
+
+ if (mParentAsSlot) {
+ const nsTArray<RefPtr<nsINode>>& assignedNodes =
+ mParentAsSlot->AssignedNodes();
+
+ mChild = (--mIndexInInserted) ?
+ assignedNodes[mIndexInInserted - 1]->AsContent() : nullptr;
+
+ if (!mChild) {
+ mIsFirst = true;
+ }
+ return mChild;
+ }
+
// NB: mIndexInInserted points one past the last returned child so we need
// to look *two* indices back in order to return the previous child.
MatchedNodes assignedChildren = GetMatchedNodesForPoint(mChild);
@@ -218,6 +271,18 @@ ExplicitChildIterator::GetPreviousChild()
} else if (mChild) { // in the middle of the child list
mChild = mChild->GetPreviousSibling();
} else { // at the end of the child list
+ // For slot parent, iterate over assigned nodes if not empty, otherwise
+ // fall through and iterate over direct children (fallback content).
+ if (mParentAsSlot) {
+ const nsTArray<RefPtr<nsINode>>& assignedNodes =
+ mParentAsSlot->AssignedNodes();
+ if (!assignedNodes.IsEmpty()) {
+ mIndexInInserted = assignedNodes.Length();
+ mChild = assignedNodes[mIndexInInserted - 1]->AsContent();
+ return mChild;
+ }
+ }
+
mChild = mParent->GetLastChild();
}
diff --git a/dom/base/ChildIterator.h b/dom/base/ChildIterator.h
index f78ba7ca3..ec6dfa61d 100644
--- a/dom/base/ChildIterator.h
+++ b/dom/base/ChildIterator.h
@@ -36,22 +36,19 @@ class ExplicitChildIterator
{
public:
explicit ExplicitChildIterator(const nsIContent* aParent,
- bool aStartAtBeginning = true)
- : mParent(aParent),
- mChild(nullptr),
- mDefaultChild(nullptr),
- mIndexInInserted(0),
- mIsFirst(aStartAtBeginning)
- {
- }
+ bool aStartAtBeginning = true);
ExplicitChildIterator(const ExplicitChildIterator& aOther)
- : mParent(aOther.mParent), mChild(aOther.mChild),
+ : mParent(aOther.mParent),
+ mParentAsSlot(aOther.mParentAsSlot),
+ mChild(aOther.mChild),
mDefaultChild(aOther.mDefaultChild),
mIndexInInserted(aOther.mIndexInInserted), mIsFirst(aOther.mIsFirst) {}
ExplicitChildIterator(ExplicitChildIterator&& aOther)
- : mParent(aOther.mParent), mChild(aOther.mChild),
+ : mParent(aOther.mParent),
+ mParentAsSlot(aOther.mParentAsSlot),
+ mChild(aOther.mChild),
mDefaultChild(aOther.mDefaultChild),
mIndexInInserted(aOther.mIndexInInserted), mIsFirst(aOther.mIsFirst) {}
@@ -98,6 +95,10 @@ protected:
// the <xbl:content> element for the binding.
const nsIContent* mParent;
+ // If parent is a slot element, this points to the parent as HTMLSlotElement,
+ // otherwise, it's null.
+ const HTMLSlotElement* mParentAsSlot;
+
// The current child. When we encounter an insertion point,
// mChild remains as the insertion point whose content we're iterating (and
// our state is controled by mDefaultChild or mIndexInInserted depending on
diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp
index 766e2b115..ecb18798f 100644
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -183,6 +183,24 @@ nsIContent::GetAssignedSlotByMode() const
}
nsINode*
+nsIContent::GetFlattenedTreeParentForMaybeAssignedNode() const
+{
+ if (HTMLSlotElement* assignedSlot = GetAssignedSlot()) {
+ return assignedSlot;
+ }
+
+ HTMLSlotElement* parentSlot = HTMLSlotElement::FromContent(GetParent());
+ if (!parentSlot) {
+ return nullptr;
+ }
+
+ // If this is not an unassigned node, then it must be a fallback content.
+ MOZ_ASSERT(parentSlot->AssignedNodes().IsEmpty());
+
+ return parentSlot;
+}
+
+nsINode*
nsIContent::GetFlattenedTreeParentNodeInternal(FlattenedParentType aType) const
{
nsINode* parentNode = GetParentNode();
@@ -233,16 +251,10 @@ nsIContent::GetFlattenedTreeParentNodeInternal(FlattenedParentType aType) const
if (parent && nsContentUtils::HasDistributedChildren(parent) &&
nsContentUtils::IsInSameAnonymousTree(parent, this)) {
- // This node is distributed to insertion points, thus we
- // need to consult the destination insertion points list to
- // figure out where this node was inserted in the flattened tree.
- // It may be the case that |parent| distributes its children
- // but the child does not match any insertion points, thus
- // the flattened tree parent is nullptr.
- nsTArray<nsIContent*>* destInsertionPoints = GetExistingDestInsertionPoints();
- parent = destInsertionPoints && !destInsertionPoints->IsEmpty() ?
- destInsertionPoints->LastElement()->GetParent() : nullptr;
- } else if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
+ return GetFlattenedTreeParentForMaybeAssignedNode();
+ }
+
+ if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
nsIContent* insertionParent = GetXBLInsertionParent();
if (insertionParent) {
parent = insertionParent;
@@ -890,42 +902,10 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor)
}
}
- nsIContent* parent = GetParent();
-
- // Web components have a special event chain that need to account
- // for destination insertion points where nodes have been distributed.
- nsTArray<nsIContent*>* destPoints = GetExistingDestInsertionPoints();
- if (destPoints && !destPoints->IsEmpty()) {
- // Push destination insertion points to aVisitor.mDestInsertionPoints.
- for (uint32_t i = 0; i < destPoints->Length(); i++) {
- nsIContent* point = destPoints->ElementAt(i);
- aVisitor.mDestInsertionPoints.AppendElement(point);
- }
- }
-
- ShadowRoot* thisShadowRoot = ShadowRoot::FromNode(this);
- if (thisShadowRoot) {
- if (!aVisitor.mEvent->mFlags.mComposed) {
- // If we do stop propagation, we still want to propagate
- // the event to chrome (nsPIDOMWindow::GetParentTarget()).
- // The load event is special in that we don't ever propagate it
- // to chrome.
- nsCOMPtr<nsPIDOMWindowOuter> win = OwnerDoc()->GetWindow();
- EventTarget* parentTarget = win && aVisitor.mEvent->mMessage != eLoad
- ? win->GetParentTarget() : nullptr;
-
- aVisitor.mParentTarget = parentTarget;
- return NS_OK;
- }
-
- if (!aVisitor.mDestInsertionPoints.IsEmpty()) {
- parent = aVisitor.mDestInsertionPoints.LastElement();
- aVisitor.mDestInsertionPoints.SetLength(
- aVisitor.mDestInsertionPoints.Length() - 1);
- } else {
- parent = thisShadowRoot->GetHost();
- }
- }
+ // Event parent is the assigned slot, if node is assigned, or node's parent
+ // otherwise.
+ HTMLSlotElement* slot = GetAssignedSlot();
+ nsIContent* parent = slot ? slot : GetParent();
// Event may need to be retargeted if this is the root of a native
// anonymous content subtree or event is dispatched somewhere inside XBL.
diff --git a/dom/base/ShadowRoot.cpp b/dom/base/ShadowRoot.cpp
index 97214e050..308f57cf7 100644
--- a/dom/base/ShadowRoot.cpp
+++ b/dom/base/ShadowRoot.cpp
@@ -14,7 +14,9 @@
#include "nsIDOMHTMLElement.h"
#include "nsIStyleSheetLinkingElement.h"
#include "mozilla/dom/Element.h"
+#include "mozilla/dom/HTMLSlotElement.h"
#include "nsXBLPrototypeBinding.h"
+#include "mozilla/EventDispatcher.h"
#include "mozilla/StyleSheet.h"
#include "mozilla/StyleSheetInlines.h"
@@ -110,6 +112,87 @@ ShadowRoot::FromNode(nsINode* aNode)
}
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);
+
+ nsTArray<HTMLSlotElement*>* currentSlots = mSlotMap.LookupOrAdd(name);
+ MOZ_ASSERT(currentSlots);
+
+ HTMLSlotElement* oldSlot = currentSlots->IsEmpty() ?
+ nullptr : currentSlots->ElementAt(0);
+
+ TreeOrderComparator comparator;
+ currentSlots->InsertElementSorted(aSlot, comparator);
+
+ HTMLSlotElement* currentSlot = currentSlots->ElementAt(0);
+ if (currentSlot != aSlot) {
+ return;
+ }
+
+ if (oldSlot && oldSlot != currentSlot) {
+ // Move assigned nodes from old slot to new slot.
+ const nsTArray<RefPtr<nsINode>>& assignedNodes = oldSlot->AssignedNodes();
+ while (assignedNodes.Length() > 0) {
+ nsINode* assignedNode = assignedNodes[0];
+
+ oldSlot->RemoveAssignedNode(assignedNode);
+ currentSlot->AppendAssignedNode(assignedNode);
+ }
+ } else {
+ // Otherwise add appropriate nodes to this slot from the host.
+ for (nsIContent* child = GetHost()->GetFirstChild();
+ child;
+ child = child->GetNextSibling()) {
+ nsAutoString slotName;
+ child->GetAttr(kNameSpaceID_None, nsGkAtoms::slot, slotName);
+ if (child->IsSlotable() && slotName.Equals(name)) {
+ currentSlot->AppendAssignedNode(child);
+ }
+ }
+ }
+}
+
+void
+ShadowRoot::RemoveSlot(HTMLSlotElement* aSlot)
+{
+ MOZ_ASSERT(aSlot);
+
+ nsAutoString name;
+ aSlot->GetName(name);
+
+ nsTArray<HTMLSlotElement*>* currentSlots = mSlotMap.Get(name);
+
+ if (currentSlots) {
+ if (currentSlots->Length() == 1) {
+ MOZ_ASSERT(currentSlots->ElementAt(0) == aSlot);
+ mSlotMap.Remove(name);
+ aSlot->ClearAssignedNodes();
+ } else {
+ bool doReplaceSlot = currentSlots->ElementAt(0) == aSlot;
+ currentSlots->RemoveElement(aSlot);
+ HTMLSlotElement* replacementSlot = currentSlots->ElementAt(0);
+
+ // Move assigned nodes from removed slot to the next slot in
+ // tree order with the same name.
+ if (doReplaceSlot) {
+ const nsTArray<RefPtr<nsINode>>& assignedNodes = aSlot->AssignedNodes();
+ while (assignedNodes.Length() > 0) {
+ nsINode* assignedNode = assignedNodes[0];
+
+ aSlot->RemoveAssignedNode(assignedNode);
+ replacementSlot->AppendAssignedNode(assignedNode);
+ }
+ }
+ }
+ }
+}
+
+void
ShadowRoot::StyleSheetChanged()
{
mProtoBinding->FlushSkinSheets();
@@ -222,6 +305,128 @@ ShadowRoot::GetElementsByClassName(const nsAString& aClasses)
return nsContentUtils::GetElementsByClassName(this, aClasses);
}
+nsresult
+ShadowRoot::GetEventTargetParent(EventChainPreVisitor& aVisitor)
+{
+ aVisitor.mCanHandle = true;
+
+ // https://dom.spec.whatwg.org/#ref-for-get-the-parent%E2%91%A6
+ if (!aVisitor.mEvent->mFlags.mComposed) {
+ nsCOMPtr<nsIContent> originalTarget =
+ do_QueryInterface(aVisitor.mEvent->mOriginalTarget);
+ if (originalTarget->GetContainingShadow() == this) {
+ // If we do stop propagation, we still want to propagate
+ // the event to chrome (nsPIDOMWindow::GetParentTarget()).
+ // The load event is special in that we don't ever propagate it
+ // to chrome.
+ nsCOMPtr<nsPIDOMWindowOuter> win = OwnerDoc()->GetWindow();
+ EventTarget* parentTarget = win && aVisitor.mEvent->mMessage != eLoad
+ ? win->GetParentTarget() : nullptr;
+
+ aVisitor.mParentTarget = parentTarget;
+ return NS_OK;
+ }
+ }
+
+ nsIContent* shadowHost = GetHost();
+ aVisitor.mParentTarget = shadowHost;
+
+ if (aVisitor.mOriginalTargetIsInAnon) {
+ nsCOMPtr<nsIContent> content(do_QueryInterface(aVisitor.mEvent->mTarget));
+ if (content && content->GetBindingParent() == shadowHost) {
+ aVisitor.mEventTargetAtParent = shadowHost;
+ }
+ }
+
+ return NS_OK;
+}
+
+const HTMLSlotElement*
+ShadowRoot::AssignSlotFor(nsIContent* aContent)
+{
+ nsAutoString slotName;
+ // Note that if slot attribute is missing, assign it to the first default
+ // slot, if exists.
+ aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::slot, slotName);
+ nsTArray<HTMLSlotElement*>* slots = mSlotMap.Get(slotName);
+ if (!slots) {
+ return nullptr;
+ }
+
+ HTMLSlotElement* slot = slots->ElementAt(0);
+ MOZ_ASSERT(slot);
+
+ // Find the appropriate position in the assigned node list for the
+ // newly assigned content.
+ const nsTArray<RefPtr<nsINode>>& assignedNodes = slot->AssignedNodes();
+ nsIContent* currentContent = GetHost()->GetFirstChild();
+ bool indexFound = false;
+ uint32_t insertionIndex;
+ for (uint32_t i = 0; i < assignedNodes.Length(); i++) {
+ // Seek through the host's explicit children until the
+ // assigned content is found.
+ while (currentContent && currentContent != assignedNodes[i]) {
+ if (currentContent == aContent) {
+ indexFound = true;
+ insertionIndex = i;
+ }
+
+ currentContent = currentContent->GetNextSibling();
+ }
+
+ if (indexFound) {
+ break;
+ }
+ }
+
+ if (indexFound) {
+ slot->InsertAssignedNode(insertionIndex, aContent);
+ } else {
+ slot->AppendAssignedNode(aContent);
+ }
+
+ return slot;
+}
+
+const HTMLSlotElement*
+ShadowRoot::UnassignSlotFor(nsIContent* aNode, const nsAString& aSlotName)
+{
+ // Find the insertion point to which the content belongs. Note that if slot
+ // attribute is missing, unassign it from the first default slot, if exists.
+ nsTArray<HTMLSlotElement*>* slots = mSlotMap.Get(aSlotName);
+ if (!slots) {
+ return nullptr;
+ }
+
+ HTMLSlotElement* slot = slots->ElementAt(0);
+ MOZ_ASSERT(slot);
+
+ if (!slot->AssignedNodes().Contains(aNode)) {
+ return nullptr;
+ }
+
+ slot->RemoveAssignedNode(aNode);
+ return slot;
+}
+
+bool
+ShadowRoot::MaybeReassignElement(Element* aElement,
+ const nsAttrValue* aOldValue)
+{
+ nsIContent* parent = aElement->GetParent();
+ if (parent && parent == GetHost()) {
+ const HTMLSlotElement* oldSlot = UnassignSlotFor(aElement,
+ aOldValue ? aOldValue->GetStringValue() : EmptyString());
+ const HTMLSlotElement* newSlot = AssignSlotFor(aElement);
+
+ if (oldSlot != newSlot) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
void
ShadowRoot::DistributionChanged()
{
@@ -333,7 +538,12 @@ ShadowRoot::AttributeChanged(nsIDocument* aDocument,
int32_t aModType,
const nsAttrValue* aOldValue)
{
- if (!IsPooledNode(aElement)) {
+ if (aNameSpaceID != kNameSpaceID_None || aAttribute != nsGkAtoms::slot) {
+ return;
+ }
+
+ // Attributes may change insertion point matching, find its new distribution.
+ if (!MaybeReassignElement(aElement, aOldValue)) {
return;
}
@@ -369,11 +579,18 @@ ShadowRoot::ContentInserted(nsIDocument* aDocument,
nsIContent* aChild,
int32_t aIndexInContainer)
{
- if (mInsertionPointChanged) {
- DistributeAllNodes();
- mInsertionPointChanged = false;
+ // Check to ensure that the content is in the same anonymous tree
+ // as the container because anonymous content may report its container
+ // as the host but it may not be in the host's child list.
+ if (!nsContentUtils::IsInSameAnonymousTree(aContainer, aChild)) {
return;
}
+
+ if (!aChild->IsSlotable() || aContainer != GetHost()) {
+ return;
+ }
+
+ AssignSlotFor(aChild);
}
void
@@ -383,11 +600,20 @@ ShadowRoot::ContentRemoved(nsIDocument* aDocument,
int32_t aIndexInContainer,
nsIContent* aPreviousSibling)
{
- if (mInsertionPointChanged) {
- DistributeAllNodes();
- mInsertionPointChanged = false;
+ // Check to ensure that the content is in the same anonymous tree
+ // as the container because anonymous content may report its container
+ // as the host but it may not be in the host's child list.
+ if (!nsContentUtils::IsInSameAnonymousTree(aContainer, aChild)) {
return;
}
+
+ if (!aChild->IsSlotable() || aContainer != GetHost()) {
+ return;
+ }
+
+ nsAutoString slotName;
+ aChild->GetAttr(kNameSpaceID_None, nsGkAtoms::slot, slotName);
+ UnassignSlotFor(aChild, slotName);
}
nsresult
diff --git a/dom/base/ShadowRoot.h b/dom/base/ShadowRoot.h
index 5efff5be7..c525ba8e8 100644
--- a/dom/base/ShadowRoot.h
+++ b/dom/base/ShadowRoot.h
@@ -21,6 +21,9 @@ class nsIContent;
class nsXBLPrototypeBinding;
namespace mozilla {
+
+class EventChainPreVisitor;
+
namespace dom {
class Element;
@@ -73,10 +76,26 @@ public:
private:
/**
- * Redistributes a node of the pool, and returns whether the distribution
+ * Try to reassign an element to a slot and returns whether the assignment
* changed.
*/
- bool RedistributeElement(Element*);
+ bool MaybeReassignElement(Element* aElement, const nsAttrValue* aOldValue);
+
+ /**
+ * Try to assign aContent to a slot in the shadow tree, returns the assigned
+ * slot if found.
+ */
+ const HTMLSlotElement* AssignSlotFor(nsIContent* aContent);
+
+ /**
+ * Unassign aContent from the assigned slot in the shadow tree, returns the
+ * assigned slot if found.
+ *
+ * Note: slot attribute of aContent may have changed already, so pass slot
+ * name explicity here.
+ */
+ const HTMLSlotElement* UnassignSlotFor(nsIContent* aContent,
+ const nsAString& aSlotName);
/**
* Called when we redistribute content after insertion points have changed.
@@ -86,6 +105,9 @@ private:
bool IsPooledNode(nsIContent* aChild) const;
public:
+ void AddSlot(HTMLSlotElement* aSlot);
+ void RemoveSlot(HTMLSlotElement* aSlot);
+
void SetInsertionPointChanged() { mInsertionPointChanged = true; }
void SetAssociatedBinding(nsXBLBinding* aBinding) { mAssociatedBinding = aBinding; }
@@ -113,11 +135,18 @@ public:
mIsComposedDocParticipant = aIsComposedDocParticipant;
}
+ nsresult GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
+
protected:
virtual ~ShadowRoot();
ShadowRootMode mMode;
+ // Map from name of slot to an array of all slots in the shadow DOM with with
+ // the given name. The slots are stored as a weak pointer because the elements
+ // are in the shadow tree and should be kept alive by its parent.
+ nsClassHashtable<nsStringHashKey, nsTArray<mozilla::dom::HTMLSlotElement*>> mSlotMap;
+
nsTHashtable<nsIdentifierMapEntry> mIdentifierMap;
nsXBLPrototypeBinding* mProtoBinding;
diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
index 038da24b4..62be71b4a 100644
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -44,6 +44,7 @@
#include "mozilla/dom/Element.h"
#include "mozilla/dom/FileSystemSecurity.h"
#include "mozilla/dom/HTMLMediaElement.h"
+#include "mozilla/dom/HTMLSlotElement.h"
#include "mozilla/dom/HTMLTemplateElement.h"
#include "mozilla/dom/ipc/BlobChild.h"
#include "mozilla/dom/ipc/BlobParent.h"
@@ -7053,6 +7054,13 @@ nsContentUtils::HasDistributedChildren(nsIContent* aContent)
return true;
}
+ HTMLSlotElement* slotEl = HTMLSlotElement::FromContent(aContent);
+ if (slotEl && slotEl->GetContainingShadow()) {
+ // Children of a slot are rendered if the slot does not have any assigned
+ // nodes (fallback content).
+ return slotEl->AssignedNodes().IsEmpty();
+ }
+
return false;
}
diff --git a/dom/base/nsIContent.h b/dom/base/nsIContent.h
index 8da0ba7f2..975173656 100644
--- a/dom/base/nsIContent.h
+++ b/dom/base/nsIContent.h
@@ -999,6 +999,12 @@ protected:
*/
nsIAtom* DoGetID() const;
+ /**
+ * Returns the assigned slot, if it exists, or the direct parent, if it's a
+ * fallback content of a slot.
+ */
+ nsINode* GetFlattenedTreeParentForMaybeAssignedNode() const;
+
public:
#ifdef DEBUG
/**
diff --git a/dom/base/nsINode.h b/dom/base/nsINode.h
index 7c3eb9134..a07bcae51 100644
--- a/dom/base/nsINode.h
+++ b/dom/base/nsINode.h
@@ -408,6 +408,12 @@ public:
*/
virtual bool IsNodeOfType(uint32_t aFlags) const = 0;
+ bool
+ IsSlotable() const
+ {
+ return IsElement() || IsNodeOfType(eTEXT);
+ }
+
virtual JSObject* WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
/**
diff --git a/dom/events/EventDispatcher.h b/dom/events/EventDispatcher.h
index db7b47dbf..618c863d5 100644
--- a/dom/events/EventDispatcher.h
+++ b/dom/events/EventDispatcher.h
@@ -204,13 +204,6 @@ public:
* which should be used when the event is handled at mParentTarget.
*/
dom::EventTarget* mEventTargetAtParent;
-
- /**
- * An array of destination insertion points that need to be inserted
- * into the event path of nodes that are distributed by the
- * web components distribution algorithm.
- */
- nsTArray<nsIContent*> mDestInsertionPoints;
};
class EventChainPostVisitor : public mozilla::EventChainVisitor
diff --git a/dom/html/HTMLSlotElement.cpp b/dom/html/HTMLSlotElement.cpp
index 9f24f8ba3..1ffde7274 100644
--- a/dom/html/HTMLSlotElement.cpp
+++ b/dom/html/HTMLSlotElement.cpp
@@ -7,6 +7,7 @@
#include "mozilla/dom/HTMLSlotElement.h"
#include "mozilla/dom/HTMLSlotElementBinding.h"
#include "mozilla/dom/HTMLUnknownElement.h"
+#include "mozilla/dom/ShadowRoot.h"
#include "nsGkAtoms.h"
#include "nsDocument.h"
@@ -15,12 +16,10 @@ NS_NewHTMLSlotElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
mozilla::dom::FromParser aFromParser)
{
RefPtr<mozilla::dom::NodeInfo> nodeInfo(aNodeInfo);
- /* Disabled for now
if (nsDocument::IsWebComponentsEnabled(nodeInfo)) {
already_AddRefed<mozilla::dom::NodeInfo> nodeInfoArg(nodeInfo.forget());
return new mozilla::dom::HTMLSlotElement(nodeInfoArg);
}
- */
already_AddRefed<mozilla::dom::NodeInfo> nodeInfoArg(nodeInfo.forget());
return new mozilla::dom::HTMLUnknownElement(nodeInfoArg);
@@ -50,13 +49,161 @@ NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement)
NS_IMPL_ELEMENT_CLONE(HTMLSlotElement)
+nsresult
+HTMLSlotElement::BindToTree(nsIDocument* aDocument,
+ nsIContent* aParent,
+ nsIContent* aBindingParent,
+ bool aCompileEventHandlers)
+{
+ RefPtr<ShadowRoot> oldContainingShadow = GetContainingShadow();
+
+ nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
+ aBindingParent,
+ aCompileEventHandlers);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ ShadowRoot* containingShadow = GetContainingShadow();
+ if (containingShadow && !oldContainingShadow) {
+ containingShadow->AddSlot(this);
+ }
+
+ return NS_OK;
+}
+
+void
+HTMLSlotElement::UnbindFromTree(bool aDeep, bool aNullParent)
+{
+ RefPtr<ShadowRoot> oldContainingShadow = GetContainingShadow();
+
+ nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
+
+ if (oldContainingShadow && !GetContainingShadow()) {
+ oldContainingShadow->RemoveSlot(this);
+ }
+}
+
+nsresult
+HTMLSlotElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+ const nsAttrValueOrString* aValue,
+ bool aNotify)
+{
+ if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::name) {
+ if (ShadowRoot* containingShadow = GetContainingShadow()) {
+ containingShadow->RemoveSlot(this);
+ }
+ }
+
+ return nsGenericHTMLElement::BeforeSetAttr(aNameSpaceID, aName, aValue,
+ aNotify);
+}
+
+nsresult
+HTMLSlotElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify)
+{
+
+ if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::name) {
+ if (ShadowRoot* containingShadow = GetContainingShadow()) {
+ containingShadow->AddSlot(this);
+ }
+ }
+
+ return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
+ aOldValue, aNotify);
+}
+
+/**
+ * Flatten assigned nodes given a slot, as in:
+ * https://dom.spec.whatwg.org/#find-flattened-slotables
+ */
+static void
+FlattenAssignedNodes(HTMLSlotElement* aSlot, nsTArray<RefPtr<nsINode>>& aNodes)
+{
+ if (!aSlot->GetContainingShadow()) {
+ return;
+ }
+
+ const nsTArray<RefPtr<nsINode>>& assignedNodes = aSlot->AssignedNodes();
+
+ // If assignedNodes is empty, use children of slot as fallback content.
+ if (assignedNodes.IsEmpty()) {
+ for (nsIContent* child = aSlot->AsContent()->GetFirstChild();
+ child;
+ child = child->GetNextSibling()) {
+ if (!child->IsSlotable()) {
+ continue;
+ }
+
+ if (child->IsHTMLElement(nsGkAtoms::slot)) {
+ FlattenAssignedNodes(HTMLSlotElement::FromContent(child), aNodes);
+ } else {
+ aNodes.AppendElement(child);
+ }
+ }
+ return;
+ }
+
+ for (uint32_t i = 0; i < assignedNodes.Length(); i++) {
+ nsINode* assignedNode = assignedNodes[i];
+ if (assignedNode->IsHTMLElement(nsGkAtoms::slot)) {
+ FlattenAssignedNodes(
+ HTMLSlotElement::FromContent(assignedNode->AsContent()), aNodes);
+ } else {
+ aNodes.AppendElement(assignedNode);
+ }
+ }
+}
+
void
HTMLSlotElement::AssignedNodes(const AssignedNodesOptions& aOptions,
nsTArray<RefPtr<nsINode>>& aNodes)
{
+ if (aOptions.mFlatten) {
+ return FlattenAssignedNodes(this, aNodes);
+ }
+
aNodes = mAssignedNodes;
}
+const nsTArray<RefPtr<nsINode>>&
+HTMLSlotElement::AssignedNodes() const
+{
+ return mAssignedNodes;
+}
+
+void
+HTMLSlotElement::InsertAssignedNode(uint32_t aIndex, nsINode* aNode)
+{
+ mAssignedNodes.InsertElementAt(aIndex, aNode);
+ aNode->AsContent()->SetAssignedSlot(this);
+}
+
+void
+HTMLSlotElement::AppendAssignedNode(nsINode* aNode)
+{
+ mAssignedNodes.AppendElement(aNode);
+ aNode->AsContent()->SetAssignedSlot(this);
+}
+
+void
+HTMLSlotElement::RemoveAssignedNode(nsINode* aNode)
+{
+ mAssignedNodes.RemoveElement(aNode);
+ aNode->AsContent()->SetAssignedSlot(nullptr);
+}
+
+void
+HTMLSlotElement::ClearAssignedNodes()
+{
+ for (uint32_t i = 0; i < mAssignedNodes.Length(); i++) {
+ mAssignedNodes[i]->AsContent()->SetAssignedSlot(nullptr);
+ }
+
+ mAssignedNodes.Clear();
+}
+
JSObject*
HTMLSlotElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
diff --git a/dom/html/HTMLSlotElement.h b/dom/html/HTMLSlotElement.h
index 187a295db..4f8546200 100644
--- a/dom/html/HTMLSlotElement.h
+++ b/dom/html/HTMLSlotElement.h
@@ -26,6 +26,22 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLSlotElement, nsGenericHTMLElement)
virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override;
+ // nsIContent
+ virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+ nsIContent* aBindingParent,
+ bool aCompileEventHandlers) override;
+ virtual void UnbindFromTree(bool aDeep = true,
+ bool aNullParent = true) override;
+
+ virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+ const nsAttrValueOrString* aValue,
+ bool aNotify) override;
+ virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
+
+ // WebIDL
void SetName(const nsAString& aName, ErrorResult& aRv)
{
SetHTMLAttr(nsGkAtoms::name, aName, aRv);
@@ -39,6 +55,13 @@ public:
void AssignedNodes(const AssignedNodesOptions& aOptions,
nsTArray<RefPtr<nsINode>>& aNodes);
+ // Helper methods
+ const nsTArray<RefPtr<nsINode>>& AssignedNodes() const;
+ void InsertAssignedNode(uint32_t aIndex, nsINode* aNode);
+ void AppendAssignedNode(nsINode* aNode);
+ void RemoveAssignedNode(nsINode* aNode);
+ void ClearAssignedNodes();
+
protected:
virtual ~HTMLSlotElement();
virtual JSObject*
diff --git a/layout/reftests/webcomponents/basic-insertion-point-1-ref.html b/layout/reftests/webcomponents/basic-insertion-point-1-ref.html
deleted file mode 100644
index 16f6afb28..000000000
--- a/layout/reftests/webcomponents/basic-insertion-point-1-ref.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<body>
-<div>
- <div style="border: 10px solid green">Hello</div>
-</div>
-</body>
-</html>
diff --git a/layout/reftests/webcomponents/basic-insertion-point-1.html b/layout/reftests/webcomponents/basic-insertion-point-1.html
deleted file mode 100644
index 727175ef3..000000000
--- a/layout/reftests/webcomponents/basic-insertion-point-1.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
- <script>
- function tweak() {
- // div with style "border: 10px solid green"
- var shadowDiv = document.createElement("div");
- shadowDiv.style.border = "10px solid green";
-
- var insertionPoint = document.createElement("content");
- shadowDiv.appendChild(insertionPoint);
-
- var shadowRoot = document.getElementById('outer').createShadowRoot();
- shadowRoot.appendChild(shadowDiv);
- }
- </script>
-</head>
-<body onload="tweak()">
-<div id="outer">Hello</div>
-</body>
-</html>
diff --git a/layout/reftests/webcomponents/basic-insertion-point-2-ref.html b/layout/reftests/webcomponents/basic-insertion-point-2-ref.html
deleted file mode 100644
index 5e9213775..000000000
--- a/layout/reftests/webcomponents/basic-insertion-point-2-ref.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<body>
-<div>
- <div style="border: 10px solid green">
- <span style="background-color: purple">Hello</span>
- <span style="background-color: orange">World</span>
- </div>
-</div>
-</body>
-</html>
diff --git a/layout/reftests/webcomponents/basic-insertion-point-2.html b/layout/reftests/webcomponents/basic-insertion-point-2.html
deleted file mode 100644
index 595edb471..000000000
--- a/layout/reftests/webcomponents/basic-insertion-point-2.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
- <script>
- function tweak() {
- // div with style "border: 10px solid green"
- var shadowDiv = document.createElement("div");
- shadowDiv.style.border = "10px solid green";
-
- var insertionPoint = document.createElement("content");
- shadowDiv.appendChild(insertionPoint);
-
- var shadowRoot = document.getElementById('outer').createShadowRoot();
- shadowRoot.appendChild(shadowDiv);
- }
- </script>
-</head>
-<body onload="tweak()">
-<div id="outer">
- <span style="background-color: purple">Hello</span>
- <span style="background-color: orange">World</span>
-</div>
-</body>
-</html>
diff --git a/layout/reftests/webcomponents/basic-shadow-1.html b/layout/reftests/webcomponents/basic-shadow-1.html
index 944a594d2..8949dfc6d 100644
--- a/layout/reftests/webcomponents/basic-shadow-1.html
+++ b/layout/reftests/webcomponents/basic-shadow-1.html
@@ -9,7 +9,7 @@
shadowDiv.style.height = "100px";
shadowDiv.style.backgroundColor = "green";
- var shadowRoot = document.getElementById('outer').createShadowRoot();
+ var shadowRoot = document.getElementById('outer').attachShadow({mode: 'open'});
shadowRoot.appendChild(shadowDiv);
}
</script>
diff --git a/layout/reftests/webcomponents/basic-shadow-2.html b/layout/reftests/webcomponents/basic-shadow-2.html
index 587c47221..8e066997d 100644
--- a/layout/reftests/webcomponents/basic-shadow-2.html
+++ b/layout/reftests/webcomponents/basic-shadow-2.html
@@ -6,7 +6,7 @@
var shadowDiv = document.createElement("div");
shadowDiv.style.border = "10px solid green";
- var shadowRoot = document.getElementById('outer').createShadowRoot();
+ var shadowRoot = document.getElementById('outer').attachShadow({mode: 'open'});
shadowRoot.appendChild(shadowDiv);
var orangeDiv = document.createElement("div");
diff --git a/layout/reftests/webcomponents/basic-shadow-3.html b/layout/reftests/webcomponents/basic-shadow-3.html
index 2ae53b5a9..3226c4baa 100644
--- a/layout/reftests/webcomponents/basic-shadow-3.html
+++ b/layout/reftests/webcomponents/basic-shadow-3.html
@@ -6,7 +6,7 @@
var shadowDiv = document.createElement("div");
shadowDiv.style.border = "10px solid green";
- var shadowRoot = document.getElementById('outer').createShadowRoot();
+ var shadowRoot = document.getElementById('outer').attachShadow({mode: 'open'});
shadowRoot.appendChild(shadowDiv);
var orangeDiv = document.createElement("div");
diff --git a/layout/reftests/webcomponents/basic-shadow-4.html b/layout/reftests/webcomponents/basic-shadow-4.html
index 70f91773e..39dc51a9e 100644
--- a/layout/reftests/webcomponents/basic-shadow-4.html
+++ b/layout/reftests/webcomponents/basic-shadow-4.html
@@ -6,7 +6,7 @@
var shadowDiv = document.createElement("div");
shadowDiv.style.border = "10px solid green";
- var shadowRoot = document.getElementById('outer').createShadowRoot();
+ var shadowRoot = document.getElementById('outer').attachShadow({mode: 'open'});
shadowRoot.appendChild(shadowDiv);
var orangeDiv = document.createElement("div");
diff --git a/layout/reftests/webcomponents/basic-slot-1-ref.html b/layout/reftests/webcomponents/basic-slot-1-ref.html
new file mode 100644
index 000000000..4f7418498
--- /dev/null
+++ b/layout/reftests/webcomponents/basic-slot-1-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <style>
+ body { color: green; }
+ </style>
+ </head>
+ <body>
+ This text should be green
+ </body>
+</html>
diff --git a/layout/reftests/webcomponents/basic-slot-1.html b/layout/reftests/webcomponents/basic-slot-1.html
new file mode 100644
index 000000000..b31f4c1c3
--- /dev/null
+++ b/layout/reftests/webcomponents/basic-slot-1.html
@@ -0,0 +1,6 @@
+<!DOCTYPE HTML>
+<html>
+ <body>
+ <slot style="color: green">This text should be green</slot>
+ </body>
+</html>
diff --git a/layout/reftests/webcomponents/basic-slot-2-ref.html b/layout/reftests/webcomponents/basic-slot-2-ref.html
new file mode 100644
index 000000000..d4d1b8c06
--- /dev/null
+++ b/layout/reftests/webcomponents/basic-slot-2-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <style>
+ div {
+ width: 100px;
+ height: 100px;
+ background: green;
+ }
+ </style>
+</head>
+<body>
+ <p>There should be a green box below.</p>
+ <div></div>
+</body>
+</html>
diff --git a/layout/reftests/webcomponents/basic-slot-2.html b/layout/reftests/webcomponents/basic-slot-2.html
new file mode 100644
index 000000000..3754ace20
--- /dev/null
+++ b/layout/reftests/webcomponents/basic-slot-2.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML>
+<html>
+ <body>
+ <p>There should be a green box below.</p>
+ <slot style="display: block; width: 100px; height: 100px; background: green;"></slot>
+ </body>
+</html>
diff --git a/layout/reftests/webcomponents/basic-slot-3-ref.html b/layout/reftests/webcomponents/basic-slot-3-ref.html
new file mode 100644
index 000000000..54be54848
--- /dev/null
+++ b/layout/reftests/webcomponents/basic-slot-3-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<div>
+ <div style="color: green">This text should be green</div>
+</div>
+</body>
+</html>
diff --git a/layout/reftests/webcomponents/basic-slot-3.html b/layout/reftests/webcomponents/basic-slot-3.html
new file mode 100644
index 000000000..c00483fe2
--- /dev/null
+++ b/layout/reftests/webcomponents/basic-slot-3.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <script>
+ function tweak() {
+ var slot = document.createElement("slot");
+ slot.style.color = "green";
+
+ var shadowRoot =
+ document.getElementById('outer').attachShadow({mode: 'open'});
+ shadowRoot.appendChild(slot);
+ }
+ </script>
+</head>
+<body onload="tweak()">
+<div id="outer">This text should be green</div>
+</body>
+</html>
diff --git a/layout/reftests/webcomponents/basic-slot-4.html b/layout/reftests/webcomponents/basic-slot-4.html
new file mode 100644
index 000000000..496a92651
--- /dev/null
+++ b/layout/reftests/webcomponents/basic-slot-4.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <script>
+ function tweak() {
+ var slot = document.createElement("slot");
+ // The border shouldn't be visible, due to display: contents.
+ slot.style.border = "1px solid red";
+ slot.style.color = "green";
+
+ var shadowRoot =
+ document.getElementById('outer').attachShadow({mode: 'open'});
+ shadowRoot.appendChild(slot);
+ }
+ </script>
+</head>
+<body onload="tweak()">
+<div id="outer">This text should be green</div>
+</body>
+</html>
diff --git a/layout/reftests/webcomponents/dynamic-insertion-point-distribution-1.html b/layout/reftests/webcomponents/dynamic-insertion-point-distribution-1.html
index c57f72b37..aefe84f25 100644
--- a/layout/reftests/webcomponents/dynamic-insertion-point-distribution-1.html
+++ b/layout/reftests/webcomponents/dynamic-insertion-point-distribution-1.html
@@ -5,9 +5,11 @@
<body>
<div id="host"></div>
<script>
- var host = document.getElementById("host");
- var root = host.createShadowRoot();
- root.innerHTML = 'a <content></content> c';
+ var host, root;
+
+ host = document.getElementById("host");
+ root = host.attachShadow({mode: 'open'});
+ root.innerHTML = 'a <slot></slot> c';
function tweak() {
var span = document.createElement("span");
@@ -19,7 +21,7 @@
document.documentElement.removeAttribute("class");
}
- window.addEventListener("MozReftestInvalidate", tweak, false);
+ window.addEventListener("MozReftestInvalidate", tweak);
</script>
</body>
</html>
diff --git a/layout/reftests/webcomponents/dynamic-insertion-point-distribution-2.html b/layout/reftests/webcomponents/dynamic-insertion-point-distribution-2.html
index 29a850e90..d753af09c 100644
--- a/layout/reftests/webcomponents/dynamic-insertion-point-distribution-2.html
+++ b/layout/reftests/webcomponents/dynamic-insertion-point-distribution-2.html
@@ -5,8 +5,10 @@
<body>
<div id="host"></div>
<script>
- var host = document.getElementById("host");
- var root = host.createShadowRoot();
+ var host, root;
+
+ host = document.getElementById("host");
+ root = host.attachShadow({mode: 'open'});
root.innerHTML = "<span>a</span>";
function tweak() {
@@ -20,7 +22,7 @@
document.documentElement.removeAttribute("class");
}
- window.addEventListener("MozReftestInvalidate", tweak, false);
+ window.addEventListener("MozReftestInvalidate", tweak);
</script>
</body>
</html>
diff --git a/layout/reftests/webcomponents/dynamic-shadow-element-1-ref.html b/layout/reftests/webcomponents/dynamic-shadow-element-1-ref.html
deleted file mode 100644
index a3b5150f6..000000000
--- a/layout/reftests/webcomponents/dynamic-shadow-element-1-ref.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-</head>
-<body>
-<div>
- <div style="background-color: green"><span>Hello</span><span> </span><span>World</span></div>
-</div>
-</body>
-</html>
diff --git a/layout/reftests/webcomponents/dynamic-shadow-element-1.html b/layout/reftests/webcomponents/dynamic-shadow-element-1.html
deleted file mode 100644
index 0142164a1..000000000
--- a/layout/reftests/webcomponents/dynamic-shadow-element-1.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
- <script>
- function tweak() {
- var oldestShadow = document.getElementById('outer').createShadowRoot();
- oldestShadow.innerHTML = 'Hello';
-
- var olderShadow = document.getElementById('outer').createShadowRoot();
-
- var youngerShadow = document.getElementById('outer').createShadowRoot();
- youngerShadow.innerHTML = '<div style="background-color:green"><shadow></shadow></div>';
-
- olderShadow.innerHTML = '<shadow></shadow> World';
- }
- </script>
-</head>
-<body onload="tweak()">
-<div id="outer">
- <div style="width:300px; height:100px; background-color:red;"></div>
-</div>
-</body>
-</html>
diff --git a/layout/reftests/webcomponents/fallback-content-1.html b/layout/reftests/webcomponents/fallback-content-1.html
index ac3b5d02a..0bcd2abbd 100644
--- a/layout/reftests/webcomponents/fallback-content-1.html
+++ b/layout/reftests/webcomponents/fallback-content-1.html
@@ -8,13 +8,13 @@
shadowDiv.style.border = "10px solid green";
// Insertion point will match nothing and use fallback content.
- var insertionPoint = document.createElement("content");
- shadowDiv.appendChild(insertionPoint);
+ var slot = document.createElement("slot");
+ shadowDiv.appendChild(slot);
// Append three nodes as children to use as fallback content.
- insertionPoint.innerHTML = '<span style="background-color: orange">Hello</span> <span style="background-color: green">World</span>';
+ slot.innerHTML = '<span style="background-color: orange">Hello</span> <span style="background-color: green">World</span>';
- var shadowRoot = document.getElementById('outer').createShadowRoot();
+ var shadowRoot = document.getElementById('outer').attachShadow({mode: 'open'});
shadowRoot.appendChild(shadowDiv);
}
</script>
diff --git a/layout/reftests/webcomponents/input-transition-1.html b/layout/reftests/webcomponents/input-transition-1.html
index ede0fa40b..c11444d05 100644
--- a/layout/reftests/webcomponents/input-transition-1.html
+++ b/layout/reftests/webcomponents/input-transition-1.html
@@ -5,19 +5,21 @@
<body>
<div id="host"></div>
<script>
- var host = document.getElementById("host");
- var root = host.createShadowRoot();
+ var host, root;
+
+ host = document.getElementById("host");
+ root = host.attachShadow({mode: 'open'});
root.innerHTML = '<style>input ~ div { background: red; transition: background 100ms; } input:checked ~ div { background: green; }</style><input id="one" type="checkbox"><div style="height: 50px; width: 50px;"></div>';
function tweak() {
- var el = root.getElementById("one");
- el.checked = true;
- el.nextSibling.addEventListener("transitionend", function() {
- document.documentElement.removeAttribute("class");
- }, false);
+ var el = root.getElementById("one");
+ el.checked = true;
+ el.nextSibling.addEventListener("transitionend", function() {
+ setTimeout(()=>{document.documentElement.removeAttribute("class")}, 1000); // wait for the checkbox SVG image to load on Android
+ });
}
- window.addEventListener("MozReftestInvalidate", tweak, false);
+ window.addEventListener("MozReftestInvalidate", tweak);
</script>
</body>
</html>
diff --git a/layout/reftests/webcomponents/nested-insertion-point-1.html b/layout/reftests/webcomponents/nested-insertion-point-1.html
index 66892029a..3d0d92f0d 100644
--- a/layout/reftests/webcomponents/nested-insertion-point-1.html
+++ b/layout/reftests/webcomponents/nested-insertion-point-1.html
@@ -7,19 +7,20 @@
var outerShadow = document.createElement("div");
outerShadow.style.border = "10px solid green";
- var outerInsertionPoint = document.createElement("content");
+ var outerInsertionPoint = document.createElement("slot");
outerShadow.appendChild(outerInsertionPoint);
// div with style "border: 10px solid orange"
var innerShadow = document.createElement("div");
innerShadow.style.border = "10px solid orange";
- var innerInsertionPoint = document.createElement("content");
- innerShadow.appendChild(innerInsertionPoint);
+ var slot = document.createElement("slot");
+ innerShadow.appendChild(slot);
- outerShadow.createShadowRoot().appendChild(innerShadow);
+ outerShadow.attachShadow({mode: 'open'}).appendChild(innerShadow);
- var shadowRoot = document.getElementById('outer').createShadowRoot();
+ var shadowRoot =
+ document.getElementById('outer').attachShadow({mode: 'open'});
shadowRoot.appendChild(outerShadow);
}
</script>
diff --git a/layout/reftests/webcomponents/reframe-shadow-child-1.html b/layout/reftests/webcomponents/reframe-shadow-child-1.html
new file mode 100644
index 000000000..d953beb6d
--- /dev/null
+++ b/layout/reftests/webcomponents/reframe-shadow-child-1.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<template id="tmpl">
+ <div style="display: table">
+ Some text
+ <span style="display: table-cell">something</span>
+ More text
+ </div>
+</template>
+<div id="host"></div>
+<script>
+ let shadowRoot = document.getElementById("host").attachShadow({mode: 'open'});
+ let tmpl = document.getElementById("tmpl");
+ shadowRoot.appendChild(document.importNode(tmpl.content, true));
+ document.body.offsetTop;
+ shadowRoot.firstElementChild.querySelector("span").remove();
+</script>
diff --git a/layout/reftests/webcomponents/reframe-shadow-child-2.html b/layout/reftests/webcomponents/reframe-shadow-child-2.html
new file mode 100644
index 000000000..0ebbe7433
--- /dev/null
+++ b/layout/reftests/webcomponents/reframe-shadow-child-2.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<template id="tmpl">
+ <div style="display: block">
+ Some text
+ More text
+ </div>
+</template>
+<div id="host"></div>
+<script>
+ let shadowRoot = document.getElementById("host").attachShadow({mode: 'open'});
+ let tmpl = document.getElementById("tmpl");
+ shadowRoot.appendChild(document.importNode(tmpl.content, true));
+ document.body.offsetTop;
+ shadowRoot.firstElementChild.style.display = "table";
+</script>
diff --git a/layout/reftests/webcomponents/reftest.list b/layout/reftests/webcomponents/reftest.list
index 280cd204e..6afbc2720 100644
--- a/layout/reftests/webcomponents/reftest.list
+++ b/layout/reftests/webcomponents/reftest.list
@@ -3,8 +3,6 @@ pref(dom.webcomponents.enabled,true) == basic-shadow-1.html basic-shadow-1-ref.h
pref(dom.webcomponents.enabled,true) == basic-shadow-2.html basic-shadow-2-ref.html
pref(dom.webcomponents.enabled,true) == basic-shadow-3.html basic-shadow-3-ref.html
pref(dom.webcomponents.enabled,true) == basic-shadow-4.html basic-shadow-4-ref.html
-#bug 1421542 pref(dom.webcomponents.enabled,true) == basic-insertion-point-1.html basic-insertion-point-1-ref.html
-#bug 1421542 pref(dom.webcomponents.enabled,true) == basic-insertion-point-2.html basic-insertion-point-2-ref.html
pref(dom.webcomponents.enabled,true) == fallback-content-1.html fallback-content-1-ref.html
pref(dom.webcomponents.enabled,true) == remove-insertion-point-1.html remove-insertion-point-1-ref.html
#bug 1421542 pref(dom.webcomponents.enabled,true) == nested-insertion-point-1.html nested-insertion-point-1-ref.html
@@ -13,3 +11,9 @@ pref(dom.webcomponents.enabled,true) == input-transition-1.html input-transition
#bug 1421542 pref(dom.webcomponents.enabled,true) == dynamic-insertion-point-distribution-1.html dynamic-insertion-point-distribution-1-ref.html
pref(dom.webcomponents.enabled,true) == dynamic-insertion-point-distribution-2.html dynamic-insertion-point-distribution-2-ref.html
pref(dom.webcomponents.enabled,true) == remove-append-shadow-host-1.html remove-append-shadow-host-1-ref.html
+pref(dom.webcomponents.enabled,true) == basic-slot-1.html basic-slot-1-ref.html
+pref(dom.webcomponents.enabled,true) == basic-slot-2.html basic-slot-2-ref.html
+pref(dom.webcomponents.enabled,true) == basic-slot-3.html basic-slot-3-ref.html
+pref(dom.webcomponents.enabled,true) == basic-slot-4.html basic-slot-3-ref.html
+pref(dom.webcomponents.enabled,true) == basic-slot-5.html basic-slot-5-ref.html
+pref(dom.webcomponents.enabled,true) == basic-slot-6.html basic-slot-6-ref.html
diff --git a/layout/reftests/webcomponents/remove-append-shadow-host-1.html b/layout/reftests/webcomponents/remove-append-shadow-host-1.html
index 85161565e..1a752eba6 100644
--- a/layout/reftests/webcomponents/remove-append-shadow-host-1.html
+++ b/layout/reftests/webcomponents/remove-append-shadow-host-1.html
@@ -6,7 +6,7 @@
<div id="container"><div id="host"></div></div>
<script>
var host = document.getElementById("host");
- var root = host.createShadowRoot();
+ var root = host.attachShadow({mode: 'open'});
root.innerHTML = 'inside shadow DOM';
var container = document.getElementById("container");
diff --git a/layout/reftests/webcomponents/remove-insertion-point-1.html b/layout/reftests/webcomponents/remove-insertion-point-1.html
index 195673ca8..1b7588daf 100644
--- a/layout/reftests/webcomponents/remove-insertion-point-1.html
+++ b/layout/reftests/webcomponents/remove-insertion-point-1.html
@@ -8,15 +8,15 @@
shadowDiv.style.border = "10px solid green";
// Insertion point will match nothing and use fallback content.
- var insertionPoint = document.createElement("content");
- shadowDiv.appendChild(insertionPoint);
+ var slot = document.createElement("slot");
+ shadowDiv.appendChild(slot);
- var shadowRoot = document.getElementById('outer').createShadowRoot();
+ var shadowRoot = document.getElementById('outer').attachShadow({mode: 'open'});
shadowRoot.appendChild(shadowDiv);
// Remove the insertion point from the ShadowRoot, "Hello" should no
// longer be rendered.
- shadowDiv.removeChild(insertionPoint);
+ shadowDiv.removeChild(slot);
}
</script>
</head>
diff --git a/layout/reftests/webcomponents/style-sharing-across-shadow.html b/layout/reftests/webcomponents/style-sharing-across-shadow.html
new file mode 100644
index 000000000..b41cf7479
--- /dev/null
+++ b/layout/reftests/webcomponents/style-sharing-across-shadow.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<style>
+ div { display: contents }
+</style>
+<div></div>
+<div></div>
+<script>
+ let divs = document.querySelectorAll('div');
+ divs[0].attachShadow({mode: 'open'}).innerHTML = `
+ <style>
+ * { color: green; }
+ </style>
+ <span>Should be green</span>
+ `;
+ divs[1].attachShadow({mode: 'open'}).innerHTML = `
+ <style>
+ * { color: initial; }
+ [foo] { }
+ </style>
+ <span>Should not be green</span>
+ `;
+</script>
diff --git a/layout/reftests/webcomponents/style-sharing.html b/layout/reftests/webcomponents/style-sharing.html
new file mode 100644
index 000000000..0a1e3c95c
--- /dev/null
+++ b/layout/reftests/webcomponents/style-sharing.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<div id="host"></div>
+<script>
+ let root = host.attachShadow({mode: 'open'});
+ root.innerHTML = `
+ <style>
+ #test {
+ color: green;
+ }
+ </style>
+ <span id="test">Should be green</span>
+ <span id="test2">Should not be green</span>
+ `;
+</script>
diff --git a/layout/reftests/webcomponents/update-dist-node-descendants-1.html b/layout/reftests/webcomponents/update-dist-node-descendants-1.html
index e2dd4ebb7..003c23394 100644
--- a/layout/reftests/webcomponents/update-dist-node-descendants-1.html
+++ b/layout/reftests/webcomponents/update-dist-node-descendants-1.html
@@ -5,17 +5,18 @@
<body>
<div id="outer"><span id="distnode">text</span></div>
<script>
-var shadowRoot = document.getElementById('outer').createShadowRoot();
-shadowRoot.innerHTML = '<div><content></content></div>';
-function tweak() {
- var distNode = document.getElementById("distnode");
- distNode.textContent = "Hello World";
+ var shadowRoot = document.getElementById('outer').attachShadow({mode: 'open'});
+ shadowRoot.innerHTML = '<div><slot></slot></div>';
- document.documentElement.removeAttribute("class");
-}
+ function tweak() {
+ var distNode = document.getElementById("distnode");
+ distNode.textContent = "Hello World";
-window.addEventListener("MozReftestInvalidate", tweak);
+ document.documentElement.removeAttribute("class");
+ }
+
+ window.addEventListener("MozReftestInvalidate", tweak);
</script>
</body>
</html>
diff --git a/layout/style/res/ua.css b/layout/style/res/ua.css
index 931b32eb8..504f5dc57 100644
--- a/layout/style/res/ua.css
+++ b/layout/style/res/ua.css
@@ -471,3 +471,9 @@ div:-moz-native-anonymous.moz-custom-content-container {
width: 100%;
height: 100%;
}
+
+/* Shadow DOM v1
+ * https://drafts.csswg.org/css-scoping/#slots-in-shadow-tree */
+slot {
+ display: contents;
+} \ No newline at end of file
diff --git a/testing/web-platform/meta/html/dom/interfaces.html.ini b/testing/web-platform/meta/html/dom/interfaces.html.ini
index db6a464d0..d0ebb0c7d 100644
--- a/testing/web-platform/meta/html/dom/interfaces.html.ini
+++ b/testing/web-platform/meta/html/dom/interfaces.html.ini
@@ -1,6 +1,6 @@
[interfaces.html]
type: testharness
- prefs: [dom.forms.inputmode:true, dom.dialog_element.enabled:true]
+ prefs: [dom.forms.inputmode:true, dom.dialog_element.enabled:true, dom.webcomponents.enabled:true]
[Document interface: attribute domain]
expected: FAIL
@@ -2524,21 +2524,6 @@
[HTMLSlotElement interface: operation assignedNodes(AssignedNodesOptions)]
expected: FAIL
- [HTMLSlotElement must be primary interface of document.createElement("slot")]
- expected: FAIL
-
- [Stringification of document.createElement("slot")]
- expected: FAIL
-
- [HTMLSlotElement interface: document.createElement("slot") must inherit property "name" with the proper type (0)]
- expected: FAIL
-
- [HTMLSlotElement interface: document.createElement("slot") must inherit property "assignedNodes" with the proper type (1)]
- expected: FAIL
-
- [HTMLSlotElement interface: calling assignedNodes(AssignedNodesOptions) on document.createElement("slot") with too few arguments must throw TypeError]
- expected: FAIL
-
[HTMLInputElement interface: createInput("text") must inherit property "dirName" with the proper type (6)]
expected: FAIL
diff --git a/testing/web-platform/meta/html/dom/reflection-misc.html.ini b/testing/web-platform/meta/html/dom/reflection-misc.html.ini
index bc65d4191..05bb9c4cd 100644
--- a/testing/web-platform/meta/html/dom/reflection-misc.html.ini
+++ b/testing/web-platform/meta/html/dom/reflection-misc.html.ini
@@ -1,6 +1,6 @@
[reflection-misc.html]
type: testharness
- prefs: [dom.dialog_element.enabled: true]
+ prefs: [dom.dialog_element.enabled: true, dom.webcomponents.enabled:true]
[html.tabIndex: setAttribute() to object "3" followed by getAttribute()]
expected: FAIL
diff --git a/testing/web-platform/meta/shadow-dom/HTMLSlotElement-interface.html.ini b/testing/web-platform/meta/shadow-dom/HTMLSlotElement-interface.html.ini
deleted file mode 100644
index c045a3006..000000000
--- a/testing/web-platform/meta/shadow-dom/HTMLSlotElement-interface.html.ini
+++ /dev/null
@@ -1,44 +0,0 @@
-[HTMLSlotElement-interface.html]
- type: testharness
- [HTMLSlotElement must be defined on window]
- expected: FAIL
-
- ["name" attribute on HTMLSlotElement must reflect "name" attribute]
- expected: FAIL
-
- [assignedNodes() on a HTMLSlotElement must return an empty array when the slot element is not in a tree or in a document tree]
- expected: FAIL
-
- [assignedNodes({"flattened":false}) on a HTMLSlotElement must return an empty array when the slot element is not in a tree or in a document tree]
- expected: FAIL
-
- [assignedNodes({"flattened":true}) on a HTMLSlotElement must return an empty array when the slot element is not in a tree or in a document tree]
- expected: FAIL
-
- [assignedNodes() must return the list of assigned nodes when none of the assigned nodes themselves are slots]
- expected: FAIL
-
- [assignedNodes({"flattened":false}) must return the list of assigned nodes when none of the assigned nodes themselves are slots]
- expected: FAIL
-
- [assignedNodes({"flattened":true}) must return the list of assigned nodes when none of the assigned nodes themselves are slots]
- expected: FAIL
-
- [assignedNodes() must update when slot and name attributes are modified]
- expected: FAIL
-
- [assignedNodes({"flattened":false}) must update when slot and name attributes are modified]
- expected: FAIL
-
- [assignedNodes({"flattened":true}) must update when slot and name attributes are modified]
- expected: FAIL
-
- [assignedNodes must update when a default slot is introduced dynamically by a slot rename]
- expected: FAIL
-
- [assignedNodes must update when slot elements are inserted or removed]
- expected: FAIL
-
- [assignedNodes({flatten: true}) must return the distributed nodes, and assignedNodes() and assignedNodes({flatten: false}) must returned the assigned nodes]
- expected: FAIL
-
diff --git a/testing/web-platform/meta/shadow-dom/Slotable-interface.html.ini b/testing/web-platform/meta/shadow-dom/Slotable-interface.html.ini
deleted file mode 100644
index 6ef193dee..000000000
--- a/testing/web-platform/meta/shadow-dom/Slotable-interface.html.ini
+++ /dev/null
@@ -1,12 +0,0 @@
-[Slotable-interface.html]
- type: testharness
- prefs: [dom.webcomponents.enabled:true]
- [assignedSlot must return null when the node does not have an assigned node]
- expected: FAIL
-
- [assignedSlot must return the assigned slot]
- expected: FAIL
-
- [assignedSlot must return null when the assigned slot element is inside a closed shadow tree]
- expected: FAIL
-
diff --git a/testing/web-platform/meta/shadow-dom/event-inside-slotted-node.html.ini b/testing/web-platform/meta/shadow-dom/event-inside-slotted-node.html.ini
deleted file mode 100644
index 7e42670a3..000000000
--- a/testing/web-platform/meta/shadow-dom/event-inside-slotted-node.html.ini
+++ /dev/null
@@ -1,38 +0,0 @@
-[event-inside-slotted-node.html]
- type: testharness
- [Firing an event inside a grand child of a detached open mode shadow host]
- expected: FAIL
-
- [Firing an event inside a grand child of a detached closed mode shadow host]
- expected: FAIL
-
- [Firing an event inside a grand child of an in-document open mode shadow host]
- expected: FAIL
-
- [Firing an event inside a grand child of an in-document closed mode shadow host]
- expected: FAIL
-
- [Firing an event on a node with two ancestors with a detached open and open shadow trees with an inner open shadow tree]
- expected: FAIL
-
- [Firing an event on a node with two ancestors with a detached open and open shadow trees with an inner closed shadow tree]
- expected: FAIL
-
- [Firing an event on a node with two ancestors with a detached open and closed shadow trees with an inner open shadow tree]
- expected: FAIL
-
- [Firing an event on a node with two ancestors with a detached open and closed shadow trees with an inner closed shadow tree]
- expected: FAIL
-
- [Firing an event on a node with two ancestors with a detached closed and open shadow trees with an inner open shadow tree]
- expected: FAIL
-
- [Firing an event on a node with two ancestors with a detached closed and open shadow trees with an inner closed shadow tree]
- expected: FAIL
-
- [Firing an event on a node with two ancestors with a detached closed and closed shadow trees with an inner open shadow tree]
- expected: FAIL
-
- [Firing an event on a node with two ancestors with a detached closed and closed shadow trees with an inner closed shadow tree]
- expected: FAIL
-
diff --git a/testing/web-platform/meta/shadow-dom/slots-fallback.html.ini b/testing/web-platform/meta/shadow-dom/slots-fallback.html.ini
deleted file mode 100644
index d32ae812b..000000000
--- a/testing/web-platform/meta/shadow-dom/slots-fallback.html.ini
+++ /dev/null
@@ -1,32 +0,0 @@
-[slots-fallback.html]
- type: testharness
- [Slots fallback: Basic.]
- expected: FAIL
-
- [Slots fallback: Slots in Slots.]
- expected: FAIL
-
- [Slots fallback: Fallback contents should not be used if a node is assigned.]
- expected: FAIL
-
- [Slots fallback: Slots in Slots: Assinged nodes should be used as fallback contents of another slot]
- expected: FAIL
-
- [Slots fallback: Complex case.]
- expected: FAIL
-
- [Slots fallback: Mutation. Append fallback contents.]
- expected: FAIL
-
- [Slots fallback: Mutation. Remove fallback contents.]
- expected: FAIL
-
- [Slots fallback: Mutation. Assign a node to a slot so that fallback contens are no longer used.]
- expected: FAIL
-
- [Slots fallback: Mutation. Remove an assigned node from a slot so that fallback contens will be used.]
- expected: FAIL
-
- [Slots fallback: Mutation. Remove a slot which is a fallback content of another slot.]
- expected: FAIL
-
diff --git a/testing/web-platform/meta/shadow-dom/slots.html.ini b/testing/web-platform/meta/shadow-dom/slots.html.ini
deleted file mode 100644
index 3c047e482..000000000
--- a/testing/web-platform/meta/shadow-dom/slots.html.ini
+++ /dev/null
@@ -1,71 +0,0 @@
-[slots.html]
- type: testharness
- [Slots: Basic.]
- expected: FAIL
-
- [Slots: Slots in closed.]
- expected: FAIL
-
- [Slots: Slots not in a shadow tree.]
- expected: FAIL
-
- [Slots: Distributed nooes for Slots not in a shadow tree.]
- expected: FAIL
-
- [Slots: Name matching]
- expected: FAIL
-
- [Slots: No direct host child.]
- expected: FAIL
-
- [Slots: Default Slot.]
- expected: FAIL
-
- [Slots: Slot in Slot does not matter in assignment.]
- expected: FAIL
-
- [Slots: Slot is assigned to another slot]
- expected: FAIL
-
- [Slots: Open > Closed.]
- expected: FAIL
-
- [Slots: Closed > Closed.]
- expected: FAIL
-
- [Slots: Closed > Open.]
- expected: FAIL
-
- [Slots: Complex case: Basi line.]
- expected: FAIL
-
- [Slots: Mutation: appendChild.]
- expected: FAIL
-
- [Slots: Mutation: Change slot= attribute 1.]
- expected: FAIL
-
- [Slots: Mutation: Change slot= attribute 2.]
- expected: FAIL
-
- [Slots: Mutation: Change slot= attribute 3.]
- expected: FAIL
-
- [Slots: Mutation: Remove a child.]
- expected: FAIL
-
- [Slots: Mutation: Add a slot: after.]
- expected: FAIL
-
- [Slots: Mutation: Add a slot: before.]
- expected: FAIL
-
- [Slots: Mutation: Remove a slot.]
- expected: FAIL
-
- [Slots: Mutation: Change slot name= attribute.]
- expected: FAIL
-
- [Slots: Mutation: Change slot slot= attribute.]
- expected: FAIL
-