Skip to content

Commit

Permalink
Allow add/remove listeners in callbacks (videojs#119) (videojs#121)
Browse files Browse the repository at this point in the history
Using a callback to mutate the listeners (e.g. removing yourself), previously
changed the iterated array, causing bugs.  Remove the problem by always copying
the array, so on()/off() become safe to call at any time.
  • Loading branch information
odinho authored and Stepan Smagin committed Apr 28, 2017
1 parent 240d891 commit a21e763
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 1 deletion.
3 changes: 2 additions & 1 deletion lib/utils/stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ var Stream = function() {
if (!listeners[type]) {
listeners[type] = [];
}
listeners[type].push(listener);
listeners[type] = listeners[type].concat(listener);
};
/**
* Remove a listener for a specified event type.
Expand All @@ -36,6 +36,7 @@ var Stream = function() {
return false;
}
index = listeners[type].indexOf(listener);
listeners[type] = listeners[type].slice();
listeners[type].splice(index, 1);
return index > -1;
};
Expand Down
48 changes: 48 additions & 0 deletions test/stream.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
'use strict';

var
stream,
Stream = require('../lib/utils/stream'),
QUnit = require('qunit');

QUnit.module('Stream', {
beforeEach: function() {
stream = new Stream();
stream.init();
}
});

QUnit.test('trigger calls listeners', function() {
var args = [];

stream.on('test', function(data) {
args.push(data);
});

stream.trigger('test', 1);
stream.trigger('test', 2);

QUnit.deepEqual(args, [1, 2]);
});

QUnit.test('callbacks can remove themselves', function() {
var args1 = [], args2 = [], args3 = [];

stream.on('test', function(event) {
args1.push(event);
});
stream.on('test', function t(event) {
args2.push(event);
stream.off('test', t);
});
stream.on('test', function(event) {
args3.push(event);
});

stream.trigger('test', 1);
stream.trigger('test', 2);

QUnit.deepEqual(args1, [1, 2], 'first callback ran all times');
QUnit.deepEqual(args2, [1], 'second callback removed after first run');
QUnit.deepEqual(args3, [1, 2], 'third callback ran all times');
});

0 comments on commit a21e763

Please sign in to comment.