avm2: Improve accuracy of gotoAndPlay / gotoAndStop (partially fix #8954)

Partially based on AVM1 implementation, partially based on the new
regression tests added in this commit.
This commit is contained in:
MrCheeze 2023-01-02 19:35:25 -05:00 committed by kmeisthax
parent 664a86161a
commit 77104ca473
5 changed files with 67 additions and 6 deletions

View File

@ -388,13 +388,17 @@ pub fn goto_frame<'gc>(
.scene_label_to_number(&v.coerce_to_string(activation)?)
.map(|v| v.saturating_sub(1)),
}
.unwrap_or(0) as u32;
.unwrap_or(0) as i32;
let frame = match frame_or_label {
Value::Integer(i) => i as u32 + scene,
Value::Integer(i) => i + scene,
frame_or_label => {
let frame_or_label = frame_or_label.coerce_to_string(activation)?;
if let Ok(frame) = frame_or_label.parse::<u32>() {
frame + scene
let frame = crate::avm2::value::string_to_int(&frame_or_label, 10, true);
if !frame.is_nan() {
(frame as i32)
.wrapping_sub(1)
.wrapping_add(scene)
.saturating_add(1)
} else {
if let Some(scene) = args.get(1).cloned() {
//If the user specified a scene, we need to validate that
@ -410,12 +414,12 @@ pub fn goto_frame<'gc>(
mc.frame_label_to_number(&frame_or_label).ok_or_else(|| {
format!("ArgumentError: {frame_or_label} is not a valid frame label.")
})? as u32
})? as i32
}
}
};
mc.goto_frame(&mut activation.context, frame as u16, stop);
mc.goto_frame(&mut activation.context, frame.max(1) as u16, stop);
Ok(())
}

View File

@ -343,6 +343,7 @@ swf_tests! {
(as3_get_qualified_super_class_name, "avm2/get_qualified_super_class_name", 1),
(as3_get_timer, "avm2/get_timer", 1),
(as3_getouterscope, "avm2/getouterscope", 1),
(as3_goto_methods, "avm2/goto_methods", 1),
(as3_greaterequals, "avm2/greaterequals", 1),
(as3_greaterthan, "avm2/greaterthan", 1),
(as3_has_own_property, "avm2/has_own_property", 1),

View File

@ -0,0 +1,56 @@
// clip.gotoAndStop(999)
3
// clip.gotoAndStop(0)
1
// clip.gotoAndPlay(1)
1
// clip.gotoAndPlay(2)
2
// clip.gotoAndPlay(0x80000000)
3
// clip.gotoAndPlay(2)
2
// clip.gotoAndPlay(0x100000002)
3
// clip.gotoAndPlay(2)
2
// clip.gotoAndPlay(-0x80000000)
3
// clip.gotoAndPlay(2)
2
// clip.gotoAndPlay(-0x7FFFFFFF)
1
// clip.gotoAndPlay(2)
2
// clip.gotoAndPlay(-99999999999999999999)
3
// clip.gotoAndPlay(2)
2
// clip.gotoAndPlay('3 ')
3
// clip.gotoAndPlay(2)
2
// clip.gotoAndPlay('-99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999')
3
// clip.gotoAndPlay(Number(2.0))
2
// clip.gotoAndPlay(Number(-99.0))
1
// clip.gotoAndPlay(2)
2
// clip.gotoAndPlay(-99)
1
// clip.prevFrame()
1
// clip.prevFrame()
1
// clip.prevFrame()
1
// clip.gotoAndStop('TheFrame')
2
// clip.nextFrame()
3
// clip.nextFrame()
3
// clip.gotoAndStop({toString: function() { return 'TheFrame' }})
2

Binary file not shown.

Binary file not shown.