diff --git a/lib/timers.js b/lib/timers.js index e3e6428750..e5c0c9eaef 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -173,8 +173,9 @@ exports.active = function(item) { */ -exports.setTimeout = function(callback, after) { - var timer; +exports.setTimeout = function(callback, after, arg1, arg2, arg3) { + var timer, i, args; + var len = arguments.length; after *= 1; // coalesce to number or NaN @@ -184,22 +185,38 @@ exports.setTimeout = function(callback, after) { timer = new Timeout(after); - if (arguments.length <= 2) { - timer._onTimeout = callback; - } else { - /* - * Sometimes setTimeout is called with arguments, EG - * - * setTimeout(callback, 2000, "hello", "world") - * - * If that's the case we need to call the callback with - * those args. The overhead of an extra closure is not - * desired in the normal case. - */ - var args = Array.prototype.slice.call(arguments, 2); - timer._onTimeout = function() { - callback.apply(timer, args); - }; + switch (len) { + // fast cases + case 0: + case 1: + case 2: + timer._onTimeout = callback; + break; + case 3: + timer._onTimeout = function() { + callback.call(timer, arg1); + }; + break; + case 4: + timer._onTimeout = function() { + callback.call(timer, arg1, arg2); + }; + break; + case 5: + timer._onTimeout = function() { + callback.call(timer, arg1, arg2, arg3); + }; + break; + // slow case + default: + args = new Array(len - 2); + for (i = 2; i < len; i++) + args[i - 2] = arguments[i]; + + timer._onTimeout = function() { + callback.apply(timer, args); + }; + break; } if (process.domain) timer.domain = process.domain; @@ -222,17 +239,24 @@ exports.clearTimeout = function(timer) { }; -exports.setInterval = function(callback, repeat) { +exports.setInterval = function(callback, repeat, arg1, arg2, arg3) { repeat *= 1; // coalesce to number or NaN if (!(repeat >= 1 && repeat <= TIMEOUT_MAX)) { repeat = 1; // schedule on next tick, follows browser behaviour } + var args, i; var timer = new Timeout(repeat); - var args = Array.prototype.slice.call(arguments, 2); + var len = arguments.length - 2; timer._onTimeout = wrapper; timer._repeat = true; + // Initialize args once for repeated invocation of slow case below + if (len > 3) { + args = new Array(len); + for (i = 0; i < len; i++) + args[i] = arguments[i + 2]; + } if (process.domain) timer.domain = process.domain; exports.active(timer); @@ -240,7 +264,25 @@ exports.setInterval = function(callback, repeat) { return timer; function wrapper() { - callback.apply(this, args); + switch (len) { + // fast cases + case 0: + callback.call(this); + break; + case 1: + callback.call(this, arg1); + break; + case 2: + callback.call(this, arg1, arg2); + break; + case 3: + callback.call(this, arg1, arg2, arg3); + break; + // slow case + default: + callback.apply(this, args); + break; + } // If callback called clearInterval(). if (timer._repeat === false) return; // If timer is unref'd (or was - it's permanently removed from the list.) @@ -361,22 +403,44 @@ Immediate.prototype._idleNext = undefined; Immediate.prototype._idlePrev = undefined; -exports.setImmediate = function(callback) { +exports.setImmediate = function(callback, arg1, arg2, arg3) { + var i, args; + var len = arguments.length; var immediate = new Immediate(); - var args, index; L.init(immediate); - immediate._onImmediate = callback; - - if (arguments.length > 1) { - args = []; - for (index = 1; index < arguments.length; index++) - args.push(arguments[index]); - - immediate._onImmediate = function() { - callback.apply(immediate, args); - }; + switch (len) { + // fast cases + case 0: + case 1: + immediate._onImmediate = callback; + break; + case 2: + immediate._onImmediate = function() { + callback.call(immediate, arg1); + }; + break; + case 3: + immediate._onImmediate = function() { + callback.call(immediate, arg1, arg2); + }; + break; + case 4: + immediate._onImmediate = function() { + callback.call(immediate, arg1, arg2, arg3); + }; + break; + // slow case + default: + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + + immediate._onImmediate = function() { + callback.apply(immediate, args); + }; + break; } if (!process._needImmediateCallback) {