diff --git a/lib/common/timers.ts b/lib/common/timers.ts index 91f750d5f..bdf2378b6 100644 --- a/lib/common/timers.ts +++ b/lib/common/timers.ts @@ -19,14 +19,21 @@ export function patchTimer(window: any, setName: string, cancelName: string, nam setName += nameSuffix; cancelName += nameSuffix; + const tasksByHandleId: Object = {}; + function scheduleTask(task: Task) { const data = task.data; - data.args[0] = task.invoke; + data.args[0] = function() { + task.invoke.apply(this, arguments); + delete tasksByHandleId[data.handleId]; + }; data.handleId = setNative.apply(window, data.args); + tasksByHandleId[data.handleId] = task; return task; } function clearTask(task: Task) { + delete tasksByHandleId[(task.data).handleId]; return clearNative((task.data).handleId); } @@ -60,6 +67,9 @@ export function patchTimer(window: any, setName: string, cancelName: string, nam clearNative = patchMethod(window, cancelName, (delegate: Function) => function(self: any, args: any[]) { var task: Task = args[0]; + if (task && typeof task === 'number') { + task = tasksByHandleId[task]; + } if (task && typeof task.type === 'string') { if (task.cancelFn && task.data.isPeriodic || task.runCount === 0) { // Do not cancel already canceled functions diff --git a/test/common/setTimeout.spec.ts b/test/common/setTimeout.spec.ts index cf7e98256..e58ac1a84 100644 --- a/test/common/setTimeout.spec.ts +++ b/test/common/setTimeout.spec.ts @@ -102,6 +102,27 @@ describe('setTimeout', function() { expect(typeof(cancelId.toString())).toBe('number'); }); + it('should allow cancelation by numeric timeout Id', function (done) { + // Node returns complex object from setTimeout, ignore this test. + if (isNode) { + done(); + return; + } + + const testZone = Zone.current.fork(Zone['wtfZoneSpec']).fork({ name: 'TestZone' }); + testZone.run(() => { + const spy = jasmine.createSpy('spy'); + const task: Task = setTimeout(spy, 0); + const cancelId: number = task; + clearTimeout(0 + cancelId); + setTimeout(function () { + expect(spy).not.toHaveBeenCalled(); + expect(task.runCount).toEqual(-1); + done(); + }); + }); + }); + it('should pass invalid values through', function() { clearTimeout(null); clearTimeout({});