Browse Source

events: pass the original listener added by once

When removing a `once` listener, the listener being passed to
the `removeListener` callback is the wrapper. This unwraps the
listener so that `removeListener` is passed the actual listener.

PR-URL: https://github.com/nodejs/node/pull/6394
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
process-exit-stdio-flushing
DavidCai 9 years ago
committed by James M Snell
parent
commit
706778a902
  1. 7
      lib/events.js
  2. 11
      test/parallel/test-event-emitter-remove-listeners.js

7
lib/events.js

@ -308,7 +308,7 @@ EventEmitter.prototype.prependOnceListener =
// emits a 'removeListener' event iff the listener was removed // emits a 'removeListener' event iff the listener was removed
EventEmitter.prototype.removeListener = EventEmitter.prototype.removeListener =
function removeListener(type, listener) { function removeListener(type, listener) {
var list, events, position, i; var list, events, position, i, originalListener;
if (typeof listener !== 'function') if (typeof listener !== 'function')
throw new TypeError('"listener" argument must be a function'); throw new TypeError('"listener" argument must be a function');
@ -327,7 +327,7 @@ EventEmitter.prototype.removeListener =
else { else {
delete events[type]; delete events[type];
if (events.removeListener) if (events.removeListener)
this.emit('removeListener', type, listener); this.emit('removeListener', type, list.listener || listener);
} }
} else if (typeof list !== 'function') { } else if (typeof list !== 'function') {
position = -1; position = -1;
@ -335,6 +335,7 @@ EventEmitter.prototype.removeListener =
for (i = list.length; i-- > 0;) { for (i = list.length; i-- > 0;) {
if (list[i] === listener || if (list[i] === listener ||
(list[i].listener && list[i].listener === listener)) { (list[i].listener && list[i].listener === listener)) {
originalListener = list[i].listener;
position = i; position = i;
break; break;
} }
@ -356,7 +357,7 @@ EventEmitter.prototype.removeListener =
} }
if (events.removeListener) if (events.removeListener)
this.emit('removeListener', type, listener); this.emit('removeListener', type, originalListener || listener);
} }
return this; return this;

11
test/parallel/test-event-emitter-remove-listeners.js

@ -102,3 +102,14 @@ e6.emit('hello');
// Interal listener array [listener3] // Interal listener array [listener3]
e6.emit('hello'); e6.emit('hello');
const e7 = new events.EventEmitter();
const listener5 = () => {};
e7.once('hello', listener5);
e7.on('removeListener', common.mustCall((eventName, listener) => {
assert.strictEqual(eventName, 'hello');
assert.strictEqual(listener, listener5);
}));
e7.emit('hello');

Loading…
Cancel
Save