1// Copyright Joyent, Inc. and other Node contributors. 2// 3// Permission is hereby granted, free of charge, to any person obtaining a 4// copy of this software and associated documentation files (the 5// "Software"), to deal in the Software without restriction, including 6// without limitation the rights to use, copy, modify, merge, publish, 7// distribute, sublicense, and/or sell copies of the Software, and to permit 8// persons to whom the Software is furnished to do so, subject to the 9// following conditions: 10// 11// The above copyright notice and this permission notice shall be included 12// in all copies or substantial portions of the Software. 13// 14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20// USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22'use strict'; 23const common = require('../common'); 24const assert = require('assert'); 25const EventEmitter = require('events'); 26 27function listener1() {} 28 29function listener2() {} 30 31{ 32 const ee = new EventEmitter(); 33 ee.on('hello', listener1); 34 ee.on('removeListener', common.mustCall((name, cb) => { 35 assert.strictEqual(name, 'hello'); 36 assert.strictEqual(cb, listener1); 37 })); 38 ee.removeListener('hello', listener1); 39 assert.deepStrictEqual([], ee.listeners('hello')); 40} 41 42{ 43 const ee = new EventEmitter(); 44 ee.on('hello', listener1); 45 ee.on('removeListener', common.mustNotCall()); 46 ee.removeListener('hello', listener2); 47 assert.deepStrictEqual([listener1], ee.listeners('hello')); 48} 49 50{ 51 const ee = new EventEmitter(); 52 ee.on('hello', listener1); 53 ee.on('hello', listener2); 54 ee.once('removeListener', common.mustCall((name, cb) => { 55 assert.strictEqual(name, 'hello'); 56 assert.strictEqual(cb, listener1); 57 assert.deepStrictEqual([listener2], ee.listeners('hello')); 58 })); 59 ee.removeListener('hello', listener1); 60 assert.deepStrictEqual([listener2], ee.listeners('hello')); 61 ee.once('removeListener', common.mustCall((name, cb) => { 62 assert.strictEqual(name, 'hello'); 63 assert.strictEqual(cb, listener2); 64 assert.deepStrictEqual([], ee.listeners('hello')); 65 })); 66 ee.removeListener('hello', listener2); 67 assert.deepStrictEqual([], ee.listeners('hello')); 68} 69 70{ 71 const ee = new EventEmitter(); 72 73 function remove1() { 74 assert.fail('remove1 should not have been called'); 75 } 76 77 function remove2() { 78 assert.fail('remove2 should not have been called'); 79 } 80 81 ee.on('removeListener', common.mustCall(function(name, cb) { 82 if (cb !== remove1) return; 83 this.removeListener('quux', remove2); 84 this.emit('quux'); 85 }, 2)); 86 ee.on('quux', remove1); 87 ee.on('quux', remove2); 88 ee.removeListener('quux', remove1); 89} 90 91{ 92 const ee = new EventEmitter(); 93 ee.on('hello', listener1); 94 ee.on('hello', listener2); 95 ee.once('removeListener', common.mustCall((name, cb) => { 96 assert.strictEqual(name, 'hello'); 97 assert.strictEqual(cb, listener1); 98 assert.deepStrictEqual([listener2], ee.listeners('hello')); 99 ee.once('removeListener', common.mustCall((name, cb) => { 100 assert.strictEqual(name, 'hello'); 101 assert.strictEqual(cb, listener2); 102 assert.deepStrictEqual([], ee.listeners('hello')); 103 })); 104 ee.removeListener('hello', listener2); 105 assert.deepStrictEqual([], ee.listeners('hello')); 106 })); 107 ee.removeListener('hello', listener1); 108 assert.deepStrictEqual([], ee.listeners('hello')); 109} 110 111{ 112 const ee = new EventEmitter(); 113 const listener3 = common.mustCall(() => { 114 ee.removeListener('hello', listener4); 115 }, 2); 116 const listener4 = common.mustCall(); 117 118 ee.on('hello', listener3); 119 ee.on('hello', listener4); 120 121 // listener4 will still be called although it is removed by listener 3. 122 ee.emit('hello'); 123 // This is so because the internal listener array at time of emit 124 // was [listener3,listener4] 125 126 // Internal listener array [listener3] 127 ee.emit('hello'); 128} 129 130{ 131 const ee = new EventEmitter(); 132 133 ee.once('hello', listener1); 134 ee.on('removeListener', common.mustCall((eventName, listener) => { 135 assert.strictEqual(eventName, 'hello'); 136 assert.strictEqual(listener, listener1); 137 })); 138 ee.emit('hello'); 139} 140 141{ 142 const ee = new EventEmitter(); 143 144 assert.deepStrictEqual(ee, ee.removeListener('foo', () => {})); 145} 146 147{ 148 const ee = new EventEmitter(); 149 const listener = () => {}; 150 ee._events = undefined; 151 const e = ee.removeListener('foo', listener); 152 assert.strictEqual(e, ee); 153} 154 155{ 156 const ee = new EventEmitter(); 157 158 ee.on('foo', listener1); 159 ee.on('foo', listener2); 160 assert.deepStrictEqual(ee.listeners('foo'), [listener1, listener2]); 161 162 ee.removeListener('foo', listener1); 163 assert.strictEqual(ee._events.foo, listener2); 164 165 ee.on('foo', listener1); 166 assert.deepStrictEqual(ee.listeners('foo'), [listener2, listener1]); 167 168 ee.removeListener('foo', listener1); 169 assert.strictEqual(ee._events.foo, listener2); 170} 171