Skip to content

core: Refresh frame script on registration #20293

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion core/src/display_object/movie_clip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2179,7 +2179,9 @@ impl<'gc> MovieClip<'gc> {
callable: Option<Avm2Object<'gc>>,
context: &mut UpdateContext<'gc>,
) {
let frame_scripts = &mut self.0.write(context.gc()).frame_scripts;
let mut write = self.0.write(context.gc());
let current_frame = write.current_frame;
let frame_scripts = &mut write.frame_scripts;

let index = frame_id as usize;
if let Some(callable) = callable {
Expand All @@ -2190,6 +2192,12 @@ impl<'gc> MovieClip<'gc> {
} else if frame_scripts.len() > index {
frame_scripts[index] = None;
}
if frame_id == current_frame {
// Ensure newly registered frame scripts are executed,
// even if the frame is repeated due to goto.
write.last_queued_script_frame = None;
write.queued_script_frame = Some(current_frame);
}
}

/// Handle a RemoveObject tag when running a goto action.
Expand Down
35 changes: 35 additions & 0 deletions tests/tests/swfs/avm2/register_script_refresh/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Main constructor
Container constructor
Child constructor
GrandChild constructor
GrandChild addFrameScript
Child addFrameScript
LeafChild constructor
LeafChild addFrameScript
Container addFrameScript
Main addFrameScript
Main frame1
Container frame1
Child frame1
GrandChild frame1
LeafChild frame1
entered frame 2
calling goto on grandchild
Main frame2
Container frame2
Child frame2
GrandChild frame1
LeafChild frame2
calling goto on child
Child frame1
adding frame-script to grandchild
secret reached!
entered frame 1
Container frame1
Child frame2
LeafChild frame1
entered frame 2
Main frame1
Container frame2
LeafChild frame2
Main frame2
52 changes: 52 additions & 0 deletions tests/tests/swfs/avm2/register_script_refresh/scripts/Main.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package
{
import flash.display.MovieClip;

public class Main extends MovieClip
{
public var child:*;

public var repeats:uint = 0;

public var descendant_names:Array = ["Container","Child","GrandChild","LeafChild"];

public var descendant_order:Array = [0,0,0,0];

public function Main()
{
trace("Main constructor");
super();
this.addScripts();
}

public function collectDescendants() : Array
{
return [this.child].concat(this.child.collectDescendants());
}

public function addScripts() : *
{
trace("Main addFrameScript");
addFrameScript(0,this.frame1,1,this.frame2);
}

internal function frame1() : *
{
trace("Main frame1");
}

internal function frame2() : *
{
trace("Main frame2");
if(this.repeats > 0)
{
stop();
}
else
{
this.repeats += 1;
}
}
}
}

55 changes: 55 additions & 0 deletions tests/tests/swfs/avm2/register_script_refresh/scripts/MyChild.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package
{
import flash.display.MovieClip;

public class MyChild extends MovieClip
{
public static var counter:uint = 1;

public var grandchild:*;

public var id:uint = counter;

public var repeats:uint = 0;

public var name:String = "Child";

public function MyChild()
{
counter += 1;
trace(this.name + " constructor");
super();
this.addScripts();
}

public function collectDescendants() : Array
{
return [this.grandchild].concat(this.grandchild.collectDescendants());
}

public function addScripts() : *
{
trace(this.name + " addFrameScript");
addFrameScript(0,this.frame1,1,this.frame2);
}

internal function frame1() : *
{
trace(this.name + " frame1");
}

internal function frame2() : *
{
trace(this.name + " frame2");
if(this.repeats > 0)
{
stop();
}
else
{
this.repeats += 1;
}
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package
{
import flash.display.MovieClip;
import flash.events.*;

public class MyContainer extends MovieClip
{
public var myChild1:*;

public var myChild2:*;

public var went_once:Boolean = false;

public var repeats:uint = 0;

public function MyContainer()
{
trace("Container constructor");
super();
this.addScripts()
addEventListener(Event.ENTER_FRAME,this.enter_frame);
}

public function collectDescendants() : Array
{
return [this.myChild1].concat(this.myChild1.collectDescendants()).concat([this.myChild2]).concat(this.myChild2.collectDescendants());
}

public function addScripts() : *
{
trace("Container addFrameScript");
addFrameScript(0,this.frame1,1,this.frame2);
}

internal function enter_frame(param1:Event = null) : *
{
trace("entered frame", this.currentFrame);
if (!went_once) {
went_once = true;
trace("calling goto on grandchild");
myChild1.grandchild.gotoAndStop(1);
trace("calling goto on child");
myChild1.gotoAndPlay(1);
trace("adding frame-script to grandchild");
myChild1.addFrameScript(0,this.secret_frame);
}
}

internal function secret_frame() : *
{
trace("secret reached!");
}

internal function frame1() : *
{
trace("Container frame1");
}

internal function frame2() : *
{
trace("Container frame2");
if(this.repeats > 0)
{
removeEventListener(Event.ENTER_FRAME,this.enter_frame);
stop();
}
else
{
this.repeats += 1;
}
}
}
}

61 changes: 61 additions & 0 deletions tests/tests/swfs/avm2/register_script_refresh/scripts/MyLeaf.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package
{
import flash.display.MovieClip;

public class MyLeaf extends MovieClip
{
public static var counter:uint = 1;

public var id:uint = counter;

public var repeats:uint = 0;

public var name:String = "";

public function MyLeaf()
{
if(this.id == 1)
{
this.name = "GrandChild";
}
else
{
this.name = "LeafChild";
}
counter += 1;
trace(this.name + " constructor");
super();
this.addScripts();
}

public function collectDescendants() : Array
{
return [];
}

public function addScripts() : *
{
trace(this.name + " addFrameScript");
addFrameScript(0,this.frame1,1,this.frame2);
}

internal function frame1() : *
{
trace(this.name + " frame1");
}

internal function frame2() : *
{
trace(this.name + " frame2");
if(this.repeats > 0)
{
stop();
}
else
{
this.repeats += 1;
}
}
}
}

Binary file not shown.
Binary file not shown.
1 change: 1 addition & 0 deletions tests/tests/swfs/avm2/register_script_refresh/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
num_ticks = 5
Loading