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"
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.
22 #include "nsAutoPtr.h"
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
38 explicit ExplicitChildIterator(nsIContent
* aParent
, bool aStartAtBeginning
= true)
41 mDefaultChild(nullptr),
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
) :
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
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.
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.
86 // The inverse of GetNextChild. Properly steps in and out of insertion
88 nsIContent
* GetPreviousChild();
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.
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).
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
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.
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
129 explicit FlattenedChildIterator(nsIContent
* aParent
)
130 : ExplicitChildIterator(aParent
), mXBLInvolved(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
; }
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)
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.
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
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
)
181 , mMutationGuard(aOther
.mMutationGuard
)
186 ~AllChildrenIterator() { MOZ_ASSERT(!mMutationGuard
.Mutated(0)); }
189 nsIContent
* GetNextChild();
201 nsIContent
* mOriginalContent
;
202 nsTArray
<nsIContent
*> mAnonKids
;
204 IteratorPhase mPhase
;
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
;
213 } // namespace mozilla