avm2: Run orphan framescripts that didn't get a chance to run

This is necessary to make Steambirds get past the preloader screen.
All of the previous tests continue to pass with this change.

This commit modifies the existing test to start from within
the symbol_class constructor, instead of a frame script. In
this situation, a freshly-created orphan with a framescript will
run directly after the constructor returns, *before* an enterFrame
handler for the same orphan. I've verified that this modified test
fails without my change.
This commit is contained in:
Aaron Hill 2023-03-06 21:25:41 -06:00
parent 93834b63de
commit 7ab7c31bb6
6 changed files with 73 additions and 4 deletions

View File

@ -14,6 +14,7 @@
use crate::avm2::Avm2; use crate::avm2::Avm2;
use crate::context::UpdateContext; use crate::context::UpdateContext;
use crate::display_object::{DisplayObject, TDisplayObject}; use crate::display_object::{DisplayObject, TDisplayObject};
use fnv::FnvHashSet;
use tracing::instrument; use tracing::instrument;
/// Which phase of the frame we're currently in. /// Which phase of the frame we're currently in.
@ -85,6 +86,8 @@ pub fn run_all_phases_avm2(context: &mut UpdateContext<'_, '_>) {
stage.enter_frame(context); stage.enter_frame(context);
let mut ran_framescript = FnvHashSet::default();
Avm2::each_orphan_movie(context, |movie, context| { Avm2::each_orphan_movie(context, |movie, context| {
if movie.initialized() { if movie.initialized() {
// Orphan frame scripts run in a really weird place. // Orphan frame scripts run in a really weird place.
@ -93,6 +96,7 @@ pub fn run_all_phases_avm2(context: &mut UpdateContext<'_, '_>) {
// (but is updated when we call an enterFrame listener) // (but is updated when we call an enterFrame listener)
movie.run_frame_scripts(context); movie.run_frame_scripts(context);
movie.enter_frame(context); movie.enter_frame(context);
ran_framescript.insert(movie.downgrade().as_ptr());
} }
}); });
@ -101,6 +105,7 @@ pub fn run_all_phases_avm2(context: &mut UpdateContext<'_, '_>) {
Avm2::each_orphan_movie(context, |movie, context| { Avm2::each_orphan_movie(context, |movie, context| {
if !movie.initialized() { if !movie.initialized() {
movie.run_frame_scripts(context); movie.run_frame_scripts(context);
ran_framescript.insert(movie.downgrade().as_ptr());
} }
}); });
@ -108,6 +113,9 @@ pub fn run_all_phases_avm2(context: &mut UpdateContext<'_, '_>) {
Avm2::each_orphan_movie(context, |movie, context| { Avm2::each_orphan_movie(context, |movie, context| {
movie.construct_frame(context); movie.construct_frame(context);
if !ran_framescript.contains(&movie.downgrade().as_ptr()) {
movie.run_frame_scripts(context);
}
}); });
stage.frame_constructed(context); stage.frame_constructed(context);

View File

@ -0,0 +1,37 @@
package {
import flash.display.MovieClip;
public class MainTimeline extends MovieClip {
private var immediateOrphan:FrameHelper;
private var frameScriptDone:Boolean = false;
public function MainTimeline() {
trace("In MainTimeline constructor");
new Test(this);
var mainTimeline = this;
this.immediateOrphan = new FrameHelper();
this.immediateOrphan.addFrameScript(0, function() {
// Only run this once - we have other framescripts in 'Test',
// and the relative order in which framescripts run seems to
// be pseudorandom (probably based on the iteration order of some
// internal hashset)
if (mainTimeline.frameScriptDone) {
return;
}
mainTimeline.frameScriptDone = true;
trace("Running immediate orphan frame script: mainTimeline.immediateOrphan.currentFrame = " + mainTimeline.immediateOrphan.currentFrame);
});
mainTimeline.immediateOrphan.addEventListener("enterFrame", function(e) {
trace("Running immediateOrphan enterFrame: immediateOrphan.currentFrame = " + immediateOrphan.currentFrame);
})
trace("Finished MainTimeline constructor");
}
}
}

View File

@ -1,11 +1,17 @@
In MainTimeline constructor
Finished MainTimeline constructor
Running immediate orphan frame script: mainTimeline.immediateOrphan.currentFrame = 1
Running immediateOrphan enterFrame: immediateOrphan.currentFrame = 1
Orphan 1 in framescript=0 currentFrame=1 Orphan 1 in framescript=0 currentFrame=1
enterFrame: Movie counter=0 currentFrame=3 enterFrame: Movie counter=0 currentFrame=3
Running immediateOrphan enterFrame: immediateOrphan.currentFrame = 2
enterFrame: Orphan 1 in frame: 1 enterFrame: Orphan 1 in frame: 1
enterFrame: Orphan 2 in frame: 1 enterFrame: Orphan 2 in frame: 1
enterFrame: Orphan 3 in frame: 1 enterFrame: Orphan 3 in frame: 1
enterFrame: Orphan 4 in frame: 1 enterFrame: Orphan 4 in frame: 1
enterFrame: Orphan 5 in frame: 1 enterFrame: Orphan 5 in frame: 1
enterFrame: Movie counter=1 currentFrame=4 enterFrame: Movie counter=1 currentFrame=4
Running immediateOrphan enterFrame: immediateOrphan.currentFrame = 3
enterFrame: Orphan 1 in frame: 2 enterFrame: Orphan 1 in frame: 2
enterFrame: Orphan 2 in frame: 2 enterFrame: Orphan 2 in frame: 2
enterFrame: Orphan 3 in frame: 2 enterFrame: Orphan 3 in frame: 2
@ -14,6 +20,7 @@ enterFrame: Orphan 5 in frame: 2
Orphan 1 in framescript=1 currentFrame=2 Orphan 1 in framescript=1 currentFrame=2
enterFrame: Movie counter=2 currentFrame=5 enterFrame: Movie counter=2 currentFrame=5
Adding and removing orphan2 as child Adding and removing orphan2 as child
Running immediateOrphan enterFrame: immediateOrphan.currentFrame = 4
enterFrame: Orphan 1 in frame: 3 enterFrame: Orphan 1 in frame: 3
enterFrame: Orphan 2 in frame: 3 enterFrame: Orphan 2 in frame: 3
enterFrame: Orphan 3 in frame: 3 enterFrame: Orphan 3 in frame: 3
@ -21,6 +28,7 @@ enterFrame: Orphan 4 in frame: 3
enterFrame: Orphan 5 in frame: 3 enterFrame: Orphan 5 in frame: 3
Orphan 1 in framescript=2 currentFrame=3 Orphan 1 in framescript=2 currentFrame=3
enterFrame: Movie counter=3 currentFrame=6 enterFrame: Movie counter=3 currentFrame=6
Running immediateOrphan enterFrame: immediateOrphan.currentFrame = 5
enterFrame: Orphan 1 in frame: 4 enterFrame: Orphan 1 in frame: 4
enterFrame: Orphan 2 in frame: 4 enterFrame: Orphan 2 in frame: 4
enterFrame: Orphan 3 in frame: 4 enterFrame: Orphan 3 in frame: 4
@ -28,6 +36,7 @@ enterFrame: Orphan 4 in frame: 4
enterFrame: Orphan 5 in frame: 4 enterFrame: Orphan 5 in frame: 4
Orphan 1 in framescript=3 currentFrame=4 Orphan 1 in framescript=3 currentFrame=4
enterFrame: Movie counter=4 currentFrame=7 enterFrame: Movie counter=4 currentFrame=7
Running immediateOrphan enterFrame: immediateOrphan.currentFrame = 6
enterFrame: Orphan 1 in frame: 5 enterFrame: Orphan 1 in frame: 5
enterFrame: Orphan 2 in frame: 5 enterFrame: Orphan 2 in frame: 5
enterFrame: Orphan 3 in frame: 5 enterFrame: Orphan 3 in frame: 5
@ -36,6 +45,7 @@ enterFrame: Orphan 5 in frame: 5
Orphan 1 in framescript=4 currentFrame=5 Orphan 1 in framescript=4 currentFrame=5
enterFrame: Movie counter=5 currentFrame=8 enterFrame: Movie counter=5 currentFrame=8
Adding orphan 3 as child Adding orphan 3 as child
Running immediateOrphan enterFrame: immediateOrphan.currentFrame = 7
enterFrame: Orphan 1 in frame: 6 enterFrame: Orphan 1 in frame: 6
enterFrame: Orphan 2 in frame: 6 enterFrame: Orphan 2 in frame: 6
enterFrame: Orphan 3 in frame: 6 enterFrame: Orphan 3 in frame: 6
@ -43,6 +53,7 @@ enterFrame: Orphan 4 in frame: 6
enterFrame: Orphan 5 in frame: 6 enterFrame: Orphan 5 in frame: 6
Orphan 1 in framescript=5 currentFrame=6 Orphan 1 in framescript=5 currentFrame=6
enterFrame: Movie counter=6 currentFrame=9 enterFrame: Movie counter=6 currentFrame=9
Running immediateOrphan enterFrame: immediateOrphan.currentFrame = 8
enterFrame: Orphan 1 in frame: 7 enterFrame: Orphan 1 in frame: 7
enterFrame: Orphan 2 in frame: 7 enterFrame: Orphan 2 in frame: 7
enterFrame: Orphan 3 in frame: 7 enterFrame: Orphan 3 in frame: 7
@ -50,6 +61,7 @@ enterFrame: Orphan 4 in frame: 7
enterFrame: Orphan 5 in frame: 7 enterFrame: Orphan 5 in frame: 7
Orphan 1 in framescript=6 currentFrame=7 Orphan 1 in framescript=6 currentFrame=7
enterFrame: Movie counter=7 currentFrame=10 enterFrame: Movie counter=7 currentFrame=10
Running immediateOrphan enterFrame: immediateOrphan.currentFrame = 9
enterFrame: Orphan 1 in frame: 8 enterFrame: Orphan 1 in frame: 8
enterFrame: Orphan 2 in frame: 8 enterFrame: Orphan 2 in frame: 8
enterFrame: Orphan 3 in frame: 8 enterFrame: Orphan 3 in frame: 8
@ -58,6 +70,7 @@ enterFrame: Orphan 5 in frame: 8
Orphan 1 in framescript=7 currentFrame=8 Orphan 1 in framescript=7 currentFrame=8
enterFrame: Movie counter=8 currentFrame=1 enterFrame: Movie counter=8 currentFrame=1
Removing orphan 3 as child Removing orphan 3 as child
Running immediateOrphan enterFrame: immediateOrphan.currentFrame = 10
enterFrame: Orphan 1 in frame: 9 enterFrame: Orphan 1 in frame: 9
enterFrame: Orphan 2 in frame: 9 enterFrame: Orphan 2 in frame: 9
enterFrame: Orphan 3 in frame: 9 enterFrame: Orphan 3 in frame: 9
@ -65,23 +78,34 @@ enterFrame: Orphan 4 in frame: 9
enterFrame: Orphan 5 in frame: 9 enterFrame: Orphan 5 in frame: 9
Orphan 1 in framescript=8 currentFrame=9 Orphan 1 in framescript=8 currentFrame=9
enterFrame: Movie counter=9 currentFrame=2 enterFrame: Movie counter=9 currentFrame=2
Running immediateOrphan enterFrame: immediateOrphan.currentFrame = 11
enterFrame: Orphan 1 in frame: 10 enterFrame: Orphan 1 in frame: 10
enterFrame: Orphan 2 in frame: 10 enterFrame: Orphan 2 in frame: 10
enterFrame: Orphan 3 in frame: 10 enterFrame: Orphan 3 in frame: 10
enterFrame: Orphan 4 in frame: 10 enterFrame: Orphan 4 in frame: 10
enterFrame: Orphan 5 in frame: 10 enterFrame: Orphan 5 in frame: 10
Orphan 1 in framescript=9 currentFrame=10 Orphan 1 in framescript=9 currentFrame=10
Orphan 1 in framescript=0 currentFrame=1
enterFrame: Movie counter=10 currentFrame=3 enterFrame: Movie counter=10 currentFrame=3
enterFrame: Movie counter=0 currentFrame=3 Running immediateOrphan enterFrame: immediateOrphan.currentFrame = 1
enterFrame: Orphan 1 in frame: 11 enterFrame: Orphan 1 in frame: 11
enterFrame: Orphan 2 in frame: 11 enterFrame: Orphan 2 in frame: 11
enterFrame: Orphan 3 in frame: 11 enterFrame: Orphan 3 in frame: 11
enterFrame: Orphan 4 in frame: 11 enterFrame: Orphan 4 in frame: 11
enterFrame: Orphan 5 in frame: 11 enterFrame: Orphan 5 in frame: 11
Orphan 1 in framescript=10 currentFrame=11
enterFrame: Movie counter=11 currentFrame=4
Running immediateOrphan enterFrame: immediateOrphan.currentFrame = 2
enterFrame: Orphan 1 in frame: 1 enterFrame: Orphan 1 in frame: 1
enterFrame: Orphan 2 in frame: 1 enterFrame: Orphan 2 in frame: 1
enterFrame: Orphan 3 in frame: 1 enterFrame: Orphan 3 in frame: 1
enterFrame: Orphan 4 in frame: 1 enterFrame: Orphan 4 in frame: 1
enterFrame: Orphan 5 in frame: 1 enterFrame: Orphan 5 in frame: 1
Orphan 1 in framescript=10 currentFrame=11 Orphan 1 in framescript=0 currentFrame=1
enterFrame: Movie counter=12 currentFrame=5
Running immediateOrphan enterFrame: immediateOrphan.currentFrame = 3
enterFrame: Orphan 1 in frame: 2
enterFrame: Orphan 2 in frame: 2
enterFrame: Orphan 3 in frame: 2
enterFrame: Orphan 4 in frame: 2
enterFrame: Orphan 5 in frame: 2
Orphan 1 in framescript=1 currentFrame=2

View File

@ -1 +1 @@
num_frames = 13 num_frames = 15