diff --git a/core/src/avm2/globals/flash/utils/Timer.as b/core/src/avm2/globals/flash/utils/Timer.as index b94b483f1..c53e78b16 100644 --- a/core/src/avm2/globals/flash/utils/Timer.as +++ b/core/src/avm2/globals/flash/utils/Timer.as @@ -49,7 +49,7 @@ package flash.utils { } public function get running(): Boolean { - return this._timerId != -1 && (this.repeatCount == 0 || this._currentCount < this._repeatCount); + return this._timerId != -1; } public function reset():void { @@ -65,6 +65,8 @@ package flash.utils { this._currentCount += 1; this.dispatchEvent(new TimerEvent(TimerEvent.TIMER, false, false)); if (this.repeatCount != 0 && this._currentCount >= this._repeatCount) { + // This will make 'running' return false in a TIMER_COMPLETE event handler + this._timerId = -1; this.dispatchEvent(new TimerEvent(TimerEvent.TIMER_COMPLETE, false, false)); return true; } diff --git a/core/src/avm2/globals/flash/utils/timer.rs b/core/src/avm2/globals/flash/utils/timer.rs index 3e98b9a9e..b13fc1add 100644 --- a/core/src/avm2/globals/flash/utils/timer.rs +++ b/core/src/avm2/globals/flash/utils/timer.rs @@ -64,6 +64,9 @@ pub fn start<'gc>( activation, )? .coerce_to_object(activation)?; + // Note - we deliberately do *not* check if currentCount is less than repeatCount. + // Calling 'start' on a timer that has currentCount >= repeatCount will tick exactly + // once, and then stop immediately. This is handeld by Timer.onUpdate let id = activation.context.timers.add_timer( TimerCallback::Avm2Callback { closure: on_update, diff --git a/tests/tests/swfs/avm2/timer_finished/Test.as b/tests/tests/swfs/avm2/timer_finished/Test.as new file mode 100644 index 000000000..9b3f592d1 --- /dev/null +++ b/tests/tests/swfs/avm2/timer_finished/Test.as @@ -0,0 +1,31 @@ +package { + import flash.events.TimerEvent; + import flash.utils.Timer; + import flash.utils.setTimeout; + + public class Test { + public function Test() { + var timer = new Timer(100, 2); + timer.addEventListener(TimerEvent.TIMER, function(e) { + trace("TimerEvent.TIMER: timer.running=" + timer.running + " timer.currentCount=" + timer.currentCount + " timer.repeatCount=" + timer.repeatCount); + }); + timer.addEventListener(TimerEvent.TIMER_COMPLETE, function(e) { + trace("TimerEvent.TIMER_COMPLETE: timer.running=" + timer.running + " timer.currentCount=" + timer.currentCount + " timer.repeatCount=" + timer.repeatCount); + }) + timer.start(); + + setTimeout(function() { + trace("After 300ms: timer.running=" + timer.running + " timer.currentCount=" + timer.currentCount + " timer.repeatCount=" + timer.repeatCount); + trace("Starting timer again"); + timer.start(); + + setTimeout(function() { + trace("After 200ms: timer.running=" + timer.running + " timer.currentCount=" + timer.currentCount + " timer.repeatCount=" + timer.repeatCount); + trace("Stopping/Starting timer again"); + timer.stop(); + timer.start(); + }, 200); + }, 300); + } + } +} \ No newline at end of file diff --git a/tests/tests/swfs/avm2/timer_finished/output.txt b/tests/tests/swfs/avm2/timer_finished/output.txt new file mode 100644 index 000000000..88326e467 --- /dev/null +++ b/tests/tests/swfs/avm2/timer_finished/output.txt @@ -0,0 +1,11 @@ +TimerEvent.TIMER: timer.running=true timer.currentCount=1 timer.repeatCount=2 +TimerEvent.TIMER: timer.running=true timer.currentCount=2 timer.repeatCount=2 +TimerEvent.TIMER_COMPLETE: timer.running=false timer.currentCount=2 timer.repeatCount=2 +After 300ms: timer.running=false timer.currentCount=2 timer.repeatCount=2 +Starting timer again +TimerEvent.TIMER: timer.running=true timer.currentCount=3 timer.repeatCount=2 +TimerEvent.TIMER_COMPLETE: timer.running=false timer.currentCount=3 timer.repeatCount=2 +After 200ms: timer.running=false timer.currentCount=3 timer.repeatCount=2 +Stopping/Starting timer again +TimerEvent.TIMER: timer.running=true timer.currentCount=4 timer.repeatCount=2 +TimerEvent.TIMER_COMPLETE: timer.running=false timer.currentCount=4 timer.repeatCount=2 diff --git a/tests/tests/swfs/avm2/timer_finished/test.fla b/tests/tests/swfs/avm2/timer_finished/test.fla new file mode 100644 index 000000000..38ec3616b Binary files /dev/null and b/tests/tests/swfs/avm2/timer_finished/test.fla differ diff --git a/tests/tests/swfs/avm2/timer_finished/test.swf b/tests/tests/swfs/avm2/timer_finished/test.swf new file mode 100644 index 000000000..259a1d98b Binary files /dev/null and b/tests/tests/swfs/avm2/timer_finished/test.swf differ diff --git a/tests/tests/swfs/avm2/timer_finished/test.toml b/tests/tests/swfs/avm2/timer_finished/test.toml new file mode 100644 index 000000000..3b88eb49b --- /dev/null +++ b/tests/tests/swfs/avm2/timer_finished/test.toml @@ -0,0 +1 @@ +num_frames = 16