Skip to content

Commit

Permalink
Fix once, onceBefore and onceAfter with wildcards
Browse files Browse the repository at this point in the history
- When using once with wildcards it did not unregister properly.
- It used to add an additional listener that unregisterd the actual
  listener on emit.

The second point could only be fixed by using eval to generate a proxy
function or else the function length could not be retained.
  • Loading branch information
mantoni committed Feb 7, 2013
1 parent f224533 commit 5be57ea
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 12 deletions.
21 changes: 14 additions & 7 deletions lib/hub.js
Original file line number Diff line number Diff line change
Expand Up @@ -319,22 +319,29 @@ function create() {
return multiple(function (event, fn) {
this.emit('newListener', event, fn, noop, function () {
if (!this.stopped()) {
var register = (event.indexOf('*') === -1 ? listener : matcher);
register(event)[type].push(fn);
var bucket = (event.indexOf('*') === -1 ? listener : matcher);
bucket(event)[type].push(fn);
}
});
});
}

var vars = "a,b,c,d,e,f,g,h,i,j,k,l";
function registerOnce(type) {
return multiple(function (event, fn) {
/*jslint evil:true*/
var self = this;
function once() {
self.un(event, once);
self.un(event, fn);
var proxy;
if (fn.length) {
eval('proxy = (function (' + vars.substring(0, fn.length * 2 - 1) +
') { self.un(event, proxy); return fn.apply(this, arguments); });');
} else {
proxy = function () {
self.un(event, proxy);
return fn.apply(this, arguments);
};
}
listener(event)[type].push(once);
this[type](event, fn);
this[type](event, proxy);
});
}

Expand Down
6 changes: 3 additions & 3 deletions test/test-event-newListener.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ var hub = require('../lib/hub');

function emitsNewListener(method, event) {
return function () {
var spy = sinon.spy();
var listener = function () {};
var spy = sinon.spy();
var listener = function () {};

this.hub.on('newListener', spy);
this.hub[method](event, listener);

sinon.assert.calledOnce(spy);
sinon.assert.calledWith(spy, event, listener);
sinon.assert.calledWith(spy, event, sinon.match.func);
};
}

Expand Down
27 changes: 25 additions & 2 deletions test/test-once.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ function unsubscribeTests(method) {


'should not invoke listener again if it emits same event': function () {
var self = this;
var spy = sinon.spy(function () {
var self = this;
var spy = sinon.spy(function () {
self.hub.emit('a');
});

Expand All @@ -45,6 +45,29 @@ function unsubscribeTests(method) {
});

sinon.assert.calledOnce(spy);
},


'should not invoke listener again if it emits same wildcard event':
function () {
var self = this;
var spy = sinon.spy(function () {
self.hub.emit('a.b.c');
});

this.hub[method]('a.**', spy);
assert.doesNotThrow(function () {
self.hub.emit('a.b.c');
});

sinon.assert.calledOnce(spy);
},


'should not add additional listeners': function () {
this.hub[method]('test', function () {});

assert.equal(this.hub.listeners('test').length, 1);
}

};
Expand Down

0 comments on commit 5be57ea

Please sign in to comment.