Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80522 views
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
function EventEmitter() {
23
this._events = this._events || {};
24
this._maxListeners = this._maxListeners || undefined;
25
}
26
module.exports = EventEmitter;
27
28
// Backwards-compat with node 0.10.x
29
EventEmitter.EventEmitter = EventEmitter;
30
31
EventEmitter.prototype._events = undefined;
32
EventEmitter.prototype._maxListeners = undefined;
33
34
// By default EventEmitters will print a warning if more than 10 listeners are
35
// added to it. This is a useful default which helps finding memory leaks.
36
EventEmitter.defaultMaxListeners = 10;
37
38
// Obviously not all Emitters should be limited to 10. This function allows
39
// that to be increased. Set to zero for unlimited.
40
EventEmitter.prototype.setMaxListeners = function(n) {
41
if (!isNumber(n) || n < 0 || isNaN(n))
42
throw TypeError('n must be a positive number');
43
this._maxListeners = n;
44
return this;
45
};
46
47
EventEmitter.prototype.emit = function(type) {
48
var er, handler, len, args, i, listeners;
49
50
if (!this._events)
51
this._events = {};
52
53
// If there is no 'error' event listener then throw.
54
if (type === 'error') {
55
if (!this._events.error ||
56
(isObject(this._events.error) && !this._events.error.length)) {
57
er = arguments[1];
58
if (er instanceof Error) {
59
throw er; // Unhandled 'error' event
60
}
61
throw TypeError('Uncaught, unspecified "error" event.');
62
}
63
}
64
65
handler = this._events[type];
66
67
if (isUndefined(handler))
68
return false;
69
70
if (isFunction(handler)) {
71
switch (arguments.length) {
72
// fast cases
73
case 1:
74
handler.call(this);
75
break;
76
case 2:
77
handler.call(this, arguments[1]);
78
break;
79
case 3:
80
handler.call(this, arguments[1], arguments[2]);
81
break;
82
// slower
83
default:
84
len = arguments.length;
85
args = new Array(len - 1);
86
for (i = 1; i < len; i++)
87
args[i - 1] = arguments[i];
88
handler.apply(this, args);
89
}
90
} else if (isObject(handler)) {
91
len = arguments.length;
92
args = new Array(len - 1);
93
for (i = 1; i < len; i++)
94
args[i - 1] = arguments[i];
95
96
listeners = handler.slice();
97
len = listeners.length;
98
for (i = 0; i < len; i++)
99
listeners[i].apply(this, args);
100
}
101
102
return true;
103
};
104
105
EventEmitter.prototype.addListener = function(type, listener) {
106
var m;
107
108
if (!isFunction(listener))
109
throw TypeError('listener must be a function');
110
111
if (!this._events)
112
this._events = {};
113
114
// To avoid recursion in the case that type === "newListener"! Before
115
// adding it to the listeners, first emit "newListener".
116
if (this._events.newListener)
117
this.emit('newListener', type,
118
isFunction(listener.listener) ?
119
listener.listener : listener);
120
121
if (!this._events[type])
122
// Optimize the case of one listener. Don't need the extra array object.
123
this._events[type] = listener;
124
else if (isObject(this._events[type]))
125
// If we've already got an array, just append.
126
this._events[type].push(listener);
127
else
128
// Adding the second element, need to change to array.
129
this._events[type] = [this._events[type], listener];
130
131
// Check for listener leak
132
if (isObject(this._events[type]) && !this._events[type].warned) {
133
var m;
134
if (!isUndefined(this._maxListeners)) {
135
m = this._maxListeners;
136
} else {
137
m = EventEmitter.defaultMaxListeners;
138
}
139
140
if (m && m > 0 && this._events[type].length > m) {
141
this._events[type].warned = true;
142
console.error('(node) warning: possible EventEmitter memory ' +
143
'leak detected. %d listeners added. ' +
144
'Use emitter.setMaxListeners() to increase limit.',
145
this._events[type].length);
146
if (typeof console.trace === 'function') {
147
// not supported in IE 10
148
console.trace();
149
}
150
}
151
}
152
153
return this;
154
};
155
156
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
157
158
EventEmitter.prototype.once = function(type, listener) {
159
if (!isFunction(listener))
160
throw TypeError('listener must be a function');
161
162
var fired = false;
163
164
function g() {
165
this.removeListener(type, g);
166
167
if (!fired) {
168
fired = true;
169
listener.apply(this, arguments);
170
}
171
}
172
173
g.listener = listener;
174
this.on(type, g);
175
176
return this;
177
};
178
179
// emits a 'removeListener' event iff the listener was removed
180
EventEmitter.prototype.removeListener = function(type, listener) {
181
var list, position, length, i;
182
183
if (!isFunction(listener))
184
throw TypeError('listener must be a function');
185
186
if (!this._events || !this._events[type])
187
return this;
188
189
list = this._events[type];
190
length = list.length;
191
position = -1;
192
193
if (list === listener ||
194
(isFunction(list.listener) && list.listener === listener)) {
195
delete this._events[type];
196
if (this._events.removeListener)
197
this.emit('removeListener', type, listener);
198
199
} else if (isObject(list)) {
200
for (i = length; i-- > 0;) {
201
if (list[i] === listener ||
202
(list[i].listener && list[i].listener === listener)) {
203
position = i;
204
break;
205
}
206
}
207
208
if (position < 0)
209
return this;
210
211
if (list.length === 1) {
212
list.length = 0;
213
delete this._events[type];
214
} else {
215
list.splice(position, 1);
216
}
217
218
if (this._events.removeListener)
219
this.emit('removeListener', type, listener);
220
}
221
222
return this;
223
};
224
225
EventEmitter.prototype.removeAllListeners = function(type) {
226
var key, listeners;
227
228
if (!this._events)
229
return this;
230
231
// not listening for removeListener, no need to emit
232
if (!this._events.removeListener) {
233
if (arguments.length === 0)
234
this._events = {};
235
else if (this._events[type])
236
delete this._events[type];
237
return this;
238
}
239
240
// emit removeListener for all listeners on all events
241
if (arguments.length === 0) {
242
for (key in this._events) {
243
if (key === 'removeListener') continue;
244
this.removeAllListeners(key);
245
}
246
this.removeAllListeners('removeListener');
247
this._events = {};
248
return this;
249
}
250
251
listeners = this._events[type];
252
253
if (isFunction(listeners)) {
254
this.removeListener(type, listeners);
255
} else {
256
// LIFO order
257
while (listeners.length)
258
this.removeListener(type, listeners[listeners.length - 1]);
259
}
260
delete this._events[type];
261
262
return this;
263
};
264
265
EventEmitter.prototype.listeners = function(type) {
266
var ret;
267
if (!this._events || !this._events[type])
268
ret = [];
269
else if (isFunction(this._events[type]))
270
ret = [this._events[type]];
271
else
272
ret = this._events[type].slice();
273
return ret;
274
};
275
276
EventEmitter.listenerCount = function(emitter, type) {
277
var ret;
278
if (!emitter._events || !emitter._events[type])
279
ret = 0;
280
else if (isFunction(emitter._events[type]))
281
ret = 1;
282
else
283
ret = emitter._events[type].length;
284
return ret;
285
};
286
287
function isFunction(arg) {
288
return typeof arg === 'function';
289
}
290
291
function isNumber(arg) {
292
return typeof arg === 'number';
293
}
294
295
function isObject(arg) {
296
return typeof arg === 'object' && arg !== null;
297
}
298
299
function isUndefined(arg) {
300
return arg === void 0;
301
}
302
303