diff --git a/benchmark/events/ee-once.js b/benchmark/events/ee-once.js new file mode 100644 index 0000000000..29ea562c40 --- /dev/null +++ b/benchmark/events/ee-once.js @@ -0,0 +1,20 @@ +'use strict'; +var common = require('../common.js'); +var EventEmitter = require('events').EventEmitter; + +var bench = common.createBenchmark(main, {n: [2e7]}); + +function main(conf) { + var n = conf.n | 0; + + var ee = new EventEmitter(); + + function listener() {} + + bench.start(); + for (var i = 0; i < n; i += 1) { + ee.once('dummy', listener); + ee.emit('dummy'); + } + bench.end(n); +} diff --git a/lib/events.js b/lib/events.js index e7202bfedd..4ccec4e595 100644 --- a/lib/events.js +++ b/lib/events.js @@ -283,17 +283,20 @@ EventEmitter.prototype.prependListener = return _addListener(this, type, listener, true); }; -function _onceWrap(target, type, listener) { - var fired = false; - function g() { - target.removeListener(type, g); - if (!fired) { - fired = true; - listener.apply(target, arguments); - } +function onceWrapper() { + this.target.removeListener(this.type, this.wrapFn); + if (!this.fired) { + this.fired = true; + this.listener.apply(this.target, arguments); } - g.listener = listener; - return g; +} + +function _onceWrap(target, type, listener) { + var state = { fired: false, wrapFn: undefined, target, type, listener }; + var wrapped = onceWrapper.bind(state); + wrapped.listener = listener; + state.wrapFn = wrapped; + return wrapped; } EventEmitter.prototype.once = function once(type, listener) {