diff --git a/core/src/display_object/avm2_button.rs b/core/src/display_object/avm2_button.rs index 93d1393d4421..721759b27bb0 100644 --- a/core/src/display_object/avm2_button.rs +++ b/core/src/display_object/avm2_button.rs @@ -483,6 +483,21 @@ impl<'gc> TDisplayObject<'gc> for Avm2Button<'gc> { let needs_frame_construction = self.0.read().needs_frame_construction; if needs_frame_construction { + if needs_avm2_construction { + let mut activation = Avm2Activation::from_nothing(context.reborrow()); + match Avm2StageObject::for_display_object(&mut activation, (*self).into(), class) { + Ok(object) => { + self.0.write(activation.context.gc_context).object = Some(object.into()) + } + Err(e) => tracing::error!("Got {} when constructing AVM2 side of button", e), + }; + if !self.placed_by_script() { + // This is run before we actually call the constructor - the un-constructed object + // is exposed to ActionScript via `parent.`. + self.set_on_parent_field(&mut activation.context); + } + } + // Prevent re-entrantly constructing this button (since we may run a nested frame here) self.0.write(context.gc_context).needs_frame_construction = false; let (up_state, up_should_fire) = self.create_state(context, swf::ButtonState::UP); @@ -548,36 +563,20 @@ impl<'gc> TDisplayObject<'gc> for Avm2Button<'gc> { if needs_avm2_construction { self.set_state(context, ButtonState::Up); - let mut activation = Avm2Activation::from_nothing(context.reborrow()); - match Avm2StageObject::for_display_object(&mut activation, (*self).into(), class) { - Ok(object) => { - self.0.write(activation.context.gc_context).object = Some(object.into()) - } - Err(e) => tracing::error!("Got {} when constructing AVM2 side of button", e), - }; - - if !self.placed_by_script() { - // This is run before we actually call the constructor - the un-constructed object - // is exposed to ActionScript via `parent.`. - self.set_on_parent_field(&mut activation.context); - } - if has_movie_clip_state && self.movie().version() > 9 { - self.0 - .write(activation.context.gc_context) - .weird_framescript_order = true; - - let stage = activation.context.stage; - - stage.construct_frame(&mut activation.context); - stage.frame_constructed(&mut activation.context); - self.set_state(&mut activation.context, ButtonState::Up); - stage.run_frame_scripts(&mut activation.context); - stage.exit_frame(&mut activation.context); + self.0.write(context.gc_context).weird_framescript_order = true; + + let stage = context.stage; + stage.construct_frame(context); + stage.frame_constructed(context); + self.set_state(context, ButtonState::Up); + stage.run_frame_scripts(context); + stage.exit_frame(context); } let avm2_object = self.0.read().object; if let Some(avm2_object) = avm2_object { + let mut activation = Avm2Activation::from_nothing(context.reborrow()); if let Err(e) = class.call_native_init(avm2_object.into(), &[], &mut activation) { tracing::error!("Got {} when constructing AVM2 side of button", e); @@ -586,7 +585,7 @@ impl<'gc> TDisplayObject<'gc> for Avm2Button<'gc> { // Note - we do *not* call `on_construction_complete` here, since we already // set the button object on a parent field (and we don't want to re-run a setter) - self.fire_added_events(&mut activation.context); + self.fire_added_events(context); } } } diff --git a/tests/tests/swfs/avm2/simplebutton_childevents/Main.as b/tests/tests/swfs/avm2/simplebutton_childevents/Main.as new file mode 100755 index 000000000000..02082e6099a9 --- /dev/null +++ b/tests/tests/swfs/avm2/simplebutton_childevents/Main.as @@ -0,0 +1,71 @@ +package +{ + import flash.display.*; + import flash.events.*; + import flash.system.*; + + public class Main extends EventWatcher + { + + public static var frame1ScriptRan:Array = []; + + public static var frame2ScriptRan:Array = []; + + + public var my_button:SimpleButton; + + public static var INSTANCE: Main; + + public function Main() + { + INSTANCE = this; + var self:*; + + addFrameScript(0,this.frame1,1,this.frame2); + self = this; + this.addEventListener(Event.EXIT_FRAME,function(e:*):* + { + frame1ScriptRan.sort(); + frame2ScriptRan.sort(); + trace("frame1ScriptRan = " + frame1ScriptRan); + trace("frame2ScriptRan = " + frame2ScriptRan); + frame1ScriptRan = []; + frame2ScriptRan = []; + }); + trace("Calling Main super()"); + super(); + } + + public function stop_display_object_handlers(dobj:DisplayObject) : * + { + var i:* = undefined; + if(dobj instanceof EventWatcher) + { + dobj.destroy(); + } + if(dobj instanceof DisplayObjectContainer) + { + for(i = 0; i < dobj.numChildren; i += 1) + { + this.stop_display_object_handlers(dobj.getChildAt(i)); + } + } + } + + internal function frame1() : * + { + Main.frame1ScriptRan.push("MainTimeline"); + } + + internal function frame2() : * + { + Main.frame2ScriptRan.push("MainTimeline"); + this.stop(); + this.stop_display_object_handlers(this.my_button.upState); + this.stop_display_object_handlers(this.my_button.downState); + this.stop_display_object_handlers(this.my_button.overState); + this.stop_display_object_handlers(this.my_button.hitTestState); + System.gc(); + } + } +} diff --git a/tests/tests/swfs/avm2/simplebutton_childevents/MyButton.as b/tests/tests/swfs/avm2/simplebutton_childevents/MyButton.as new file mode 100755 index 000000000000..02b8a1f81680 --- /dev/null +++ b/tests/tests/swfs/avm2/simplebutton_childevents/MyButton.as @@ -0,0 +1,16 @@ +package { + + import flash.display.SimpleButton; + + + public class MyButton extends SimpleButton { + + + public function MyButton() { + trace("Calling MyButton super()"); + super(); + trace("Called MyButton super()"); + } + } + +} diff --git a/tests/tests/swfs/avm2/simplebutton_childevents/UpButtonShape.as b/tests/tests/swfs/avm2/simplebutton_childevents/UpButtonShape.as index 502ce1356a1c..5a4485c491d7 100644 --- a/tests/tests/swfs/avm2/simplebutton_childevents/UpButtonShape.as +++ b/tests/tests/swfs/avm2/simplebutton_childevents/UpButtonShape.as @@ -3,7 +3,7 @@ public class UpButtonShape extends EventWatcher { public function UpButtonShape() { - trace("//Constructed UpButtonShape (", this.name, "): this.parent = " + this.parent + " this.stage " + this.stage); + trace("//Constructed UpButtonShape (", this.name, "): this.parent = " + this.parent + " this.stage " + this.stage + " Main.INSTANCE.my_button = " + Main.INSTANCE.my_button); } } diff --git a/tests/tests/swfs/avm2/simplebutton_childevents/output.txt b/tests/tests/swfs/avm2/simplebutton_childevents/output.txt index ef45d6b3af45..266f91f54c21 100644 --- a/tests/tests/swfs/avm2/simplebutton_childevents/output.txt +++ b/tests/tests/swfs/avm2/simplebutton_childevents/output.txt @@ -3,7 +3,7 @@ instance2:[Event type="added" bubbles=true cancelable=false eventPhase=3] target target.stage: [object Stage] target.name: instance3 target.parent: [object UpButtonShape] target.parent.parent: null root1:[Event type="added" bubbles=true cancelable=false eventPhase=3] target: [object Shape] target.stage: [object Stage] target.name: instance3 target.parent: [object UpButtonShape] target.parent.parent: null -//Constructed UpButtonShape ( instance2 ): this.parent = null this.stage [object Stage] +//Constructed UpButtonShape ( instance2 ): this.parent = null this.stage [object Stage] Main.INSTANCE.my_button = [object MyButton] instance4:[Event type="added" bubbles=true cancelable=false eventPhase=3] target: [object Shape] target.stage: [object Stage] target.name: instance5 target.parent: [object OverButtonShape] target.parent.parent: null root1:[Event type="added" bubbles=true cancelable=false eventPhase=3] target: [object Shape] @@ -38,7 +38,9 @@ instance4:[Event type="exitFrame" bubbles=false cancelable=false eventPhase=2] t target.stage: null target.name: instance4 target.parent: null target.parent.parent: instance6:[Event type="exitFrame" bubbles=false cancelable=false eventPhase=2] target: [object DownButtonShape] target.stage: null target.name: instance6 target.parent: null target.parent.parent: -root1:[Event type="added" bubbles=true cancelable=false eventPhase=3] target: [object SimpleButton] +Calling MyButton super() +Called MyButton super() +root1:[Event type="added" bubbles=true cancelable=false eventPhase=3] target: [object MyButton] target.stage: [object Stage] target.name: my_button target.parent: [object Main] target.parent.parent: [object Stage] root1:[Event type="added" bubbles=true cancelable=false eventPhase=2] target: [object Main] target.stage: [object Stage] target.name: root1 target.parent: [object Stage] target.parent.parent: null diff --git a/tests/tests/swfs/avm2/simplebutton_childevents/test.fla b/tests/tests/swfs/avm2/simplebutton_childevents/test.fla index d3de2052ebb4..4dfac1266337 100755 Binary files a/tests/tests/swfs/avm2/simplebutton_childevents/test.fla and b/tests/tests/swfs/avm2/simplebutton_childevents/test.fla differ diff --git a/tests/tests/swfs/avm2/simplebutton_childevents/test.swf b/tests/tests/swfs/avm2/simplebutton_childevents/test.swf index 30ac15a5eb8c..9ed1d290c4a6 100644 Binary files a/tests/tests/swfs/avm2/simplebutton_childevents/test.swf and b/tests/tests/swfs/avm2/simplebutton_childevents/test.swf differ diff --git a/tests/tests/swfs/avm2/simplebutton_symbolclass/Main.as b/tests/tests/swfs/avm2/simplebutton_symbolclass/Main.as new file mode 100755 index 000000000000..d30ac749c2c3 --- /dev/null +++ b/tests/tests/swfs/avm2/simplebutton_symbolclass/Main.as @@ -0,0 +1,98 @@ +package +{ + import flash.accessibility.*; + import flash.display.*; + import flash.errors.*; + import flash.events.*; + import flash.filters.*; + import flash.geom.*; + import flash.media.*; + import flash.net.*; + import flash.net.drm.*; + import flash.system.*; + import flash.text.*; + import flash.text.ime.*; + import flash.ui.*; + import flash.utils.*; + + public dynamic class Main extends MovieClip + { + + public static var INSTANCE: Main; + + + public var timeline_symbol:MyButton; + + public var my_button:*; + + public function Main() + { + INSTANCE = this; + trace("Calling Main super()"); + super(); + trace("Called Main super()"); + addFrameScript(0,this.frame1,1,this.frame2); + } + + public function inspect_display_object(dobj:DisplayObject) : * + { + var i:* = undefined; + trace(dobj); + if(dobj instanceof DisplayObjectContainer) + { + trace("// numChildren: ",dobj.numChildren); + for(i = 0; i < dobj.numChildren; i += 1) + { + trace(dobj.getChildAt(i)); + } + } + } + + internal function frame1() : * + { + trace("//var my_button = new MyButton();"); + this.my_button = new MyButton(); + trace("//this.addChild(my_button);"); + this.addChild(this.my_button); + trace("//my_button"); + trace(this.my_button); + trace("//my_button.upState"); + this.inspect_display_object(this.my_button.upState); + trace("//my_button.overState"); + this.inspect_display_object(this.my_button.overState); + trace("//my_button.downState"); + this.inspect_display_object(this.my_button.downState); + trace("//my_button.hitTestState"); + this.inspect_display_object(this.my_button.hitTestState); + trace("//my_button.upState = new UpButtonShape();"); + this.my_button.upState = new UpButtonShape(); + trace("//my_button.overState = new OverButtonShape();"); + this.my_button.overState = new OverButtonShape(); + trace("//my_button.downState = new DownButtonShape();"); + this.my_button.downState = new DownButtonShape(); + trace("//my_button.hitTestState = new HitButtonShape();"); + this.my_button.hitTestState = new HitButtonShape(); + trace("//my_button.upState"); + this.inspect_display_object(this.my_button.upState); + trace("//my_button.overState"); + this.inspect_display_object(this.my_button.overState); + trace("//my_button.downState"); + this.inspect_display_object(this.my_button.downState); + trace("//my_button.hitTestState"); + this.inspect_display_object(this.my_button.hitTestState); + } + + internal function frame2() : * + { + trace("//this.timeline_symbol.upState"); + this.inspect_display_object(this.timeline_symbol.upState); + trace("//this.timeline_symbol.overState"); + this.inspect_display_object(this.timeline_symbol.overState); + trace("//this.timeline_symbol.downState"); + this.inspect_display_object(this.timeline_symbol.downState); + trace("//this.timeline_symbol.hitTestState"); + this.inspect_display_object(this.timeline_symbol.hitTestState); + this.stop(); + } + } +} diff --git a/tests/tests/swfs/avm2/simplebutton_symbolclass/OverButtonShape.as b/tests/tests/swfs/avm2/simplebutton_symbolclass/OverButtonShape.as index 9e7579bca6e8..d51abb3d1be5 100644 --- a/tests/tests/swfs/avm2/simplebutton_symbolclass/OverButtonShape.as +++ b/tests/tests/swfs/avm2/simplebutton_symbolclass/OverButtonShape.as @@ -3,7 +3,7 @@ public class OverButtonShape extends MovieClip { public function OverButtonShape() { - trace("//Constructed OverButtonShape (", this.name, ")!"); + trace("//Constructed OverButtonShape (", this.name, "): Main.INSTANCE.my_button = " + Main.INSTANCE.my_button); } } diff --git a/tests/tests/swfs/avm2/simplebutton_symbolclass/output.txt b/tests/tests/swfs/avm2/simplebutton_symbolclass/output.txt index b8e7c1e3e343..7a7912b10cc6 100644 --- a/tests/tests/swfs/avm2/simplebutton_symbolclass/output.txt +++ b/tests/tests/swfs/avm2/simplebutton_symbolclass/output.txt @@ -1,6 +1,8 @@ +Calling Main super() +Called Main super() //var my_button = new MyButton(); //Constructed UpButtonShape ( instance3 )! -//Constructed OverButtonShape ( instance5 )! +//Constructed OverButtonShape ( instance5 ): Main.INSTANCE.my_button = undefined //Constructed DownButtonShape ( instance7 )! ///MyButton constructor! //this.addChild(my_button); @@ -24,7 +26,7 @@ //my_button.upState = new UpButtonShape(); //Constructed UpButtonShape ( instance11 )! //my_button.overState = new OverButtonShape(); -//Constructed OverButtonShape ( instance13 )! +//Constructed OverButtonShape ( instance13 ): Main.INSTANCE.my_button = [object MyButton] //my_button.downState = new DownButtonShape(); //Constructed DownButtonShape ( instance15 )! //my_button.hitTestState = new HitButtonShape(); @@ -46,7 +48,7 @@ // numChildren: 1 [object Shape] //Constructed UpButtonShape ( instance20 )! -//Constructed OverButtonShape ( instance22 )! +//Constructed OverButtonShape ( instance22 ): Main.INSTANCE.my_button = [object MyButton] //Constructed DownButtonShape ( instance24 )! //this.timeline_symbol.upState [object Sprite] diff --git a/tests/tests/swfs/avm2/simplebutton_symbolclass/test.fla b/tests/tests/swfs/avm2/simplebutton_symbolclass/test.fla old mode 100644 new mode 100755 index a7bd385d8736..01d06ce501a8 Binary files a/tests/tests/swfs/avm2/simplebutton_symbolclass/test.fla and b/tests/tests/swfs/avm2/simplebutton_symbolclass/test.fla differ diff --git a/tests/tests/swfs/avm2/simplebutton_symbolclass/test.swf b/tests/tests/swfs/avm2/simplebutton_symbolclass/test.swf index f39bf30f512a..e4ce3e5a2d02 100644 Binary files a/tests/tests/swfs/avm2/simplebutton_symbolclass/test.swf and b/tests/tests/swfs/avm2/simplebutton_symbolclass/test.swf differ