Skip to content

Commit

Permalink
process: refactor unhandled rejection handling
Browse files Browse the repository at this point in the history
- 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: #28228
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
  • Loading branch information
joyeecheung authored and BridgeAR committed Jun 17, 2019
1 parent 2201484 commit 50c8038
Showing 1 changed file with 57 additions and 22 deletions.
79 changes: 57 additions & 22 deletions lib/internal/process/promises.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,24 @@ const pendingUnhandledRejections = [];
const asyncHandledRejections = [];
let lastPromiseId = 0;

const states = {
none: 0,
warn: 1,
strict: 2,
default: 3
};

let state;
// --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 unhandledRejectionsMode;

function setHasRejectionToWarn(value) {
tickInfo[kHasRejectionToWarn] = value ? 1 : 0;
Expand All @@ -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:
Expand Down Expand Up @@ -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 ' +
Expand All @@ -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, ' +
Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit 50c8038

Please sign in to comment.