events: _events to object and undefined not null

By making sure the _events is always an object there is one less check
that needs to be performed by emit.

Use undefined instead of null. typeof checks are a lot faster than
isArray.

There are a few places where the this._events check cannot be removed
because it is possible for the user to call those methods after using
utils.extend to create their own EventEmitter, but before it has
actually been instantiated.
This commit is contained in:
Trevor Norris 2013-02-26 09:47:36 -08:00 committed by isaacs
parent b3ea8443bd
commit 4f7f8bbdf8
4 changed files with 20 additions and 18 deletions

View File

@ -19,7 +19,6 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var isArray = Array.isArray;
var domain;
exports.usingDomains = false;
@ -33,7 +32,7 @@ function EventEmitter() {
this.domain = domain.active;
}
}
this._events = this._events || null;
this._events = this._events || {};
this._maxListeners = this._maxListeners || defaultMaxListeners;
}
exports.EventEmitter = EventEmitter;
@ -57,8 +56,9 @@ var PROCESS;
EventEmitter.prototype.emit = function(type) {
// If there is no 'error' event listener then throw.
if (type === 'error') {
if (!this._events || !this._events.error ||
(isArray(this._events.error) && !this._events.error.length)) {
if (!this._events.error ||
(typeof this._events.error === 'object' &&
!this._events.error.length)) {
if (this.domain) {
var er = arguments[1];
er.domainEmitter = this;
@ -77,7 +77,6 @@ EventEmitter.prototype.emit = function(type) {
}
}
if (!this._events) return false;
var handler = this._events[type];
if (!handler) return false;
@ -111,7 +110,7 @@ EventEmitter.prototype.emit = function(type) {
}
return true;
} else if (isArray(handler)) {
} else if (typeof handler === 'object') {
if (this.domain) {
PROCESS = PROCESS || process;
if (this !== PROCESS) {
@ -153,7 +152,7 @@ EventEmitter.prototype.addListener = function(type, listener) {
if (!this._events[type]) {
// Optimize the case of one listener. Don't need the extra array object.
this._events[type] = listener;
} else if (isArray(this._events[type])) {
} else if (typeof this._events[type] === 'object') {
// If we've already got an array, just append.
this._events[type].push(listener);
@ -165,7 +164,7 @@ EventEmitter.prototype.addListener = function(type, listener) {
}
// Check for listener leak
if (isArray(this._events[type]) && !this._events[type].warned) {
if (typeof this._events[type] === 'object' && !this._events[type].warned) {
var m;
m = this._maxListeners;
@ -219,11 +218,11 @@ EventEmitter.prototype.removeListener = function(type, listener) {
if (list === listener ||
(typeof list.listener === 'function' && list.listener === listener)) {
this._events[type] = null;
this._events[type] = undefined;
if (this._events.removeListener)
this.emit('removeListener', type, listener);
} else if (isArray(list)) {
} else if (typeof list === 'object') {
for (i = 0; i < length; i++) {
if (list[i] === listener ||
(list[i].listener && list[i].listener === listener)) {
@ -237,7 +236,7 @@ EventEmitter.prototype.removeListener = function(type, listener) {
if (list.length === 1) {
list.length = 0;
this._events[type] = null;
this._events[type] = undefined;
} else {
list.splice(position, 1);
}
@ -261,9 +260,9 @@ EventEmitter.prototype.removeAllListeners = function(type) {
// not listening for removeListener, no need to emit
if (!this._events.removeListener) {
if (arguments.length === 0)
this._events = null;
this._events = {};
else if (this._events[type])
this._events[type] = null;
this._events[type] = undefined;
return this;
}
@ -274,7 +273,7 @@ EventEmitter.prototype.removeAllListeners = function(type) {
this.removeAllListeners(key);
}
this.removeAllListeners('removeListener');
this._events = null;
this._events = {};
return this;
}
@ -287,7 +286,7 @@ EventEmitter.prototype.removeAllListeners = function(type) {
while (listeners.length)
this.removeListener(type, listeners[listeners.length - 1]);
}
this._events[type] = null;
this._events[type] = undefined;
return this;
};

View File

@ -2477,6 +2477,9 @@ Handle<Object> SetupProcessObject(int argc, char *argv[]) {
3);
process->Set(String::NewSymbol("_tickInfoBox"), info_box);
// pre-set _events object for faster emit checks
process->Set(String::NewSymbol("_events"), Object::New());
return process;
}

View File

@ -33,7 +33,7 @@ var fl; // foo listeners
fl = e.listeners('foo');
assert(Array.isArray(fl));
assert(fl.length === 0);
assert.equal(e._events, null);
assert.deepEqual(e._events, {});
e.on('foo', assert.fail);
fl = e.listeners('foo');

View File

@ -25,6 +25,6 @@ var events = require('events');
var e = new events.EventEmitter;
assert.strictEqual(e._events, null);
assert.deepEqual(e._events, {});
e.setMaxListeners(5);
assert.strictEqual(e._events, null);
assert.deepEqual(e._events, {});