Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Commit

Permalink
fix: support clearing the timeouts with numeric IDs
Browse files Browse the repository at this point in the history
Fixes #461
  • Loading branch information
platosha authored and mhevery committed Oct 12, 2016
1 parent 63bca67 commit fea6d68
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 2 deletions.
11 changes: 9 additions & 2 deletions lib/common/timers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,21 @@ export function patchTimer(window: any, setName: string, cancelName: string, nam
setName += nameSuffix;
cancelName += nameSuffix;

const tasksByHandleId: {[id: number]: Task} = {};

function scheduleTask(task: Task) {
const data = <TimerOptions>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[(<TimerOptions>task.data).handleId];
return clearNative((<TimerOptions>task.data).handleId);
}

Expand Down Expand Up @@ -59,7 +66,7 @@ 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];
var task: Task = typeof args[0] === 'number' ? tasksByHandleId[args[0]] : args[0];
if (task && typeof task.type === 'string') {
if (task.cancelFn && task.data.isPeriodic || task.runCount === 0) {
// Do not cancel already canceled functions
Expand Down
21 changes: 21 additions & 0 deletions test/common/setTimeout.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <any>setTimeout(spy, 0);
const cancelId: number = <any>task;
clearTimeout(0 + cancelId);
setTimeout(function () {
expect(spy).not.toHaveBeenCalled();
expect(task.runCount).toEqual(-1);
done();
}, 1);
});
});

it('should pass invalid values through', function() {
clearTimeout(null);
clearTimeout(<any>{});
Expand Down

0 comments on commit fea6d68

Please sign in to comment.