Skip to content

Commit

Permalink
Fix setTimeout/setInterval to return a numeric ID
Browse files Browse the repository at this point in the history
  • Loading branch information
alvarorahul authored and domenic committed Jan 15, 2016
1 parent 28f00b3 commit f53876a
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 20 deletions.
37 changes: 17 additions & 20 deletions lib/jsdom/browser/Window.js
Expand Up @@ -50,7 +50,7 @@ function Window(options) {
// vm initialization is defered until script processing is activated (in level1/core)
this._globalProxy = this;

this.__timers = [];
this.__timers = Object.create(null);

// Set up the window as if it's a top level window.
// If it's not, then references will be corrected by frame/iframe code.
Expand Down Expand Up @@ -133,11 +133,13 @@ function Window(options) {

///// METHODS

let latestTimerId = 0;

this.setTimeout = function (fn, ms) {
return startTimer(window, setTimeout, clearTimeout, fn, ms);
return startTimer(window, setTimeout, clearTimeout, latestTimerId++, fn, ms);
};
this.setInterval = function (fn, ms) {
return startTimer(window, setInterval, clearInterval, fn, ms);
return startTimer(window, setInterval, clearInterval, latestTimerId++, fn, ms);
};
this.clearInterval = stopTimer.bind(this, window);
this.clearTimeout = stopTimer.bind(this, window);
Expand Down Expand Up @@ -402,29 +404,24 @@ function matchesDontThrow(el, selector) {
}
}

function startTimer(window, startFn, stopFn, callback, ms) {
function startTimer(window, startFn, stopFn, timerId, callback, ms) {
const res = startFn(callback, ms);
window.__timers.push([res, stopFn]);
return res;
window.__timers[timerId] = [res, stopFn];
return timerId;
}

function stopTimer(window, id) {
if (typeof id === "undefined") {
return;
}
for (const i in window.__timers) {
if (window.__timers[i][0] === id) {
window.__timers[i][1].call(window, id);
window.__timers.splice(i, 1);
break;
}
const timer = window.__timers[id];
if (timer) {
timer[1].call(window, timer[0]);
delete window.__timers[id];
}
}

function stopAllTimers(window) {
for (const t of window.__timers) {
t[1].call(window, t[0]);
}
window.__timers = [];
Object.keys(window.__timers).forEach(key => {
const timer = window.__timers[key];
timer[1].call(window, timer[0]);
});
window.__timers = Object.create(null);
}

@@ -0,0 +1,40 @@
<!doctype html>
<title>Handles returned by setTimeout and setInterval</title>
<link rel="author" title="Alvaro Dias" href="mailto:alvarorahul@gmail.com">
<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-windowtimers-settimeout">
<link rel="help" href="https://heycam.github.io/webidl/#es-operations">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script>
"use strict";

async_test(t => {
const a = setTimeout(() => {
// shouldn't execute since we clear immediately
assert_true(false);
}, 50);
clearTimeout(a);

let c;

const b = setTimeout(() => {
// this callback should execute since we haven't cleared the timeout
const d = setInterval(() => {
clearInterval(d);
t.done();
}, 50);

assert_equals(d, c + 1); // since we created the interval after the handle c
}, 50);
assert_equals(b, a + 1);

c = setInterval(() => {
// shouldn't execute since we clear immediately
assert_true(false);
}, 50);
clearInterval(c);
assert_equals(c, b + 1);

}, "setTimeout and setInterval should return numeric handles which increment");
</script>

0 comments on commit f53876a

Please sign in to comment.