Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / dom / ComposedTreeIterator.h
1 /*
2  * Copyright (C) 2015 Apple 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
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "NodeTraversal.h"
27 #include "ShadowRoot.h"
28
29 #ifndef ComposedTreeIterator_h
30 #define ComposedTreeIterator_h
31
32 namespace WebCore {
33
34 class HTMLSlotElement;
35
36 class ComposedTreeIterator {
37 public:
38     ComposedTreeIterator(ContainerNode& root);
39     ComposedTreeIterator(ContainerNode& root, Node& current);
40
41     Node& operator*() { return *m_current; }
42     Node* operator->() { return m_current; }
43
44     bool operator==(const ComposedTreeIterator& other) const { return m_current == other.m_current; }
45     bool operator!=(const ComposedTreeIterator& other) const { return m_current != other.m_current; }
46
47     ComposedTreeIterator& operator++() { return traverseNextSibling(); }
48
49     ComposedTreeIterator& traverseNext();
50     ComposedTreeIterator& traverseNextSibling();
51     ComposedTreeIterator& traversePreviousSibling();
52     ComposedTreeIterator& traverseParent();
53
54 private:
55     void initializeShadowStack();
56     void traverseNextInShadowTree();
57     void traverseParentInShadowTree();
58 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
59     void traverseNextSiblingSlot();
60     void traversePreviousSiblingSlot();
61 #endif
62
63     ContainerNode& m_root;
64     Node* m_current { 0 };
65
66     struct ShadowContext {
67         ShadowContext(Element* host)
68             : host(host)
69         { }
70
71         Element* host;
72 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
73         HTMLSlotElement* currentSlot { nullptr };
74         unsigned currentSlotNodeIndex { 0 };
75 #endif
76     };
77     Vector<ShadowContext, 4> m_shadowStack;
78 };
79
80 inline ComposedTreeIterator::ComposedTreeIterator(ContainerNode& root)
81     : m_root(root)
82 {
83     ASSERT(!is<ShadowRoot>(m_root));
84 }
85
86 inline ComposedTreeIterator::ComposedTreeIterator(ContainerNode& root, Node& current)
87     : m_root(root)
88     , m_current(&current)
89 {
90     ASSERT(!is<ShadowRoot>(m_root));
91     ASSERT(!is<ShadowRoot>(m_current));
92
93     bool mayNeedShadowStack = m_root.shadowRoot() || (m_current != &m_root && current.parentNode() != &m_root);
94     if (mayNeedShadowStack)
95         initializeShadowStack();
96 }
97
98 inline ComposedTreeIterator& ComposedTreeIterator::traverseNext()
99 {
100     if (auto* shadowRoot = m_current->shadowRoot()) {
101         m_shadowStack.append(shadowRoot->host());
102         m_current = shadowRoot;
103     }
104
105     if (m_shadowStack.isEmpty())
106         m_current = NodeTraversal::next(*m_current, &m_root);
107     else
108         traverseNextInShadowTree();
109
110     return *this;
111 }
112
113 inline ComposedTreeIterator& ComposedTreeIterator::traverseNextSibling()
114 {
115 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
116     bool isAssignedToSlot = !m_shadowStack.isEmpty() && m_current->parentNode()->shadowRoot();
117     if (isAssignedToSlot) {
118         traverseNextSiblingSlot();
119         return *this;
120     }
121 #endif
122     m_current = m_current->nextSibling();
123     return *this;
124 }
125
126 inline ComposedTreeIterator& ComposedTreeIterator::traversePreviousSibling()
127 {
128 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
129     bool isAssignedToSlot = !m_shadowStack.isEmpty() && m_current->parentNode()->shadowRoot();
130     if (isAssignedToSlot) {
131         traversePreviousSiblingSlot();
132         return *this;
133     }
134 #endif
135     m_current = m_current->previousSibling();
136     return *this;
137 }
138
139 inline ComposedTreeIterator& ComposedTreeIterator::traverseParent()
140 {
141     if (m_shadowStack.isEmpty())
142         m_current = m_current->parentNode();
143     else
144         traverseParentInShadowTree();
145
146     return *this;
147 }
148
149 class ComposedTreeDescendantAdapter {
150 public:
151     ComposedTreeDescendantAdapter(ContainerNode& parent)
152         : m_parent(parent)
153     { }
154
155     ComposedTreeIterator begin() { return ComposedTreeIterator(m_parent, m_parent).traverseNext(); }
156     ComposedTreeIterator end() { return ComposedTreeIterator(m_parent); }
157     ComposedTreeIterator at(const Node& child) { return ComposedTreeIterator(m_parent, const_cast<Node&>(child)); }
158     
159 private:
160     ContainerNode& m_parent;
161 };
162
163 class ComposedTreeChildAdapter {
164 public:
165     class Iterator : public ComposedTreeIterator {
166     public:
167         Iterator(ContainerNode& root)
168             : ComposedTreeIterator(root)
169         { }
170         Iterator(ContainerNode& root, Node& current)
171             : ComposedTreeIterator(root, current)
172         { }
173
174         Iterator& operator++() { return static_cast<Iterator&>(traverseNextSibling()); }
175         Iterator& operator--() { return static_cast<Iterator&>(traversePreviousSibling()); }
176     };
177
178     ComposedTreeChildAdapter(ContainerNode& parent)
179         : m_parent(parent)
180     { }
181
182     Iterator begin() { return static_cast<Iterator&>(Iterator(m_parent, m_parent).traverseNext()); }
183     Iterator end() { return Iterator(m_parent); }
184     Iterator at(const Node& child) { return Iterator(m_parent, const_cast<Node&>(child)); }
185
186 private:
187     ContainerNode& m_parent;
188 };
189
190 // FIXME: We should have const versions too.
191 inline ComposedTreeDescendantAdapter composedTreeDescendants(ContainerNode& parent)
192 {
193     return ComposedTreeDescendantAdapter(parent);
194 }
195
196 inline ComposedTreeChildAdapter composedTreeChildren(ContainerNode& parent)
197 {
198     return ComposedTreeChildAdapter(parent);
199 }
200
201 }
202
203 #endif