script/dom/node/
children_mutation.rs1use js::context::NoGC;
6
7use crate::dom::Node;
8use crate::dom::bindings::inheritance::Castable;
9use crate::dom::bindings::root::DomRoot;
10use crate::dom::element::Element;
11
12pub(crate) enum ChildrenMutation<'a> {
13 Append {
14 prev: &'a Node,
15 },
16 Insert {
17 prev: &'a Node,
18 next: &'a Node,
19 },
20 Prepend {
21 next: &'a Node,
22 },
23 Replace {
24 prev: Option<&'a Node>,
25 next: Option<&'a Node>,
26 },
27 ReplaceAll,
28 ChangeText,
33}
34
35impl<'a> ChildrenMutation<'a> {
36 pub(super) fn insert(prev: Option<&'a Node>, next: Option<&'a Node>) -> ChildrenMutation<'a> {
37 match (prev, next) {
38 (None, None) => ChildrenMutation::ReplaceAll,
39 (Some(prev), None) => ChildrenMutation::Append { prev },
40 (None, Some(next)) => ChildrenMutation::Prepend { next },
41 (Some(prev), Some(next)) => ChildrenMutation::Insert { prev, next },
42 }
43 }
44
45 pub(super) fn replace(
46 prev: Option<&'a Node>,
47 removed: &'a Option<&'a Node>,
48 next: Option<&'a Node>,
49 ) -> ChildrenMutation<'a> {
50 if removed.is_some() {
51 if let (None, None) = (prev, next) {
52 ChildrenMutation::ReplaceAll
53 } else {
54 ChildrenMutation::Replace { prev, next }
55 }
56 } else {
57 ChildrenMutation::insert(prev, next)
58 }
59 }
60
61 pub(crate) fn next_child(&self) -> Option<&Node> {
66 match *self {
67 ChildrenMutation::Append { .. } => None,
68 ChildrenMutation::Insert { next, .. } => Some(next),
69 ChildrenMutation::Prepend { next, .. } => Some(next),
70 ChildrenMutation::Replace { next, .. } => next,
71 ChildrenMutation::ReplaceAll => None,
72 ChildrenMutation::ChangeText => None,
73 }
74 }
75
76 pub(crate) fn modified_edge_element(&self, no_gc: &NoGC) -> Option<DomRoot<Node>> {
83 match *self {
84 ChildrenMutation::Prepend { next, .. } |
86 ChildrenMutation::Replace {
87 prev: None,
88 next: Some(next),
89 ..
90 } => next
91 .inclusively_following_siblings_unrooted(no_gc)
92 .find(|node| node.is::<Element>())
93 .map(|node| node.as_rooted()),
94 ChildrenMutation::Append { prev } |
96 ChildrenMutation::Replace {
97 prev: Some(prev),
98 next: None,
99 ..
100 } => prev
101 .inclusively_preceding_siblings_unrooted(no_gc)
102 .find(|node| node.is::<Element>())
103 .map(|node| node.as_rooted()),
104 ChildrenMutation::Insert { prev, next, .. } |
106 ChildrenMutation::Replace {
107 prev: Some(prev),
108 next: Some(next),
109 ..
110 } => {
111 if prev
112 .inclusively_preceding_siblings_unrooted(no_gc)
113 .all(|node| !node.is::<Element>())
114 {
115 next.inclusively_following_siblings_unrooted(no_gc)
117 .find(|node| node.is::<Element>())
118 .map(|node| node.as_rooted())
119 } else if next
120 .inclusively_following_siblings_unrooted(no_gc)
121 .all(|node| !node.is::<Element>())
122 {
123 prev.inclusively_preceding_siblings_unrooted(no_gc)
125 .find(|node| node.is::<Element>())
126 .map(|node| node.as_rooted())
127 } else {
128 None
129 }
130 },
131
132 ChildrenMutation::Replace {
133 prev: None,
134 next: None,
135 ..
136 } => unreachable!(),
137 ChildrenMutation::ReplaceAll => None,
138 ChildrenMutation::ChangeText => None,
139 }
140 }
141}