diff --git a/lib/events.js b/lib/events.js index 0cd841b8445a..f07464c5d586 100644 --- a/lib/events.js +++ b/lib/events.js @@ -65,7 +65,7 @@ EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { return this; }; -EventEmitter.prototype.emit = function emit(type) { +EventEmitter.prototype.emit = function emit(type, arg1, arg2) { var er, handler, len, args, i, listeners; if (!this._events) @@ -97,36 +97,50 @@ EventEmitter.prototype.emit = function emit(type) { if (this.domain && this !== process) this.domain.enter(); + len = arguments.length; if (util.isFunction(handler)) { - switch (arguments.length) { + switch (len) { // fast cases case 1: handler.call(this); break; case 2: - handler.call(this, arguments[1]); + handler.call(this, arg1); break; case 3: - handler.call(this, arguments[1], arguments[2]); + handler.call(this, arg1, arg2); break; // slower default: - len = arguments.length; args = new Array(len - 1); for (i = 1; i < len; i++) args[i - 1] = arguments[i]; handler.apply(this, args); } - } else if (util.isObject(handler)) { - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - + } else if (util.isArray(handler)) { listeners = handler.slice(); - len = listeners.length; - for (i = 0; i < len; i++) - listeners[i].apply(this, args); + switch (len) { + // fast cases + case 1: + for (i = 0, len = listeners.length; i < len; i++) + listeners[i].call(this); + break; + case 2: + for (i = 0, len = listeners.length; i < len; i++) + listeners[i].call(this, arg1); + break; + case 3: + for (i = 0, len = listeners.length; i < len; i++) + listeners[i].call(this, arg1, arg2); + break; + // slower + default: + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + for (i = 0, len = listeners.length; i < len; i++) + listeners[i].apply(this, args); + } } if (this.domain && this !== process) diff --git a/lib/timers.js b/lib/timers.js index 3039b49f2c37..c4e22f68a78b 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -217,8 +217,8 @@ exports.active = function(item) { */ -exports.setTimeout = function(callback, after) { - var timer; +exports.setTimeout = function(callback, after, arg1, arg2) { + var timer, i, args, len = arguments.length; after *= 1; // coalesce to number or NaN @@ -228,22 +228,41 @@ 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); - } + /* + * 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. + */ + 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; + // 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); + } } if (process.domain) timer.domain = process.domain; @@ -266,17 +285,21 @@ exports.clearTimeout = function(timer) { }; -exports.setInterval = function(callback, repeat) { +exports.setInterval = function(callback, repeat, arg1, arg2) { repeat *= 1; // coalesce to number or NaN if (!(repeat >= 1 && repeat <= TIMEOUT_MAX)) { repeat = 1; // schedule on next tick, follows browser behaviour } - var timer = new Timeout(repeat); - var args = Array.prototype.slice.call(arguments, 2); + var timer = new Timeout(repeat), len = arguments.length - 2, args, i; timer._onTimeout = wrapper; timer._repeat = true; + if (len > 2) { + 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); @@ -284,7 +307,21 @@ 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; + // slow case + default: + callback.apply(this, args); + } // If callback called clearInterval(). if (timer._repeat === false) return; // If timer is unref'd (or was - it's permanently removed from the list.) @@ -413,22 +450,37 @@ Immediate.prototype._idlePrev = undefined; Immediate.prototype._asyncFlags = 0; -exports.setImmediate = function(callback) { +exports.setImmediate = function(callback, arg1, arg2) { var immediate = new Immediate(); - var args, index; + var i, args, len = arguments.length; 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; + // 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); + }; } if (!process._needImmediateCallback) {