Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1018)

Side by Side Diff: third_party/WebKit/Source/core/dom/shadow/SlotAssignment.cpp

Issue 1995203002: Rewrite Shadow DOM distribution engine to support partial synchronous distribution for v1 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: clean up Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 HTMLSlotElement* SlotAssignment::assignedSlotFor(const Node& node) const 17 void SlotAssignment::slotAdded(HTMLSlotElement& slot)
18 { 18 {
19 return m_assignment.get(const_cast<Node*>(&node)); 19 // Relevant DOM Standard:
20 // https://dom.spec.whatwg.org/#concept-node-insert
21 // 6.4: Run assign slotables for a tree with node's tree and a set containi ng each inclusive descendant of node that is a slot.
22
23 ++m_slotCount;
24 m_needsCollectSlots = true;
25
26 if (!m_slotMap->contains(slot.name())) {
27 m_slotMap->add(slot.name(), &slot);
28 return;
29 }
30
31 HTMLSlotElement& oldFirst = *findSlotByName(slot.name());
kochi 2016/05/25 06:40:26 nit: maybe oldActive or oldActiveSlot is better? I
hayato 2016/05/26 04:46:07 Done
32 DCHECK_NE(oldFirst, slot);
33 m_slotMap->add(slot.name(), &slot);
34 if (findSlotByName(slot.name()) == &oldFirst)
kochi 2016/05/25 06:40:26 nit: No need for &
hayato 2016/05/26 04:46:07 Done
35 return;
36 // |oldFirst| is no longer an active slot.
37 if (oldFirst.findHostChildWithSameSlotName())
38 oldFirst.enqueueSlotChangeEvent();
39 // TODO(hayato): We should not enqeueue a slotchange event for |oldFirst|
40 // if |oldFirst| was inserted together with |slot|.
41 // This could happen if |oldFirst| and |slot| are descendants of the inserte d node, and
42 // |oldFirst| is preceding |slot|.
43 }
44
45 void SlotAssignment::slotRemoved(HTMLSlotElement& slot)
46 {
47 DCHECK_GT(m_slotCount, 0u);
48 --m_slotCount;
49 m_needsCollectSlots = true;
50
51 DCHECK(m_slotMap->contains(slot.name()));
52 HTMLSlotElement* oldFirst = findSlotByName(slot.name());
kochi 2016/05/25 06:40:26 nit: oldActive and newActive in this function?
hayato 2016/05/26 04:46:07 Done
53 m_slotMap->remove(slot.name(), &slot);
54 HTMLSlotElement* newFirst = findSlotByName(slot.name());
55 if (newFirst && newFirst != oldFirst) {
56 // |newFirst| slot becomes an active slot.
57 if (newFirst->findHostChildWithSameSlotName())
58 newFirst->enqueueSlotChangeEvent();
59 // TODO(hayato): Prevent a false-positive slotchange.
60 // This could happen if more than one slots which have the same name are descendants of the removed node.
61 }
62 }
63
64 bool SlotAssignment::findHostChildBySlotName(const AtomicString& slotName) const
65 {
66 // TODO(hayato): Avoid traversing children every time.
67 for (Node& child : NodeTraversal::childrenOf(*m_owner->host())) {
68 if (!child.isSlotable())
69 continue;
70 if (child.slotName() == slotName)
71 return true;
72 }
73 return false;
74 }
75
76 void SlotAssignment::slotRenamed(const AtomicString& oldSlotName, HTMLSlotElemen t& slot)
77 {
78 // |slot| has already new name. Thus, we can not use slot.hasAssignedNodesSy nchronously.
79 bool hasAssignedNodesBefore = (findSlotByName(oldSlotName) == &slot) && find HostChildBySlotName(oldSlotName);
80
81 m_slotMap->remove(oldSlotName, &slot);
82 m_slotMap->add(slot.name(), &slot);
83
84 bool hasAssignedNodesAfter = slot.hasAssignedNodesSlow();
85
86 if (hasAssignedNodesBefore || hasAssignedNodesAfter)
87 slot.enqueueSlotChangeEvent();
88 }
89
90 void SlotAssignment::hostChildSlotNameChanged(const AtomicString& oldValue, cons t AtomicString& newValue)
91 {
92 if (HTMLSlotElement* slot = findSlotByName(HTMLSlotElement::normalizeSlotNam e(oldValue))) {
93 slot->enqueueSlotChangeEvent();
94 m_owner->owner()->setNeedsDistributionRecalc();
95 }
96 if (HTMLSlotElement* slot = findSlotByName(HTMLSlotElement::normalizeSlotNam e(newValue))) {
97 slot->enqueueSlotChangeEvent();
98 m_owner->owner()->setNeedsDistributionRecalc();
99 }
100 }
101
102 SlotAssignment::SlotAssignment(ShadowRoot& owner)
103 : m_slotMap(DocumentOrderedMap::create())
104 , m_owner(&owner)
105 , m_needsCollectSlots(false)
106 , m_slotCount(0)
107 {
20 } 108 }
21 109
22 static void detachNotAssignedNode(Node& node) 110 static void detachNotAssignedNode(Node& node)
23 { 111 {
24 if (node.layoutObject()) 112 if (node.layoutObject())
25 node.lazyReattachIfAttached(); 113 node.lazyReattachIfAttached();
26 } 114 }
27 115
28 void SlotAssignment::resolveAssignment(ShadowRoot& shadowRoot) 116 void SlotAssignment::resolveAssignment()
29 { 117 {
30 m_assignment.clear(); 118 for (Member<HTMLSlotElement> slot : slots())
119 slot->clearDistribution();
31 120
32 using Name2Slot = HeapHashMap<AtomicString, Member<HTMLSlotElement>>; 121 for (Node& child : NodeTraversal::childrenOf(*m_owner->host())) {
33 Name2Slot name2slot; 122 if (!child.isSlotable()) {
34
35 const HeapVector<Member<HTMLSlotElement>>& slots = shadowRoot.descendantSlot s();
36
37 for (Member<HTMLSlotElement> slot : slots) {
38 slot->willUpdateAssignment();
39 slot->willUpdateFallback();
40 name2slot.add(slot->name(), slot.get());
41 }
42
43 for (Node& child : NodeTraversal::childrenOf(*shadowRoot.host())) {
44 if (child.isInsertionPoint()) {
45 // A re-distribution across v0 and v1 shadow trees is not supported.
46 detachNotAssignedNode(child); 123 detachNotAssignedNode(child);
47 continue; 124 continue;
48 } 125 }
49 if (!child.slottable()) { 126 HTMLSlotElement* slot = findSlotByName(child.slotName());
50 detachNotAssignedNode(child);
51 continue;
52 }
53 AtomicString slotName = child.slotName();
54 HTMLSlotElement* slot = name2slot.get(slotName);
55 if (slot) 127 if (slot)
56 assign(child, *slot); 128 slot->appendAssignedNode(child);
57 else 129 else
58 detachNotAssignedNode(child); 130 detachNotAssignedNode(child);
59 } 131 }
60
61 for (auto slot = slots.rbegin(); slot != slots.rend(); ++slot)
62 (*slot)->updateFallbackNodes();
63
64 // For each slot, check if assigned nodes have changed
65 // If so, call fireSlotchange function
66 for (const auto& slot : slots)
67 slot->didUpdateAssignment();
68 } 132 }
69 133
70 void SlotAssignment::resolveDistribution(ShadowRoot& shadowRoot) 134 void SlotAssignment::resolveDistribution()
71 { 135 {
72 const HeapVector<Member<HTMLSlotElement>>& slots = shadowRoot.descendantSlot s(); 136 resolveAssignment();
73 for (Member<HTMLSlotElement> slot : slots) { 137 const HeapVector<Member<HTMLSlotElement>>& slots = this->slots();
74 slot->willUpdateDistribution();
75 }
76 138
77 for (auto slot : slots) { 139 for (auto slot : slots)
78 for (auto node : slot->assignedNodes()) 140 slot->resolveDistributedNodes();
79 distribute(*node, *slot);
80 }
81 141
82 // Update each slot's distribution in reverse tree order so that a child slo t is visited before its parent slot. 142 // Update each slot's distribution in reverse tree order so that a child slo t is visited before its parent slot.
83 for (auto slot = slots.rbegin(); slot != slots.rend(); ++slot) 143 for (auto slot = slots.rbegin(); slot != slots.rend(); ++slot)
84 (*slot)->updateDistributedNodesWithFallback(); 144 (*slot)->updateDistributedNodesWithFallback();
85 for (const auto& slot : slots)
86 slot->didUpdateDistribution();
87 } 145 }
88 146
89 void SlotAssignment::assign(Node& hostChild, HTMLSlotElement& slot) 147 const HeapVector<Member<HTMLSlotElement>>& SlotAssignment::slots()
90 { 148 {
91 DCHECK(hostChild.isSlotAssignable()); 149 if (m_needsCollectSlots)
92 m_assignment.add(&hostChild, &slot); 150 collectSlots();
93 slot.appendAssignedNode(hostChild); 151 return m_slots;
94 } 152 }
95 153
96 void SlotAssignment::distribute(Node& hostChild, HTMLSlotElement& slot) 154 HTMLSlotElement* SlotAssignment::findSlot(const Node& node)
97 { 155 {
98 DCHECK(hostChild.isSlotAssignable()); 156 return node.isSlotable() ? findSlotByName(node.slotName()) : nullptr;
99 if (isHTMLSlotElement(hostChild)) 157 }
100 slot.appendDistributedNodesFrom(toHTMLSlotElement(hostChild));
101 else
102 slot.appendDistributedNode(hostChild);
103 158
104 if (slot.isChildOfV1ShadowHost()) 159 HTMLSlotElement* SlotAssignment::findSlotByName(const AtomicString& slotName)
105 slot.parentElementShadow()->setNeedsDistributionRecalc(); 160 {
161 return m_slotMap->getSlotByName(slotName, m_owner.get());
162 }
163
164 void SlotAssignment::collectSlots()
165 {
166 DCHECK(m_needsCollectSlots);
167 m_slots.clear();
168
169 m_slots.reserveCapacity(m_slotCount);
170 for (HTMLSlotElement& slot : Traversal<HTMLSlotElement>::descendantsOf(*m_ow ner)) {
171 m_slots.append(&slot);
172 }
173 m_needsCollectSlots = false;
174 DCHECK_EQ(m_slots.size(), m_slotCount);
106 } 175 }
107 176
108 DEFINE_TRACE(SlotAssignment) 177 DEFINE_TRACE(SlotAssignment)
109 { 178 {
110 visitor->trace(m_descendantSlots); 179 visitor->trace(m_slots);
111 visitor->trace(m_assignment); 180 visitor->trace(m_slotMap);
181 visitor->trace(m_owner);
112 } 182 }
113 183
114 } // namespace blink 184 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698