core: Prevent recursive execution of frame scripts on the same movie clip.
To be clear, recursive execution of frame scripts between *different* movie clips is still allowed.
This commit is contained in:
parent
85d98d8c07
commit
e926af7796
|
@ -1798,37 +1798,52 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> {
|
||||||
|
|
||||||
if let Some(avm2_object) = avm2_object {
|
if let Some(avm2_object) = avm2_object {
|
||||||
if let Some(frame_id) = write.queued_script_frame {
|
if let Some(frame_id) = write.queued_script_frame {
|
||||||
let is_fresh_frame = write.queued_script_frame != write.last_queued_script_frame;
|
// If we are already executing frame scripts, then we shouldn't
|
||||||
|
// run frame scripts recursively. This is because AVM2 can run
|
||||||
write.last_queued_script_frame = Some(frame_id);
|
// gotos, which will both queue and run frame scripts for the
|
||||||
write.queued_script_frame = None;
|
// whole movie again. If a goto is attempting to queue frame
|
||||||
write
|
// scripts on us AGAIN, we should allow the current stack to
|
||||||
|
// wind down before handling that.
|
||||||
|
if !write
|
||||||
.flags
|
.flags
|
||||||
.insert(MovieClipFlags::EXECUTING_AVM2_FRAME_SCRIPT);
|
.contains(MovieClipFlags::EXECUTING_AVM2_FRAME_SCRIPT)
|
||||||
|
{
|
||||||
|
let is_fresh_frame =
|
||||||
|
write.queued_script_frame != write.last_queued_script_frame;
|
||||||
|
|
||||||
if is_fresh_frame {
|
write.last_queued_script_frame = Some(frame_id);
|
||||||
while let Some(fs) = write.frame_scripts.get(index) {
|
write.queued_script_frame = None;
|
||||||
if fs.frame_id == frame_id {
|
write
|
||||||
let callable = fs.callable;
|
.flags
|
||||||
drop(write);
|
.insert(MovieClipFlags::EXECUTING_AVM2_FRAME_SCRIPT);
|
||||||
if let Err(e) = Avm2::run_stack_frame_for_callable(
|
|
||||||
callable,
|
if is_fresh_frame {
|
||||||
Some(avm2_object),
|
while let Some(fs) = write.frame_scripts.get(index) {
|
||||||
&[],
|
if fs.frame_id == frame_id {
|
||||||
context,
|
let callable = fs.callable;
|
||||||
) {
|
drop(write);
|
||||||
log::error!("Error occured when running AVM2 frame script: {}", e);
|
if let Err(e) = Avm2::run_stack_frame_for_callable(
|
||||||
|
callable,
|
||||||
|
Some(avm2_object),
|
||||||
|
&[],
|
||||||
|
context,
|
||||||
|
) {
|
||||||
|
log::error!(
|
||||||
|
"Error occured when running AVM2 frame script: {}",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
write = self.0.write(context.gc_context);
|
||||||
}
|
}
|
||||||
write = self.0.write(context.gc_context);
|
|
||||||
|
index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
index += 1;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
write
|
write
|
||||||
.flags
|
.flags
|
||||||
.remove(MovieClipFlags::EXECUTING_AVM2_FRAME_SCRIPT);
|
.remove(MovieClipFlags::EXECUTING_AVM2_FRAME_SCRIPT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -356,6 +356,7 @@ swf_tests! {
|
||||||
(as3_movieclip_goto_during_frame_script, "avm2/movieclip_goto_during_frame_script", 1),
|
(as3_movieclip_goto_during_frame_script, "avm2/movieclip_goto_during_frame_script", 1),
|
||||||
(as3_movieclip_gotoandplay, "avm2/movieclip_gotoandplay", 5),
|
(as3_movieclip_gotoandplay, "avm2/movieclip_gotoandplay", 5),
|
||||||
(as3_movieclip_gotoandstop, "avm2/movieclip_gotoandstop", 5),
|
(as3_movieclip_gotoandstop, "avm2/movieclip_gotoandstop", 5),
|
||||||
|
(as3_movieclip_gotoandstop_queueing, "avm2/movieclip_gotoandstop_queueing", 2),
|
||||||
(as3_movieclip_next_frame, "avm2/movieclip_next_frame", 5),
|
(as3_movieclip_next_frame, "avm2/movieclip_next_frame", 5),
|
||||||
(as3_movieclip_next_scene, "avm2/movieclip_next_scene", 5),
|
(as3_movieclip_next_scene, "avm2/movieclip_next_scene", 5),
|
||||||
(as3_movieclip_play, "avm2/movieclip_play", 5),
|
(as3_movieclip_play, "avm2/movieclip_play", 5),
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
///Parent frame 1
|
||||||
|
///this.gotoAndStop(2);
|
||||||
|
///this.child.gotoAndStop(3);
|
||||||
|
///Child frame 3
|
||||||
|
///this.gotoAndStop(2);
|
||||||
|
///this.parent.gotoAndStop(5);
|
||||||
|
///End child frame 3
|
||||||
|
///End parent frame 1
|
||||||
|
///Parent frame 5
|
||||||
|
///this.child.gotoAndStop(5);
|
||||||
|
///Child frame 5
|
||||||
|
///End parent frame 5
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue