diff --git a/src/util/evented.js b/src/util/evented.js index 77705a48ceb..b596b57b66d 100644 --- a/src/util/evented.js +++ b/src/util/evented.js @@ -6,8 +6,11 @@ type Listener = (Object) => any; type Listeners = { [string]: Array }; function _addEventListener(type: string, listener: Listener, listenerList: Listeners) { - listenerList[type] = listenerList[type] || []; - listenerList[type].push(listener); + const listenerExists = listenerList[type] && listenerList[type].indexOf(listener) !== -1; + if (!listenerExists) { + listenerList[type] = listenerList[type] || []; + listenerList[type].push(listener); + } } function _removeEventListener(type: string, listener: Listener, listenerList: Listeners) { diff --git a/test/unit/util/evented.test.js b/test/unit/util/evented.test.js index b3ddf6c140e..8c2dc476de7 100644 --- a/test/unit/util/evented.test.js +++ b/test/unit/util/evented.test.js @@ -119,6 +119,19 @@ test('Evented', (t) => { t.end(); }); + t.test('on is idempotent', (t) => { + const evented = new Evented(); + const listenerA = t.spy(); + const listenerB = t.spy(); + evented.on('a', listenerA); + evented.on('a', listenerB); + evented.on('a', listenerA); + evented.fire(new Event('a')); + t.ok(listenerA.calledOnce); + t.ok(listenerA.calledBefore(listenerB)); + t.end(); + }); + t.test('evented parents', (t) => { t.test('adds parents with "setEventedParent"', (t) => {