Bug 1750871 - run mochitest-remote on fission everywhere. r=releng-reviewers,aki
[gecko.git] / dom / base / ContentIterator.h
blob012443c8dd36ba29a548ba8ea7dd3b12ea96ded8
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_ContentIterator_h
8 #define mozilla_ContentIterator_h
10 #include "mozilla/RangeBoundary.h"
11 #include "nsCOMPtr.h"
12 #include "nsCycleCollectionParticipant.h"
13 #include "nsRange.h"
14 #include "nsTArray.h"
16 class nsIContent;
17 class nsINode;
19 namespace mozilla {
21 /**
22 * ContentIteratorBase is a base class of PostContentIterator,
23 * PreContentIterator and ContentSubtreeIterator. Making each concrete
24 * classes "final", compiler can avoid virtual calls if they are treated
25 * by the users directly.
27 class ContentIteratorBase {
28 public:
29 ContentIteratorBase() = delete;
30 ContentIteratorBase(const ContentIteratorBase&) = delete;
31 ContentIteratorBase& operator=(const ContentIteratorBase&) = delete;
32 virtual ~ContentIteratorBase();
34 NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(ContentIteratorBase)
36 /**
37 * Allows to iterate over the inclusive descendants
38 * (https://dom.spec.whatwg.org/#concept-tree-inclusive-descendant) of
39 * aRoot.
41 virtual nsresult Init(nsINode* aRoot);
43 virtual nsresult Init(nsRange* aRange);
44 virtual nsresult Init(nsINode* aStartContainer, uint32_t aStartOffset,
45 nsINode* aEndContainer, uint32_t aEndOffset);
46 virtual nsresult Init(const RawRangeBoundary& aStart,
47 const RawRangeBoundary& aEnd);
49 virtual void First();
50 virtual void Last();
51 virtual void Next();
52 virtual void Prev();
54 nsINode* GetCurrentNode() const { return mCurNode; }
56 bool IsDone() const { return !mCurNode; }
58 virtual nsresult PositionAt(nsINode* aCurNode);
60 protected:
61 enum class Order {
62 Pre, /*!< <https://en.wikipedia.org/wiki/Tree_traversal#Pre-order_(NLR)>.
64 Post /*!< <https://en.wikipedia.org/wiki/Tree_traversal#Post-order_(LRN)>.
68 explicit ContentIteratorBase(Order aOrder);
70 class Initializer;
72 /**
73 * Callers must guarantee that:
74 * - Neither aStartContainer nor aEndContainer is nullptr.
75 * - aStartOffset and aEndOffset are valid for its container.
76 * - The start point and the end point are in document order.
78 nsresult InitInternal(const RawRangeBoundary& aStart,
79 const RawRangeBoundary& aEnd);
81 // Recursively get the deepest first/last child of aRoot. This will return
82 // aRoot itself if it has no children.
83 static nsINode* GetDeepFirstChild(nsINode* aRoot);
84 static nsIContent* GetDeepFirstChild(nsIContent* aRoot);
85 static nsINode* GetDeepLastChild(nsINode* aRoot);
86 static nsIContent* GetDeepLastChild(nsIContent* aRoot);
88 // Get the next/previous sibling of aNode, or its parent's, or grandparent's,
89 // etc. Returns null if aNode and all its ancestors have no next/previous
90 // sibling.
91 static nsIContent* GetNextSibling(nsINode* aNode);
92 static nsIContent* GetPrevSibling(nsINode* aNode);
94 nsINode* NextNode(nsINode* aNode);
95 nsINode* PrevNode(nsINode* aNode);
97 void SetEmpty();
99 nsCOMPtr<nsINode> mCurNode;
100 nsCOMPtr<nsINode> mFirst;
101 nsCOMPtr<nsINode> mLast;
102 // See <https://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor>.
103 nsCOMPtr<nsINode> mClosestCommonInclusiveAncestor;
105 const Order mOrder;
107 friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback&,
108 ContentIteratorBase&, const char*,
109 uint32_t);
110 friend void ImplCycleCollectionUnlink(ContentIteratorBase&);
114 * A simple iterator class for traversing the content in "close tag" order.
116 class PostContentIterator final : public ContentIteratorBase {
117 public:
118 PostContentIterator() : ContentIteratorBase(Order::Post) {}
119 PostContentIterator(const PostContentIterator&) = delete;
120 PostContentIterator& operator=(const PostContentIterator&) = delete;
121 virtual ~PostContentIterator() = default;
122 friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback&,
123 PostContentIterator&, const char*,
124 uint32_t);
125 friend void ImplCycleCollectionUnlink(PostContentIterator&);
128 inline void ImplCycleCollectionTraverse(
129 nsCycleCollectionTraversalCallback& aCallback, PostContentIterator& aField,
130 const char* aName, uint32_t aFlags = 0) {
131 ImplCycleCollectionTraverse(
132 aCallback, static_cast<ContentIteratorBase&>(aField), aName, aFlags);
135 inline void ImplCycleCollectionUnlink(PostContentIterator& aField) {
136 ImplCycleCollectionUnlink(static_cast<ContentIteratorBase&>(aField));
140 * A simple iterator class for traversing the content in "start tag" order.
142 class PreContentIterator final : public ContentIteratorBase {
143 public:
144 PreContentIterator() : ContentIteratorBase(Order::Pre) {}
145 PreContentIterator(const PreContentIterator&) = delete;
146 PreContentIterator& operator=(const PreContentIterator&) = delete;
147 virtual ~PreContentIterator() = default;
148 friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback&,
149 PreContentIterator&, const char*,
150 uint32_t);
151 friend void ImplCycleCollectionUnlink(PreContentIterator&);
154 inline void ImplCycleCollectionTraverse(
155 nsCycleCollectionTraversalCallback& aCallback, PreContentIterator& aField,
156 const char* aName, uint32_t aFlags = 0) {
157 ImplCycleCollectionTraverse(
158 aCallback, static_cast<ContentIteratorBase&>(aField), aName, aFlags);
161 inline void ImplCycleCollectionUnlink(PreContentIterator& aField) {
162 ImplCycleCollectionUnlink(static_cast<ContentIteratorBase&>(aField));
166 * A simple iterator class for traversing the content in "top subtree" order.
168 class ContentSubtreeIterator final : public ContentIteratorBase {
169 public:
170 ContentSubtreeIterator() : ContentIteratorBase(Order::Pre) {}
171 ContentSubtreeIterator(const ContentSubtreeIterator&) = delete;
172 ContentSubtreeIterator& operator=(const ContentSubtreeIterator&) = delete;
173 virtual ~ContentSubtreeIterator() = default;
176 * Not supported.
178 virtual nsresult Init(nsINode* aRoot) override;
180 virtual nsresult Init(nsRange* aRange) override;
181 virtual nsresult Init(nsINode* aStartContainer, uint32_t aStartOffset,
182 nsINode* aEndContainer, uint32_t aEndOffset) override;
183 virtual nsresult Init(const RawRangeBoundary& aStartBoundary,
184 const RawRangeBoundary& aEndBoundary) override;
186 void Next() override;
187 void Prev() override;
188 // Must override these because we don't do PositionAt
189 void First() override;
190 // Must override these because we don't do PositionAt
191 void Last() override;
193 nsresult PositionAt(nsINode* aCurNode) override;
195 friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback&,
196 ContentSubtreeIterator&, const char*,
197 uint32_t);
198 friend void ImplCycleCollectionUnlink(ContentSubtreeIterator&);
200 private:
202 * See <https://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor>.
204 void CacheInclusiveAncestorsOfEndContainer();
207 * @return may be nullptr.
209 nsIContent* DetermineCandidateForFirstContent() const;
212 * @return may be nullptr.
214 nsIContent* DetermineCandidateForLastContent() const;
217 * @return may be nullptr.
219 nsIContent* DetermineFirstContent() const;
222 * @return may be nullptr.
224 nsIContent* DetermineLastContent() const;
227 * Callers must guarantee that mRange isn't nullptr and is positioned.
229 nsresult InitWithRange();
231 // Returns the highest inclusive ancestor of aNode that's in the range
232 // (possibly aNode itself). Returns null if aNode is null, or is not itself
233 // in the range. A node is in the range if (node, 0) comes strictly after
234 // the range endpoint, and (node, node.length) comes strictly before it, so
235 // the range's start and end nodes will never be considered "in" it.
236 nsIContent* GetTopAncestorInRange(nsINode* aNode) const;
238 RefPtr<nsRange> mRange;
240 // See <https://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor>.
241 AutoTArray<nsIContent*, 8> mInclusiveAncestorsOfEndContainer;
244 inline void ImplCycleCollectionTraverse(
245 nsCycleCollectionTraversalCallback& aCallback,
246 ContentSubtreeIterator& aField, const char* aName, uint32_t aFlags = 0) {
247 ImplCycleCollectionTraverse(aCallback, aField.mRange, aName, aFlags);
248 ImplCycleCollectionTraverse(
249 aCallback, static_cast<ContentIteratorBase&>(aField), aName, aFlags);
252 inline void ImplCycleCollectionUnlink(ContentSubtreeIterator& aField) {
253 ImplCycleCollectionUnlink(aField.mRange);
254 ImplCycleCollectionUnlink(static_cast<ContentIteratorBase&>(aField));
257 } // namespace mozilla
259 #endif // #ifndef mozilla_ContentIterator_h