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
27pub enum ServoLayoutNodeChildrenIterator<'dom> {
28 Node(Option<ServoLayoutNode<'dom>>),
30 Slottables(<Vec<ServoDangerousStyleNode<'dom>> as IntoIterator>::IntoIter),
32}
33
34impl<'dom> ServoLayoutNodeChildrenIterator<'dom> {
35 #[expect(unsafe_code)]
36 pub(super) fn new_for_flat_tree(parent: ServoLayoutNode<'dom>) -> Self {
37 if let Some(element) = parent.as_element() {
38 if let Some(shadow) = element.shadow_root() {
39 return Self::new_for_flat_tree(shadow.as_node().layout_node());
40 };
41
42 let element = unsafe { element.dangerous_style_element() };
43 let slotted_nodes = element.slotted_nodes();
44 if !slotted_nodes.is_empty() {
45 #[expect(clippy::unnecessary_to_owned)] return Self::Slottables(slotted_nodes.to_owned().into_iter());
47 }
48 }
49
50 Self::Node(unsafe { parent.dangerous_first_child() })
51 }
52
53 #[expect(unsafe_code)]
54 pub(super) fn new_for_dom_tree(parent: ServoLayoutNode<'dom>) -> Self {
55 Self::Node(unsafe { parent.dangerous_first_child() })
56 }
57}
58
59impl<'dom> Iterator for ServoLayoutNodeChildrenIterator<'dom> {
60 type Item = ServoLayoutNode<'dom>;
61
62 fn next(&mut self) -> Option<Self::Item> {
63 match self {
64 Self::Node(node) => {
65 #[expect(unsafe_code)]
66 let next_sibling = unsafe { (*node)?.dangerous_next_sibling() };
67 std::mem::replace(node, next_sibling)
68 },
69 Self::Slottables(slots) => slots.next().map(|node| node.layout_node()),
70 }
71 }
72}
73
74impl FusedIterator for ServoLayoutNodeChildrenIterator<'_> {}
75
76pub enum DOMDescendantIterator<'dom> {
77 Children(DomChildren<ServoDangerousStyleNode<'dom>>),
80 Slottables {
82 slot: ServoDangerousStyleElement<'dom>,
83 index: usize,
84 },
85}
86
87impl<'dom> Iterator for DOMDescendantIterator<'dom> {
88 type Item = ServoDangerousStyleNode<'dom>;
89
90 fn next(&mut self) -> Option<Self::Item> {
91 match self {
92 Self::Children(children) => children.next(),
93 Self::Slottables { slot, index } => {
94 let slottables = slot.slotted_nodes();
95 let slot = slottables.get(*index)?;
96 *index += 1;
97 Some(*slot)
98 },
99 }
100 }
101}