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

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

Powered by Google App Engine
This is Rietveld 408576698