1use js::context::NoGC;
6
7use super::FlatTreeParent;
8use crate::dom::Node;
9use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
10use crate::dom::bindings::inheritance::Castable;
11use crate::dom::bindings::root::{DomRoot, UnrootedDom};
12use crate::dom::element::Element;
13use crate::dom::shadowroot::shadowroot::ShadowRoot;
14
15#[derive(Clone, Copy, PartialEq)]
17pub(crate) enum ShadowIncluding {
18 No,
19 Yes,
20}
21
22pub(crate) struct FollowingNodeIterator {
23 current: Option<DomRoot<Node>>,
24 root: DomRoot<Node>,
25 shadow_including: ShadowIncluding,
26}
27
28impl FollowingNodeIterator {
29 pub(crate) fn new(
30 current: Option<DomRoot<Node>>,
31 root: DomRoot<Node>,
32 shadow_including: ShadowIncluding,
33 ) -> Self {
34 FollowingNodeIterator {
35 current,
36 root,
37 shadow_including,
38 }
39 }
40}
41
42impl FollowingNodeIterator {
43 pub(crate) fn next_skipping_children(&mut self) -> Option<DomRoot<Node>> {
45 let current = self.current.take()?;
46 self.next_skipping_children_impl(current)
47 }
48
49 fn next_skipping_children_impl(&mut self, current: DomRoot<Node>) -> Option<DomRoot<Node>> {
50 if self.root == current {
51 self.current = None;
52 return None;
53 }
54
55 if let Some(next_sibling) = current.GetNextSibling() {
56 self.current = Some(next_sibling);
57 return current.GetNextSibling();
58 }
59
60 for ancestor in current.inclusive_ancestors(self.shadow_including) {
61 if self.root == ancestor {
62 break;
63 }
64 if let Some(next_sibling) = ancestor.GetNextSibling() {
65 self.current = Some(next_sibling);
66 return ancestor.GetNextSibling();
67 }
68 }
69 self.current = None;
70 None
71 }
72}
73
74impl Iterator for FollowingNodeIterator {
75 type Item = DomRoot<Node>;
76
77 fn next(&mut self) -> Option<DomRoot<Node>> {
79 let current = self.current.take()?;
80
81 if let Some(first_child) = current.GetFirstChild() {
82 self.current = Some(first_child);
83 return current.GetFirstChild();
84 }
85
86 self.next_skipping_children_impl(current)
87 }
88}
89
90pub(crate) struct UnrootedFollowingNodeIterator<'b> {
91 current: Option<UnrootedDom<'b, Node>>,
92 root: UnrootedDom<'b, Node>,
93 shadow_including: ShadowIncluding,
94 no_gc: &'b NoGC,
95}
96
97impl<'b> UnrootedFollowingNodeIterator<'b> {
98 pub(crate) fn new(
99 current: Option<UnrootedDom<'b, Node>>,
100 root: UnrootedDom<'b, Node>,
101 shadow_including: ShadowIncluding,
102 no_gc: &'b NoGC,
103 ) -> Self {
104 UnrootedFollowingNodeIterator {
105 current,
106 root,
107 shadow_including,
108 no_gc,
109 }
110 }
111}
112
113impl<'b> UnrootedFollowingNodeIterator<'b> {
114 fn next_skipping_children_impl(
115 &mut self,
116 current: UnrootedDom<'b, Node>,
117 ) -> Option<UnrootedDom<'b, Node>> {
118 if self.root == current {
119 self.current = None;
120 return None;
121 }
122
123 if let Some(next_sibling) = current.get_next_sibling_unrooted(self.no_gc) {
124 self.current = Some(next_sibling);
125 return current.get_next_sibling_unrooted(self.no_gc);
126 }
127
128 for ancestor in current.inclusive_ancestors_unrooted(self.no_gc, self.shadow_including) {
129 if self.root == ancestor {
130 break;
131 }
132 if let Some(next_sibling) = ancestor.get_next_sibling_unrooted(self.no_gc) {
133 self.current = Some(next_sibling);
134 return ancestor.get_next_sibling_unrooted(self.no_gc);
135 }
136 }
137 self.current = None;
138 None
139 }
140}
141
142impl<'b> Iterator for UnrootedFollowingNodeIterator<'b> {
143 type Item = UnrootedDom<'b, Node>;
144
145 fn next(&mut self) -> Option<UnrootedDom<'b, Node>> {
147 let current = self.current.take()?;
148
149 if let Some(first_child) = current.get_first_child_unrooted(self.no_gc) {
150 self.current = Some(first_child);
151 return current.get_first_child_unrooted(self.no_gc);
152 }
153
154 self.next_skipping_children_impl(current)
155 }
156}
157
158pub(crate) struct PrecedingNodeIterator {
159 current: Option<DomRoot<Node>>,
160 root: DomRoot<Node>,
161}
162
163impl PrecedingNodeIterator {
164 pub(crate) fn new(current: Option<DomRoot<Node>>, root: DomRoot<Node>) -> Self {
165 PrecedingNodeIterator { current, root }
166 }
167}
168
169impl Iterator for PrecedingNodeIterator {
170 type Item = DomRoot<Node>;
171
172 fn next(&mut self) -> Option<DomRoot<Node>> {
174 let current = self.current.take()?;
175
176 self.current = if self.root == current {
177 None
178 } else if let Some(previous_sibling) = current.GetPreviousSibling() {
179 if self.root == previous_sibling {
180 None
181 } else if let Some(last_child) = previous_sibling.descending_last_children().last() {
182 Some(last_child)
183 } else {
184 Some(previous_sibling)
185 }
186 } else {
187 current.GetParentNode()
188 };
189 self.current.clone()
190 }
191}
192
193pub(crate) struct UnrootedPrecedingNodeIterator<'b> {
194 current: Option<UnrootedDom<'b, Node>>,
195 no_gc: &'b NoGC,
196 root: UnrootedDom<'b, Node>,
197}
198
199impl<'b> UnrootedPrecedingNodeIterator<'b> {
200 pub(crate) fn new(
201 current: Option<UnrootedDom<'b, Node>>,
202 root: UnrootedDom<'b, Node>,
203 no_gc: &'b NoGC,
204 ) -> Self {
205 UnrootedPrecedingNodeIterator {
206 current,
207 no_gc,
208 root,
209 }
210 }
211}
212
213impl<'b> Iterator for UnrootedPrecedingNodeIterator<'b> {
214 type Item = UnrootedDom<'b, Node>;
215
216 fn next(&mut self) -> Option<UnrootedDom<'b, Node>> {
218 let current = self.current.take()?;
219
220 self.current = if self.root == current {
221 None
222 } else if let Some(previous_sibling) = current.get_previous_sibling_unrooted(self.no_gc) {
223 if self.root == previous_sibling {
224 None
225 } else if let Some(last_child) = previous_sibling
226 .descending_last_children_unrooted(self.no_gc)
227 .last()
228 {
229 Some(last_child)
230 } else {
231 Some(previous_sibling)
232 }
233 } else {
234 current.get_parent_node_unrooted(self.no_gc)
235 };
236
237 self.current.clone()
238 }
239}
240
241pub(crate) struct SimpleNodeIterator<I>
242where
243 I: Fn(&Node) -> Option<DomRoot<Node>>,
244{
245 current: Option<DomRoot<Node>>,
246 next_node: I,
247}
248
249impl<I> SimpleNodeIterator<I>
250where
251 I: Fn(&Node) -> Option<DomRoot<Node>>,
252{
253 pub(crate) fn new(current: Option<DomRoot<Node>>, next_node: I) -> Self {
254 SimpleNodeIterator { current, next_node }
255 }
256}
257
258impl<I> Iterator for SimpleNodeIterator<I>
259where
260 I: Fn(&Node) -> Option<DomRoot<Node>>,
261{
262 type Item = DomRoot<Node>;
263
264 fn next(&mut self) -> Option<Self::Item> {
265 let current = self.current.take();
266 self.current = current.as_ref().and_then(|c| (self.next_node)(c));
267 current
268 }
269}
270
271#[cfg_attr(crown, crown::unrooted_must_root_lint::allow_unrooted_interior)]
279pub(crate) struct UnrootedSimpleNodeIterator<'b, I>
280where
281 I: Fn(&Node, &'b NoGC) -> Option<UnrootedDom<'b, Node>>,
282{
283 current: Option<UnrootedDom<'b, Node>>,
284 next_node: I,
285 no_gc: &'b NoGC,
287}
288
289impl<'b, I> UnrootedSimpleNodeIterator<'b, I>
290where
291 I: Fn(&Node, &'b NoGC) -> Option<UnrootedDom<'b, Node>>,
292{
293 pub(crate) fn new(
294 current: Option<UnrootedDom<'b, Node>>,
295 next_node: I,
296 no_gc: &'b NoGC,
297 ) -> Self {
298 UnrootedSimpleNodeIterator {
299 current,
300 next_node,
301 no_gc,
302 }
303 }
304}
305
306impl<'b, I> Iterator for UnrootedSimpleNodeIterator<'b, I>
307where
308 I: Fn(&Node, &'b NoGC) -> Option<UnrootedDom<'b, Node>>,
309{
310 type Item = UnrootedDom<'b, Node>;
311
312 fn next(&mut self) -> Option<Self::Item> {
313 let current = self.current.take();
314 self.current = current
315 .as_ref()
316 .and_then(|c| (self.next_node)(c, self.no_gc));
317 current
318 }
319}
320
321pub(crate) type UnrootedAncestorIterator<'no_gc> = UnrootedSimpleNodeIterator<
322 'no_gc,
323 fn(&Node, &'no_gc NoGC) -> Option<UnrootedDom<'no_gc, Node>>,
324>;
325
326struct TreeIteratorInner {
329 depth: usize,
330 shadow_including: ShadowIncluding,
331}
332
333impl TreeIteratorInner {
334 fn next_skipping_children<'a>(
335 &mut self,
336 no_gc: &'a NoGC,
337 current: &Node,
338 ) -> Option<UnrootedDom<'a, Node>> {
339 for ancestor in current.inclusive_ancestors_unrooted(no_gc, self.shadow_including) {
340 if self.depth == 0 {
341 break;
342 }
343 if let Some(next_sibling) = ancestor.get_next_sibling_unrooted(no_gc) {
344 return Some(next_sibling);
345 }
346 if let Some(shadow_root) = ancestor.downcast::<ShadowRoot>() &&
349 let Some(child) = shadow_root
350 .host_unrooted(no_gc)
351 .upcast::<Node>()
352 .get_first_child_unrooted(no_gc)
353 {
354 return Some(child);
355 }
356
357 self.depth -= 1;
358 }
359 debug_assert_eq!(self.depth, 0);
360 None
361 }
362
363 fn next<'a>(&mut self, no_gc: &'a NoGC, current: &Node) -> Option<UnrootedDom<'a, Node>> {
366 if self.shadow_including == ShadowIncluding::Yes &&
368 let Some(element) = current.downcast::<Element>() &&
369 let Some(shadow_root) = element.shadow_root_unrooted(no_gc)
370 {
371 self.depth += 1;
372 return Some(UnrootedDom::upcast(shadow_root));
373 }
374 if let Some(first_child) = current.get_first_child_unrooted(no_gc) {
375 self.depth += 1;
376 return Some(first_child);
377 }
378 self.next_skipping_children(no_gc, current)
379 }
380}
381
382pub(crate) struct TreeIterator {
383 current: Option<DomRoot<Node>>,
384 inner: TreeIteratorInner,
385}
386
387impl TreeIterator {
388 pub(crate) fn new(root: &Node, shadow_including: ShadowIncluding) -> TreeIterator {
389 TreeIterator {
390 current: Some(DomRoot::from_ref(root)),
391 inner: TreeIteratorInner {
392 depth: 0,
393 shadow_including,
394 },
395 }
396 }
397
398 #[expect(unsafe_code)]
399 pub(crate) fn next_skipping_children(&mut self) -> Option<DomRoot<Node>> {
400 let no_gc = unsafe { NoGC::new() };
406 let current = self.current.take()?;
407 self.current = self
408 .inner
409 .next_skipping_children(&no_gc, ¤t)
410 .map(|node| node.as_rooted());
411 Some(current)
412 }
413
414 pub(crate) fn peek(&self) -> Option<&DomRoot<Node>> {
415 self.current.as_ref()
416 }
417}
418
419impl Iterator for TreeIterator {
420 type Item = DomRoot<Node>;
421
422 #[expect(unsafe_code)]
423 fn next(&mut self) -> Option<DomRoot<Node>> {
424 let no_gc = unsafe { NoGC::new() };
430 let current = self.current.take()?;
431 self.current = self
432 .inner
433 .next(&no_gc, ¤t)
434 .map(|node| node.as_rooted());
435 Some(current)
436 }
437}
438
439#[cfg_attr(crown, crown::unrooted_must_root_lint::allow_unrooted_interior)]
447pub(crate) struct UnrootedTreeIterator<'b> {
448 inner: TreeIteratorInner,
449 current: Option<UnrootedDom<'b, Node>>,
450 no_gc: &'b NoGC,
451}
452
453impl<'b> UnrootedTreeIterator<'b> {
454 pub(crate) fn new(root: &Node, shadow_including: ShadowIncluding, no_gc: &'b NoGC) -> Self {
455 Self {
456 inner: TreeIteratorInner {
457 depth: 0,
458 shadow_including,
459 },
460 current: Some(UnrootedDom::from_ref(root, no_gc)),
461 no_gc,
462 }
463 }
464
465 pub(crate) fn next_skipping_children(&mut self) -> Option<UnrootedDom<'b, Node>> {
466 let current = self.current.take()?;
467 self.current = self.inner.next_skipping_children(self.no_gc, ¤t);
468 Some(current)
469 }
470
471 pub(crate) fn peek(&self) -> Option<&UnrootedDom<'b, Node>> {
472 self.current.as_ref()
473 }
474}
475
476impl<'b> Iterator for UnrootedTreeIterator<'b> {
477 type Item = UnrootedDom<'b, Node>;
478 fn next(&mut self) -> Option<Self::Item> {
479 let current = self.current.take()?;
480 self.current = self.inner.next(self.no_gc, ¤t);
481 Some(current)
482 }
483}
484
485#[derive(Clone)]
489pub(crate) enum PrePostIteration<T: Clone> {
490 Enter(T),
493 Leave(T),
496}
497
498#[cfg_attr(crown, crown::unrooted_must_root_lint::allow_unrooted_interior)]
505pub(crate) struct UnrootedFollowingFlatTreeNodesTraversal<'no_gc> {
506 start: UnrootedDom<'no_gc, Node>,
507 previously_returned_item: Option<PrePostIteration<UnrootedDom<'no_gc, Node>>>,
508 no_gc: &'no_gc NoGC,
509}
510
511impl<'no_gc> UnrootedFollowingFlatTreeNodesTraversal<'no_gc> {
512 pub(crate) fn new(root: &Node, no_gc: &'no_gc NoGC) -> Self {
513 Self {
514 start: UnrootedDom::from_ref(root, no_gc),
515 previously_returned_item: None,
516 no_gc,
517 }
518 }
519
520 pub(crate) fn next_skipping_subtree(
521 &mut self,
522 ) -> Option<PrePostIteration<UnrootedDom<'no_gc, Node>>> {
523 let next = self.find_next_skipping_subtree()?;
524 self.previously_returned_item = Some(next);
525 self.previously_returned_item.clone()
526 }
527
528 fn find_next_skipping_subtree(
529 &mut self,
530 ) -> Option<PrePostIteration<UnrootedDom<'no_gc, Node>>> {
531 match &self.previously_returned_item {
532 None => Some(PrePostIteration::Leave(self.start.clone())),
533 Some(PrePostIteration::Enter(previous)) => {
534 Some(PrePostIteration::Leave(previous.clone()))
535 },
536 Some(PrePostIteration::Leave(previous)) => {
537 Self::find_next_after_post(self.no_gc, previous)
538 },
539 }
540 }
541
542 fn find_next_after_post(
543 no_gc: &'no_gc NoGC,
544 previous: &UnrootedDom<'no_gc, Node>,
545 ) -> Option<PrePostIteration<UnrootedDom<'no_gc, Node>>> {
546 if let Some(next_sibling) = previous.next_flat_tree_sibling_unrooted(no_gc) {
547 return Some(PrePostIteration::Enter(next_sibling));
548 }
549 match previous.parent_in_flat_tree(no_gc) {
550 FlatTreeParent::Parent(parent_node) => Some(PrePostIteration::Leave(parent_node)),
551 FlatTreeParent::NotInFlatTree => None,
552 FlatTreeParent::RootNode => None,
553 }
554 }
555
556 fn find_next(&mut self) -> Option<PrePostIteration<UnrootedDom<'no_gc, Node>>> {
557 match &self.previously_returned_item {
558 None => Some(PrePostIteration::Enter(self.start.clone())),
559 Some(PrePostIteration::Enter(previous)) => {
560 if let Some(first_child) = previous.first_flat_tree_child_unrooted(self.no_gc) {
561 return Some(PrePostIteration::Enter(first_child));
562 }
563 Some(PrePostIteration::Leave(previous.clone()))
564 },
565 Some(PrePostIteration::Leave(previous)) => {
566 Self::find_next_after_post(self.no_gc, previous)
567 },
568 }
569 }
570}
571
572impl<'no_gc> Iterator for UnrootedFollowingFlatTreeNodesTraversal<'no_gc> {
573 type Item = PrePostIteration<UnrootedDom<'no_gc, Node>>;
574
575 fn next(&mut self) -> Option<Self::Item> {
576 let next = self.find_next()?;
577 self.previously_returned_item = Some(next);
578 self.previously_returned_item.clone()
579 }
580}