Skip to content

Commit 98609fc

Browse files
committed
timers: do not use user object call/apply
Timers should work even if the user has monkey-patched `.call()` and `.apply()` to undesirable values. PR-URL: #12960 Ref: #12956 Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Jeremiah Senkpiel <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Joyee Cheung <[email protected]> Reviewed-By: Rich Trott <[email protected]>
1 parent 7c3a23b commit 98609fc

File tree

2 files changed

+46
-6
lines changed

2 files changed

+46
-6
lines changed

lib/timers.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -485,20 +485,20 @@ function ontimeout(timer) {
485485
if (typeof callback !== 'function')
486486
return promiseResolve(callback, args[0]);
487487
if (!args)
488-
callback.call(timer);
488+
timer._onTimeout();
489489
else {
490490
switch (args.length) {
491491
case 1:
492-
callback.call(timer, args[0]);
492+
timer._onTimeout(args[0]);
493493
break;
494494
case 2:
495-
callback.call(timer, args[0], args[1]);
495+
timer._onTimeout(args[0], args[1]);
496496
break;
497497
case 3:
498-
callback.call(timer, args[0], args[1], args[2]);
498+
timer._onTimeout(args[0], args[1], args[2]);
499499
break;
500500
default:
501-
callback.apply(timer, args);
501+
Function.prototype.apply.call(callback, timer, args);
502502
}
503503
}
504504
if (timer._repeat)
@@ -806,7 +806,7 @@ function runCallback(timer) {
806806
return timer._callback(argv[0], argv[1], argv[2]);
807807
// more than 3 arguments run slower with .apply
808808
default:
809-
return timer._callback.apply(timer, argv);
809+
return Function.prototype.apply.call(timer._callback, timer, argv);
810810
}
811811
}
812812

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Make sure `setTimeout()` and friends don't throw if the user-supplied
2+
// function has .call() and .apply() monkey-patched to undesirable values.
3+
4+
// Refs: https://github.com/nodejs/node/issues/12956
5+
6+
'use strict';
7+
8+
const common = require('../common');
9+
10+
{
11+
const fn = common.mustCall(10);
12+
fn.call = 'not a function';
13+
fn.apply = 'also not a function';
14+
setTimeout(fn, 1);
15+
setTimeout(fn, 1, 'oneArg');
16+
setTimeout(fn, 1, 'two', 'args');
17+
setTimeout(fn, 1, 'three', '(3)', 'args');
18+
setTimeout(fn, 1, 'more', 'than', 'three', 'args');
19+
20+
setImmediate(fn, 1);
21+
setImmediate(fn, 1, 'oneArg');
22+
setImmediate(fn, 1, 'two', 'args');
23+
setImmediate(fn, 1, 'three', '(3)', 'args');
24+
setImmediate(fn, 1, 'more', 'than', 'three', 'args');
25+
}
26+
27+
{
28+
const testInterval = (...args) => {
29+
const fn = common.mustCall(() => { clearInterval(interval); });
30+
fn.call = 'not a function';
31+
fn.apply = 'also not a function';
32+
const interval = setInterval(fn, 1, ...args);
33+
};
34+
35+
testInterval();
36+
testInterval('oneArg');
37+
testInterval('two', 'args');
38+
testInterval('three', '(3)', 'args');
39+
testInterval('more', 'than', 'three', 'args');
40+
}

0 commit comments

Comments
 (0)