Skip to content

Commit 69b96c4

Browse files
committed
avm1: Do not panic when swapping children on depth/render list desync
Unfortunately sometimes the render list and the depth list become desynchronized. When swapping children this caused panics. I haven't been able to reproduce those scenarios, but it's better to leave the render/depth list messed up than to panic in this case.
1 parent 1fc72d3 commit 69b96c4

File tree

1 file changed

+25
-10
lines changed

1 file changed

+25
-10
lines changed

core/src/display_object/container.rs

+25-10
Original file line numberDiff line numberDiff line change
@@ -993,31 +993,46 @@ impl<'gc> ChildContainer<'gc> {
993993
let prev_position = self
994994
.render_list
995995
.iter()
996-
.position(|x| DisplayObject::ptr_eq(*x, prev_child))
997-
.unwrap();
996+
.position(|x| DisplayObject::ptr_eq(*x, prev_child));
998997
let next_position = self
999998
.render_list
1000999
.iter()
1001-
.position(|x| DisplayObject::ptr_eq(*x, child))
1002-
.unwrap();
1003-
self.render_list_mut().swap(prev_position, next_position);
1000+
.position(|x| DisplayObject::ptr_eq(*x, child));
1001+
1002+
match (prev_position, next_position) {
1003+
(Some(prev_position), Some(next_position)) => {
1004+
self.render_list_mut().swap(prev_position, next_position);
1005+
}
1006+
_ => {
1007+
tracing::error!(
1008+
"ChildContainer::swap_at_depth: A child is missing in the render list"
1009+
);
1010+
}
1011+
}
10041012
} else {
10051013
self.depth_list.remove(&prev_depth);
10061014

1007-
let old_position = self
1015+
if let Some(old_position) = self
10081016
.render_list
10091017
.iter()
10101018
.position(|x| DisplayObject::ptr_eq(*x, child))
1011-
.unwrap();
1012-
self.render_list_mut().remove(old_position);
1019+
{
1020+
self.render_list_mut().remove(old_position);
1021+
}
10131022

10141023
if let Some((_, below_child)) = self.depth_list.range(..depth).next_back() {
10151024
let new_position = self
10161025
.render_list
10171026
.iter()
10181027
.position(|x| DisplayObject::ptr_eq(*x, *below_child))
1019-
.unwrap();
1020-
self.render_list_mut().insert(new_position + 1, child);
1028+
.map(|pos| pos + 1)
1029+
.unwrap_or_else(|| {
1030+
tracing::error!(
1031+
"ChildContainer::swap_at_depth: below_child is missing in the render list"
1032+
);
1033+
0
1034+
});
1035+
self.render_list_mut().insert(new_position, child);
10211036
} else {
10221037
self.render_list_mut().insert(0, child);
10231038
}

0 commit comments

Comments
 (0)