void SlotAssignment::resolveAssignment(const ShadowRoot& shadowRoot) { m_assignment.clear(); using Name2Slot = WillBeHeapHashMap<AtomicString, RefPtrWillBeMember<HTMLSlotElement>>; Name2Slot name2slot; HTMLSlotElement* defaultSlot = nullptr; WillBeHeapVector<RefPtrWillBeMember<HTMLSlotElement>> slots; // TODO(hayato): Cache slots elements so that we do not have to travese the shadow tree. See ShadowRoot::descendantInsertionPoints() for (HTMLSlotElement& slot : Traversal<HTMLSlotElement>::descendantsOf(shadowRoot)) { slot.clearDistribution(); slots.append(&slot); AtomicString name = slot.fastGetAttribute(HTMLNames::nameAttr); if (name.isNull() || name.isEmpty()) { if (!defaultSlot) defaultSlot = &slot; } else { name2slot.add(name, &slot); } } for (Node& child : NodeTraversal::childrenOf(*shadowRoot.host())) { if (child.isElementNode()) { if (isActiveInsertionPoint(child)) { // TODO(hayato): Support re-distribution across v0 and v1 shadow trees detachNotAssignedNode(child); continue; } AtomicString slotName = toElement(child).fastGetAttribute(HTMLNames::slotAttr); if (slotName.isNull() || slotName.isEmpty()) { if (defaultSlot) assign(child, *defaultSlot); else detachNotAssignedNode(child); } else { HTMLSlotElement* slot = name2slot.get(slotName); if (slot) assign(child, *slot); else detachNotAssignedNode(child); } } else if (defaultSlot) { assign(child, *defaultSlot); } else { detachNotAssignedNode(child); } } // Update each slot's distribution in reverse tree order so that a child slot is visited before its parent slot. for (auto slot = slots.rbegin(); slot != slots.rend(); ++slot) (*slot)->updateDistributedNodesWithFallback(); }