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
Joyee Cheung 2019-06-15 00:01:01 +08:00
parent 1432065e9d
commit 370873c59e
No known key found for this signature in database
GPG Key ID: 92B78A53C8303B8D
1 changed files with 56 additions and 21 deletions

View File

@ -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;
}