diff --git a/doc/api/events.markdown b/doc/api/events.markdown index 940b8e242ecab0..1403aa6cb62898 100644 --- a/doc/api/events.markdown +++ b/doc/api/events.markdown @@ -68,9 +68,19 @@ Removes all listeners, or those of the specified event. ### emitter.setMaxListeners(n) By default EventEmitters will print a warning if more than 10 listeners are -added for a particular event. This is a useful default which helps finding memory leaks. -Obviously not all Emitters should be limited to 10. This function allows -that to be increased. Set to zero for unlimited. +added for a particular event. This is a useful default which helps finding +memory leaks. Obviously not all Emitters should be limited to 10. This function +allows that to be increased. Set to zero for unlimited. + + +### EventEmitter.defaultMaxListeners + +`emitter.setMaxListeners(n)` sets the maximum on a per-instance basis. +This class property lets you set it for *all* `EventEmitter` instances, +current and future, effective immediately. Use with care. + +Note that `emitter.setMaxListeners(n)` still has precedence over +`EventEmitter.defaultMaxListeners`. ### emitter.listeners(event) diff --git a/lib/events.js b/lib/events.js index 38422dab0f395f..ef9ff7426c5151 100644 --- a/lib/events.js +++ b/lib/events.js @@ -33,17 +33,18 @@ function EventEmitter() { } } this._events = this._events || {}; - this._maxListeners = this._maxListeners || defaultMaxListeners; + this._maxListeners = this._maxListeners || undefined; } exports.EventEmitter = EventEmitter; -// By default EventEmitters will print a warning if more than -// 10 listeners are added to it. This is a useful default which -// helps finding memory leaks. -// + +// By default EventEmitters will print a warning if more than 10 listeners are +// added to it. This is a useful default which helps finding memory leaks. +EventEmitter.defaultMaxListeners = 10; + + // Obviously not all Emitters should be limited to 10. This function allows // that to be increased. Set to zero for unlimited. -var defaultMaxListeners = 10; EventEmitter.prototype.setMaxListeners = function(n) { if (typeof n !== 'number' || n < 0) throw TypeError('n must be a positive number'); @@ -150,7 +151,13 @@ EventEmitter.prototype.addListener = function(type, listener) { // Check for listener leak if (typeof this._events[type] === 'object' && !this._events[type].warned) { - m = this._maxListeners; + var m; + if (this._maxListeners !== undefined) { + m = this._maxListeners; + } else { + m = EventEmitter.defaultMaxListeners; + } + if (m && m > 0 && this._events[type].length > m) { this._events[type].warned = true; console.error('(node) warning: possible EventEmitter memory ' + diff --git a/test/simple/test-event-emitter-check-listener-leaks.js b/test/simple/test-event-emitter-check-listener-leaks.js index 7d9c203243c5dd..3d45e01c72105b 100644 --- a/test/simple/test-event-emitter-check-listener-leaks.js +++ b/test/simple/test-event-emitter-check-listener-leaks.js @@ -56,3 +56,29 @@ for (var i = 0; i < 1000; i++) { } assert.ok(!e._events['unlimited'].hasOwnProperty('warned')); +// process-wide +events.EventEmitter.defaultMaxListeners = 42; +e = new events.EventEmitter(); + +for (var i = 0; i < 42; ++i) { + e.on('fortytwo', function() {}); +} +assert.ok(!e._events['fortytwo'].hasOwnProperty('warned')); +e.on('fortytwo', function() {}); +assert.ok(e._events['fortytwo'].hasOwnProperty('warned')); +delete e._events['fortytwo'].warned; + +events.EventEmitter.defaultMaxListeners = 44; +e.on('fortytwo', function() {}); +assert.ok(!e._events['fortytwo'].hasOwnProperty('warned')); +e.on('fortytwo', function() {}); +assert.ok(e._events['fortytwo'].hasOwnProperty('warned')); + +// but _maxListeners still has precedence over defaultMaxListeners +events.EventEmitter.defaultMaxListeners = 42; +e = new events.EventEmitter(); +e.setMaxListeners(1); +e.on('uno', function() {}); +assert.ok(!e._events['uno'].hasOwnProperty('warned')); +e.on('uno', function() {}); +assert.ok(e._events['uno'].hasOwnProperty('warned'));