diff --git a/core/src/avm2/globals/flash/display/movieclip.rs b/core/src/avm2/globals/flash/display/movieclip.rs index 5b61702c1..8f616afb1 100644 --- a/core/src/avm2/globals/flash/display/movieclip.rs +++ b/core/src/avm2/globals/flash/display/movieclip.rs @@ -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::() { - 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(()) } diff --git a/tests/tests/regression_tests.rs b/tests/tests/regression_tests.rs index 74ce87b9c..816e359fb 100644 --- a/tests/tests/regression_tests.rs +++ b/tests/tests/regression_tests.rs @@ -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), diff --git a/tests/tests/swfs/avm2/goto_methods/output.txt b/tests/tests/swfs/avm2/goto_methods/output.txt new file mode 100644 index 000000000..d19d9b8ca --- /dev/null +++ b/tests/tests/swfs/avm2/goto_methods/output.txt @@ -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 diff --git a/tests/tests/swfs/avm2/goto_methods/test.fla b/tests/tests/swfs/avm2/goto_methods/test.fla new file mode 100644 index 000000000..48d4cb999 Binary files /dev/null and b/tests/tests/swfs/avm2/goto_methods/test.fla differ diff --git a/tests/tests/swfs/avm2/goto_methods/test.swf b/tests/tests/swfs/avm2/goto_methods/test.swf new file mode 100644 index 000000000..03639f1e3 Binary files /dev/null and b/tests/tests/swfs/avm2/goto_methods/test.swf differ