Skip to content

Commit eb9295b

Browse files
benjamingrcodebytere
authored andcommitted
promise: emit error on domain unhandled rejections
PR-URL: #36082 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Yongsheng Zhang <zyszys98@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
1 parent 89da0c3 commit eb9295b

File tree

3 files changed

+24
-33
lines changed

3 files changed

+24
-33
lines changed

lib/internal/process/promises.js

+14-8
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ function unhandledRejection(promise, reason) {
117117
maybeUnhandledPromises.set(promise, {
118118
reason,
119119
uid: ++lastPromiseId,
120-
warned: false
120+
warned: false,
121+
domain: process.domain
121122
});
122123
// This causes the promise to be referenced at least for one tick.
123124
pendingUnhandledRejections.push(promise);
@@ -192,26 +193,32 @@ function processPromiseRejections() {
192193
}
193194
promiseInfo.warned = true;
194195
const { reason, uid } = promiseInfo;
196+
function emit(reason, promise, promiseInfo) {
197+
if (promiseInfo.domain) {
198+
return promiseInfo.domain.emit('error', reason);
199+
}
200+
return process.emit('unhandledRejection', reason, promise);
201+
}
195202
switch (unhandledRejectionsMode) {
196203
case kStrictUnhandledRejections: {
197204
const err = reason instanceof Error ?
198205
reason : generateUnhandledRejectionError(reason);
199206
triggerUncaughtException(err, true /* fromPromise */);
200-
const handled = process.emit('unhandledRejection', reason, promise);
207+
const handled = emit(reason, promise, promiseInfo);
201208
if (!handled) emitUnhandledRejectionWarning(uid, reason);
202209
break;
203210
}
204211
case kIgnoreUnhandledRejections: {
205-
process.emit('unhandledRejection', reason, promise);
212+
emit(reason, promise, promiseInfo);
206213
break;
207214
}
208215
case kAlwaysWarnUnhandledRejections: {
209-
process.emit('unhandledRejection', reason, promise);
216+
emit(reason, promise, promiseInfo);
210217
emitUnhandledRejectionWarning(uid, reason);
211218
break;
212219
}
213220
case kThrowUnhandledRejections: {
214-
const handled = process.emit('unhandledRejection', reason, promise);
221+
const handled = emit(reason, promise, promiseInfo);
215222
if (!handled) {
216223
const err = reason instanceof Error ?
217224
reason : generateUnhandledRejectionError(reason);
@@ -220,7 +227,7 @@ function processPromiseRejections() {
220227
break;
221228
}
222229
case kWarnWithErrorCodeUnhandledRejections: {
223-
const handled = process.emit('unhandledRejection', reason, promise);
230+
const handled = emit(reason, promise, promiseInfo);
224231
if (!handled) {
225232
emitUnhandledRejectionWarning(uid, reason);
226233
process.exitCode = 1;
@@ -266,10 +273,9 @@ function generateUnhandledRejectionError(reason) {
266273
function listenForRejections() {
267274
setPromiseRejectCallback(promiseRejectHandler);
268275
}
269-
270276
module.exports = {
271277
hasRejectionToWarn,
272278
setHasRejectionToWarn,
273279
listenForRejections,
274-
processPromiseRejections
280+
processPromiseRejections,
275281
};

test/parallel/test-domain-promise.js

+10
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,13 @@ process.on('warning', common.mustNotCall());
126126
}));
127127
}));
128128
}
129+
{
130+
// Unhandled rejections become errors on the domain
131+
const d = domain.create();
132+
d.on('error', common.mustCall((e) => {
133+
assert.strictEqual(e.message, 'foo');
134+
}));
135+
d.run(common.mustCall(() => {
136+
Promise.reject(new Error('foo'));
137+
}));
138+
}

test/parallel/test-promises-unhandled-rejections.js

-25
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use strict';
22
const common = require('../common');
33
const assert = require('assert');
4-
const domain = require('domain');
54
const { inspect } = require('util');
65

76
common.disableCrashOnUnhandledRejection();
@@ -622,30 +621,6 @@ asyncTest('setImmediate + promise microtasks is too late to attach a catch' +
622621
});
623622
});
624623

625-
asyncTest(
626-
'Promise unhandledRejection handler does not interfere with domain' +
627-
' error handlers being given exceptions thrown from nextTick.',
628-
function(done) {
629-
const d = domain.create();
630-
let domainReceivedError;
631-
d.on('error', function(e) {
632-
domainReceivedError = e;
633-
});
634-
d.run(function() {
635-
const e = new Error('error');
636-
const domainError = new Error('domain error');
637-
onUnhandledSucceed(done, function(reason, promise) {
638-
assert.strictEqual(reason, e);
639-
assert.strictEqual(domainReceivedError, domainError);
640-
});
641-
Promise.reject(e);
642-
process.nextTick(function() {
643-
throw domainError;
644-
});
645-
});
646-
}
647-
);
648-
649624
asyncTest('nextTick is immediately scheduled when called inside an event' +
650625
' handler', function(done) {
651626
clean();

0 commit comments

Comments
 (0)