script/layout_dom/
iterators.rs1use std::iter::FusedIterator;
6
7use layout_api::{DangerousStyleNode, LayoutElement, LayoutNode};
8use style::dom::{DomChildren, TElement, TShadowRoot};
9
10use crate::layout_dom::{ServoDangerousStyleElement, ServoDangerousStyleNode, ServoLayoutNode};
11
12pub struct ReverseChildrenIterator<'dom> {
13 current: Option<ServoLayoutNode<'dom>>,
14}
15
16impl<'dom> Iterator for ReverseChildrenIterator<'dom> {
17 type Item = ServoLayoutNode<'dom>;
18
19 #[expect(unsafe_code)]
20 fn next(&mut self) -> Option<Self::Item> {
21 let node = self.current;
22 self.current = node.and_then(|node| unsafe { node.dangerous_previous_sibling() });
23 node
24 }
25
26 fn size_hint(&self) -> (usize, Option<usize>) {
27 if let Some(node) = self.current {
28 (node.node.children_count() as usize, None)
29 } else {
30 (0, None)
31 }
32 }
33}
34
35pub enum ServoLayoutNodeChildrenIterator<'dom> {
36 Node(Option<ServoLayoutNode<'dom>>),
38 Slottables(<Vec<ServoDangerousStyleNode<'dom>> as IntoIterator>::IntoIter),
40}
41
42impl<'dom> ServoLayoutNodeChildrenIterator<'dom> {
43 #[expect(unsafe_code)]
44 pub(super) fn new_for_flat_tree(parent: ServoLayoutNode<'dom>) -> Self {
45 if let Some(element) = parent.as_element() {
46 if let Some(shadow) = element.shadow_root() {
47 return Self::new_for_flat_tree(shadow.as_node().layout_node());
48 };
49
50 let element = unsafe { element.dangerous_style_element() };
51 let slotted_nodes = element.slotted_nodes();
52 if !slotted_nodes.is_empty() {
53 #[expect(clippy::unnecessary_to_owned)] return Self::Slottables(slotted_nodes.to_owned().into_iter());
55 }
56 }
57
58 Self::Node(unsafe { parent.dangerous_first_child() })
59 }
60
61 #[expect(unsafe_code)]
62 pub(super) fn new_for_dom_tree(parent: ServoLayoutNode<'dom>) -> Self {
63 Self::Node(unsafe { parent.dangerous_first_child() })
64 }
65}
66
67impl<'dom> Iterator for ServoLayoutNodeChildrenIterator<'dom> {
68 type Item = ServoLayoutNode<'dom>;
69
70 fn next(&mut self) -> Option<Self::Item> {
71 match self {
72 Self::Node(node) => {
73 #[expect(unsafe_code)]
74 let next_sibling = unsafe { (*node)?.dangerous_next_sibling() };
75 std::mem::replace(node, next_sibling)
76 },
77 Self::Slottables(slots) => slots.next().map(|node| node.layout_node()),
78 }
79 }
80
81 fn size_hint(&self) -> (usize, Option<usize>) {
82 match self {
83 Self::Node(node) if node.is_some() => {
84 (node.unwrap().node.children_count() as usize, None)
85 },
86 _ => (0, None),
87 }
88 }
89}
90
91impl FusedIterator for ServoLayoutNodeChildrenIterator<'_> {}
92
93pub enum DOMDescendantIterator<'dom> {
94 Children(DomChildren<ServoDangerousStyleNode<'dom>>),
97 Slottables {
99 slot: ServoDangerousStyleElement<'dom>,
100 index: usize,
101 },
102}
103
104impl<'dom> Iterator for DOMDescendantIterator<'dom> {
105 type Item = ServoDangerousStyleNode<'dom>;
106
107 fn next(&mut self) -> Option<Self::Item> {
108 match self {
109 Self::Children(children) => children.next(),
110 Self::Slottables { slot, index } => {
111 let slottables = slot.slotted_nodes();
112 let slot = slottables.get(*index)?;
113 *index += 1;
114 Some(*slot)
115 },
116 }
117 }
118}