@@ -50,15 +50,38 @@ var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) {
50
50
return value !== value ;
51
51
}
52
52
53
- function EventEmitter ( ) {
54
- EventEmitter . init . call ( this ) ;
53
+ var kCapture = typeof Symbol === 'function' ? Symbol ( 'kCapture' ) : '_fakeSymbol_kCapture' ;
54
+ var kRejection = typeof Symbol === 'function' && typeof Symbol . for === 'function' ? Symbol . for ( 'nodejs.rejection' ) : '_fakeSymbol_nodejs.rejection' ;
55
+
56
+ function EventEmitter ( opts ) {
57
+ EventEmitter . init . call ( this , opts ) ;
55
58
}
56
59
module . exports = EventEmitter ;
57
60
module . exports . once = once ;
58
61
59
62
// Backwards-compat with node 0.10.x
60
63
EventEmitter . EventEmitter = EventEmitter ;
61
64
65
+ EventEmitter . captureRejectionSymbol = kRejection ;
66
+ Object . defineProperty ( EventEmitter , 'captureRejections' , {
67
+ get : function ( ) {
68
+ return EventEmitter . prototype [ kCapture ] ;
69
+ } ,
70
+ set : function ( value ) {
71
+ if ( typeof value !== 'boolean' ) {
72
+ throw new TypeError ( 'The "EventEmitter.captureRejections" argument must be of type boolean. Received type ' + typeof value ) ;
73
+ }
74
+ EventEmitter . prototype [ kCapture ] = value ;
75
+ } ,
76
+ enumerable : true
77
+ } ) ;
78
+
79
+ Object . defineProperty ( EventEmitter . prototype , kCapture , {
80
+ value : false ,
81
+ writable : true ,
82
+ enumerable : false
83
+ } ) ;
84
+
62
85
EventEmitter . prototype . _events = undefined ;
63
86
EventEmitter . prototype . _eventsCount = 0 ;
64
87
EventEmitter . prototype . _maxListeners = undefined ;
@@ -86,7 +109,7 @@ Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
86
109
}
87
110
} ) ;
88
111
89
- EventEmitter . init = function ( ) {
112
+ EventEmitter . init = function init ( opts ) {
90
113
91
114
if ( this . _events === undefined ||
92
115
this . _events === Object . getPrototypeOf ( this ) . _events ) {
@@ -95,8 +118,61 @@ EventEmitter.init = function() {
95
118
}
96
119
97
120
this . _maxListeners = this . _maxListeners || undefined ;
121
+
122
+ if ( opts && opts . captureRejections ) {
123
+ if ( typeof opts . captureRejections !== 'boolean' ) {
124
+ throw new TypeError ( 'The "options.captureRejections" argument must be of type boolean. Received type ' + typeof opts . captureRejections ) ;
125
+ }
126
+ this [ kCapture ] = Boolean ( opts . captureRejections ) ;
127
+ } else {
128
+ this [ kCapture ] = EventEmitter . prototype [ kCapture ] ;
129
+ }
98
130
} ;
99
131
132
+ var ProcessNextTick = typeof queueMicrotask === 'function'
133
+ ? queueMicrotask
134
+ : typeof setImmediate === 'function'
135
+ ? setImmediate
136
+ : setTimeout ;
137
+
138
+ function addCatch ( that , promise , type , args ) {
139
+ if ( ! that [ kCapture ] ) {
140
+ return ;
141
+ }
142
+
143
+ // Handle Promises/A+ spec, then could be a getter
144
+ // that throws on second use.
145
+ try {
146
+ var then = promise . then ;
147
+ if ( typeof then === 'function' ) {
148
+ then . call ( promise , undefined , function ( err ) {
149
+ ProcessNextTick ( function ( ) {
150
+ emitUnhandledRejectionOrErr ( that , err , type , args ) ;
151
+ } ) ;
152
+ } ) ;
153
+ }
154
+ } catch ( err ) {
155
+ that . emit ( 'error' , err ) ;
156
+ }
157
+ }
158
+
159
+ function emitUnhandledRejectionOrErr ( ee , err , type , args ) {
160
+ if ( typeof ee [ kRejection ] === 'function' ) {
161
+ ee [ kRejection ] . apply ( ee , [ err , type ] . concat ( args ) ) ;
162
+ } else {
163
+ // We have to disable the capture rejections mechanism, otherwise
164
+ // we might end up in an infinite loop.
165
+ var prev = ee [ kCapture ] ;
166
+
167
+ try {
168
+ ee [ kCapture ] = false ;
169
+ ee . emit ( 'error' , err ) ;
170
+ } finally {
171
+ ee [ kCapture ] = prev ;
172
+ }
173
+ }
174
+ }
175
+
100
176
// Obviously not all Emitters should be limited to 10. This function allows
101
177
// that to be increased. Set to zero for unlimited.
102
178
EventEmitter . prototype . setMaxListeners = function setMaxListeners ( n ) {
@@ -150,12 +226,29 @@ EventEmitter.prototype.emit = function emit(type) {
150
226
return false ;
151
227
152
228
if ( typeof handler === 'function' ) {
153
- ReflectApply ( handler , this , args ) ;
229
+ var result = ReflectApply ( handler , this , args ) ;
230
+
231
+ // We check if result is undefined first because that
232
+ // is the most common case so we do not pay any perf
233
+ // penalty
234
+ if ( result !== undefined && result !== null ) {
235
+ addCatch ( this , result , type , args ) ;
236
+ }
154
237
} else {
155
238
var len = handler . length ;
156
239
var listeners = arrayClone ( handler , len ) ;
157
- for ( var i = 0 ; i < len ; ++ i )
158
- ReflectApply ( listeners [ i ] , this , args ) ;
240
+ for ( var i = 0 ; i < len ; ++ i ) {
241
+ var result = ReflectApply ( listeners [ i ] , this , args ) ;
242
+
243
+ // We check if result is undefined first because that
244
+ // is the most common case so we do not pay any perf
245
+ // penalty.
246
+ // This code is duplicated because extracting it away
247
+ // would make it non-inlineable.
248
+ if ( result !== undefined && result !== null ) {
249
+ addCatch ( this , result , type , args ) ;
250
+ }
251
+ }
159
252
}
160
253
161
254
return true ;
0 commit comments