From 43fa824a3b3765ab402ca37bfecd62d79d129ca4 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Sat, 15 Jun 2019 00:01:01 +0800 Subject: [PATCH] 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 Reviewed-By: Ruben Bridgewater --- lib/internal/process/promises.js | 79 +++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 22 deletions(-) diff --git a/lib/internal/process/promises.js b/lib/internal/process/promises.js index 324541551ef8b3..031997fc1b3467 100644 --- a/lib/internal/process/promises.js +++ b/lib/internal/process/promises.js @@ -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; @@ -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; }