Bumping gaia.json for 2 gaia revision(s) a=gaia-bump
[gecko.git] / content / base / src / ChildIterator.h
bloba0d8c2fa099c196944fc497b92436bc14ab503cf
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 sw=2 et 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 file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef ChildIterator_h
8 #define ChildIterator_h
10 #include "nsIContent.h"
12 /**
13 * Iterates over the children on a node. If a child is an insertion point,
14 * iterates over the children inserted there instead, or the default content
15 * if no children are inserted there.
17 * The FlattenedChildIterator expands any anonymous content bound from an XBL
18 * binding's <xbl:content> element.
21 #include <stdint.h>
22 #include "nsAutoPtr.h"
24 class nsIContent;
26 namespace mozilla {
27 namespace dom {
29 // This class iterates normal DOM child nodes of a given DOM node with
30 // <xbl:children> nodes replaced by the elements that have been filtered into that
31 // insertion point. Any bindings on the given element are ignored for purposes
32 // of determining which insertion point children are filtered into. The iterator
33 // can be initialized to start at the end by providing false for aStartAtBeginning
34 // in order to start iterating in reverse from the last child.
35 class ExplicitChildIterator
37 public:
38 explicit ExplicitChildIterator(nsIContent* aParent, bool aStartAtBeginning = true)
39 : mParent(aParent),
40 mChild(nullptr),
41 mDefaultChild(nullptr),
42 mIndexInInserted(0),
43 mIsFirst(aStartAtBeginning)
47 ExplicitChildIterator(const ExplicitChildIterator& aOther)
48 : mParent(aOther.mParent), mChild(aOther.mChild),
49 mDefaultChild(aOther.mDefaultChild),
50 mShadowIterator(aOther.mShadowIterator ?
51 new ExplicitChildIterator(*aOther.mShadowIterator) :
52 nullptr),
53 mIndexInInserted(aOther.mIndexInInserted), mIsFirst(aOther.mIsFirst) {}
55 ExplicitChildIterator(ExplicitChildIterator&& aOther)
56 : mParent(aOther.mParent), mChild(aOther.mChild),
57 mDefaultChild(aOther.mDefaultChild),
58 mShadowIterator(Move(aOther.mShadowIterator)),
59 mIndexInInserted(aOther.mIndexInInserted), mIsFirst(aOther.mIsFirst) {}
61 nsIContent* GetNextChild();
63 // Looks for aChildToFind respecting insertion points until aChildToFind
64 // or aBound is found. If aBound is nullptr then the seek is unbounded. Returns
65 // whether aChildToFind was found as an explicit child prior to encountering
66 // aBound.
67 bool Seek(nsIContent* aChildToFind, nsIContent* aBound = nullptr)
69 // It would be nice to assert that we find aChildToFind, but bz thinks that
70 // we might not find aChildToFind when called from ContentInserted
71 // if first-letter frames are about.
73 nsIContent* child;
74 do {
75 child = GetNextChild();
76 } while (child && child != aChildToFind && child != aBound);
78 return child == aChildToFind;
81 // Returns the current target of this iterator (which might be an explicit
82 // child of the node, fallback content of an insertion point or
83 // a node distributed to an insertion point.
84 nsIContent* Get();
86 // The inverse of GetNextChild. Properly steps in and out of insertion
87 // points.
88 nsIContent* GetPreviousChild();
90 protected:
91 // The parent of the children being iterated. For the FlattenedChildIterator,
92 // if there is a binding attached to the original parent, mParent points to
93 // the <xbl:content> element for the binding.
94 nsIContent* mParent;
96 // The current child. When we encounter an insertion point,
97 // mChild remains as the insertion point whose content we're iterating (and
98 // our state is controled by mDefaultChild or mIndexInInserted depending on
99 // whether the insertion point expands to its default content or not).
100 nsIContent* mChild;
102 // If non-null, this points to the current default content for the current
103 // insertion point that we're iterating (i.e. mChild, which must be an
104 // nsXBLChildrenElement or HTMLContentElement). Once this transitions back
105 // to null, we continue iterating at mChild's next sibling.
106 nsIContent* mDefaultChild;
108 // If non-null, this points to an iterator of the explicit children of
109 // the ShadowRoot projected by the current shadow element that we're
110 // iterating.
111 nsAutoPtr<ExplicitChildIterator> mShadowIterator;
113 // If not zero, we're iterating inserted children for an insertion point. This
114 // is an index into mChild's inserted children array (mChild must be an
115 // nsXBLChildrenElement). The index is one past the "current" child (as
116 // opposed to mChild which represents the "current" child).
117 uint32_t mIndexInInserted;
119 // A flag to let us know that we haven't started iterating yet.
120 bool mIsFirst;
123 // Iterates over the flattened children of a node, which accounts for anonymous
124 // children and nodes moved by insertion points. If a node has anonymous
125 // children, those are iterated over.
126 class FlattenedChildIterator : public ExplicitChildIterator
128 public:
129 explicit FlattenedChildIterator(nsIContent* aParent)
130 : ExplicitChildIterator(aParent), mXBLInvolved(false)
132 Init(false);
135 FlattenedChildIterator(FlattenedChildIterator&& aOther)
136 : ExplicitChildIterator(Move(aOther)), mXBLInvolved(aOther.mXBLInvolved) {}
138 FlattenedChildIterator(const FlattenedChildIterator& aOther)
139 : ExplicitChildIterator(aOther), mXBLInvolved(aOther.mXBLInvolved) {}
141 bool XBLInvolved() { return mXBLInvolved; }
143 protected:
145 * This constructor is a hack to help AllChildrenIterator which sometimes
146 * doesn't want to consider XBL.
148 FlattenedChildIterator(nsIContent* aParent, bool aIgnoreXBL)
149 : ExplicitChildIterator(aParent), mXBLInvolved(false)
151 Init(aIgnoreXBL);
154 void Init(bool aIgnoreXBL);
156 // For certain optimizations, nsCSSFrameConstructor needs to know if the
157 // child list of the element that we're iterating matches its .childNodes.
158 bool mXBLInvolved;
162 * AllChildrenIterator returns the children of a element including before /
163 * after content and optionally XBL children. It assumes that no mutation of
164 * the DOM or frame tree takes place during iteration, and will break horribly
165 * if that is not true.
167 class AllChildrenIterator : private FlattenedChildIterator
169 public:
170 AllChildrenIterator(nsIContent* aNode, uint32_t aFlags) :
171 FlattenedChildIterator(aNode, (aFlags & nsIContent::eAllButXBL)),
172 mOriginalContent(aNode), mFlags(aFlags),
173 mPhase(eNeedBeforeKid) {}
175 AllChildrenIterator(AllChildrenIterator&& aOther)
176 : FlattenedChildIterator(Move(aOther)),
177 mOriginalContent(aOther.mOriginalContent),
178 mAnonKids(Move(aOther.mAnonKids)), mFlags(aOther.mFlags),
179 mPhase(aOther.mPhase)
180 #ifdef DEBUG
181 , mMutationGuard(aOther.mMutationGuard)
182 #endif
185 #ifdef DEBUG
186 ~AllChildrenIterator() { MOZ_ASSERT(!mMutationGuard.Mutated(0)); }
187 #endif
189 nsIContent* GetNextChild();
191 private:
192 enum IteratorPhase
194 eNeedBeforeKid,
195 eNeedExplicitKids,
196 eNeedAnonKids,
197 eNeedAfterKid,
198 eDone
201 nsIContent* mOriginalContent;
202 nsTArray<nsIContent*> mAnonKids;
203 uint32_t mFlags;
204 IteratorPhase mPhase;
205 #ifdef DEBUG
206 // XXX we should really assert there are no frame tree changes as well, but
207 // there's no easy way to do that.
208 nsMutationGuard mMutationGuard;
209 #endif
212 } // namespace dom
213 } // namespace mozilla
215 #endif