summaryrefslogtreecommitdiffstats
path: root/dom/base/ShadowRoot.cpp
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2020-04-17 07:35:48 -0400
committerMatt A. Tobin <email@mattatobin.com>2020-04-17 07:35:48 -0400
commit3508e79b1fe7fc928eed2f3c7bf2d628c53fbf17 (patch)
treec793eb598816afa68a560c4224b06ca15b8ad55c /dom/base/ShadowRoot.cpp
parentf164962a3dc53f4823dfff6c77e7972c72d4c61f (diff)
downloadUXP-3508e79b1fe7fc928eed2f3c7bf2d628c53fbf17.tar
UXP-3508e79b1fe7fc928eed2f3c7bf2d628c53fbf17.tar.gz
UXP-3508e79b1fe7fc928eed2f3c7bf2d628c53fbf17.tar.lz
UXP-3508e79b1fe7fc928eed2f3c7bf2d628c53fbf17.tar.xz
UXP-3508e79b1fe7fc928eed2f3c7bf2d628c53fbf17.zip
Bug 1409976 - Add `slotchange` event
* Add support for `slotchange` event * Signal `slotchange` when slot's assigned nodes changes Tag #1375
Diffstat (limited to 'dom/base/ShadowRoot.cpp')
-rw-r--r--dom/base/ShadowRoot.cpp69
1 files changed, 62 insertions, 7 deletions
diff --git a/dom/base/ShadowRoot.cpp b/dom/base/ShadowRoot.cpp
index e7f7ae93c..12f35c197 100644
--- a/dom/base/ShadowRoot.cpp
+++ b/dom/base/ShadowRoot.cpp
@@ -134,6 +134,7 @@ ShadowRoot::AddSlot(HTMLSlotElement* aSlot)
return;
}
+ bool doEnqueueSlotChange = false;
if (oldSlot && oldSlot != currentSlot) {
// Move assigned nodes from old slot to new slot.
const nsTArray<RefPtr<nsINode>>& assignedNodes = oldSlot->AssignedNodes();
@@ -142,6 +143,12 @@ ShadowRoot::AddSlot(HTMLSlotElement* aSlot)
oldSlot->RemoveAssignedNode(assignedNode);
currentSlot->AppendAssignedNode(assignedNode);
+ doEnqueueSlotChange = true;
+ }
+
+ if (doEnqueueSlotChange) {
+ oldSlot->EnqueueSlotChangeEvent();
+ currentSlot->EnqueueSlotChangeEvent();
}
} else {
// Otherwise add appropriate nodes to this slot from the host.
@@ -152,8 +159,13 @@ ShadowRoot::AddSlot(HTMLSlotElement* aSlot)
child->GetAttr(kNameSpaceID_None, nsGkAtoms::slot, slotName);
if (child->IsSlotable() && slotName.Equals(name)) {
currentSlot->AppendAssignedNode(child);
+ doEnqueueSlotChange = true;
}
}
+
+ if (doEnqueueSlotChange) {
+ currentSlot->EnqueueSlotChangeEvent();
+ }
}
}
@@ -171,8 +183,13 @@ ShadowRoot::RemoveSlot(HTMLSlotElement* aSlot)
if (currentSlots->Length() == 1) {
MOZ_ASSERT(currentSlots->ElementAt(0) == aSlot);
mSlotMap.Remove(name);
- aSlot->ClearAssignedNodes();
+
+ if (aSlot->AssignedNodes().Length() > 0) {
+ aSlot->ClearAssignedNodes();
+ aSlot->EnqueueSlotChangeEvent();
+ }
} else {
+ bool doEnqueueSlotChange = false;
bool doReplaceSlot = currentSlots->ElementAt(0) == aSlot;
currentSlots->RemoveElement(aSlot);
HTMLSlotElement* replacementSlot = currentSlots->ElementAt(0);
@@ -186,6 +203,12 @@ ShadowRoot::RemoveSlot(HTMLSlotElement* aSlot)
aSlot->RemoveAssignedNode(assignedNode);
replacementSlot->AppendAssignedNode(assignedNode);
+ doEnqueueSlotChange = true;
+ }
+
+ if (doEnqueueSlotChange) {
+ aSlot->EnqueueSlotChangeEvent();
+ replacementSlot->EnqueueSlotChangeEvent();
}
}
}
@@ -421,6 +444,12 @@ ShadowRoot::MaybeReassignElement(Element* aElement,
const HTMLSlotElement* newSlot = AssignSlotFor(aElement);
if (oldSlot != newSlot) {
+ if (oldSlot) {
+ oldSlot->EnqueueSlotChangeEvent();
+ }
+ if (newSlot) {
+ newSlot->EnqueueSlotChangeEvent();
+ }
return true;
}
}
@@ -587,11 +616,24 @@ ShadowRoot::ContentInserted(nsIDocument* aDocument,
return;
}
- if (!aChild->IsSlotable() || aContainer != GetHost()) {
+ if (!aChild->IsSlotable()) {
return;
}
- AssignSlotFor(aChild);
+ if (aContainer && aContainer == GetHost()) {
+ if (const HTMLSlotElement* slot = AssignSlotFor(aChild)) {
+ slot->EnqueueSlotChangeEvent();
+ }
+ return;
+ }
+
+ // If parent's root is a shadow root, and parent is a slot whose assigned
+ // nodes is the empty list, then run signal a slot change for parent.
+ HTMLSlotElement* slot = HTMLSlotElement::FromContentOrNull(aContainer);
+ if (slot && slot->GetContainingShadow() == this &&
+ slot->AssignedNodes().IsEmpty()) {
+ slot->EnqueueSlotChangeEvent();
+ }
}
void
@@ -608,13 +650,26 @@ ShadowRoot::ContentRemoved(nsIDocument* aDocument,
return;
}
- if (!aChild->IsSlotable() || aContainer != GetHost()) {
+ if (!aChild->IsSlotable()) {
return;
}
- nsAutoString slotName;
- aChild->GetAttr(kNameSpaceID_None, nsGkAtoms::slot, slotName);
- UnassignSlotFor(aChild, slotName);
+ if (aContainer && aContainer == GetHost()) {
+ nsAutoString slotName;
+ aChild->GetAttr(kNameSpaceID_None, nsGkAtoms::slot, slotName);
+ if (const HTMLSlotElement* slot = UnassignSlotFor(aChild, slotName)) {
+ slot->EnqueueSlotChangeEvent();
+ }
+ return;
+ }
+
+ // If parent's root is a shadow root, and parent is a slot whose assigned
+ // nodes is the empty list, then run signal a slot change for parent.
+ HTMLSlotElement* slot = HTMLSlotElement::FromContentOrNull(aContainer);
+ if (slot && slot->GetContainingShadow() == this &&
+ slot->AssignedNodes().IsEmpty()) {
+ slot->EnqueueSlotChangeEvent();
+ }
}
nsresult