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 |