Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Commit

Permalink
Revert "events: Don't crash on events named __proto__"
Browse files Browse the repository at this point in the history
Unfortunately, it's just too slow to do this in events.js.  Users will
just have to live with not having events named __proto__ or toString.

This reverts commit b48e303.
  • Loading branch information
isaacs committed Jan 17, 2013
1 parent 1528de2 commit b7d76a1
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 86 deletions.
67 changes: 31 additions & 36 deletions lib/events.js
Expand Up @@ -53,8 +53,8 @@ var PROCESS;
EventEmitter.prototype.emit = function(type) {
// If there is no 'error' event listener then throw.
if (type === 'error') {
if (!this._events || !this._events.everror ||
(isArray(this._events.everror) && !this._events.everror.length))
if (!this._events || !this._events.error ||
(isArray(this._events.error) && !this._events.error.length))
{
if (this.domain) {
var er = arguments[1];
Expand All @@ -75,8 +75,7 @@ EventEmitter.prototype.emit = function(type) {
}

if (!this._events) return false;
var evtype = 'ev' + type;
var handler = this._events[evtype];
var handler = this._events[type];
if (!handler) return false;

if (typeof handler == 'function') {
Expand Down Expand Up @@ -143,37 +142,36 @@ EventEmitter.prototype.addListener = function(type, listener) {

// To avoid recursion in the case that type == "newListener"! Before
// adding it to the listeners, first emit "newListener".
if (this._events.evnewListener) {
if (this._events.newListener) {
this.emit('newListener', type, typeof listener.listener === 'function' ?
listener.listener : listener);
}

var evtype = 'ev' + type;
if (!this._events[evtype]) {
if (!this._events[type]) {
// Optimize the case of one listener. Don't need the extra array object.
this._events[evtype] = listener;
} else if (isArray(this._events[evtype])) {
this._events[type] = listener;
} else if (isArray(this._events[type])) {

// If we've already got an array, just append.
this._events[evtype].push(listener);
this._events[type].push(listener);

} else {
// Adding the second element, need to change to array.
this._events[evtype] = [this._events[evtype], listener];
this._events[type] = [this._events[type], listener];

}

// Check for listener leak
if (isArray(this._events[evtype]) && !this._events[evtype].warned) {
if (isArray(this._events[type]) && !this._events[type].warned) {
var m;
m = this._maxListeners;

if (m && m > 0 && this._events[evtype].length > m) {
this._events[evtype].warned = true;
if (m && m > 0 && this._events[type].length > m) {
this._events[type].warned = true;
console.error('(node) warning: possible EventEmitter memory ' +
'leak detected. %d listeners added. ' +
'Use emitter.setMaxListeners() to increase limit.',
this._events[evtype].length);
this._events[type].length);
console.trace();
}
}
Expand Down Expand Up @@ -206,11 +204,10 @@ EventEmitter.prototype.removeListener = function(type, listener) {
throw new Error('removeListener only takes instances of Function');
}

var evtype = 'ev' + type;
// does not use listeners(), so no side effect of creating _events[evtype]
if (!this._events || !this._events[evtype]) return this;
// does not use listeners(), so no side effect of creating _events[type]
if (!this._events || !this._events[type]) return this;

var list = this._events[evtype];
var list = this._events[type];

if (isArray(list)) {
var position = -1;
Expand All @@ -226,17 +223,17 @@ EventEmitter.prototype.removeListener = function(type, listener) {
if (position < 0) return this;
list.splice(position, 1);
if (list.length == 0)
this._events[evtype] = null;
this._events[type] = null;

if (this._events.evremoveListener) {
if (this._events.removeListener) {
this.emit('removeListener', type, listener);
}
} else if (list === listener ||
(list.listener && list.listener === listener))
{
this._events[evtype] = null;
this._events[type] = null;

if (this._events.evremoveListener) {
if (this._events.removeListener) {
this.emit('removeListener', type, listener);
}
}
Expand All @@ -248,28 +245,27 @@ EventEmitter.prototype.removeAllListeners = function(type) {
if (!this._events) return this;

// fast path
if (!this._events.evremoveListener) {
if (!this._events.removeListener) {
if (arguments.length === 0) {
this._events = {};
} else if (type && this._events && this._events['ev' + type]) {
this._events['ev' + type] = null;
} else if (type && this._events && this._events[type]) {
this._events[type] = null;
}
return this;
}

// slow(ish) path, emit 'removeListener' events for all removals
if (arguments.length === 0) {
for (var key in this._events) {
if (key === 'evremoveListener') continue;
this.removeAllListeners(key.slice(2));
if (key === 'removeListener') continue;
this.removeAllListeners(key);
}
this.removeAllListeners('removeListener');
this._events = {};
return this;
}

var evtype = 'ev' + type;
var listeners = this._events[evtype];
var listeners = this._events[type];
if (isArray(listeners)) {
while (listeners.length) {
// LIFO order
Expand All @@ -278,16 +274,15 @@ EventEmitter.prototype.removeAllListeners = function(type) {
} else if (listeners) {
this.removeListener(type, listeners);
}
this._events[evtype] = null;
this._events[type] = null;

return this;
};

EventEmitter.prototype.listeners = function(type) {
var evtype = 'ev' + type;
if (!this._events || !this._events[evtype]) return [];
if (!isArray(this._events[evtype])) {
return [this._events[evtype]];
if (!this._events || !this._events[type]) return [];
if (!isArray(this._events[type])) {
return [this._events[type]];
}
return this._events[evtype].slice(0);
return this._events[type].slice(0);
};
14 changes: 7 additions & 7 deletions test/simple/test-event-emitter-check-listener-leaks.js
Expand Up @@ -29,30 +29,30 @@ var e = new events.EventEmitter();
for (var i = 0; i < 10; i++) {
e.on('default', function() {});
}
assert.ok(!e._events.evdefault.hasOwnProperty('warned'));
assert.ok(!e._events['default'].hasOwnProperty('warned'));
e.on('default', function() {});
assert.ok(e._events.evdefault.warned);
assert.ok(e._events['default'].warned);

// specific
e.setMaxListeners(5);
for (var i = 0; i < 5; i++) {
e.on('specific', function() {});
}
assert.ok(!e._events.evspecific.hasOwnProperty('warned'));
assert.ok(!e._events['specific'].hasOwnProperty('warned'));
e.on('specific', function() {});
assert.ok(e._events.evspecific.warned);
assert.ok(e._events['specific'].warned);

// only one
e.setMaxListeners(1);
e.on('only one', function() {});
assert.ok(!e._events['evonly one'].hasOwnProperty('warned'));
assert.ok(!e._events['only one'].hasOwnProperty('warned'));
e.on('only one', function() {});
assert.ok(e._events['evonly one'].hasOwnProperty('warned'));
assert.ok(e._events['only one'].hasOwnProperty('warned'));

// unlimited
e.setMaxListeners(0);
for (var i = 0; i < 1000; i++) {
e.on('unlimited', function() {});
}
assert.ok(!e._events['evunlimited'].hasOwnProperty('warned'));
assert.ok(!e._events['unlimited'].hasOwnProperty('warned'));

12 changes: 6 additions & 6 deletions test/simple/test-event-emitter-listeners-side-effects.js
Expand Up @@ -37,21 +37,21 @@ assert.equal(e._events, null);

e.on('foo', assert.fail);
fl = e.listeners('foo');
assert(e._events.evfoo === assert.fail);
assert(e._events.foo === assert.fail);
assert(Array.isArray(fl));
assert(fl.length === 1);
assert(fl[0] === assert.fail);

e.listeners('bar');
assert(!e._events.hasOwnProperty('evbar'));
assert(!e._events.hasOwnProperty('bar'));

e.on('foo', assert.ok);
fl = e.listeners('foo');

assert(Array.isArray(e._events.evfoo));
assert(e._events.evfoo.length === 2);
assert(e._events.evfoo[0] === assert.fail);
assert(e._events.evfoo[1] === assert.ok);
assert(Array.isArray(e._events.foo));
assert(e._events.foo.length === 2);
assert(e._events.foo[0] === assert.fail);
assert(e._events.foo[1] === assert.ok);

assert(Array.isArray(fl));
assert(fl.length === 2);
Expand Down
37 changes: 0 additions & 37 deletions test/simple/test-event-emitter-prototype-property.js

This file was deleted.

0 comments on commit b7d76a1

Please sign in to comment.