diff --git a/lib/events.js b/lib/events.js index 38422dab0f..5188205d12 100644 --- a/lib/events.js +++ b/lib/events.js @@ -197,7 +197,7 @@ EventEmitter.prototype.removeListener = function(type, listener) { if (list === listener || (typeof list.listener === 'function' && list.listener === listener)) { - this._events[type] = undefined; + delete this._events[type]; if (this._events.removeListener) this.emit('removeListener', type, listener); @@ -215,7 +215,7 @@ EventEmitter.prototype.removeListener = function(type, listener) { if (list.length === 1) { list.length = 0; - this._events[type] = undefined; + delete this._events[type]; } else { list.splice(position, 1); } @@ -238,7 +238,7 @@ EventEmitter.prototype.removeAllListeners = function(type) { if (arguments.length === 0) this._events = {}; else if (this._events[type]) - this._events[type] = undefined; + delete this._events[type]; return this; } @@ -262,7 +262,7 @@ EventEmitter.prototype.removeAllListeners = function(type) { while (listeners.length) this.removeListener(type, listeners[listeners.length - 1]); } - this._events[type] = undefined; + delete this._events[type]; return this; }; diff --git a/test/simple/test-event-emitter-memory-leak.js b/test/simple/test-event-emitter-memory-leak.js new file mode 100644 index 0000000000..d02fa80512 --- /dev/null +++ b/test/simple/test-event-emitter-memory-leak.js @@ -0,0 +1,42 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// Flags: --expose-gc + +// Add and remove a lot of different events to an EventEmitter, then check +// that we didn't leak the event names. +var common = require('../common'); +var assert = require('assert'); +var events = require('events'); + +assert.equal(typeof gc, 'function', 'Run this test with --expose-gc'); +var before = process.memoryUsage().heapUsed; +var e = new events.EventEmitter(); + +for (var i = 0; i < 2.5e5; ++i) { + var name = 'a-pretty-long-event-name-' + i; + e.on(name, assert.fail); + e.removeListener(name, assert.fail); +} +while (gc()); + +var after = process.memoryUsage().heapUsed; +assert(after - before < 1024*1024, 'EventEmitter leaks event names.');