-
Notifications
You must be signed in to change notification settings - Fork 29.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
timers: fix clearInterval to work with timers from setTimeout #19952
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SGTM, just a few small comments.
// * Refs: https://nodejs.org/api/timers.html#timers_class_timeout | ||
|
||
const assert = require('assert'); | ||
const Timer = require('timers'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't import timers
in our timer tests. You can just use the global versions.
|
||
// Disarm timeout with setInterval. | ||
const timeout = Timer.setTimeout(() => { | ||
nbTimersTriggered += 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use common.mustNotCall
instead for both of these.
Timer.clearInterval(timeout); | ||
|
||
// Check that no callback was fired. | ||
setTimeout(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once you convert to use common.mustNotCall
you can just remove this whole block.
// Disarm timeout with setInterval. | ||
const timeout = Timer.setTimeout(() => { | ||
nbTimersTriggered += 1; | ||
}, common.platformTimeout(20)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
common.platformTimeout
isn't necessary. You can also just use 1
for the timeout value since it shouldn't execute regardless.
lib/timers.js
Outdated
// It's allowed to use clearInterval to kill a setTimeout, which has its | ||
// _repeat attribute to `null` already. | ||
if (timer._repeat) { | ||
timer._repeat = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In all honesty, I would almost just go with exports.clearInterval = clearTimeout;
The distinction is pretty meaningless especially since they're now interchangeable. Unsetting _repeat
doesn't do anything. Or we could do:
exports.clearInterval = function clearInterval(timer) {
clearTimeout(timer);
};
Mostly to appease stack traces, etc. with differing function names.
@apapirovski Thank you so much for your review. Is it alright if I amend my commit or should I create another one to implement your suggestions? |
4ac68a0
to
9f7630d
Compare
// 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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we just set it to the same function instead of creating this wrapper?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW I brought up this option for the sake of users who care about the function name for profilers, stack traces and the like. I personally would just go with exports.clearInterval = clearTimeout;
but I'm not certain how other collaborators might feel about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few small nits left. (And yep, amending commits is perfectly fine.)
// * Refs: https://nodejs.org/api/timers.html#timers_class_timeout | ||
|
||
// Disarm interval with clearTimeout. | ||
const interval = setInterval(common.mustNotCall(), common.platformTimeout(20)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: common.platformTimeout(20)
can just become 1
now. We only use common.platformTimeout
when the test is timing sensitive. Since in this test no timeouts will execute — unless it's broken — it doesn't need that extra overhead.
const interval = setInterval(common.mustNotCall(), common.platformTimeout(20)); | ||
clearTimeout(interval); | ||
|
||
// Disarm timeout with setInterval. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/setInterval/clearInterval
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with @apapirovski comments addressed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please set timer._repeat = null;
in clearTimeout
? Thanks!
Also, here's a CI run: https://ci.nodejs.org/job/node-test-pull-request/14210/
// clearInterval and that timers created with setInterval can be disarmed by | ||
// clearTimeout. | ||
// | ||
// This behavior is documented in Node.js' documentation and the HTML Living |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I don't see this behavior noted in the Node.js docs? This PR also doesn't contain doc updates.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can be passed to
clearTimeout()
orclearInterval()
(respectively) in order to cancel the scheduled actions.
Is not the same as "it can be passed to either". I'm impartial to documenting it, but mentions of the docs should be correct. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, I misunderstood the current documentation. Will update it. Thanks!
@Fishrock123 is there a specific reason we want this? To elaborate: |
Thank you for the reviews. I updated with the following changes:
|
9f7630d
to
fd5a7e9
Compare
According to HTML Living Standard, "either method [clearInterval or clearTimeout] can be used to clear timers created by setTimeout() or setInterval()."[1]. The current implementation of clearTimeout is already able to destroy a timer created by setInterval, but not the other way around. Refs: https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-setinterval
fd5a7e9
to
780176e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok seems good to me. I was thinking it was still a function.
I suppose if it was set and the timer somehow got re-enrolled we'd want to keep it anyways (thinking of when we might support extending the timers prototype).
@Fishrock123 Thanks for your review. Let me know if there is anything I can do on this one. |
FWIW I do think this could potentially be |
@apapirovski well in that case the user originally intended to clear the timeout and it was a bug in the users code that it was not cleared. So it seems like a bug fix to me. We can of course run a CITGM to see if anything pops up. |
Or they have some weird structure that stores both timeouts and intervals but only want to clear the intervals. And yes, I know it's far fetched but just pointing it out. We should at least let this bake before back-porting to LTS. |
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: nodejs#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>
@BridgeAR Thank you very much! That was a very interesting experience and I will do it again if I can. I have to say that the documentation as to how to contribute was very detailed. |
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: #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>
Is this something we want to backport to v8.x? |
According to HTML Living Standard, "either method [clearInterval or
clearTimeout] can be used to clear timers created by setTimeout() or
setInterval()."[1].
The current implementation of
clearTimeout
is already able to destroy atimer created by
setInterval
, but not the other way around.Refs: https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-setinterval
Checklist
make -j4 jstest
(UNIX)Affected core subsystem(s)
timers
.