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

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

Issue 1489433002: Support the essential part of Shadow DOM v1 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Revert Internals.* 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 12 matching lines...) Expand all
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */ 25 */
26 26
27 #include "config.h" 27 #include "config.h"
28 #include "core/dom/shadow/ComposedTreeTraversal.h" 28 #include "core/dom/shadow/ComposedTreeTraversal.h"
29 29
30 #include "core/dom/Element.h" 30 #include "core/dom/Element.h"
31 #include "core/dom/shadow/ElementShadow.h" 31 #include "core/dom/shadow/ElementShadow.h"
32 #include "core/html/HTMLShadowElement.h" 32 #include "core/html/HTMLShadowElement.h"
33 #include "core/html/HTMLSlotElement.h"
33 34
34 namespace blink { 35 namespace blink {
35 36
36 static inline ElementShadow* shadowFor(const Node& node) 37 static inline ElementShadow* shadowFor(const Node& node)
37 { 38 {
38 return node.isElementNode() ? toElement(node).shadow() : nullptr; 39 return node.isElementNode() ? toElement(node).shadow() : nullptr;
39 } 40 }
40 41
41 Node* ComposedTreeTraversal::traverseChild(const Node& node, TraversalDirection direction) 42 Node* ComposedTreeTraversal::traverseChild(const Node& node, TraversalDirection direction)
42 { 43 {
43 ElementShadow* shadow = shadowFor(node); 44 ElementShadow* shadow = shadowFor(node);
44 if (shadow) { 45 if (shadow) {
45 ShadowRoot& shadowRoot = shadow->youngestShadowRoot(); 46 ShadowRoot& shadowRoot = shadow->youngestShadowRoot();
46 return resolveDistributionStartingAt(direction == TraversalDirectionForw ard ? shadowRoot.firstChild() : shadowRoot.lastChild(), direction); 47 return resolveDistributionStartingAt(direction == TraversalDirectionForw ard ? shadowRoot.firstChild() : shadowRoot.lastChild(), direction);
47 } 48 }
48 return resolveDistributionStartingAt(direction == TraversalDirectionForward ? node.firstChild() : node.lastChild(), direction); 49 return resolveDistributionStartingAt(direction == TraversalDirectionForward ? node.firstChild() : node.lastChild(), direction);
49 } 50 }
50 51
51 Node* ComposedTreeTraversal::resolveDistributionStartingAt(const Node* node, Tra versalDirection direction) 52 Node* ComposedTreeTraversal::resolveDistributionStartingAt(const Node* node, Tra versalDirection direction)
52 { 53 {
53 for (const Node* sibling = node; sibling; sibling = (direction == TraversalD irectionForward ? sibling->nextSibling() : sibling->previousSibling())) { 54 if (!node)
55 return nullptr;
56 if (node->isInShadowTree() && node->containingShadowRoot()->isV1())
57 return v1ResolveDistributionStartingAt(*node, direction);
58 return v0ResolveDistributionStartingAt(*node, direction);
59 }
60
61 Node* ComposedTreeTraversal::v0ResolveDistributionStartingAt(const Node& node, T raversalDirection direction)
62 {
63 for (const Node* sibling = &node; sibling; sibling = (direction == Traversal DirectionForward ? sibling->nextSibling() : sibling->previousSibling())) {
54 if (!isActiveInsertionPoint(*sibling)) 64 if (!isActiveInsertionPoint(*sibling))
55 return const_cast<Node*>(sibling); 65 return const_cast<Node*>(sibling);
56 const InsertionPoint& insertionPoint = toInsertionPoint(*sibling); 66 const InsertionPoint& insertionPoint = toInsertionPoint(*sibling);
57 if (Node* found = (direction == TraversalDirectionForward ? insertionPoi nt.firstDistributedNode() : insertionPoint.lastDistributedNode())) 67 if (Node* found = (direction == TraversalDirectionForward ? insertionPoi nt.firstDistributedNode() : insertionPoint.lastDistributedNode()))
58 return found; 68 return found;
59 ASSERT(isHTMLShadowElement(insertionPoint) || (isHTMLContentElement(inse rtionPoint) && !insertionPoint.hasChildren())); 69 ASSERT(isHTMLShadowElement(insertionPoint) || (isHTMLContentElement(inse rtionPoint) && !insertionPoint.hasChildren()));
60 } 70 }
61 return nullptr; 71 return nullptr;
62 } 72 }
63 73
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)
87 {
88 HTMLSlotElement* slot = node.assignedSlot();
89 if (!slot)
90 return nullptr;
91 for (HTMLSlotElement* next = slot->assignedSlot(); next; next = next->assign edSlot()) {
92 slot = next;
93 }
94 return slot;
95 }
96
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
64 // TODO(hayato): This may return a wrong result for a node which is not in a 112 // TODO(hayato): This may return a wrong result for a node which is not in a
65 // document composed tree. See ComposedTreeTraversalTest's redistribution test for details. 113 // document composed tree. See ComposedTreeTraversalTest's redistribution test for details.
66 Node* ComposedTreeTraversal::traverseSiblings(const Node& node, TraversalDirecti on direction) 114 Node* ComposedTreeTraversal::v0TraverseSiblings(const Node& node, TraversalDirec tion direction)
67 { 115 {
68 if (!shadowWhereNodeCanBeDistributed(node)) 116 if (!shadowWhereNodeCanBeDistributed(node))
69 return traverseSiblingsOrShadowInsertionPointSiblings(node, direction); 117 return traverseSiblingsOrShadowInsertionPointSiblings(node, direction);
70 118
71 const InsertionPoint* finalDestination = resolveReprojection(&node); 119 const InsertionPoint* finalDestination = resolveReprojection(&node);
72 if (!finalDestination) 120 if (!finalDestination)
73 return nullptr; 121 return nullptr;
74 if (Node* found = (direction == TraversalDirectionForward ? finalDestination ->distributedNodeNextTo(&node) : finalDestination->distributedNodePreviousTo(&no de))) 122 if (Node* found = (direction == TraversalDirectionForward ? finalDestination ->distributedNodeNextTo(&node) : finalDestination->distributedNodePreviousTo(&no de)))
75 return found; 123 return found;
76 return traverseSiblings(*finalDestination, direction); 124 return traverseSiblings(*finalDestination, direction);
77 } 125 }
78 126
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
79 Node* ComposedTreeTraversal::traverseSiblingsOrShadowInsertionPointSiblings(cons t Node& node, TraversalDirection direction) 137 Node* ComposedTreeTraversal::traverseSiblingsOrShadowInsertionPointSiblings(cons t Node& node, TraversalDirection direction)
80 { 138 {
81 if (Node* found = resolveDistributionStartingAt(direction == TraversalDirect ionForward ? node.nextSibling() : node.previousSibling(), direction)) 139 if (Node* found = resolveDistributionStartingAt(direction == TraversalDirect ionForward ? node.nextSibling() : node.previousSibling(), direction))
82 return found; 140 return found;
83 141
84 if (node.parentNode() && node.parentNode()->isShadowRoot()) { 142 if (node.parentNode() && node.parentNode()->isShadowRoot()) {
85 ShadowRoot* parentShadowRoot = toShadowRoot(node.parentNode()); 143 ShadowRoot* parentShadowRoot = toShadowRoot(node.parentNode());
86 if (!parentShadowRoot->isYoungest()) { 144 if (!parentShadowRoot->isYoungest()) {
87 HTMLShadowElement* assignedInsertionPoint = parentShadowRoot->shadow InsertionPointOfYoungerShadowRoot(); 145 HTMLShadowElement* assignedInsertionPoint = parentShadowRoot->shadow InsertionPointOfYoungerShadowRoot();
88 ASSERT(assignedInsertionPoint); 146 ASSERT(assignedInsertionPoint);
89 return traverseSiblingsOrShadowInsertionPointSiblings(*assignedInser tionPoint, direction); 147 return traverseSiblingsOrShadowInsertionPointSiblings(*assignedInser tionPoint, direction);
90 } 148 }
91 } 149 }
92 return nullptr; 150 return nullptr;
93 } 151 }
94 152
95 // FIXME: Use an iterative algorithm so that it can be inlined. 153 static ElementShadow* parentElementShadow(const Node& node)
96 // https://bugs.webkit.org/show_bug.cgi?id=90415 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 }
162
97 ContainerNode* ComposedTreeTraversal::traverseParent(const Node& node, ParentTra versalDetails* details) 163 ContainerNode* ComposedTreeTraversal::traverseParent(const Node& node, ParentTra versalDetails* details)
98 { 164 {
99 // 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 // 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.
100 if (node.isPseudoElement()) 166 if (node.isPseudoElement())
101 return node.parentOrShadowHostNode(); 167 return node.parentOrShadowHostNode();
102 168
103 if (shadowWhereNodeCanBeDistributed(node)) { 169 ElementShadow* shadow = parentElementShadow(node);
104 if (const InsertionPoint* insertionPoint = resolveReprojection(&node)) { 170 if (shadow && shadow->isV1())
105 if (details) 171 return v1TraverseParent(node);
106 details->didTraverseInsertionPoint(insertionPoint); 172 if (shadowWhereNodeCanBeDistributed(node))
107 // The node is distributed. But the distribution was stopped at this insertion point. 173 return v0TraverseParent(node, details);
108 if (shadowWhereNodeCanBeDistributed(*insertionPoint)) 174 return traverseParentOrHost(node);
109 return nullptr; 175 }
110 return traverseParentOrHost(*insertionPoint); 176
111 } 177 ContainerNode* ComposedTreeTraversal::v1TraverseParent(const Node& node)
178 {
179 HTMLSlotElement* slot = finalDestinationSlotFor(node);
180 if (!slot)
181 return nullptr;
182 if (parentElementShadow(*slot)) {
183 // The node is distributed to the |slot|, however, |slot|, which is a
184 // child of a shadow host, is not assigned to any slots.
112 return nullptr; 185 return nullptr;
113 } 186 }
114 return traverseParentOrHost(node); 187 return traverseParentOrHost(*slot);
188 }
189
190 ContainerNode* ComposedTreeTraversal::v0TraverseParent(const Node& node, ParentT raversalDetails* details)
191 {
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;
115 } 201 }
116 202
117 inline ContainerNode* ComposedTreeTraversal::traverseParentOrHost(const Node& no de) 203 inline ContainerNode* ComposedTreeTraversal::traverseParentOrHost(const Node& no de)
118 { 204 {
205 // TODO(hayato): Support fallback contents of slots. The parent can be a slo t.
119 ContainerNode* parent = node.parentNode(); 206 ContainerNode* parent = node.parentNode();
120 if (!parent) 207 if (!parent)
121 return nullptr; 208 return nullptr;
122 if (!parent->isShadowRoot()) 209 if (!parent->isShadowRoot())
123 return parent; 210 return parent;
124 ShadowRoot* shadowRoot = toShadowRoot(parent); 211 ShadowRoot* shadowRoot = toShadowRoot(parent);
125 ASSERT(!shadowRoot->shadowInsertionPointOfYoungerShadowRoot()); 212 ASSERT(!shadowRoot->shadowInsertionPointOfYoungerShadowRoot());
126 if (!shadowRoot->isYoungest()) 213 if (!shadowRoot->isYoungest())
127 return nullptr; 214 return nullptr;
128 Element* host = shadowRoot->host(); 215 Element* host = shadowRoot->host();
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 Node& ComposedTreeTraversal::lastWithinOrSelf(const Node& node) 364 Node& ComposedTreeTraversal::lastWithinOrSelf(const Node& node)
278 { 365 {
279 assertPrecondition(node); 366 assertPrecondition(node);
280 Node* lastDescendant = lastWithin(node); 367 Node* lastDescendant = lastWithin(node);
281 Node& result = lastDescendant ? *lastDescendant : const_cast<Node&>(node); 368 Node& result = lastDescendant ? *lastDescendant : const_cast<Node&>(node);
282 assertPostcondition(&result); 369 assertPostcondition(&result);
283 return result; 370 return result;
284 } 371 }
285 372
286 } // namespace 373 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698