mirror of https://github.com/nodejs/node.git
process: refactor unhandled rejection handling
- Use constants instead of a dictionary and add comments about the behavior of each mode. - Use switch cases to handle the unhandled rejection modes. - Rename the run time value of the CLI option from `state` to `unhandledRejectionsMode`. - Return in the call site of `emitWarning` when `--unhandled-rejections=none` instead of inside the function. PR-URL: https://github.com/nodejs/node/pull/28228 Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>pull/28239/head
parent
1432065e9d
commit
370873c59e
|
@ -25,14 +25,24 @@ const pendingUnhandledRejections = [];
|
|||
const asyncHandledRejections = [];
|
||||
let lastPromiseId = 0;
|
||||
|
||||
const states = {
|
||||
none: 0,
|
||||
warn: 1,
|
||||
strict: 2,
|
||||
default: 3
|
||||
};
|
||||
// --unhandled-rejection=none:
|
||||
// Emit 'unhandledRejection', but do not emit any warning.
|
||||
const kIgnoreUnhandledRejections = 0;
|
||||
// --unhandled-rejection=warn:
|
||||
// Emit 'unhandledRejection', then emit 'UnhandledPromiseRejectionWarning'.
|
||||
const kAlwaysWarnUnhandledRejections = 1;
|
||||
// --unhandled-rejection=strict:
|
||||
// Emit 'uncaughtException'. If it's not handled, print the error to stderr
|
||||
// and exit the process.
|
||||
// Otherwise, emit 'unhandledRejection'. If 'unhandledRejection' is not
|
||||
// handled, emit 'UnhandledPromiseRejectionWarning'.
|
||||
const kThrowUnhandledRejections = 2;
|
||||
// --unhandled-rejection is unset:
|
||||
// Emit 'unhandledRejection', if it's handled, emit
|
||||
// 'UnhandledPromiseRejectionWarning', then emit deprecation warning.
|
||||
const kDefaultUnhandledRejections = 3;
|
||||
|
||||
let state;
|
||||
let unhandledRejectionsMode;
|
||||
|
||||
function setHasRejectionToWarn(value) {
|
||||
tickInfo[kHasRejectionToWarn] = value ? 1 : 0;
|
||||
|
@ -42,10 +52,23 @@ function hasRejectionToWarn() {
|
|||
return tickInfo[kHasRejectionToWarn] === 1;
|
||||
}
|
||||
|
||||
function getUnhandledRejectionsMode() {
|
||||
const { getOptionValue } = require('internal/options');
|
||||
switch (getOptionValue('--unhandled-rejections')) {
|
||||
case 'none':
|
||||
return kIgnoreUnhandledRejections;
|
||||
case 'warn':
|
||||
return kAlwaysWarnUnhandledRejections;
|
||||
case 'strict':
|
||||
return kThrowUnhandledRejections;
|
||||
default:
|
||||
return kDefaultUnhandledRejections;
|
||||
}
|
||||
}
|
||||
|
||||
function promiseRejectHandler(type, promise, reason) {
|
||||
if (state === undefined) {
|
||||
const { getOptionValue } = require('internal/options');
|
||||
state = states[getOptionValue('--unhandled-rejections') || 'default'];
|
||||
if (unhandledRejectionsMode === undefined) {
|
||||
unhandledRejectionsMode = getUnhandledRejectionsMode();
|
||||
}
|
||||
switch (type) {
|
||||
case kPromiseRejectWithNoHandler:
|
||||
|
@ -104,9 +127,6 @@ function handledRejection(promise) {
|
|||
|
||||
const unhandledRejectionErrName = 'UnhandledPromiseRejectionWarning';
|
||||
function emitWarning(uid, reason) {
|
||||
if (state === states.none) {
|
||||
return;
|
||||
}
|
||||
const warning = getError(
|
||||
unhandledRejectionErrName,
|
||||
'Unhandled promise rejection. This error originated either by ' +
|
||||
|
@ -129,7 +149,8 @@ function emitWarning(uid, reason) {
|
|||
|
||||
let deprecationWarned = false;
|
||||
function emitDeprecationWarning() {
|
||||
if (state === states.default && !deprecationWarned) {
|
||||
if (unhandledRejectionsMode === kDefaultUnhandledRejections &&
|
||||
!deprecationWarned) {
|
||||
deprecationWarned = true;
|
||||
process.emitWarning(
|
||||
'Unhandled promise rejections are deprecated. In the future, ' +
|
||||
|
@ -161,13 +182,27 @@ function processPromiseRejections() {
|
|||
}
|
||||
promiseInfo.warned = true;
|
||||
const { reason, uid } = promiseInfo;
|
||||
if (state === states.strict) {
|
||||
fatalException(reason);
|
||||
}
|
||||
if (!process.emit('unhandledRejection', reason, promise) ||
|
||||
// Always warn in case the user requested it.
|
||||
state === states.warn) {
|
||||
emitWarning(uid, reason);
|
||||
switch (unhandledRejectionsMode) {
|
||||
case kThrowUnhandledRejections: {
|
||||
fatalException(reason);
|
||||
const handled = process.emit('unhandledRejection', reason, promise);
|
||||
if (!handled) emitWarning(uid, reason);
|
||||
break;
|
||||
}
|
||||
case kIgnoreUnhandledRejections: {
|
||||
process.emit('unhandledRejection', reason, promise);
|
||||
break;
|
||||
}
|
||||
case kAlwaysWarnUnhandledRejections: {
|
||||
process.emit('unhandledRejection', reason, promise);
|
||||
emitWarning(uid, reason);
|
||||
break;
|
||||
}
|
||||
case kDefaultUnhandledRejections: {
|
||||
const handled = process.emit('unhandledRejection', reason, promise);
|
||||
if (!handled) emitWarning(uid, reason);
|
||||
break;
|
||||
}
|
||||
}
|
||||
maybeScheduledTicksOrMicrotasks = true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue