Skip to content
Permalink
Browse files

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 <refack@gmail.com>
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
  • Loading branch information...
Trott committed May 11, 2017
1 parent 7c3a23b commit 98609fc1c4635f02f8f6ef9dd079207a1204b9a1
Showing with 46 additions and 6 deletions.
  1. +6 −6 lib/timers.js
  2. +40 −0 test/parallel/test-timers-user-call.js
@@ -485,20 +485,20 @@ function ontimeout(timer) {
if (typeof callback !== 'function')
return promiseResolve(callback, args[0]);
if (!args)
callback.call(timer);
timer._onTimeout();
else {
switch (args.length) {
case 1:
callback.call(timer, args[0]);
timer._onTimeout(args[0]);
break;
case 2:
callback.call(timer, args[0], args[1]);
timer._onTimeout(args[0], args[1]);
break;
case 3:
callback.call(timer, args[0], args[1], args[2]);
timer._onTimeout(args[0], args[1], args[2]);
break;
default:
callback.apply(timer, args);
Function.prototype.apply.call(callback, timer, args);
}
}
if (timer._repeat)
@@ -806,7 +806,7 @@ function runCallback(timer) {
return timer._callback(argv[0], argv[1], argv[2]);
// more than 3 arguments run slower with .apply
default:
return timer._callback.apply(timer, argv);
return Function.prototype.apply.call(timer._callback, timer, argv);
}
}

@@ -0,0 +1,40 @@
// Make sure `setTimeout()` and friends don't throw if the user-supplied
// function has .call() and .apply() monkey-patched to undesirable values.

// Refs: https://github.com/nodejs/node/issues/12956

'use strict';

const common = require('../common');

{
const fn = common.mustCall(10);
fn.call = 'not a function';
fn.apply = 'also not a function';
setTimeout(fn, 1);
setTimeout(fn, 1, 'oneArg');
setTimeout(fn, 1, 'two', 'args');
setTimeout(fn, 1, 'three', '(3)', 'args');
setTimeout(fn, 1, 'more', 'than', 'three', 'args');

setImmediate(fn, 1);
setImmediate(fn, 1, 'oneArg');
setImmediate(fn, 1, 'two', 'args');
setImmediate(fn, 1, 'three', '(3)', 'args');
setImmediate(fn, 1, 'more', 'than', 'three', 'args');
}

{
const testInterval = (...args) => {
const fn = common.mustCall(() => { clearInterval(interval); });
fn.call = 'not a function';
fn.apply = 'also not a function';
const interval = setInterval(fn, 1, ...args);
};

testInterval();
testInterval('oneArg');
testInterval('two', 'args');
testInterval('three', '(3)', 'args');
testInterval('more', 'than', 'three', 'args');
}

0 comments on commit 98609fc

Please sign in to comment.
You can’t perform that action at this time.