diff --git a/src/engine/timer.ts b/src/engine/timer.ts index 43a37d20..fefab4d0 100644 --- a/src/engine/timer.ts +++ b/src/engine/timer.ts @@ -153,7 +153,9 @@ export class Timer { */ public off(action: () => void) { const index = this._callbacks.indexOf(action); - this._callbacks.splice(index, 1); + if (index > -1) { + this._callbacks.splice(index, 1); + } } /** * Updates the timer after a certain number of milliseconds have elapsed. This is used internally by the engine. diff --git a/src/spec/vitest/timer-spec.ts b/src/spec/vitest/timer-spec.ts index 76e6281e..40f5ce59 100644 --- a/src/spec/vitest/timer-spec.ts +++ b/src/spec/vitest/timer-spec.ts @@ -528,6 +528,32 @@ describe('A Timer', () => { expect(count).toBe(1); }); + it('does not remove last callback when removing non-existent callback', () => { + const callback1 = vi.fn(); + const callback2 = vi.fn(); + const nonExistentCallback = vi.fn(); + + const timer = new ex.Timer({ + interval: 100, + repeats: true + }); + + scene.add(timer); + timer.start(); + + timer.on(callback1); + timer.on(callback2); + + // Try to remove callback that was never added + timer.off(nonExistentCallback); + + // Both original callbacks should still fire + scene.update(engine, 100); + + expect(callback1).toHaveBeenCalledTimes(1); + expect(callback2).toHaveBeenCalledTimes(1); + }); + it('can be initialized with random time range', () => { const timer = new ex.Timer({ interval: 100,