From 12bad698716dec974a5a675225d69dddbe13a413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Berson?= Date: Wed, 11 Apr 2018 17:49:07 +0200 Subject: [PATCH] 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 Reviewed-By: Ruben Bridgewater Reviewed-By: Jeremiah Senkpiel Reviewed-By: Tiancheng "Timothy" Gu --- doc/api/timers.md | 4 ++-- lib/timers.js | 11 +++++------ ...timers-clear-timeout-interval-equivalent.js | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 test/parallel/test-timers-clear-timeout-interval-equivalent.js diff --git a/doc/api/timers.md b/doc/api/timers.md index 9c455552b1454c..0cc535352a0697 100644 --- a/doc/api/timers.md +++ b/doc/api/timers.md @@ -56,8 +56,8 @@ Returns a reference to the `Immediate`. ## Class: Timeout This object is created internally and is returned from [`setTimeout()`][] and -[`setInterval()`][]. It can be passed to [`clearTimeout()`][] or -[`clearInterval()`][] (respectively) in order to cancel the scheduled actions. +[`setInterval()`][]. It can be passed to either [`clearTimeout()`][] or +[`clearInterval()`][] in order to cancel the scheduled actions. By default, when a timer is scheduled using either [`setTimeout()`][] or [`setInterval()`][], the Node.js event loop will continue running as long as the diff --git a/lib/timers.js b/lib/timers.js index 88fd31ad4ccdb7..ad00ede974895f 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -496,14 +496,13 @@ exports.setInterval = function(callback, repeat, arg1, arg2, arg3) { return timeout; }; -exports.clearInterval = function(timer) { - if (timer && timer._repeat) { - timer._repeat = null; - clearTimeout(timer); - } +exports.clearInterval = function clearInterval(timer) { + // clearTimeout and clearInterval can be used to clear timers created from + // both setTimeout and setInterval, as specified by HTML Living Standard: + // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-setinterval + clearTimeout(timer); }; - function unrefdHandle(timer, now) { try { // Don't attempt to call the callback if it is not a function. diff --git a/test/parallel/test-timers-clear-timeout-interval-equivalent.js b/test/parallel/test-timers-clear-timeout-interval-equivalent.js new file mode 100644 index 00000000000000..94611b7070960e --- /dev/null +++ b/test/parallel/test-timers-clear-timeout-interval-equivalent.js @@ -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);