diff --git a/lib/event-target.js b/lib/event-target.js index 6b185270a..fea4cbc52 100644 --- a/lib/event-target.js +++ b/lib/event-target.js @@ -178,7 +178,7 @@ const EventTarget = { * Register an event listener. * * @param {String} type A string representing the event type to listen for - * @param {(Function|Object)} listener The listener to add + * @param {(Function|Object)} handler The listener to add * @param {Object} [options] An options object specifies characteristics about * the event listener * @param {Boolean} [options.once=false] A `Boolean` indicating that the @@ -186,7 +186,17 @@ const EventTarget = { * the listener would be automatically removed when invoked. * @public */ - addEventListener(type, listener, options = {}) { + addEventListener(type, handler, options = {}) { + for (const listener of this.listeners(type)) { + if ( + !options[kForOnEventAttribute] && + listener[kListener] === handler && + !listener[kForOnEventAttribute] + ) { + return; + } + } + let wrapper; if (type === 'message') { @@ -196,7 +206,7 @@ const EventTarget = { }); event[kTarget] = this; - callListener(listener, this, event); + callListener(handler, this, event); }; } else if (type === 'close') { wrapper = function onClose(code, message) { @@ -207,7 +217,7 @@ const EventTarget = { }); event[kTarget] = this; - callListener(listener, this, event); + callListener(handler, this, event); }; } else if (type === 'error') { wrapper = function onError(error) { @@ -217,21 +227,21 @@ const EventTarget = { }); event[kTarget] = this; - callListener(listener, this, event); + callListener(handler, this, event); }; } else if (type === 'open') { wrapper = function onOpen() { const event = new Event('open'); event[kTarget] = this; - callListener(listener, this, event); + callListener(handler, this, event); }; } else { return; } wrapper[kForOnEventAttribute] = !!options[kForOnEventAttribute]; - wrapper[kListener] = listener; + wrapper[kListener] = handler; if (options.once) { this.once(type, wrapper); diff --git a/test/websocket.test.js b/test/websocket.test.js index bbbc5ae9f..6b2f3ef5c 100644 --- a/test/websocket.test.js +++ b/test/websocket.test.js @@ -3257,10 +3257,13 @@ describe('WebSocket', () => { ws.addEventListener('foo', () => {}); assert.strictEqual(ws.listenerCount('foo'), 0); - ws.addEventListener('open', () => { + function onOpen() { events.push('open'); assert.strictEqual(ws.listenerCount('open'), 1); - }); + } + + ws.addEventListener('open', onOpen); + ws.addEventListener('open', onOpen); assert.strictEqual(ws.listenerCount('open'), 1); @@ -3273,9 +3276,28 @@ describe('WebSocket', () => { }; ws.addEventListener('message', listener, { once: true }); + ws.addEventListener('message', listener); assert.strictEqual(ws.listenerCount('message'), 1); + ws.addEventListener('close', NOOP); + ws.onclose = NOOP; + + let listeners = ws.listeners('close'); + + assert.strictEqual(listeners.length, 2); + assert.strictEqual(listeners[0][kListener], NOOP); + assert.strictEqual(listeners[1][kListener], NOOP); + + ws.onerror = NOOP; + ws.addEventListener('error', NOOP); + + listeners = ws.listeners('error'); + + assert.strictEqual(listeners.length, 2); + assert.strictEqual(listeners[0][kListener], NOOP); + assert.strictEqual(listeners[1][kListener], NOOP); + ws.emit('open'); ws.emit('message', EMPTY_BUFFER, false); @@ -3353,21 +3375,6 @@ describe('WebSocket', () => { assert.strictEqual(ws.listenerCount('message'), 0); assert.strictEqual(ws.listenerCount('open'), 0); - // Multiple listeners. - ws.addEventListener('message', NOOP); - ws.addEventListener('message', NOOP); - - assert.strictEqual(ws.listeners('message')[0][kListener], NOOP); - assert.strictEqual(ws.listeners('message')[1][kListener], NOOP); - - ws.removeEventListener('message', NOOP); - - assert.strictEqual(ws.listeners('message')[0][kListener], NOOP); - - ws.removeEventListener('message', NOOP); - - assert.strictEqual(ws.listenerCount('message'), 0); - // Listeners not added with `websocket.addEventListener()`. ws.on('message', NOOP);