Fix the !(ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)) after r196281
[WebKit-https.git] / Source / WebCore / dom / ComposedTreeIterator.h
1 /*
2  * Copyright (C) 2015-2016 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 "ElementAndTextDescendantIterator.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();
39     ComposedTreeIterator(ContainerNode& root);
40     ComposedTreeIterator(ContainerNode& root, Node& current);
41
42     Node& operator*() { return current(); }
43     Node* operator->() { return &current(); }
44
45     bool operator==(const ComposedTreeIterator& other) const { return context().iterator == other.context().iterator; }
46     bool operator!=(const ComposedTreeIterator& other) const { return context().iterator != other.context().iterator; }
47
48     ComposedTreeIterator& operator++() { return traverseNext(); }
49
50     ComposedTreeIterator& traverseNext();
51     ComposedTreeIterator& traverseNextSkippingChildren();
52     ComposedTreeIterator& traverseNextSibling();
53     ComposedTreeIterator& traversePreviousSibling();
54
55     unsigned depth() const;
56
57 private:
58     void initializeContextStack(ContainerNode& root, Node& current);
59     void traverseNextInShadowTree();
60     void traverseNextLeavingContext();
61     bool pushContext(ShadowRoot&);
62 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
63     bool advanceInSlot(int direction);
64     void traverseSiblingInSlot(int direction);
65 #endif
66
67     struct Context {
68         Context() { }
69         explicit Context(ContainerNode& root)
70             : iterator(root)
71         { }
72         Context(ContainerNode& root, Node& node, size_t slotNodeIndex = notFound)
73             : iterator(root, &node)
74 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
75             , slotNodeIndex(slotNodeIndex)
76         { }
77 #else
78         {
79             UNUSED_PARAM(slotNodeIndex);
80         }
81 #endif
82
83         ElementAndTextDescendantIterator iterator;
84 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
85         size_t slotNodeIndex { notFound };
86 #endif
87     };
88     Context& context() { return m_contextStack.last(); }
89     const Context& context() const { return m_contextStack.last(); }
90     Node& current() { return *context().iterator; }
91
92     Vector<Context, 4> m_contextStack;
93 };
94
95 inline ComposedTreeIterator::ComposedTreeIterator()
96 {
97     m_contextStack.uncheckedAppend({ });
98 }
99
100 inline ComposedTreeIterator& ComposedTreeIterator::traverseNext()
101 {
102     if (auto* shadowRoot = context().iterator->shadowRoot()) {
103         if (pushContext(*shadowRoot))
104             return *this;
105     }
106
107     if (m_contextStack.size() > 1) {
108         traverseNextInShadowTree();
109         return *this;
110     }
111
112     context().iterator.traverseNext();
113     return *this;
114 }
115
116 inline ComposedTreeIterator& ComposedTreeIterator::traverseNextSkippingChildren()
117 {
118     context().iterator.traverseNextSkippingChildren();
119
120     if (!context().iterator && m_contextStack.size() > 1)
121         traverseNextLeavingContext();
122     
123     return *this;
124 }
125
126 inline ComposedTreeIterator& ComposedTreeIterator::traverseNextSibling()
127 {
128 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
129     if (current().parentNode()->shadowRoot()) {
130         traverseSiblingInSlot(1);
131         return *this;
132     }
133 #endif
134     context().iterator.traverseNextSibling();
135     return *this;
136 }
137
138 inline ComposedTreeIterator& ComposedTreeIterator::traversePreviousSibling()
139 {
140 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
141     if (current().parentNode()->shadowRoot()) {
142         traverseSiblingInSlot(-1);
143         return *this;
144     }
145 #endif
146     context().iterator.traversePreviousSibling();
147     return *this;
148 }
149
150 inline unsigned ComposedTreeIterator::depth() const
151 {
152     unsigned depth = 0;
153     for (auto& context : m_contextStack)
154         depth += context.iterator.depth();
155     return depth;
156 }
157
158 class ComposedTreeDescendantAdapter {
159 public:
160     ComposedTreeDescendantAdapter(ContainerNode& parent)
161         : m_parent(parent)
162     { }
163
164     ComposedTreeIterator begin() { return ComposedTreeIterator(m_parent); }
165     ComposedTreeIterator end() { return { }; }
166     ComposedTreeIterator at(const Node& child) { return ComposedTreeIterator(m_parent, const_cast<Node&>(child)); }
167     
168 private:
169     ContainerNode& m_parent;
170 };
171
172 class ComposedTreeChildAdapter {
173 public:
174     class Iterator : public ComposedTreeIterator {
175     public:
176         Iterator() = default;
177         explicit Iterator(ContainerNode& root)
178             : ComposedTreeIterator(root)
179         { }
180         Iterator(ContainerNode& root, Node& current)
181             : ComposedTreeIterator(root, current)
182         { }
183
184         Iterator& operator++() { return static_cast<Iterator&>(traverseNextSibling()); }
185         Iterator& operator--() { return static_cast<Iterator&>(traversePreviousSibling()); }
186     };
187
188     ComposedTreeChildAdapter(ContainerNode& parent)
189         : m_parent(parent)
190     { }
191
192     Iterator begin() { return Iterator(m_parent); }
193     Iterator end() { return { }; }
194     Iterator at(const Node& child) { return Iterator(m_parent, const_cast<Node&>(child)); }
195
196 private:
197     ContainerNode& m_parent;
198 };
199
200 // FIXME: We should have const versions too.
201 inline ComposedTreeDescendantAdapter composedTreeDescendants(ContainerNode& parent)
202 {
203     return ComposedTreeDescendantAdapter(parent);
204 }
205
206 inline ComposedTreeChildAdapter composedTreeChildren(ContainerNode& parent)
207 {
208     return ComposedTreeChildAdapter(parent);
209 }
210
211 }
212
213 #endif