Skip to content

Commit 09b01f1

Browse files
committed
add captureRejection option
Port of nodejs/node#27867
1 parent e9fb908 commit 09b01f1

File tree

4 files changed

+391
-55
lines changed

4 files changed

+391
-55
lines changed

events.js

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,50 @@ EventEmitter.init = function init(opts) {
129129
}
130130
};
131131

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+
132176
// Obviously not all Emitters should be limited to 10. This function allows
133177
// that to be increased. Set to zero for unlimited.
134178
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
@@ -182,12 +226,29 @@ EventEmitter.prototype.emit = function emit(type) {
182226
return false;
183227

184228
if (typeof handler === 'function') {
185-
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+
}
186237
} else {
187238
var len = handler.length;
188239
var listeners = arrayClone(handler, len);
189-
for (var i = 0; i < len; ++i)
190-
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+
}
191252
}
192253

193254
return true;

0 commit comments

Comments
 (0)