| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/dom/shadow/SlotAssignment.h" | 5 #include "core/dom/shadow/SlotAssignment.h" |
| 6 | 6 |
| 7 #include "core/HTMLNames.h" | 7 #include "core/HTMLNames.h" |
| 8 #include "core/dom/ElementTraversal.h" | 8 #include "core/dom/ElementTraversal.h" |
| 9 #include "core/dom/NodeTraversal.h" | 9 #include "core/dom/NodeTraversal.h" |
| 10 #include "core/dom/shadow/ElementShadow.h" | 10 #include "core/dom/shadow/ElementShadow.h" |
| 11 #include "core/dom/shadow/InsertionPoint.h" | 11 #include "core/dom/shadow/InsertionPoint.h" |
| 12 #include "core/dom/shadow/ShadowRoot.h" | 12 #include "core/dom/shadow/ShadowRoot.h" |
| 13 #include "core/html/HTMLSlotElement.h" | 13 #include "core/html/HTMLSlotElement.h" |
| 14 | 14 |
| 15 namespace blink { | 15 namespace blink { |
| 16 | 16 |
| 17 void SlotAssignment::slotAdded(HTMLSlotElement& slot) { | 17 void SlotAssignment::slotAdded(HTMLSlotElement& slot) { |
| 18 // Relevant DOM Standard: | 18 // Relevant DOM Standard: |
| 19 // https://dom.spec.whatwg.org/#concept-node-insert | 19 // https://dom.spec.whatwg.org/#concept-node-insert |
| 20 // 6.4: Run assign slotables for a tree with node's tree and a set containing
each inclusive descendant of node that is a slot. | 20 // 6.4: Run assign slotables for a tree with node's tree and a set containing |
| 21 // each inclusive descendant of node that is a slot. |
| 21 | 22 |
| 22 ++m_slotCount; | 23 ++m_slotCount; |
| 23 m_needsCollectSlots = true; | 24 m_needsCollectSlots = true; |
| 24 | 25 |
| 25 if (!m_slotMap->contains(slot.name())) { | 26 if (!m_slotMap->contains(slot.name())) { |
| 26 m_slotMap->add(slot.name(), &slot); | 27 m_slotMap->add(slot.name(), &slot); |
| 27 return; | 28 return; |
| 28 } | 29 } |
| 29 | 30 |
| 30 HTMLSlotElement& oldActive = *findSlotByName(slot.name()); | 31 HTMLSlotElement& oldActive = *findSlotByName(slot.name()); |
| 31 DCHECK_NE(oldActive, slot); | 32 DCHECK_NE(oldActive, slot); |
| 32 m_slotMap->add(slot.name(), &slot); | 33 m_slotMap->add(slot.name(), &slot); |
| 33 if (findSlotByName(slot.name()) == oldActive) | 34 if (findSlotByName(slot.name()) == oldActive) |
| 34 return; | 35 return; |
| 35 // |oldActive| is no longer an active slot. | 36 // |oldActive| is no longer an active slot. |
| 36 if (oldActive.findHostChildWithSameSlotName()) | 37 if (oldActive.findHostChildWithSameSlotName()) |
| 37 oldActive.enqueueSlotChangeEvent(); | 38 oldActive.enqueueSlotChangeEvent(); |
| 38 // TODO(hayato): We should not enqeueue a slotchange event for |oldActive| | 39 // TODO(hayato): We should not enqeueue a slotchange event for |oldActive| |
| 39 // if |oldActive| was inserted together with |slot|. | 40 // if |oldActive| was inserted together with |slot|. |
| 40 // This could happen if |oldActive| and |slot| are descendants of the inserted
node, and | 41 // This could happen if |oldActive| and |slot| are descendants of the inserted |
| 41 // |oldActive| is preceding |slot|. | 42 // node, and |oldActive| is preceding |slot|. |
| 42 } | 43 } |
| 43 | 44 |
| 44 void SlotAssignment::slotRemoved(HTMLSlotElement& slot) { | 45 void SlotAssignment::slotRemoved(HTMLSlotElement& slot) { |
| 45 DCHECK_GT(m_slotCount, 0u); | 46 DCHECK_GT(m_slotCount, 0u); |
| 46 --m_slotCount; | 47 --m_slotCount; |
| 47 m_needsCollectSlots = true; | 48 m_needsCollectSlots = true; |
| 48 | 49 |
| 49 DCHECK(m_slotMap->contains(slot.name())); | 50 DCHECK(m_slotMap->contains(slot.name())); |
| 50 HTMLSlotElement* oldActive = findSlotByName(slot.name()); | 51 HTMLSlotElement* oldActive = findSlotByName(slot.name()); |
| 51 m_slotMap->remove(slot.name(), &slot); | 52 m_slotMap->remove(slot.name(), &slot); |
| 52 HTMLSlotElement* newActive = findSlotByName(slot.name()); | 53 HTMLSlotElement* newActive = findSlotByName(slot.name()); |
| 53 if (newActive && newActive != oldActive) { | 54 if (newActive && newActive != oldActive) { |
| 54 // |newActive| slot becomes an active slot. | 55 // |newActive| slot becomes an active slot. |
| 55 if (newActive->findHostChildWithSameSlotName()) | 56 if (newActive->findHostChildWithSameSlotName()) |
| 56 newActive->enqueueSlotChangeEvent(); | 57 newActive->enqueueSlotChangeEvent(); |
| 57 // TODO(hayato): Prevent a false-positive slotchange. | 58 // TODO(hayato): Prevent a false-positive slotchange. |
| 58 // This could happen if more than one slots which have the same name are des
cendants of the removed node. | 59 // This could happen if more than one slots which have the same name are |
| 60 // descendants of the removed node. |
| 59 } | 61 } |
| 60 } | 62 } |
| 61 | 63 |
| 62 bool SlotAssignment::findHostChildBySlotName( | 64 bool SlotAssignment::findHostChildBySlotName( |
| 63 const AtomicString& slotName) const { | 65 const AtomicString& slotName) const { |
| 64 // TODO(hayato): Avoid traversing children every time. | 66 // TODO(hayato): Avoid traversing children every time. |
| 65 for (Node& child : NodeTraversal::childrenOf(m_owner->host())) { | 67 for (Node& child : NodeTraversal::childrenOf(m_owner->host())) { |
| 66 if (!child.isSlotable()) | 68 if (!child.isSlotable()) |
| 67 continue; | 69 continue; |
| 68 if (child.slotName() == slotName) | 70 if (child.slotName() == slotName) |
| 69 return true; | 71 return true; |
| 70 } | 72 } |
| 71 return false; | 73 return false; |
| 72 } | 74 } |
| 73 | 75 |
| 74 void SlotAssignment::slotRenamed(const AtomicString& oldSlotName, | 76 void SlotAssignment::slotRenamed(const AtomicString& oldSlotName, |
| 75 HTMLSlotElement& slot) { | 77 HTMLSlotElement& slot) { |
| 76 // |slot| has already new name. Thus, we can not use slot.hasAssignedNodesSync
hronously. | 78 // |slot| has already new name. Thus, we can not use |
| 79 // slot.hasAssignedNodesSynchronously. |
| 77 bool hasAssignedNodesBefore = (findSlotByName(oldSlotName) == &slot) && | 80 bool hasAssignedNodesBefore = (findSlotByName(oldSlotName) == &slot) && |
| 78 findHostChildBySlotName(oldSlotName); | 81 findHostChildBySlotName(oldSlotName); |
| 79 | 82 |
| 80 m_slotMap->remove(oldSlotName, &slot); | 83 m_slotMap->remove(oldSlotName, &slot); |
| 81 m_slotMap->add(slot.name(), &slot); | 84 m_slotMap->add(slot.name(), &slot); |
| 82 | 85 |
| 83 bool hasAssignedNodesAfter = slot.hasAssignedNodesSlow(); | 86 bool hasAssignedNodesAfter = slot.hasAssignedNodesSlow(); |
| 84 | 87 |
| 85 if (hasAssignedNodesBefore || hasAssignedNodesAfter) | 88 if (hasAssignedNodesBefore || hasAssignedNodesAfter) |
| 86 slot.enqueueSlotChangeEvent(); | 89 slot.enqueueSlotChangeEvent(); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 } | 133 } |
| 131 } | 134 } |
| 132 | 135 |
| 133 void SlotAssignment::resolveDistribution() { | 136 void SlotAssignment::resolveDistribution() { |
| 134 resolveAssignment(); | 137 resolveAssignment(); |
| 135 const HeapVector<Member<HTMLSlotElement>>& slots = this->slots(); | 138 const HeapVector<Member<HTMLSlotElement>>& slots = this->slots(); |
| 136 | 139 |
| 137 for (auto slot : slots) | 140 for (auto slot : slots) |
| 138 slot->resolveDistributedNodes(); | 141 slot->resolveDistributedNodes(); |
| 139 | 142 |
| 140 // Update each slot's distribution in reverse tree order so that a child slot
is visited before its parent slot. | 143 // Update each slot's distribution in reverse tree order so that a child slot |
| 144 // is visited before its parent slot. |
| 141 for (auto slot = slots.rbegin(); slot != slots.rend(); ++slot) { | 145 for (auto slot = slots.rbegin(); slot != slots.rend(); ++slot) { |
| 142 (*slot)->updateDistributedNodesWithFallback(); | 146 (*slot)->updateDistributedNodesWithFallback(); |
| 143 (*slot)->lazyReattachDistributedNodesIfNeeded(); | 147 (*slot)->lazyReattachDistributedNodesIfNeeded(); |
| 144 } | 148 } |
| 145 } | 149 } |
| 146 | 150 |
| 147 const HeapVector<Member<HTMLSlotElement>>& SlotAssignment::slots() { | 151 const HeapVector<Member<HTMLSlotElement>>& SlotAssignment::slots() { |
| 148 if (m_needsCollectSlots) | 152 if (m_needsCollectSlots) |
| 149 collectSlots(); | 153 collectSlots(); |
| 150 return m_slots; | 154 return m_slots; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 171 DCHECK_EQ(m_slots.size(), m_slotCount); | 175 DCHECK_EQ(m_slots.size(), m_slotCount); |
| 172 } | 176 } |
| 173 | 177 |
| 174 DEFINE_TRACE(SlotAssignment) { | 178 DEFINE_TRACE(SlotAssignment) { |
| 175 visitor->trace(m_slots); | 179 visitor->trace(m_slots); |
| 176 visitor->trace(m_slotMap); | 180 visitor->trace(m_slotMap); |
| 177 visitor->trace(m_owner); | 181 visitor->trace(m_owner); |
| 178 } | 182 } |
| 179 | 183 |
| 180 } // namespace blink | 184 } // namespace blink |
| OLD | NEW |