From 52efbd98a821f26c7c1c7cf908288052aa120a83 Mon Sep 17 00:00:00 2001 From: David Wendt Date: Sun, 25 Oct 2020 00:15:36 -0400 Subject: [PATCH] core: Remove child's sibling pointers when removing the child from the parent's exec list. This fixes a hang in as-of-yet uncommitted AS3 tests that reused display objects, where repeated removals and additions to the same MovieClip caused the construction of a cyclic render list. --- core/src/display_object/movie_clip.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/core/src/display_object/movie_clip.rs b/core/src/display_object/movie_clip.rs index 0b8d6b498..d64933ff1 100644 --- a/core/src/display_object/movie_clip.rs +++ b/core/src/display_object/movie_clip.rs @@ -1684,6 +1684,10 @@ impl<'gc> MovieClip<'gc> { if let Some(next) = next { next.set_prev_sibling(context.gc_context, prev); } + + child.set_prev_sibling(context.gc_context, None); + child.set_next_sibling(context.gc_context, None); + if let Some(head) = self.first_child() { if DisplayObject::ptr_eq(head, child) { self.set_first_child(context.gc_context, next); @@ -1718,8 +1722,10 @@ impl<'gc> MovieClip<'gc> { // Don't do this for rewinds, because they conceptually // start from an empty display list, and we also want to examine // the old children to decide if they persist (place_frame <= goto_frame). - if let Some(child) = self.0.read().children.get(&depth).cloned() { + let read = self.0.read(); + if let Some(child) = read.children.get(&depth).cloned() { if !child.placed_by_script() { + drop(read); self.0.write(context.gc_context).children.remove(&depth); self.remove_child_from_exec_list(context, child); } @@ -2961,13 +2967,15 @@ impl<'gc, 'a> MovieClip<'gc> { reader.read_remove_object_2() }?; - if let Some(child) = self.0.read().children.get(&remove_object.depth.into()).cloned() { + let read = self.0.read(); + if let Some(child) = read.children.get(&remove_object.depth.into()).cloned() { if !child.placed_by_script() { + drop(read); self.0.write(context.gc_context).children.remove(&remove_object.depth.into()); self.remove_child_from_exec_list(context, child); } } - + Ok(()) }