1 /* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Neither the name of Google Inc. nor the names of its 11 * contributors may be used to endorse or promote products derived from 12 * this software without specific prior written permission. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 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. 25 */ 26 27 #ifndef ComposedShadowTreeWalker_h 28 #define ComposedShadowTreeWalker_h 29 30 #include "core/dom/NodeRenderingTraversal.h" 31 #include "core/dom/shadow/InsertionPoint.h" 32 #include "core/dom/shadow/ShadowRoot.h" 33 34 namespace WebCore { 35 36 class Node; 37 class ShadowRoot; 38 39 // FIXME: Make some functions inline to optimise the performance. 40 // https://bugs.webkit.org/show_bug.cgi?id=82702 41 class ComposedShadowTreeWalker { 42 public: 43 typedef NodeRenderingTraversal::ParentDetails ParentTraversalDetails; 44 45 enum Policy { 46 CrossUpperBoundary, 47 DoNotCrossUpperBoundary, 48 }; 49 50 enum StartPolicy { 51 CanStartFromShadowBoundary, 52 CannotStartFromShadowBoundary 53 }; 54 55 ComposedShadowTreeWalker(const Node*, Policy = CrossUpperBoundary, StartPolicy = CannotStartFromShadowBoundary); 56 57 Node* get() const { return const_cast<Node*>(m_node); } 58 59 void firstChild(); 60 void lastChild(); 61 62 void nextSibling(); 63 void previousSibling(); 64 65 void parent(); 66 67 void next(); 68 void previous(); 69 70 Node* traverseParent(const Node*, ParentTraversalDetails* = 0) const; 71 72 private: 73 ComposedShadowTreeWalker(const Node*, ParentTraversalDetails*); 74 75 enum TraversalDirection { 76 TraversalDirectionForward, 77 TraversalDirectionBackward 78 }; 79 80 bool canCrossUpperBoundary() const { return m_policy == CrossUpperBoundary; } 81 82 void assertPrecondition() const 83 { 84 #ifndef NDEBUG 85 ASSERT(m_node); 86 if (canCrossUpperBoundary()) 87 ASSERT(!m_node->isShadowRoot()); 88 else 89 ASSERT(!m_node->isShadowRoot() || toShadowRoot(m_node)->isYoungest()); 90 ASSERT(!isActiveInsertionPoint(m_node)); 91 #endif 92 } 93 94 void assertPostcondition() const 95 { 96 #ifndef NDEBUG 97 if (m_node) 98 assertPrecondition(); 99 #endif 100 } 101 102 static Node* traverseNode(const Node*, TraversalDirection); 103 static Node* traverseLightChildren(const Node*, TraversalDirection); 104 105 Node* traverseFirstChild(const Node*) const; 106 Node* traverseLastChild(const Node*) const; 107 Node* traverseChild(const Node*, TraversalDirection) const; 108 109 static Node* traverseNextSibling(const Node*); 110 static Node* traversePreviousSibling(const Node*); 111 112 static Node* traverseSiblingOrBackToInsertionPoint(const Node*, TraversalDirection); 113 static Node* traverseSiblingInCurrentTree(const Node*, TraversalDirection); 114 115 static Node* traverseSiblings(const Node*, TraversalDirection); 116 static Node* traverseDistributedNodes(const Node*, const InsertionPoint*, TraversalDirection); 117 118 static Node* traverseBackToYoungerShadowRoot(const Node*, TraversalDirection); 119 static Node* escapeFallbackContentElement(const Node*, TraversalDirection); 120 121 Node* traverseNodeEscapingFallbackContents(const Node*, ParentTraversalDetails* = 0) const; 122 Node* traverseParentInCurrentTree(const Node*, ParentTraversalDetails* = 0) const; 123 Node* traverseParentBackToYoungerShadowRootOrHost(const ShadowRoot*, ParentTraversalDetails* = 0) const; 124 125 const Node* m_node; 126 Policy m_policy; 127 }; 128 129 inline ComposedShadowTreeWalker::ComposedShadowTreeWalker(const Node* node, Policy policy, StartPolicy startPolicy) 130 : m_node(node) 131 , m_policy(policy) 132 { 133 UNUSED_PARAM(startPolicy); 134 #ifndef NDEBUG 135 if (m_node && startPolicy == CannotStartFromShadowBoundary) 136 assertPrecondition(); 137 #endif 138 } 139 140 inline void ComposedShadowTreeWalker::parent() 141 { 142 assertPrecondition(); 143 m_node = traverseParent(m_node); 144 assertPostcondition(); 145 } 146 147 inline void ComposedShadowTreeWalker::nextSibling() 148 { 149 assertPrecondition(); 150 m_node = traverseSiblingOrBackToInsertionPoint(m_node, TraversalDirectionForward); 151 assertPostcondition(); 152 } 153 154 inline void ComposedShadowTreeWalker::previousSibling() 155 { 156 assertPrecondition(); 157 m_node = traverseSiblingOrBackToInsertionPoint(m_node, TraversalDirectionBackward); 158 assertPostcondition(); 159 } 160 161 inline void ComposedShadowTreeWalker::next() 162 { 163 assertPrecondition(); 164 if (Node* next = traverseFirstChild(m_node)) { 165 m_node = next; 166 } else { 167 while (m_node) { 168 if (Node* sibling = traverseNextSibling(m_node)) { 169 m_node = sibling; 170 break; 171 } 172 m_node = traverseParent(m_node); 173 } 174 } 175 assertPostcondition(); 176 } 177 178 inline void ComposedShadowTreeWalker::previous() 179 { 180 assertPrecondition(); 181 if (Node* previous = traversePreviousSibling(m_node)) { 182 while (Node* child = traverseLastChild(previous)) 183 previous = child; 184 m_node = previous; 185 } else { 186 parent(); 187 } 188 assertPostcondition(); 189 } 190 191 inline void ComposedShadowTreeWalker::firstChild() 192 { 193 assertPrecondition(); 194 m_node = traverseChild(m_node, TraversalDirectionForward); 195 assertPostcondition(); 196 } 197 198 inline void ComposedShadowTreeWalker::lastChild() 199 { 200 assertPrecondition(); 201 m_node = traverseLastChild(m_node); 202 assertPostcondition(); 203 } 204 205 inline Node* ComposedShadowTreeWalker::traverseNextSibling(const Node* node) 206 { 207 ASSERT(node); 208 return traverseSiblingOrBackToInsertionPoint(node, TraversalDirectionForward); 209 } 210 211 inline Node* ComposedShadowTreeWalker::traversePreviousSibling(const Node* node) 212 { 213 ASSERT(node); 214 return traverseSiblingOrBackToInsertionPoint(node, TraversalDirectionBackward); 215 } 216 217 inline Node* ComposedShadowTreeWalker::traverseFirstChild(const Node* node) const 218 { 219 ASSERT(node); 220 return traverseChild(node, TraversalDirectionForward); 221 } 222 223 inline Node* ComposedShadowTreeWalker::traverseLastChild(const Node* node) const 224 { 225 ASSERT(node); 226 return traverseChild(node, TraversalDirectionBackward); 227 } 228 229 } // namespace 230 231 #endif 232