From ebc5c3dd64eed2ab9c9587c5dc12e1fbe9479fd1 Mon Sep 17 00:00:00 2001 From: David Wendt Date: Thu, 8 Apr 2021 21:22:43 -0400 Subject: [PATCH] avm2: Ensure that objects are only *ever* constructed at frame construction time. This ensures that root movie classes see their children in their constructor. --- core/src/display_object/movie_clip.rs | 16 +++++++++++----- core/src/player.rs | 2 +- core/tests/regression_tests.rs | 1 + core/tests/swfs/avm2/documentclass/Child.as | 11 +++++++++++ .../tests/swfs/avm2/documentclass/Grandchild.as | 9 +++++++++ core/tests/swfs/avm2/documentclass/Main.as | 13 +++++++++++++ core/tests/swfs/avm2/documentclass/output.txt | 9 +++++++++ core/tests/swfs/avm2/documentclass/test.fla | Bin 0 -> 5335 bytes core/tests/swfs/avm2/documentclass/test.swf | Bin 0 -> 780 bytes 9 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 core/tests/swfs/avm2/documentclass/Child.as create mode 100644 core/tests/swfs/avm2/documentclass/Grandchild.as create mode 100644 core/tests/swfs/avm2/documentclass/Main.as create mode 100644 core/tests/swfs/avm2/documentclass/output.txt create mode 100644 core/tests/swfs/avm2/documentclass/test.fla create mode 100644 core/tests/swfs/avm2/documentclass/test.swf 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 0000000000000000000000000000000000000000..1e7c39c547e0928020b29cb623ce28f2288adc6e GIT binary patch literal 5335 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 literal 0 HcmV?d00001 diff --git a/core/tests/swfs/avm2/documentclass/test.swf b/core/tests/swfs/avm2/documentclass/test.swf new file mode 100644 index 0000000000000000000000000000000000000000..4b713f5e7f58774402332b2e7254d9034bb68991 GIT binary patch literal 780 zcmV+n1M~btS5qr21pokeoSjt9PZL2Delz=HI&JwSZ7B#!2;rcnT|`WT10=;D1_FdM z@lay7+iAL{v}AW%e_S9Qycmr)ulxsI^h`Vw6VrH3crqrYzS*@@qFmT)XI{Sd z-uHcPI_)FS?gRAf0VD}5^o0N*LtCxZ<=*<>_~dx??s)dbs5OInf2u- zYf~xMk4LbUz=kENVssLq6-)U*)_A-2{4l%lX8pq}LJ)!$iOCh;zUgdy$SbJQ<#`t8~EIK`Ss^+ zi;rPSZIdYg`+5|S35p6sFTTZh3qJiHlwj%b?)#_nChW(K6=@xxUXWA32t+bvyHZU1 zYkbi$t3}HPIw4;%?P^*snqSpbs+ev$RkYphiustY)Ec(PRP1e12zQ!PSx?N_rI}o& zRunm>UMf{Y&Z;>g=Ly$ybMC{En=>0**K@_1Ro@a-&q7{zcGee3nXcwJrX}L(bb8c> zMy*=a^_;rp)tsKPptNtP>Ivlb z?1l)C#HoCyR`t-maP*CB$M(ehIfm$*1Wqy}-FA?_2bnnsw>(;8jY(D+|NmgjXeUe+ zSb`+@Zi=^2zKIM z+fJ+oyFw^efDlC@D&@FOv`kwIvaHA{+&ICfAZO819CXjlee9||UoAWf)kWbjB8aF!9;HlksjG&0wJ$v=A){NE9Njh(xQ33-M5 KKaAg`4^G1!HiB3H literal 0 HcmV?d00001