diff --git a/core/src/display_object/movie_clip.rs b/core/src/display_object/movie_clip.rs index 5150d1d7a..8c126c7b7 100644 --- a/core/src/display_object/movie_clip.rs +++ b/core/src/display_object/movie_clip.rs @@ -78,6 +78,7 @@ pub struct MovieClipData<'gc> { has_button_clip_event: bool, flags: MovieClipFlags, avm2_constructor: Option>, + avm2_constructor_ran: bool, drawing: Drawing, is_focusable: bool, has_focus: bool, @@ -105,6 +106,7 @@ impl<'gc> MovieClip<'gc> { has_button_clip_event: false, flags: MovieClipFlags::empty(), avm2_constructor: None, + avm2_constructor_ran: false, drawing: Drawing::new(), is_focusable: false, has_focus: false, @@ -137,6 +139,7 @@ impl<'gc> MovieClip<'gc> { has_button_clip_event: false, flags: MovieClipFlags::empty(), avm2_constructor: Some(constr), + avm2_constructor_ran: false, drawing: Drawing::new(), is_focusable: false, has_focus: false, @@ -172,6 +175,7 @@ impl<'gc> MovieClip<'gc> { has_button_clip_event: false, flags: MovieClipFlags::PLAYING, avm2_constructor: None, + avm2_constructor_ran: false, drawing: Drawing::new(), is_focusable: false, has_focus: false, @@ -595,8 +599,6 @@ impl<'gc> MovieClip<'gc> { if id == 0 { //TODO: This assumes only the root movie has `SymbolClass` tags. self.set_avm2_constructor(activation.context.gc_context, Some(proto)); - self.allocate_as_avm2_object(&mut activation.context, self.into()); - self.construct_as_avm2_object(&mut activation.context); } else if let Some(Character::MovieClip(mc)) = library.character_by_id(id) { mc.set_avm2_constructor(activation.context.gc_context, Some(proto)) } else { @@ -1576,6 +1578,8 @@ impl<'gc> MovieClip<'gc> { log::error!("Got {} when constructing AVM2 side of display object", e); } } + + self.0.write(context.gc_context).avm2_constructor_ran = true; } pub fn register_frame_script( @@ -1711,6 +1715,10 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> { }; let _ = tag_utils::decode_tags(&mut reader, tag_callback, TagCode::ShowFrame); } + + if !self.0.read().avm2_constructor_ran { + self.construct_as_avm2_object(context); + } } } @@ -2010,9 +2018,7 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> { self.set_default_instance_name(context); let vm_type = self.vm_type(context); - if vm_type == AvmType::Avm2 { - self.construct_as_avm2_object(context); - } else if vm_type == AvmType::Avm1 { + if vm_type == AvmType::Avm1 { self.construct_as_avm1_object( context, display_object, diff --git a/core/src/player.rs b/core/src/player.rs index 19bc69852..c8432c88c 100644 --- a/core/src/player.rs +++ b/core/src/player.rs @@ -409,7 +409,7 @@ impl Player { } else { None }; - root.construct_frame(context); + root.post_instantiation(context, root, flashvars, Instantiator::Movie, false); root.set_default_root_name(context); context.levels.insert(0, root); diff --git a/core/tests/regression_tests.rs b/core/tests/regression_tests.rs index 9057c87f0..af1e067dd 100644 --- a/core/tests/regression_tests.rs +++ b/core/tests/regression_tests.rs @@ -548,6 +548,7 @@ swf_tests! { (as3_loaderinfo_quine, "avm2/loaderinfo_quine", 2), (nan_scale, "avm1/nan_scale", 1), (as3_nan_scale, "avm2/nan_scale", 1), + (as3_documentclass, "avm2/documentclass", 1), } // TODO: These tests have some inaccuracies currently, so we use approx_eq to test that numeric values are close enough. diff --git a/core/tests/swfs/avm2/documentclass/Child.as b/core/tests/swfs/avm2/documentclass/Child.as new file mode 100644 index 000000000..32dff1e7b --- /dev/null +++ b/core/tests/swfs/avm2/documentclass/Child.as @@ -0,0 +1,11 @@ +package { + import flash.display.MovieClip; + + public class Child extends MovieClip { + public function Child() { + trace("/// Child constructor"); + trace("/// this.b"); + trace(this.b); + } + } +} \ No newline at end of file diff --git a/core/tests/swfs/avm2/documentclass/Grandchild.as b/core/tests/swfs/avm2/documentclass/Grandchild.as new file mode 100644 index 000000000..0546c8378 --- /dev/null +++ b/core/tests/swfs/avm2/documentclass/Grandchild.as @@ -0,0 +1,9 @@ +package { + import flash.display.MovieClip; + + public class Grandchild extends MovieClip { + public function Grandchild() { + trace("/// Grandchild constructor"); + } + } +} \ No newline at end of file diff --git a/core/tests/swfs/avm2/documentclass/Main.as b/core/tests/swfs/avm2/documentclass/Main.as new file mode 100644 index 000000000..ee9704049 --- /dev/null +++ b/core/tests/swfs/avm2/documentclass/Main.as @@ -0,0 +1,13 @@ +package { + import flash.display.MovieClip; + + public class Main extends MovieClip { + public function Main() { + trace("/// Main constructor"); + trace("/// this.a"); + trace(this.a); + trace("/// this.a.b"); + trace(this.a.b); + } + } +} \ No newline at end of file diff --git a/core/tests/swfs/avm2/documentclass/output.txt b/core/tests/swfs/avm2/documentclass/output.txt new file mode 100644 index 000000000..bf30e9b15 --- /dev/null +++ b/core/tests/swfs/avm2/documentclass/output.txt @@ -0,0 +1,9 @@ +/// Grandchild constructor +/// Child constructor +/// this.b +[object Grandchild] +/// Main constructor +/// this.a +[object Child] +/// this.a.b +[object Grandchild] diff --git a/core/tests/swfs/avm2/documentclass/test.fla b/core/tests/swfs/avm2/documentclass/test.fla new file mode 100644 index 000000000..1e7c39c54 Binary files /dev/null and b/core/tests/swfs/avm2/documentclass/test.fla differ diff --git a/core/tests/swfs/avm2/documentclass/test.swf b/core/tests/swfs/avm2/documentclass/test.swf new file mode 100644 index 000000000..4b713f5e7 Binary files /dev/null and b/core/tests/swfs/avm2/documentclass/test.swf differ