timers: fix clearInterval to work with timers from setTimeout

According to HTML Living Standard, "either method [clearInterval or
clearTimeout] can be used to clear timers created by setTimeout() or
setInterval().".

The current implementation of clearTimeout is already able to destroy a
timer created by setInterval, but not the other way around.

PR-URL: https://github.com/nodejs/node/pull/19952
Refs: https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-setinterval
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
This commit is contained in:
Rémi Berson 2018-04-11 17:49:07 +02:00 committed by Ruben Bridgewater
parent 2b6bb9f588
commit 978e1524bb
No known key found for this signature in database
GPG Key ID: F07496B3EB3C1762
3 changed files with 25 additions and 8 deletions

View File

@ -56,8 +56,8 @@ Returns a reference to the `Immediate`.
## Class: Timeout ## Class: Timeout
This object is created internally and is returned from [`setTimeout()`][] and This object is created internally and is returned from [`setTimeout()`][] and
[`setInterval()`][]. It can be passed to [`clearTimeout()`][] or [`setInterval()`][]. It can be passed to either [`clearTimeout()`][] or
[`clearInterval()`][] (respectively) in order to cancel the scheduled actions. [`clearInterval()`][] in order to cancel the scheduled actions.
By default, when a timer is scheduled using either [`setTimeout()`][] or By default, when a timer is scheduled using either [`setTimeout()`][] or
[`setInterval()`][], the Node.js event loop will continue running as long as the [`setInterval()`][], the Node.js event loop will continue running as long as the

View File

@ -496,14 +496,13 @@ exports.setInterval = function(callback, repeat, arg1, arg2, arg3) {
return timeout; return timeout;
}; };
exports.clearInterval = function(timer) { exports.clearInterval = function clearInterval(timer) {
if (timer && timer._repeat) { // clearTimeout and clearInterval can be used to clear timers created from
timer._repeat = null; // both setTimeout and setInterval, as specified by HTML Living Standard:
clearTimeout(timer); // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-setinterval
} clearTimeout(timer);
}; };
function unrefdHandle(timer, now) { function unrefdHandle(timer, now) {
try { try {
// Don't attempt to call the callback if it is not a function. // Don't attempt to call the callback if it is not a function.

View File

@ -0,0 +1,18 @@
'use strict';
const common = require('../common');
// This test makes sure that timers created with setTimeout can be disarmed by
// clearInterval and that timers created with setInterval can be disarmed by
// clearTimeout.
//
// This behavior is documented in the HTML Living Standard:
//
// * Refs: https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-setinterval
// Disarm interval with clearTimeout.
const interval = setInterval(common.mustNotCall(), 1);
clearTimeout(interval);
// Disarm timeout with clearInterval.
const timeout = setTimeout(common.mustNotCall(), 1);
clearInterval(timeout);