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

Side by Side Diff: third_party/WebKit/Source/core/html/HTMLSlotElement.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: wip Created 4 years, 7 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 /* 1 /*
2 * Copyright (C) 2015 Google Inc. All rights reserved. 2 * Copyright (C) 2015 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 20 matching lines...) Expand all
31 #include "core/html/HTMLSlotElement.h" 31 #include "core/html/HTMLSlotElement.h"
32 32
33 #include "bindings/core/v8/Microtask.h" 33 #include "bindings/core/v8/Microtask.h"
34 #include "core/HTMLNames.h" 34 #include "core/HTMLNames.h"
35 #include "core/dom/ElementTraversal.h" 35 #include "core/dom/ElementTraversal.h"
36 #include "core/dom/NodeTraversal.h" 36 #include "core/dom/NodeTraversal.h"
37 #include "core/dom/StyleChangeReason.h" 37 #include "core/dom/StyleChangeReason.h"
38 #include "core/dom/StyleEngine.h" 38 #include "core/dom/StyleEngine.h"
39 #include "core/dom/shadow/ElementShadow.h" 39 #include "core/dom/shadow/ElementShadow.h"
40 #include "core/dom/shadow/InsertionPoint.h" 40 #include "core/dom/shadow/InsertionPoint.h"
41 #include "core/dom/shadow/SlotAssignment.h"
41 #include "core/events/Event.h" 42 #include "core/events/Event.h"
42 #include "core/html/AssignedNodesOptions.h" 43 #include "core/html/AssignedNodesOptions.h"
43 44
44 namespace blink { 45 namespace blink {
45 46
46 using namespace HTMLNames; 47 using namespace HTMLNames;
47 48
48 inline HTMLSlotElement::HTMLSlotElement(Document& document) 49 inline HTMLSlotElement::HTMLSlotElement(Document& document)
49 : HTMLElement(slotTag, document) 50 : HTMLElement(slotTag, document)
50 , m_distributionState(DistributionDone)
51 , m_assignmentState(AssignmentDone)
52 , m_slotchangeEventAdded(false)
53 { 51 {
54 setHasCustomStyleCallbacks(); 52 setHasCustomStyleCallbacks();
55 } 53 }
56 54
57 DEFINE_NODE_FACTORY(HTMLSlotElement); 55 DEFINE_NODE_FACTORY(HTMLSlotElement);
58 56
57 // static
58 AtomicString HTMLSlotElement::normalizeSlotName(const AtomicString& name)
59 {
60 return (name.isNull() || name.isEmpty()) ? emptyAtom : name;
esprehn 2016/05/23 06:41:00 Why does your code care if the name is null or emp
hayato 2016/05/24 13:23:39 |name| here came from the result of Element::fastG
61 }
62
63 const HeapVector<Member<Node>>& HTMLSlotElement::assignedNodes()
64 {
65 #if DCHECK_IS_ON
66 DCHECK(!needsDistributionRecalc());
67 #endif
68 DCHECK(isInShadowTree() || m_assignedNodes.isEmpty());
69 return m_assignedNodes;
70 }
71
59 const HeapVector<Member<Node>> HTMLSlotElement::assignedNodesForBinding(const As signedNodesOptions& options) 72 const HeapVector<Member<Node>> HTMLSlotElement::assignedNodesForBinding(const As signedNodesOptions& options)
60 { 73 {
61 updateDistribution(); 74 updateDistribution();
62 if (options.hasFlatten() && options.flatten()) 75 if (options.hasFlatten() && options.flatten())
63 return getDistributedNodes(); 76 return getDistributedNodes();
64 return m_assignedNodes; 77 return m_assignedNodes;
65 } 78 }
66 79
67 const HeapVector<Member<Node>>& HTMLSlotElement::getDistributedNodes() 80 const HeapVector<Member<Node>>& HTMLSlotElement::getDistributedNodes()
68 { 81 {
69 ASSERT(!needsDistributionRecalc()); 82 #if DCHECK_IS_ON
esprehn 2016/05/23 06:41:00 why is this needed now?
hayato 2016/05/24 13:23:39 Done. Removed.
83 DCHECK(!needsDistributionRecalc());
84 #endif
70 if (isInShadowTree()) 85 if (isInShadowTree())
71 return m_distributedNodes; 86 return m_distributedNodes;
72 87
73 // A slot is unlikely to be used outside of a shadow tree. 88 // A slot is unlikely to be used outside of a shadow tree.
74 // We do not need to optimize this case in most cases. 89 // We do not need to optimize this case in most cases.
75 // TODO(hayato): If this path causes a performance issue, we should move 90 // TODO(hayato): If this path causes a performance issue, we should move
76 // ShadowRootRaraDate::m_descendantSlots into TreeScopreRareData-ish and 91 // ShadowRootRaraDate::m_descendantSlots into TreeScopreRareData-ish and
77 // update the distribution code so it considers a document tree too. 92 // update the distribution code so it considers a document tree too.
78 willUpdateDistribution(); 93 clearDistribution();
79 for (Node& child : NodeTraversal::childrenOf(*this)) { 94 for (Node& child : NodeTraversal::childrenOf(*this)) {
80 if (!child.isSlotAssignable()) 95 if (!child.isSlotable())
81 continue; 96 continue;
82 if (isHTMLSlotElement(child)) 97 if (isHTMLSlotElement(child))
83 m_distributedNodes.appendVector(toHTMLSlotElement(child).getDistribu tedNodes()); 98 m_distributedNodes.appendVector(toHTMLSlotElement(child).getDistribu tedNodes());
esprehn 2016/05/23 06:41:00 This code doesn't make sense, if the slot itself i
hayato 2016/05/24 13:23:39 That's an expected behavior. A slot itself can be
esprehn 2016/05/25 05:45:02 If you're not in a shadow tree then none of the el
hayato 2016/05/26 04:46:06 I am afraid that it is not easy with NodeTraversal
84 else 99 else
85 m_distributedNodes.append(&child); 100 m_distributedNodes.append(&child);
86 } 101 }
87 didUpdateDistribution();
88 return m_distributedNodes; 102 return m_distributedNodes;
89 } 103 }
90 104
91 void HTMLSlotElement::appendAssignedNode(Node& node) 105 void HTMLSlotElement::appendAssignedNode(Node& node)
92 { 106 {
93 ASSERT(m_assignmentState == AssignmentOnGoing);
94 m_assignedNodes.append(&node); 107 m_assignedNodes.append(&node);
95 } 108 }
96 109
97 void HTMLSlotElement::appendDistributedNode(Node& node) 110 void HTMLSlotElement::appendDistributedNode(Node& node)
98 { 111 {
99 ASSERT(m_distributionState == DistributionOnGoing);
100 size_t size = m_distributedNodes.size(); 112 size_t size = m_distributedNodes.size();
101 m_distributedNodes.append(&node); 113 m_distributedNodes.append(&node);
102 m_distributedIndices.set(&node, size); 114 m_distributedIndices.set(&node, size);
103 } 115 }
104 116
105 void HTMLSlotElement::appendFallbackNode(Node& node)
106 {
107 ASSERT(m_assignmentState == AssignmentOnGoing);
108 m_fallbackNodes.append(&node);
109 }
110
111 void HTMLSlotElement::appendDistributedNodesFrom(const HTMLSlotElement& other) 117 void HTMLSlotElement::appendDistributedNodesFrom(const HTMLSlotElement& other)
112 { 118 {
113 ASSERT(m_distributionState == DistributionOnGoing);
114 size_t index = m_distributedNodes.size(); 119 size_t index = m_distributedNodes.size();
115 m_distributedNodes.appendVector(other.m_distributedNodes); 120 m_distributedNodes.appendVector(other.m_distributedNodes);
116 for (const auto& node : other.m_distributedNodes) 121 for (const auto& node : other.m_distributedNodes)
117 m_distributedIndices.set(node.get(), index++); 122 m_distributedIndices.set(node.get(), index++);
118 } 123 }
119 124
120 void HTMLSlotElement::willUpdateAssignment() 125 void HTMLSlotElement::clearDistribution()
121 { 126 {
122 ASSERT(m_assignmentState != AssignmentOnGoing);
123 m_assignmentState = AssignmentOnGoing;
124 m_oldAssignedNodes.swap(m_assignedNodes);
125 m_assignedNodes.clear(); 127 m_assignedNodes.clear();
126 }
127
128 void HTMLSlotElement::willUpdateDistribution()
129 {
130 ASSERT(m_distributionState != DistributionOnGoing);
131 m_distributionState = DistributionOnGoing;
132 m_oldDistributedNodes.swap(m_distributedNodes);
133 m_distributedNodes.clear(); 128 m_distributedNodes.clear();
134 m_distributedIndices.clear(); 129 m_distributedIndices.clear();
135 } 130 }
136 131
137 void HTMLSlotElement::willUpdateFallback()
138 {
139 m_oldFallbackNodes.swap(m_fallbackNodes);
140 m_fallbackNodes.clear();
141 }
142
143 void HTMLSlotElement::dispatchSlotChangeEvent() 132 void HTMLSlotElement::dispatchSlotChangeEvent()
144 { 133 {
145 Event* event = Event::create(EventTypeNames::slotchange); 134 Event* event = Event::create(EventTypeNames::slotchange);
146 event->setTarget(this); 135 event->setTarget(this);
147 dispatchScopedEvent(event); 136 dispatchScopedEvent(event);
148 m_slotchangeEventAdded = false; 137 m_slotchangeEventEnqueued = false;
esprehn 2016/05/23 06:41:00 you need to set this to false before you dispatch
149 } 138 }
150 139
151 Node* HTMLSlotElement::distributedNodeNextTo(const Node& node) const 140 Node* HTMLSlotElement::distributedNodeNextTo(const Node& node) const
152 { 141 {
153 const auto& it = m_distributedIndices.find(&node); 142 const auto& it = m_distributedIndices.find(&node);
154 if (it == m_distributedIndices.end()) 143 if (it == m_distributedIndices.end())
155 return nullptr; 144 return nullptr;
156 size_t index = it->value; 145 size_t index = it->value;
157 if (index + 1 == m_distributedNodes.size()) 146 if (index + 1 == m_distributedNodes.size())
158 return nullptr; 147 return nullptr;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 for (auto& node : m_distributedNodes) 179 for (auto& node : m_distributedNodes)
191 node->lazyReattachIfAttached(); 180 node->lazyReattachIfAttached();
192 181
193 HTMLElement::detach(context); 182 HTMLElement::detach(context);
194 } 183 }
195 184
196 void HTMLSlotElement::attributeChanged(const QualifiedName& name, const AtomicSt ring& oldValue, const AtomicString& newValue, AttributeModificationReason reason ) 185 void HTMLSlotElement::attributeChanged(const QualifiedName& name, const AtomicSt ring& oldValue, const AtomicString& newValue, AttributeModificationReason reason )
197 { 186 {
198 if (name == nameAttr) { 187 if (name == nameAttr) {
199 if (ShadowRoot* root = containingShadowRoot()) { 188 if (ShadowRoot* root = containingShadowRoot()) {
200 root->owner()->willAffectSelector();
201 if (root->isV1() && oldValue != newValue) 189 if (root->isV1() && oldValue != newValue)
202 root->assignV1(); 190 root->ensureSlotAssignment().slotRenamed(normalizeSlotName(oldVa lue), *this);
esprehn 2016/05/23 06:41:00 slotRenamed shouldn't care if the string is empty
hayato 2016/05/24 13:23:39 That should be cared because a slot with name of "
203 } 191 }
204 } 192 }
205 HTMLElement::attributeChanged(name, oldValue, newValue, reason); 193 HTMLElement::attributeChanged(name, oldValue, newValue, reason);
206 } 194 }
207 195
208 void HTMLSlotElement::childrenChanged(const ChildrenChange& change) 196 static bool wasInShadowTreeBeforeInserted(HTMLSlotElement& slot, ContainerNode& insertionPoint)
209 { 197 {
210 HTMLElement::childrenChanged(change); 198 ShadowRoot* root1 = slot.containingShadowRoot();
211 if (ShadowRoot* root = containingShadowRoot()) { 199 ShadowRoot* root2 = insertionPoint.containingShadowRoot();
212 if (ElementShadow* rootOwner = root->owner()) { 200 if (root1 && root2 && root1 == root2)
213 rootOwner->setNeedsDistributionRecalc(); 201 return false;
214 } 202 return root1;
kochi 2016/05/24 10:02:56 The caller of this is only insertedInto() below (a
hayato 2016/05/24 13:23:39 No. It looks you are focusing on the node tree's *
kochi 2016/05/25 05:37:11 Acknowledged.
215 if (m_assignedNodes.isEmpty() && root->isV1())
216 root->assignV1();
217 }
218 } 203 }
219 204
220 Node::InsertionNotificationRequest HTMLSlotElement::insertedInto(ContainerNode* insertionPoint) 205 Node::InsertionNotificationRequest HTMLSlotElement::insertedInto(ContainerNode* insertionPoint)
221 { 206 {
222 HTMLElement::insertedInto(insertionPoint); 207 HTMLElement::insertedInto(insertionPoint);
223 ShadowRoot* root = containingShadowRoot(); 208 ShadowRoot* root = containingShadowRoot();
224 if (root) { 209 if (root) {
225 if (ElementShadow* rootOwner = root->owner()) 210 DCHECK(root->owner());
226 rootOwner->setNeedsDistributionRecalc(); 211 root->owner()->setNeedsDistributionRecalc();
227 if (root == insertionPoint->treeScope().rootNode()) 212 // Relevant DOM Standard: https://dom.spec.whatwg.org/#concept-node-inse rt
228 root->didAddSlot(); 213 // - 6.4: Run assign slotables for a tree with node's tree and a set co ntaining each inclusive descendant of node that is a slot.
214 if (!wasInShadowTreeBeforeInserted(*this, *insertionPoint))
215 root->ensureSlotAssignment().slotAdded(*this);
kochi 2016/05/24 10:02:56 I'm confused at following the logic here - could y
229 } 216 }
230 217
231 // We could have been distributed into in a detached subtree, make sure to 218 // We could have been distributed into in a detached subtree, make sure to
232 // clear the distribution when inserted again to avoid cycles. 219 // clear the distribution when inserted again to avoid cycles.
233 clearDistribution(); 220 clearDistribution();
234 221
235 if (root && root->isV1()) 222 return InsertionDone;
236 root->assignV1(); 223 }
237 224
238 return InsertionDone; 225 static ShadowRoot* containingShadowRootBeforeRemoved(Node& removedDescendant, Co ntainerNode& insertionPoint)
226 {
227 if (ShadowRoot* root = removedDescendant.containingShadowRoot())
228 return root;
229 return insertionPoint.containingShadowRoot();
239 } 230 }
240 231
241 void HTMLSlotElement::removedFrom(ContainerNode* insertionPoint) 232 void HTMLSlotElement::removedFrom(ContainerNode* insertionPoint)
242 { 233 {
243 ShadowRoot* root = containingShadowRoot(); 234 // `removedFrom` is called after the node is removed from the tree.
244 if (!root) 235 // That means:
245 root = insertionPoint->containingShadowRoot(); 236 // 1. If this slot is still in a tree scope, it means the slot has been in a shadow tree. An inclusive inclusive shadow-including ancestor of the shadow hos t was originally removed from its parent.
kochi 2016/05/24 10:02:56 nit: s/inclusive inclusive/inclusive/
237 // 2. Or (this slot is now not in a tree scope), this slot's inclusive ances tor was orginally removed from its parent (== insertion point). This slot and th e originally removed node was in the same tree.
238
239 ShadowRoot* root = containingShadowRootBeforeRemoved(*this, *insertionPoint) ;
246 if (root) { 240 if (root) {
247 if (ElementShadow* rootOwner = root->owner()) 241 if (ElementShadow* rootOwner = root->owner())
248 rootOwner->setNeedsDistributionRecalc(); 242 rootOwner->setNeedsDistributionRecalc();
249 } 243 }
250 244
251 // Since this insertion point is no longer visible from the shadow subtree, it need to clean itself up. 245 // Since this insertion point is no longer visible from the shadow subtree, it need to clean itself up.
252 clearDistribution(); 246 clearDistribution();
253 247
254 ContainerNode& rootNode = insertionPoint->treeScope().rootNode(); 248 if (root && root->isV1() && root == &insertionPoint->treeScope().rootNode()) {
255 if (root == &rootNode) 249 // This slot was in a shadow tree and got disconnected from the shadow r oot.
256 root->didRemoveSlot(); 250 root->ensureSlotAssignment().slotRemoved(*this);
257 else if (rootNode.isShadowRoot() && toShadowRoot(rootNode).isV1()) 251 }
258 toShadowRoot(rootNode).assignV1();
259 252
260 if (root && root->isV1())
261 root->assignV1();
262 HTMLElement::removedFrom(insertionPoint); 253 HTMLElement::removedFrom(insertionPoint);
263 } 254 }
264 255
265 void HTMLSlotElement::willRecalcStyle(StyleRecalcChange change) 256 void HTMLSlotElement::willRecalcStyle(StyleRecalcChange change)
266 { 257 {
267 if (change < Inherit && getStyleChangeType() < SubtreeStyleChange) 258 if (change < Inherit && getStyleChangeType() < SubtreeStyleChange)
268 return; 259 return;
269 260
270 for (auto& node : m_distributedNodes) 261 for (auto& node : m_distributedNodes)
271 node->setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing: :create(StyleChangeReason::PropagateInheritChangeToDistributedNodes)); 262 node->setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing: :create(StyleChangeReason::PropagateInheritChangeToDistributedNodes));
272 } 263 }
273 264
274 void HTMLSlotElement::updateFallbackNodes()
275 {
276 if (!m_fallbackNodes.isEmpty())
277 return;
278 for (auto& child : NodeTraversal::childrenOf(*this)) {
279 if (!child.isSlotAssignable())
280 continue;
281 // Insertion points are not supported as slots fallback
282 if (isActiveInsertionPoint(child))
283 continue;
284 appendFallbackNode(child);
285 }
286 }
287
288 void HTMLSlotElement::updateDistributedNodesWithFallback() 265 void HTMLSlotElement::updateDistributedNodesWithFallback()
289 { 266 {
290 if (!m_distributedNodes.isEmpty()) 267 if (!m_distributedNodes.isEmpty())
291 return; 268 return;
292 for (auto node : m_fallbackNodes) { 269 for (auto& child : NodeTraversal::childrenOf(*this)) {
293 if (isHTMLSlotElement(node)) 270 if (!child.isSlotable())
294 appendDistributedNodesFrom(*toHTMLSlotElement(node)); 271 continue;
272 if (isHTMLSlotElement(child))
273 appendDistributedNodesFrom(toHTMLSlotElement(child));
295 else 274 else
296 appendDistributedNode(*node); 275 appendDistributedNode(child);
297 } 276 }
298 } 277 }
299 278
300 bool HTMLSlotElement::assignmentChanged() 279 void HTMLSlotElement::enqueueSlotChangeEvent()
301 { 280 {
302 ASSERT(m_assignmentState != AssignmentOnGoing); 281 if (!m_slotchangeEventEnqueued) {
303 if (m_assignmentState == AssignmentDone) 282 Microtask::enqueueMicrotask(WTF::bind(&HTMLSlotElement::dispatchSlotChan geEvent, this));
esprehn 2016/05/23 06:41:00 Does a Persistent<> get magically created for |thi
hayato 2016/05/24 13:23:39 Good point! It looks it does not. Let me use Per
304 m_assignmentState = m_oldAssignedNodes == m_assignedNodes ? AssignmentUn changed : AssignmentChanged; 283 m_slotchangeEventEnqueued = true;
305 return m_assignmentState == AssignmentChanged; 284 }
306 }
307 285
308 bool HTMLSlotElement::distributionChanged() 286 ShadowRoot* root = containingShadowRoot();
309 { 287 DCHECK(root);
310 ASSERT(m_distributionState != DistributionOnGoing); 288 DCHECK(root->isV1());
311 if (m_distributionState == DistributionDone) 289 root->owner()->setNeedsDistributionRecalc();
312 m_distributionState = m_oldDistributedNodes == m_distributedNodes ? Dist ributionUnchanged : DistributionChanged;
313 return m_distributionState == DistributionChanged;
314 }
315 290
316 bool HTMLSlotElement::fallbackChanged() 291 if (ShadowRoot* parentShadowRoot = v1ShadowRootOfParent()) {
317 { 292 if (HTMLSlotElement* next = parentShadowRoot->ensureSlotAssignment().fin dSlot(*this))
318 return m_oldFallbackNodes == m_fallbackNodes; 293 next->enqueueSlotChangeEvent();
319 }
320
321 void HTMLSlotElement::didUpdateAssignment()
322 {
323 ASSERT(m_assignmentState == AssignmentOnGoing);
324 m_assignmentState = AssignmentDone;
325 if ((assignmentChanged() || fallbackChanged()) && !m_slotchangeEventAdded)
326 fireSlotChangeEvent();
327 }
328
329 void HTMLSlotElement::didUpdateDistribution()
330 {
331 ASSERT(m_distributionState == DistributionOnGoing);
332 m_distributionState = DistributionDone;
333 if (isChildOfV1ShadowHost()) {
334 ElementShadow* shadow = parentElementShadow();
335 ASSERT(shadow);
336 if (!shadow->needsDistributionRecalc() && distributionChanged())
337 shadow->setNeedsDistributionRecalc();
338 } 294 }
339 } 295 }
340 296
341 void HTMLSlotElement::fireSlotChangeEvent() 297 bool HTMLSlotElement::hasAssignedNodesSynchronously() const
342 { 298 {
343 ASSERT(!m_slotchangeEventAdded); 299 ShadowRoot* root = containingShadowRoot();
344 Microtask::enqueueMicrotask(WTF::bind(&HTMLSlotElement::dispatchSlotChangeEv ent, this)); 300 DCHECK(root);
345 m_slotchangeEventAdded = true; 301 DCHECK(root->isV1());
346 302 SlotAssignment& assignment = root->ensureSlotAssignment();
347 Element* shadowHost = isShadowHost(parentElement()) ? parentElement() : null ptr; 303 if (assignment.findSlot(*this) != this)
348 // If this slot is assigned to another slot, fire slot change event of that slot too. 304 return false;
349 if (shadowHost && shadowHost->shadowRootIfV1()) { 305 return assignment.findHostChildBySlotName(name());
350 if (HTMLSlotElement* assigned = assignedSlot()) {
351 if (!assigned->m_slotchangeEventAdded)
352 assigned->fireSlotChangeEvent();
353 }
354 }
355 } 306 }
356 307
357 void HTMLSlotElement::clearDistribution() 308 bool HTMLSlotElement::findHostChildWithSameSlotName() const
358 { 309 {
359 willUpdateDistribution(); 310 ShadowRoot* root = containingShadowRoot();
360 didUpdateDistribution(); 311 DCHECK(root);
312 DCHECK(root->isV1());
313 SlotAssignment& assignment = root->ensureSlotAssignment();
314 return assignment.findHostChildBySlotName(name());
361 } 315 }
362 316
363 short HTMLSlotElement::tabIndex() const 317 short HTMLSlotElement::tabIndex() const
364 { 318 {
365 return Element::tabIndex(); 319 return Element::tabIndex();
366 } 320 }
367 321
368 DEFINE_TRACE(HTMLSlotElement) 322 DEFINE_TRACE(HTMLSlotElement)
369 { 323 {
370 visitor->trace(m_assignedNodes); 324 visitor->trace(m_assignedNodes);
371 visitor->trace(m_distributedNodes); 325 visitor->trace(m_distributedNodes);
372 visitor->trace(m_fallbackNodes);
373 visitor->trace(m_distributedIndices); 326 visitor->trace(m_distributedIndices);
374 visitor->trace(m_oldAssignedNodes);
375 visitor->trace(m_oldDistributedNodes);
376 visitor->trace(m_oldFallbackNodes);
377 HTMLElement::trace(visitor); 327 HTMLElement::trace(visitor);
378 } 328 }
379 329
380 } // namespace blink 330 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698