/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// If assignedNodes is empty, use children of slot as fallback content.
if (assignedNodes.IsEmpty()) {
for (nsIContent* child = aSlot->GetFirstChild(); child;
child = child->GetNextSibling()) {
if (!child->IsSlotable()) { continue;
}
// no-op if the input nodes and the assigned nodes are identical // This also works if the two 'assign' calls are like // > slot.assign(node1, node2); // > slot.assign(node1, node2, node1, node2);
if (!mAssignedNodes.IsEmpty() && aNodes.Length() >= mAssignedNodes.Length()) {
nsTHashMap<nsPtrHashKey<nsIContent>, size_t> nodeIndexMap;
for (size_t i = 0; i < aNodes.Length(); ++i) {
nsIContent* content;
if (aNodes[i].IsElement()) {
content = aNodes[i].GetAsElement();
} else {
content = aNodes[i].GetAsText();
}
MOZ_ASSERT(content); // We only care about the first index this content appears // in the array
nodeIndexMap.LookupOrInsert(content, i);
}
if (nodeIndexMap.Count() == mAssignedNodes.Length()) { bool isIdentical = true;
for (size_t i = 0; i < mAssignedNodes.Length(); ++i) {
size_t indexInInputNodes;
if (!nodeIndexMap.Get(mAssignedNodes[i]->AsContent(),
&indexInInputNodes) ||
indexInInputNodes != i) {
isIdentical = false; break;
}
}
if (isIdentical) { return;
}
}
}
// 1. For each node of this's manually assigned nodes, set node's manual slot // assignment to null.
for (nsINode* node : mManuallyAssignedNodes) {
MOZ_ASSERT(node->AsContent()->GetManualSlotAssignment() == this);
node->AsContent()->SetManualSlotAssignment(nullptr);
}
// 2. Let nodesSet be a new ordered set.
mManuallyAssignedNodes.Clear();
// An optimization to keep track which slots need to enqueue // slotchange event, such that they can be enqueued later in // tree order.
nsTHashSet<RefPtr<HTMLSlotElement>> changedSlots;
// Clear out existing assigned nodes
if (mInManualShadowRoot) {
if (!mAssignedNodes.IsEmpty()) {
changedSlots.EnsureInserted(this);
if (root) { // If not in a shadow tree, the flat tree is not really changing, so no // need to invalidate layout. Same applies to other callers here.
ShadowRoot::InvalidateStyleAndLayoutOnSubtree(this);
}
ClearAssignedNodes();
}
MOZ_ASSERT(content); // XXXsmaug Should we have a helper for // https://infra.spec.whatwg.org/#ordered-set?
if (content->GetManualSlotAssignment() != this) { // Step 3.1: If content's manual slot assignment refers to a slot, // then remove node from that slot's manually assigned nodes.
if (HTMLSlotElement* prevSlot = content->GetManualSlotAssignment()) {
ShadowRoot* prevSlotRoot = prevSlot->GetContainingShadow(); constbool wasAssigned = content->GetAssignedSlot() == prevSlot;
if (wasAssigned && prevSlotRoot &&
changedSlots.EnsureInserted(prevSlot)) {
ShadowRoot::InvalidateStyleAndLayoutOnSubtree(prevSlot);
}
prevSlot->RemoveManuallyAssignedNode(*content);
}
// Step 3.2: Set content's manual slot assignment to this.
content->SetManualSlotAssignment(this); // Step 3.3: Append content to nodesSet.
mManuallyAssignedNodes.AppendElement(content);
if (changedSlots.EnsureInserted(this) && root) {
ShadowRoot::InvalidateStyleAndLayoutOnSubtree(this);
}
if (root && host && content->GetParent() == host) { // Equivalent to 4.2.2.4.3 (DOM Spec) `Set slot's assigned nodes to // slottables`
root->MaybeReassignContent(*content);
}
}
}
// The `assign slottables` step is completed already at this point, // however we haven't fired the `slotchange` event yet because this // needs to be done in tree order.
if (root) {
for (nsIContent* child = root->GetFirstChild(); child;
child = child->GetNextNode()) {
if (HTMLSlotElement* slot = HTMLSlotElement::FromNode(child)) {
if (changedSlots.EnsureRemoved(slot)) {
slot->EnqueueSlotChangeEvent();
}
}
}
} // Fire slotchange for any remaining slots that are in a different shadow // tree (cross-root case). The spec doesn't define an ordering here.
for (constauto& slot : changedSlots) {
slot->EnqueueSlotChangeEvent();
}
}
void HTMLSlotElement::InsertAssignedNode(uint32_t aIndex, nsIContent& aNode) {
MOZ_ASSERT(!aNode.GetAssignedSlot(), "Losing track of a slot");
mAssignedNodes.InsertElementAt(aIndex, &aNode);
aNode.SetAssignedSlot(this);
RecalculateHasSlottedState();
SlotAssignedNodeAdded(this, aNode);
}
void HTMLSlotElement::AppendAssignedNode(nsIContent& aNode) {
MOZ_ASSERT(!aNode.GetAssignedSlot(), "Losing track of a slot");
mAssignedNodes.AppendElement(&aNode);
aNode.SetAssignedSlot(this);
RecalculateHasSlottedState();
SlotAssignedNodeAdded(this, aNode);
}
void HTMLSlotElement::RecalculateHasSlottedState() { bool hasSlotted = false; // Find the first node that makes this a slotted element.
for (const RefPtr<nsINode>& assignedNode : mAssignedNodes.AsSpan()) {
if (auto* slot = HTMLSlotElement::FromNode(assignedNode)) {
if (slot->IsInShadowTree() &&
!slot->State().HasState(ElementState::HAS_SLOTTED)) { continue;
}
}
hasSlotted = true; break;
}
if (State().HasState(ElementState::HAS_SLOTTED) != hasSlotted) {
SetStates(ElementState::HAS_SLOTTED, hasSlotted); // If slot is a slotted node itself, the assigned slot needs to // RecalculateHasSlottedState:
if (auto* slot = GetAssignedSlot()) {
slot->RecalculateHasSlottedState();
}
}
}
void HTMLSlotElement::RemoveAssignedNode(nsIContent& aNode) { // This one runs from unlinking, so we can't guarantee that the slot pointer // hasn't been cleared.
MOZ_ASSERT(!aNode.GetAssignedSlot() || aNode.GetAssignedSlot() == this, "How exactly?");
mAssignedNodes.RemoveElement(&aNode);
aNode.SetAssignedSlot(nullptr);
RecalculateHasSlottedState();
SlotAssignedNodeRemoved(this, aNode);
if (StaticPrefs::dom_headingoffset_enabled()) {
aNode.AsContent()->UpdateHeadingElementsOffsetChange();
}
}
void HTMLSlotElement::EnqueueSlotChangeEvent() {
if (mInSignalSlotList) { return;
}
// FIXME(bug 1459704): Need to figure out how to deal with microtasks posted // during shutdown.
if (AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMShutdownThreads)) { return;
}
DocGroup* docGroup = OwnerDoc()->GetDocGroup();
if (!docGroup) { return;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.