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

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

Issue 1530643003: Support slot element's fallback content feature (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: wip Created 5 years 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) 2012 Google Inc. All rights reserved. 2 * Copyright (C) 2012 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 * * Neither the name of Google Inc. nor the names of its 10 * * Neither the name of Google Inc. nor the names of its
(...skipping 21 matching lines...) Expand all
32 #include "core/html/HTMLShadowElement.h" 32 #include "core/html/HTMLShadowElement.h"
33 #include "core/html/HTMLSlotElement.h" 33 #include "core/html/HTMLSlotElement.h"
34 34
35 namespace blink { 35 namespace blink {
36 36
37 static inline ElementShadow* shadowFor(const Node& node) 37 static inline ElementShadow* shadowFor(const Node& node)
38 { 38 {
39 return node.isElementNode() ? toElement(node).shadow() : nullptr; 39 return node.isElementNode() ? toElement(node).shadow() : nullptr;
40 } 40 }
41 41
42 static inline bool canBeDistributedToInsertionPoint(const Node& node)
43 {
44 return node.isInV0ShadowTree() || node.isChildOfV0ShadowHost();
45 }
46
42 Node* ComposedTreeTraversal::traverseChild(const Node& node, TraversalDirection direction) 47 Node* ComposedTreeTraversal::traverseChild(const Node& node, TraversalDirection direction)
43 { 48 {
44 ElementShadow* shadow = shadowFor(node); 49 ElementShadow* shadow = shadowFor(node);
45 if (shadow) { 50 if (shadow) {
46 ShadowRoot& shadowRoot = shadow->youngestShadowRoot(); 51 ShadowRoot& shadowRoot = shadow->youngestShadowRoot();
47 return resolveDistributionStartingAt(direction == TraversalDirectionForw ard ? shadowRoot.firstChild() : shadowRoot.lastChild(), direction); 52 return resolveDistributionStartingAt(direction == TraversalDirectionForw ard ? shadowRoot.firstChild() : shadowRoot.lastChild(), direction);
48 } 53 }
49 return resolveDistributionStartingAt(direction == TraversalDirectionForward ? node.firstChild() : node.lastChild(), direction); 54 return resolveDistributionStartingAt(direction == TraversalDirectionForward ? node.firstChild() : node.lastChild(), direction);
50 } 55 }
51 56
52 Node* ComposedTreeTraversal::resolveDistributionStartingAt(const Node* node, Tra versalDirection direction) 57 Node* ComposedTreeTraversal::resolveDistributionStartingAt(const Node* node, Tra versalDirection direction)
53 { 58 {
54 if (!node) 59 if (!node)
55 return nullptr; 60 return nullptr;
56 if (node->isInShadowTree() && node->containingShadowRoot()->isV1()) 61 for (const Node* sibling = node; sibling; sibling = (direction == TraversalD irectionForward ? sibling->nextSibling() : sibling->previousSibling())) {
57 return v1ResolveDistributionStartingAt(*node, direction); 62 if (isHTMLSlotElement(*sibling)) {
58 return v0ResolveDistributionStartingAt(*node, direction); 63 const HTMLSlotElement& slot = toHTMLSlotElement(*sibling);
64 if (Node* found = (direction == TraversalDirectionForward ? slot.fir stDistributedNode() : slot.lastDistributedNode()))
65 return found;
66 continue;
67 }
68 if (node->isInV0ShadowTree())
69 return v0ResolveDistributionStartingAt(*sibling, direction);
70 return const_cast<Node*>(sibling);
71 }
72 return nullptr;
59 } 73 }
60 74
61 Node* ComposedTreeTraversal::v0ResolveDistributionStartingAt(const Node& node, T raversalDirection direction) 75 Node* ComposedTreeTraversal::v0ResolveDistributionStartingAt(const Node& node, T raversalDirection direction)
62 { 76 {
77 ASSERT(!isHTMLSlotElement(node));
63 for (const Node* sibling = &node; sibling; sibling = (direction == Traversal DirectionForward ? sibling->nextSibling() : sibling->previousSibling())) { 78 for (const Node* sibling = &node; sibling; sibling = (direction == Traversal DirectionForward ? sibling->nextSibling() : sibling->previousSibling())) {
64 if (!isActiveInsertionPoint(*sibling)) 79 if (!isActiveInsertionPoint(*sibling))
65 return const_cast<Node*>(sibling); 80 return const_cast<Node*>(sibling);
66 const InsertionPoint& insertionPoint = toInsertionPoint(*sibling); 81 const InsertionPoint& insertionPoint = toInsertionPoint(*sibling);
67 if (Node* found = (direction == TraversalDirectionForward ? insertionPoi nt.firstDistributedNode() : insertionPoint.lastDistributedNode())) 82 if (Node* found = (direction == TraversalDirectionForward ? insertionPoi nt.firstDistributedNode() : insertionPoint.lastDistributedNode()))
68 return found; 83 return found;
69 ASSERT(isHTMLShadowElement(insertionPoint) || (isHTMLContentElement(inse rtionPoint) && !insertionPoint.hasChildren())); 84 ASSERT(isHTMLShadowElement(insertionPoint) || (isHTMLContentElement(inse rtionPoint) && !insertionPoint.hasChildren()));
70 } 85 }
71 return nullptr; 86 return nullptr;
72 } 87 }
73 88
74 Node* ComposedTreeTraversal::v1ResolveDistributionStartingAt(const Node& node, T raversalDirection direction)
75 {
76 for (const Node* sibling = &node; sibling; sibling = (direction == Traversal DirectionForward ? sibling->nextSibling() : sibling->previousSibling())) {
77 if (!isHTMLSlotElement(*sibling))
78 return const_cast<Node*>(sibling);
79 const HTMLSlotElement& slot = toHTMLSlotElement(*sibling);
80 if (Node* found = (direction == TraversalDirectionForward ? slot.firstDi stributedNode() : slot.lastDistributedNode()))
81 return found;
82 }
83 return nullptr;
84 }
85
86 static HTMLSlotElement* finalDestinationSlotFor(const Node& node) 89 static HTMLSlotElement* finalDestinationSlotFor(const Node& node)
87 { 90 {
88 HTMLSlotElement* slot = node.assignedSlot(); 91 HTMLSlotElement* slot = node.assignedSlot();
89 if (!slot) 92 if (!slot)
90 return nullptr; 93 return nullptr;
91 for (HTMLSlotElement* next = slot->assignedSlot(); next; next = next->assign edSlot()) { 94 for (HTMLSlotElement* next = slot->assignedSlot(); next; next = next->assign edSlot()) {
92 slot = next; 95 slot = next;
93 } 96 }
94 return slot; 97 return slot;
95 } 98 }
96 99
97 Node* ComposedTreeTraversal::traverseSiblings(const Node& node, TraversalDirecti on direction)
98 {
99 Node* parent = node.parentNode();
100 if (!parent)
101 return nullptr;
102 if (parent->isElementNode()) {
103 if (ElementShadow* shadow = toElement(parent)->shadow()) {
104 if (shadow->isV1()) {
105 return v1TraverseSiblings(node, direction);
106 }
107 }
108 }
109 return v0TraverseSiblings(node, direction);
110 }
111
112 // TODO(hayato): This may return a wrong result for a node which is not in a 100 // TODO(hayato): This may return a wrong result for a node which is not in a
113 // document composed tree. See ComposedTreeTraversalTest's redistribution test for details. 101 // document composed tree. See ComposedTreeTraversalTest's redistribution test for details.
114 Node* ComposedTreeTraversal::v0TraverseSiblings(const Node& node, TraversalDirec tion direction) 102 Node* ComposedTreeTraversal::traverseSiblings(const Node& node, TraversalDirecti on direction)
115 { 103 {
116 if (!shadowWhereNodeCanBeDistributed(node)) 104 if (node.isChildOfV1ShadowHost())
117 return traverseSiblingsOrShadowInsertionPointSiblings(node, direction); 105 return traverseSiblingsForV1HostChild(node, direction);
118 106
107 if (shadowWhereNodeCanBeDistributed(node))
108 return traverseSiblingsForV0Distribution(node, direction);
109
110 if (Node* found = resolveDistributionStartingAt(direction == TraversalDirect ionForward ? node.nextSibling() : node.previousSibling(), direction))
111 return found;
112
113 // For v0 older shadow tree
114 if (node.parentNode() && node.parentNode()->isShadowRoot()) {
kochi 2016/01/05 07:44:11 Can you add an assertion here (ASSERT(node.isInV0S
hayato 2016/01/06 05:49:09 No. This code is to support v1 shadow tree, but th
kochi 2016/01/06 06:21:34 Acknowledged.
115 ShadowRoot* parentShadowRoot = toShadowRoot(node.parentNode());
116 if (!parentShadowRoot->isYoungest()) {
117 HTMLShadowElement* assignedInsertionPoint = parentShadowRoot->shadow InsertionPointOfYoungerShadowRoot();
118 ASSERT(assignedInsertionPoint);
119 return traverseSiblings(*assignedInsertionPoint, direction);
120 }
121 }
122 return nullptr;
123 }
124
125 Node* ComposedTreeTraversal::traverseSiblingsForV1HostChild(const Node& node, Tr aversalDirection direction)
126 {
127 HTMLSlotElement* slot = finalDestinationSlotFor(node);
128 if (!slot)
129 return nullptr;
130 if (Node* siblingInDistributedNodes = (direction == TraversalDirectionForwar d ? slot->distributedNodeNextTo(node) : slot->distributedNodePreviousTo(node)))
131 return siblingInDistributedNodes;
132 return traverseSiblings(*slot, direction);
133 }
134
135 Node* ComposedTreeTraversal::traverseSiblingsForV0Distribution(const Node& node, TraversalDirection direction)
136 {
119 const InsertionPoint* finalDestination = resolveReprojection(&node); 137 const InsertionPoint* finalDestination = resolveReprojection(&node);
120 if (!finalDestination) 138 if (!finalDestination)
121 return nullptr; 139 return nullptr;
122 if (Node* found = (direction == TraversalDirectionForward ? finalDestination ->distributedNodeNextTo(&node) : finalDestination->distributedNodePreviousTo(&no de))) 140 if (Node* found = (direction == TraversalDirectionForward ? finalDestination ->distributedNodeNextTo(&node) : finalDestination->distributedNodePreviousTo(&no de)))
123 return found; 141 return found;
124 return traverseSiblings(*finalDestination, direction); 142 return traverseSiblings(*finalDestination, direction);
125 }
126 143
127 Node* ComposedTreeTraversal::v1TraverseSiblings(const Node& node, TraversalDirec tion direction)
128 {
129 HTMLSlotElement* slot = finalDestinationSlotFor(node);
130 if (!slot)
131 return resolveDistributionStartingAt(direction == TraversalDirectionForw ard ? node.nextSibling() : node.previousSibling(), direction);
132 if (Node* siblingInDistributedNodes = (direction == TraversalDirectionForwar d ? slot->distributedNodeNextTo(node) : slot->distributedNodePreviousTo(node)))
133 return siblingInDistributedNodes;
134 return v1TraverseSiblings(*slot, direction);
135 }
136
137 Node* ComposedTreeTraversal::traverseSiblingsOrShadowInsertionPointSiblings(cons t Node& node, TraversalDirection direction)
138 {
139 if (Node* found = resolveDistributionStartingAt(direction == TraversalDirect ionForward ? node.nextSibling() : node.previousSibling(), direction))
140 return found;
141
142 if (node.parentNode() && node.parentNode()->isShadowRoot()) {
143 ShadowRoot* parentShadowRoot = toShadowRoot(node.parentNode());
144 if (!parentShadowRoot->isYoungest()) {
145 HTMLShadowElement* assignedInsertionPoint = parentShadowRoot->shadow InsertionPointOfYoungerShadowRoot();
146 ASSERT(assignedInsertionPoint);
147 return traverseSiblingsOrShadowInsertionPointSiblings(*assignedInser tionPoint, direction);
148 }
149 }
150 return nullptr;
151 }
152
153 static ElementShadow* parentElementShadow(const Node& node)
154 {
155 Node* parent = node.parentNode();
156 if (!parent)
157 return nullptr;
158 if (parent->isElementNode())
159 return toElement(parent)->shadow();
160 return nullptr;
161 } 144 }
162 145
163 ContainerNode* ComposedTreeTraversal::traverseParent(const Node& node, ParentTra versalDetails* details) 146 ContainerNode* ComposedTreeTraversal::traverseParent(const Node& node, ParentTra versalDetails* details)
164 { 147 {
165 // TODO(hayato): Stop this hack for a pseudo element because a pseudo elemen t is not a child of its parentOrShadowHostNode() in a composed tree. 148 // TODO(hayato): Stop this hack for a pseudo element because a pseudo elemen t is not a child of its parentOrShadowHostNode() in a composed tree.
166 if (node.isPseudoElement()) 149 if (node.isPseudoElement())
167 return node.parentOrShadowHostNode(); 150 return node.parentOrShadowHostNode();
168 151
169 ElementShadow* shadow = parentElementShadow(node); 152 if (node.isChildOfV1ShadowHost()) {
170 if (shadow && shadow->isV1()) 153 HTMLSlotElement* slot = finalDestinationSlotFor(node);
171 return v1TraverseParent(node); 154 if (!slot)
172 if (shadowWhereNodeCanBeDistributed(node)) 155 return nullptr;
173 return v0TraverseParent(node, details); 156 return traverseParent(*slot);
157 }
158
159 Element* parent = node.parentElement();
160 if (parent && isHTMLSlotElement(parent)) {
161 HTMLSlotElement& slot = toHTMLSlotElement(*parent);
162 if (!slot.getAssignedNodes().isEmpty())
163 return nullptr;
164 return traverseParent(slot, details);
165 }
166
167 if (canBeDistributedToInsertionPoint(node))
168 return traverseParentForV0(node, details);
169
170 ASSERT(!shadowWhereNodeCanBeDistributed(node));
174 return traverseParentOrHost(node); 171 return traverseParentOrHost(node);
175 } 172 }
176 173
177 ContainerNode* ComposedTreeTraversal::v1TraverseParent(const Node& node) 174 ContainerNode* ComposedTreeTraversal::traverseParentForV0(const Node& node, Pare ntTraversalDetails* details)
178 { 175 {
179 HTMLSlotElement* slot = finalDestinationSlotFor(node); 176 if (shadowWhereNodeCanBeDistributed(node)) {
180 if (!slot) 177 if (const InsertionPoint* insertionPoint = resolveReprojection(&node)) {
181 return nullptr; 178 if (details)
182 if (parentElementShadow(*slot)) { 179 details->didTraverseInsertionPoint(insertionPoint);
183 // The node is distributed to the |slot|, however, |slot|, which is a 180 // The node is distributed. But the distribution was stopped at this insertion point.
184 // child of a shadow host, is not assigned to any slots. 181 if (shadowWhereNodeCanBeDistributed(*insertionPoint))
182 return nullptr;
183 return traverseParent(*insertionPoint);
184 }
185 return nullptr; 185 return nullptr;
186 } 186 }
187 return traverseParentOrHost(*slot); 187 ContainerNode* parent = traverseParentOrHost(node);
188 if (isActiveInsertionPoint(*parent))
189 return nullptr;
190 return parent;
188 } 191 }
189 192
190 ContainerNode* ComposedTreeTraversal::v0TraverseParent(const Node& node, ParentT raversalDetails* details) 193 ContainerNode* ComposedTreeTraversal::traverseParentOrHost(const Node& node)
191 { 194 {
192 if (const InsertionPoint* insertionPoint = resolveReprojection(&node)) {
193 if (details)
194 details->didTraverseInsertionPoint(insertionPoint);
195 // The node is distributed. But the distribution was stopped at this ins ertion point.
196 if (shadowWhereNodeCanBeDistributed(*insertionPoint))
197 return nullptr;
198 return traverseParentOrHost(*insertionPoint);
199 }
200 return nullptr;
201 }
202
203 inline ContainerNode* ComposedTreeTraversal::traverseParentOrHost(const Node& no de)
204 {
205 // TODO(hayato): Support fallback contents of slots. The parent can be a slo t.
206 ContainerNode* parent = node.parentNode(); 195 ContainerNode* parent = node.parentNode();
207 if (!parent) 196 if (!parent)
208 return nullptr; 197 return nullptr;
209 if (!parent->isShadowRoot()) 198 if (!parent->isShadowRoot())
210 return parent; 199 return parent;
211 ShadowRoot* shadowRoot = toShadowRoot(parent); 200 ShadowRoot* shadowRoot = toShadowRoot(parent);
212 ASSERT(!shadowRoot->shadowInsertionPointOfYoungerShadowRoot()); 201 ASSERT(!shadowRoot->shadowInsertionPointOfYoungerShadowRoot());
213 if (!shadowRoot->isYoungest()) 202 if (!shadowRoot->isYoungest())
214 return nullptr; 203 return nullptr;
215 Element* host = shadowRoot->host(); 204 return shadowRoot->host();
216 if (isActiveInsertionPoint(*host))
217 return nullptr;
218 return host;
219 } 205 }
220 206
221 Node* ComposedTreeTraversal::childAt(const Node& node, unsigned index) 207 Node* ComposedTreeTraversal::childAt(const Node& node, unsigned index)
222 { 208 {
223 assertPrecondition(node); 209 assertPrecondition(node);
224 Node* child = traverseFirstChild(node); 210 Node* child = traverseFirstChild(node);
225 while (child && index--) 211 while (child && index--)
226 child = nextSibling(*child); 212 child = nextSibling(*child);
227 assertPostcondition(child); 213 assertPostcondition(child);
228 return child; 214 return child;
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 Node& ComposedTreeTraversal::lastWithinOrSelf(const Node& node) 350 Node& ComposedTreeTraversal::lastWithinOrSelf(const Node& node)
365 { 351 {
366 assertPrecondition(node); 352 assertPrecondition(node);
367 Node* lastDescendant = lastWithin(node); 353 Node* lastDescendant = lastWithin(node);
368 Node& result = lastDescendant ? *lastDescendant : const_cast<Node&>(node); 354 Node& result = lastDescendant ? *lastDescendant : const_cast<Node&>(node);
369 assertPostcondition(&result); 355 assertPostcondition(&result);
370 return result; 356 return result;
371 } 357 }
372 358
373 } // namespace 359 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698