Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

promise: emit error on domain unhandled rejections #36082

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions lib/internal/process/promises.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ function unhandledRejection(promise, reason) {
maybeUnhandledPromises.set(promise, {
reason,
uid: ++lastPromiseId,
warned: false
warned: false,
domain: process.domain
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this PR is adding trailing commas to module.exports = {…}, it should probably also add them here:

Suggested change
domain: process.domain
domain: process.domain,

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't actually enforce (or particularly care) about trailing commas I believe?

I believe that if we do we should enforce it through eslint.

});
// This causes the promise to be referenced at least for one tick.
pendingUnhandledRejections.push(promise);
Expand Down Expand Up @@ -192,26 +193,32 @@ function processPromiseRejections() {
}
promiseInfo.warned = true;
const { reason, uid } = promiseInfo;
function emit(reason, promise, promiseInfo) {
if (promiseInfo.domain) {
return promiseInfo.domain.emit('error', reason);
}
return process.emit('unhandledRejection', reason, promise);
}
switch (unhandledRejectionsMode) {
case kStrictUnhandledRejections: {
const err = reason instanceof Error ?
reason : generateUnhandledRejectionError(reason);
triggerUncaughtException(err, true /* fromPromise */);
const handled = process.emit('unhandledRejection', reason, promise);
const handled = emit(reason, promise, promiseInfo);
if (!handled) emitUnhandledRejectionWarning(uid, reason);
break;
}
case kIgnoreUnhandledRejections: {
process.emit('unhandledRejection', reason, promise);
emit(reason, promise, promiseInfo);
break;
}
case kAlwaysWarnUnhandledRejections: {
process.emit('unhandledRejection', reason, promise);
emit(reason, promise, promiseInfo);
emitUnhandledRejectionWarning(uid, reason);
break;
}
case kThrowUnhandledRejections: {
const handled = process.emit('unhandledRejection', reason, promise);
const handled = emit(reason, promise, promiseInfo);
if (!handled) {
const err = reason instanceof Error ?
reason : generateUnhandledRejectionError(reason);
Expand All @@ -220,7 +227,7 @@ function processPromiseRejections() {
break;
}
case kWarnWithErrorCodeUnhandledRejections: {
const handled = process.emit('unhandledRejection', reason, promise);
const handled = emit(reason, promise, promiseInfo);
if (!handled) {
emitUnhandledRejectionWarning(uid, reason);
process.exitCode = 1;
Expand Down Expand Up @@ -266,10 +273,9 @@ function generateUnhandledRejectionError(reason) {
function listenForRejections() {
setPromiseRejectCallback(promiseRejectHandler);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line probably shouldn’t be deleted.

module.exports = {
hasRejectionToWarn,
setHasRejectionToWarn,
listenForRejections,
processPromiseRejections
processPromiseRejections,
};
10 changes: 10 additions & 0 deletions test/parallel/test-domain-promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,13 @@ process.on('warning', common.mustNotCall());
}));
}));
}
{
// Unhandled rejections become errors on the domain
const d = domain.create();
d.on('error', common.mustCall((e) => {
assert.strictEqual(e.message, 'foo');
}));
d.run(common.mustCall(() => {
Promise.reject(new Error('foo'));
}));
}
25 changes: 0 additions & 25 deletions test/parallel/test-promises-unhandled-rejections.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const domain = require('domain');
const { inspect } = require('util');

common.disableCrashOnUnhandledRejection();
Expand Down Expand Up @@ -622,30 +621,6 @@ asyncTest('setImmediate + promise microtasks is too late to attach a catch' +
});
});

asyncTest(
'Promise unhandledRejection handler does not interfere with domain' +
' error handlers being given exceptions thrown from nextTick.',
function(done) {
const d = domain.create();
let domainReceivedError;
d.on('error', function(e) {
domainReceivedError = e;
});
d.run(function() {
const e = new Error('error');
const domainError = new Error('domain error');
onUnhandledSucceed(done, function(reason, promise) {
assert.strictEqual(reason, e);
assert.strictEqual(domainReceivedError, domainError);
});
Promise.reject(e);
process.nextTick(function() {
throw domainError;
});
});
}
);

asyncTest('nextTick is immediately scheduled when called inside an event' +
' handler', function(done) {
clean();
Expand Down