EventEmitter.emitAsync   F
last analyzed

Complexity

Conditions 32
Paths 218

Size

Total Lines 96

Duplication

Lines 96
Ratio 100 %

Importance

Changes 0
Metric Value
cc 32
nc 218
dl 96
loc 96
rs 3.8997
c 0
b 0
f 0
nop 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like EventEmitter.emitAsync often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/*!
2
 * EventEmitter2
3
 * https://github.com/hij1nx/EventEmitter2
4
 *
5
 * Copyright (c) 2013 hij1nx
6
 * Licensed under the MIT license.
7
 */
8
;!function(undefined) {
9
10
  var isArray = Array.isArray ? Array.isArray : function _isArray(obj) {
11
    return Object.prototype.toString.call(obj) === "[object Array]";
12
  };
13
  var defaultMaxListeners = 10;
14
15
  function init() {
16
    this._events = {};
17
    if (this._conf) {
18
      configure.call(this, this._conf);
19
    }
20
  }
21
22
  function configure(conf) {
23
    if (conf) {
24
      this._conf = conf;
25
26
      conf.delimiter && (this.delimiter = conf.delimiter);
27
      this._maxListeners = conf.maxListeners !== undefined ? conf.maxListeners : defaultMaxListeners;
28
29
      conf.wildcard && (this.wildcard = conf.wildcard);
30
      conf.newListener && (this._newListener = conf.newListener);
31
      conf.removeListener && (this._removeListener = conf.removeListener);
32
      conf.verboseMemoryLeak && (this.verboseMemoryLeak = conf.verboseMemoryLeak);
33
34
      if (this.wildcard) {
35
        this.listenerTree = {};
36
      }
37
    } else {
38
      this._maxListeners = defaultMaxListeners;
39
    }
40
  }
41
42
  function logPossibleMemoryLeak(count, eventName) {
43
    var errorMsg = '(node) warning: possible EventEmitter memory ' +
44
        'leak detected. ' + count + ' listeners added. ' +
45
        'Use emitter.setMaxListeners() to increase limit.';
46
47
    if(this.verboseMemoryLeak){
48
      errorMsg += ' Event name: ' + eventName + '.';
49
    }
50
51
    if(typeof process !== 'undefined' && process.emitWarning){
52
      var e = new Error(errorMsg);
53
      e.name = 'MaxListenersExceededWarning';
54
      e.emitter = this;
55
      e.count = count;
56
      process.emitWarning(e);
57
    } else {
58
      console.error(errorMsg);
59
60
      if (console.trace){
61
        console.trace();
62
      }
63
    }
64
  }
65
66
  function EventEmitter(conf) {
67
    this._events = {};
68
    this._newListener = false;
69
    this._removeListener = false;
70
    this.verboseMemoryLeak = false;
71
    configure.call(this, conf);
72
  }
73
  EventEmitter.EventEmitter2 = EventEmitter; // backwards compatibility for exporting EventEmitter property
74
75
  //
76
  // Attention, function return type now is array, always !
77
  // It has zero elements if no any matches found and one or more
78
  // elements (leafs) if there are matches
79
  //
80
  function searchListenerTree(handlers, type, tree, i) {
81
    if (!tree) {
82
      return [];
83
    }
84
    var listeners=[], leaf, len, branch, xTree, xxTree, isolatedBranch, endReached,
85
        typeLength = type.length, currentType = type[i], nextType = type[i+1];
86
    if (i === typeLength && tree._listeners) {
87
      //
88
      // If at the end of the event(s) list and the tree has listeners
89
      // invoke those listeners.
90
      //
91
      if (typeof tree._listeners === 'function') {
92
        handlers && handlers.push(tree._listeners);
93
        return [tree];
94
      } else {
95
        for (leaf = 0, len = tree._listeners.length; leaf < len; leaf++) {
96
          handlers && handlers.push(tree._listeners[leaf]);
97
        }
98
        return [tree];
99
      }
100
    }
101
102
    if ((currentType === '*' || currentType === '**') || tree[currentType]) {
103
      //
104
      // If the event emitted is '*' at this part
105
      // or there is a concrete match at this patch
106
      //
107
      if (currentType === '*') {
108
        for (branch in tree) {
109
          if (branch !== '_listeners' && tree.hasOwnProperty(branch)) {
110
            listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i+1));
111
          }
112
        }
113
        return listeners;
114
      } else if(currentType === '**') {
115
        endReached = (i+1 === typeLength || (i+2 === typeLength && nextType === '*'));
116
        if(endReached && tree._listeners) {
117
          // The next element has a _listeners, add it to the handlers.
118
          listeners = listeners.concat(searchListenerTree(handlers, type, tree, typeLength));
119
        }
120
121
        for (branch in tree) {
122
          if (branch !== '_listeners' && tree.hasOwnProperty(branch)) {
123
            if(branch === '*' || branch === '**') {
124
              if(tree[branch]._listeners && !endReached) {
125
                listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], typeLength));
126
              }
127
              listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i));
128
            } else if(branch === nextType) {
129
              listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i+2));
130
            } else {
131
              // No match on this one, shift into the tree but not in the type array.
132
              listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i));
133
            }
134
          }
135
        }
136
        return listeners;
137
      }
138
139
      listeners = listeners.concat(searchListenerTree(handlers, type, tree[currentType], i+1));
140
    }
141
142
    xTree = tree['*'];
143
    if (xTree) {
144
      //
145
      // If the listener tree will allow any match for this part,
146
      // then recursively explore all branches of the tree
147
      //
148
      searchListenerTree(handlers, type, xTree, i+1);
149
    }
150
151
    xxTree = tree['**'];
152
    if(xxTree) {
153
      if(i < typeLength) {
154
        if(xxTree._listeners) {
155
          // If we have a listener on a '**', it will catch all, so add its handler.
156
          searchListenerTree(handlers, type, xxTree, typeLength);
157
        }
158
159
        // Build arrays of matching next branches and others.
160
        for(branch in xxTree) {
161
          if(branch !== '_listeners' && xxTree.hasOwnProperty(branch)) {
162
            if(branch === nextType) {
163
              // We know the next element will match, so jump twice.
164
              searchListenerTree(handlers, type, xxTree[branch], i+2);
165
            } else if(branch === currentType) {
166
              // Current node matches, move into the tree.
167
              searchListenerTree(handlers, type, xxTree[branch], i+1);
168
            } else {
169
              isolatedBranch = {};
170
              isolatedBranch[branch] = xxTree[branch];
171
              searchListenerTree(handlers, type, { '**': isolatedBranch }, i+1);
172
            }
173
          }
174
        }
175
      } else if(xxTree._listeners) {
176
        // We have reached the end and still on a '**'
177
        searchListenerTree(handlers, type, xxTree, typeLength);
178
      } else if(xxTree['*'] && xxTree['*']._listeners) {
179
        searchListenerTree(handlers, type, xxTree['*'], typeLength);
180
      }
181
    }
182
183
    return listeners;
184
  }
185
186
  function growListenerTree(type, listener) {
187
188
    type = typeof type === 'string' ? type.split(this.delimiter) : type.slice();
189
190
    //
191
    // Looks for two consecutive '**', if so, don't add the event at all.
192
    //
193
    for(var i = 0, len = type.length; i+1 < len; i++) {
194
      if(type[i] === '**' && type[i+1] === '**') {
195
        return;
196
      }
197
    }
198
199
    var tree = this.listenerTree;
200
    var name = type.shift();
201
202
    while (name !== undefined) {
203
204
      if (!tree[name]) {
205
        tree[name] = {};
206
      }
207
208
      tree = tree[name];
209
210
      if (type.length === 0) {
211
212
        if (!tree._listeners) {
213
          tree._listeners = listener;
214
        }
215
        else {
216
          if (typeof tree._listeners === 'function') {
217
            tree._listeners = [tree._listeners];
218
          }
219
220
          tree._listeners.push(listener);
221
222
          if (
223
            !tree._listeners.warned &&
224
            this._maxListeners > 0 &&
225
            tree._listeners.length > this._maxListeners
226
          ) {
227
            tree._listeners.warned = true;
228
            logPossibleMemoryLeak.call(this, tree._listeners.length, name);
229
          }
230
        }
231
        return true;
232
      }
233
      name = type.shift();
234
    }
235
    return true;
236
  }
237
238
  // By default EventEmitters will print a warning if more than
239
  // 10 listeners are added to it. This is a useful default which
240
  // helps finding memory leaks.
241
  //
242
  // Obviously not all Emitters should be limited to 10. This function allows
243
  // that to be increased. Set to zero for unlimited.
244
245
  EventEmitter.prototype.delimiter = '.';
246
247
  EventEmitter.prototype.setMaxListeners = function(n) {
248
    if (n !== undefined) {
249
      this._maxListeners = n;
250
      if (!this._conf) this._conf = {};
251
      this._conf.maxListeners = n;
252
    }
253
  };
254
255
  EventEmitter.prototype.event = '';
256
257
258
  EventEmitter.prototype.once = function(event, fn) {
259
    return this._once(event, fn, false);
260
  };
261
262
  EventEmitter.prototype.prependOnceListener = function(event, fn) {
263
    return this._once(event, fn, true);
264
  };
265
266
  EventEmitter.prototype._once = function(event, fn, prepend) {
267
    this._many(event, 1, fn, prepend);
268
    return this;
269
  };
270
271
  EventEmitter.prototype.many = function(event, ttl, fn) {
272
    return this._many(event, ttl, fn, false);
273
  }
274
275
  EventEmitter.prototype.prependMany = function(event, ttl, fn) {
276
    return this._many(event, ttl, fn, true);
277
  }
278
279
  EventEmitter.prototype._many = function(event, ttl, fn, prepend) {
280
    var self = this;
281
282
    if (typeof fn !== 'function') {
283
      throw new Error('many only accepts instances of Function');
284
    }
285
286
    function listener() {
287
      if (--ttl === 0) {
288
        self.off(event, listener);
289
      }
290
      return fn.apply(this, arguments);
291
    }
292
293
    listener._origin = fn;
294
295
    this._on(event, listener, prepend);
296
297
    return self;
298
  };
299
300 View Code Duplication
  EventEmitter.prototype.emit = function() {
301
302
    this._events || init.call(this);
303
304
    var type = arguments[0];
305
306
    if (type === 'newListener' && !this._newListener) {
307
      if (!this._events.newListener) {
308
        return false;
309
      }
310
    }
311
312
    var al = arguments.length;
313
    var args,l,i,j;
314
    var handler;
315
316
    if (this._all && this._all.length) {
317
      handler = this._all.slice();
318
      if (al > 3) {
319
        args = new Array(al);
0 ignored issues
show
Coding Style Best Practice introduced by
Using the Array constructor is generally discouraged. Consider using an array literal instead.
Loading history...
320
        for (j = 0; j < al; j++) args[j] = arguments[j];
321
      }
322
323
      for (i = 0, l = handler.length; i < l; i++) {
324
        this.event = type;
325
        switch (al) {
326
        case 1:
327
          handler[i].call(this, type);
328
          break;
329
        case 2:
330
          handler[i].call(this, type, arguments[1]);
331
          break;
332
        case 3:
333
          handler[i].call(this, type, arguments[1], arguments[2]);
334
          break;
335
        default:
336
          handler[i].apply(this, args);
0 ignored issues
show
Bug introduced by
The variable args does not seem to be initialized in case al > 3 on line 318 is false. Are you sure the function apply handles undefined variables?
Loading history...
337
        }
338
      }
339
    }
340
341
    if (this.wildcard) {
342
      handler = [];
343
      var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();
344
      searchListenerTree.call(this, handler, ns, this.listenerTree, 0);
345
    } else {
346
      handler = this._events[type];
347
      if (typeof handler === 'function') {
348
        this.event = type;
349
        switch (al) {
350
        case 1:
351
          handler.call(this);
352
          break;
353
        case 2:
354
          handler.call(this, arguments[1]);
355
          break;
356
        case 3:
357
          handler.call(this, arguments[1], arguments[2]);
358
          break;
359
        default:
360
          args = new Array(al - 1);
361
          for (j = 1; j < al; j++) args[j - 1] = arguments[j];
362
          handler.apply(this, args);
363
        }
364
        return true;
365
      } else if (handler) {
366
        // need to make copy of handlers because list can change in the middle
367
        // of emit call
368
        handler = handler.slice();
369
      }
370
    }
371
372
    if (handler && handler.length) {
373
      if (al > 3) {
374
        args = new Array(al - 1);
375
        for (j = 1; j < al; j++) args[j - 1] = arguments[j];
376
      }
377
      for (i = 0, l = handler.length; i < l; i++) {
378
        this.event = type;
379
        switch (al) {
380
        case 1:
381
          handler[i].call(this);
382
          break;
383
        case 2:
384
          handler[i].call(this, arguments[1]);
385
          break;
386
        case 3:
387
          handler[i].call(this, arguments[1], arguments[2]);
388
          break;
389
        default:
390
          handler[i].apply(this, args);
391
        }
392
      }
393
      return true;
394
    } else if (!this._all && type === 'error') {
395
      if (arguments[1] instanceof Error) {
396
        throw arguments[1]; // Unhandled 'error' event
397
      } else {
398
        throw new Error("Uncaught, unspecified 'error' event.");
399
      }
400
      return false;
0 ignored issues
show
introduced by
This code is unreachable and can thus be removed without consequences.
Loading history...
401
    }
402
403
    return !!this._all;
404
  };
405
406 View Code Duplication
  EventEmitter.prototype.emitAsync = function() {
407
408
    this._events || init.call(this);
409
410
    var type = arguments[0];
411
412
    if (type === 'newListener' && !this._newListener) {
413
        if (!this._events.newListener) { return Promise.resolve([false]); }
414
    }
415
416
    var promises= [];
417
418
    var al = arguments.length;
419
    var args,l,i,j;
420
    var handler;
421
422
    if (this._all) {
423
      if (al > 3) {
424
        args = new Array(al);
0 ignored issues
show
Coding Style Best Practice introduced by
Using the Array constructor is generally discouraged. Consider using an array literal instead.
Loading history...
425
        for (j = 1; j < al; j++) args[j] = arguments[j];
426
      }
427
      for (i = 0, l = this._all.length; i < l; i++) {
428
        this.event = type;
429
        switch (al) {
430
        case 1:
431
          promises.push(this._all[i].call(this, type));
432
          break;
433
        case 2:
434
          promises.push(this._all[i].call(this, type, arguments[1]));
435
          break;
436
        case 3:
437
          promises.push(this._all[i].call(this, type, arguments[1], arguments[2]));
438
          break;
439
        default:
440
          promises.push(this._all[i].apply(this, args));
0 ignored issues
show
Bug introduced by
The variable args does not seem to be initialized in case al > 3 on line 423 is false. Are you sure the function apply handles undefined variables?
Loading history...
441
        }
442
      }
443
    }
444
445
    if (this.wildcard) {
446
      handler = [];
447
      var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();
448
      searchListenerTree.call(this, handler, ns, this.listenerTree, 0);
449
    } else {
450
      handler = this._events[type];
451
    }
452
453
    if (typeof handler === 'function') {
454
      this.event = type;
455
      switch (al) {
456
      case 1:
457
        promises.push(handler.call(this));
458
        break;
459
      case 2:
460
        promises.push(handler.call(this, arguments[1]));
461
        break;
462
      case 3:
463
        promises.push(handler.call(this, arguments[1], arguments[2]));
464
        break;
465
      default:
466
        args = new Array(al - 1);
467
        for (j = 1; j < al; j++) args[j - 1] = arguments[j];
468
        promises.push(handler.apply(this, args));
469
      }
470
    } else if (handler && handler.length) {
471
      handler = handler.slice();
472
      if (al > 3) {
473
        args = new Array(al - 1);
474
        for (j = 1; j < al; j++) args[j - 1] = arguments[j];
475
      }
476
      for (i = 0, l = handler.length; i < l; i++) {
477
        this.event = type;
478
        switch (al) {
479
        case 1:
480
          promises.push(handler[i].call(this));
481
          break;
482
        case 2:
483
          promises.push(handler[i].call(this, arguments[1]));
484
          break;
485
        case 3:
486
          promises.push(handler[i].call(this, arguments[1], arguments[2]));
487
          break;
488
        default:
489
          promises.push(handler[i].apply(this, args));
490
        }
491
      }
492
    } else if (!this._all && type === 'error') {
493
      if (arguments[1] instanceof Error) {
494
        return Promise.reject(arguments[1]); // Unhandled 'error' event
495
      } else {
496
        return Promise.reject("Uncaught, unspecified 'error' event.");
497
      }
498
    }
499
500
    return Promise.all(promises);
501
  };
502
503
  EventEmitter.prototype.on = function(type, listener) {
504
    return this._on(type, listener, false);
505
  };
506
507
  EventEmitter.prototype.prependListener = function(type, listener) {
508
    return this._on(type, listener, true);
509
  };
510
511
  EventEmitter.prototype.onAny = function(fn) {
512
    return this._onAny(fn, false);
513
  };
514
515
  EventEmitter.prototype.prependAny = function(fn) {
516
    return this._onAny(fn, true);
517
  };
518
519
  EventEmitter.prototype.addListener = EventEmitter.prototype.on;
520
521
  EventEmitter.prototype._onAny = function(fn, prepend){
522
    if (typeof fn !== 'function') {
523
      throw new Error('onAny only accepts instances of Function');
524
    }
525
526
    if (!this._all) {
527
      this._all = [];
528
    }
529
530
    // Add the function to the event listener collection.
531
    if(prepend){
532
      this._all.unshift(fn);
533
    }else{
534
      this._all.push(fn);
535
    }
536
537
    return this;
538
  }
539
540
  EventEmitter.prototype._on = function(type, listener, prepend) {
541
    if (typeof type === 'function') {
542
      this._onAny(type, listener);
543
      return this;
544
    }
545
546
    if (typeof listener !== 'function') {
547
      throw new Error('on only accepts instances of Function');
548
    }
549
    this._events || init.call(this);
550
551
    // To avoid recursion in the case that type == "newListeners"! Before
552
    // adding it to the listeners, first emit "newListeners".
553
    if (this._newListener)
554
       this.emit('newListener', type, listener);
555
556
    if (this.wildcard) {
557
      growListenerTree.call(this, type, listener);
558
      return this;
559
    }
560
561
    if (!this._events[type]) {
562
      // Optimize the case of one listener. Don't need the extra array object.
563
      this._events[type] = listener;
564
    }
565
    else {
566
      if (typeof this._events[type] === 'function') {
567
        // Change to array.
568
        this._events[type] = [this._events[type]];
569
      }
570
571
      // If we've already got an array, just add
572
      if(prepend){
573
        this._events[type].unshift(listener);
574
      }else{
575
        this._events[type].push(listener);
576
      }
577
578
      // Check for listener leak
579
      if (
580
        !this._events[type].warned &&
581
        this._maxListeners > 0 &&
582
        this._events[type].length > this._maxListeners
583
      ) {
584
        this._events[type].warned = true;
585
        logPossibleMemoryLeak.call(this, this._events[type].length, type);
586
      }
587
    }
588
589
    return this;
590
  }
591
592
  EventEmitter.prototype.off = function(type, listener) {
593
    if (typeof listener !== 'function') {
594
      throw new Error('removeListener only takes instances of Function');
595
    }
596
597
    var handlers,leafs=[];
598
599
    if(this.wildcard) {
600
      var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();
601
      leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0);
602
    }
603
    else {
604
      // does not use listeners(), so no side effect of creating _events[type]
605
      if (!this._events[type]) return this;
606
      handlers = this._events[type];
607
      leafs.push({_listeners:handlers});
608
    }
609
610
    for (var iLeaf=0; iLeaf<leafs.length; iLeaf++) {
611
      var leaf = leafs[iLeaf];
612
      handlers = leaf._listeners;
613
      if (isArray(handlers)) {
614
615
        var position = -1;
616
617
        for (var i = 0, length = handlers.length; i < length; i++) {
618
          if (handlers[i] === listener ||
619
            (handlers[i].listener && handlers[i].listener === listener) ||
620
            (handlers[i]._origin && handlers[i]._origin === listener)) {
621
            position = i;
622
            break;
623
          }
624
        }
625
626
        if (position < 0) {
627
          continue;
628
        }
629
630
        if(this.wildcard) {
631
          leaf._listeners.splice(position, 1);
632
        }
633
        else {
634
          this._events[type].splice(position, 1);
635
        }
636
637
        if (handlers.length === 0) {
638
          if(this.wildcard) {
639
            delete leaf._listeners;
640
          }
641
          else {
642
            delete this._events[type];
643
          }
644
        }
645
        if (this._removeListener)
646
          this.emit("removeListener", type, listener);
647
648
        return this;
649
      }
650
      else if (handlers === listener ||
651
        (handlers.listener && handlers.listener === listener) ||
652
        (handlers._origin && handlers._origin === listener)) {
653
        if(this.wildcard) {
654
          delete leaf._listeners;
655
        }
656
        else {
657
          delete this._events[type];
658
        }
659
        if (this._removeListener)
660
          this.emit("removeListener", type, listener);
661
      }
662
    }
663
664
    function recursivelyGarbageCollect(root) {
665
      if (root === undefined) {
666
        return;
667
      }
668
      var keys = Object.keys(root);
669
      for (var i in keys) {
670
        var key = keys[i];
671
        var obj = root[key];
672
        if ((obj instanceof Function) || (typeof obj !== "object") || (obj === null))
673
          continue;
674
        if (Object.keys(obj).length > 0) {
675
          recursivelyGarbageCollect(root[key]);
676
        }
677
        if (Object.keys(obj).length === 0) {
678
          delete root[key];
679
        }
680
      }
681
    }
682
    recursivelyGarbageCollect(this.listenerTree);
683
684
    return this;
685
  };
686
687
  EventEmitter.prototype.offAny = function(fn) {
688
    var i = 0, l = 0, fns;
689
    if (fn && this._all && this._all.length > 0) {
690
      fns = this._all;
691
      for(i = 0, l = fns.length; i < l; i++) {
692
        if(fn === fns[i]) {
693
          fns.splice(i, 1);
694
          if (this._removeListener)
695
            this.emit("removeListenerAny", fn);
696
          return this;
697
        }
698
      }
699
    } else {
700
      fns = this._all;
701
      if (this._removeListener) {
702
        for(i = 0, l = fns.length; i < l; i++)
703
          this.emit("removeListenerAny", fns[i]);
704
      }
705
      this._all = [];
706
    }
707
    return this;
708
  };
709
710
  EventEmitter.prototype.removeListener = EventEmitter.prototype.off;
711
712
  EventEmitter.prototype.removeAllListeners = function(type) {
713
    if (type === undefined) {
714
      !this._events || init.call(this);
715
      return this;
716
    }
717
718
    if (this.wildcard) {
719
      var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();
720
      var leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0);
721
722
      for (var iLeaf=0; iLeaf<leafs.length; iLeaf++) {
723
        var leaf = leafs[iLeaf];
724
        leaf._listeners = null;
725
      }
726
    }
727
    else if (this._events) {
728
      this._events[type] = null;
729
    }
730
    return this;
731
  };
732
733
  EventEmitter.prototype.listeners = function(type) {
734
    if (this.wildcard) {
735
      var handlers = [];
736
      var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();
737
      searchListenerTree.call(this, handlers, ns, this.listenerTree, 0);
738
      return handlers;
739
    }
740
741
    this._events || init.call(this);
742
743
    if (!this._events[type]) this._events[type] = [];
744
    if (!isArray(this._events[type])) {
745
      this._events[type] = [this._events[type]];
746
    }
747
    return this._events[type];
748
  };
749
750
  EventEmitter.prototype.eventNames = function(){
751
    return Object.keys(this._events);
752
  }
753
754
  EventEmitter.prototype.listenerCount = function(type) {
755
    return this.listeners(type).length;
756
  };
757
758
  EventEmitter.prototype.listenersAny = function() {
759
760
    if(this._all) {
761
      return this._all;
762
    }
763
    else {
764
      return [];
765
    }
766
767
  };
768
769
  if (typeof define === 'function' && define.amd) {
770
     // AMD. Register as an anonymous module.
771
    define(function() {
772
      return EventEmitter;
773
    });
774
  } else if (typeof exports === 'object') {
775
    // CommonJS
776
    module.exports = EventEmitter;
777
  }
778
  else {
779
    // Browser global.
780
    window.EventEmitter2 = EventEmitter;
781
  }
782
}();
783