diff --git a/lib/internal/process/promises.js b/lib/internal/process/promises.js index 279fba326ebb43..d976b9d38a9050 100644 --- a/lib/internal/process/promises.js +++ b/lib/internal/process/promises.js @@ -8,6 +8,11 @@ let lastPromiseId = 1; exports.setup = setupPromises; +function getAsynchronousRejectionWarningObject(uid) { + return new Error('Promise rejection was handled ' + + `asynchronously (rejection id: ${uid})`); +} + function setupPromises(scheduleMicrotasks) { process._setupPromises(function(event, promise, reason) { if (event === promiseRejectEvent.unhandled) @@ -31,10 +36,15 @@ function setupPromises(scheduleMicrotasks) { const uid = promiseToGuidProperty.get(promise); promiseToGuidProperty.delete(promise); if (hasBeenNotified === true) { + let warning = null; + if (!process.listenerCount('rejectionHandled')) { + // Generate the warning object early to get a good stack trace. + warning = getAsynchronousRejectionWarningObject(uid); + } process.nextTick(function() { if (!process.emit('rejectionHandled', promise)) { - const warning = new Error('Promise rejection was handled ' + - `asynchronously (rejection id: ${uid})`); + if (warning === null) + warning = getAsynchronousRejectionWarningObject(uid); warning.name = 'PromiseRejectionHandledWarning'; warning.id = uid; process.emitWarning(warning); @@ -58,6 +68,9 @@ function setupPromises(scheduleMicrotasks) { `(rejection id: ${uid}): ${reason}`); warning.name = 'UnhandledPromiseRejectionWarning'; warning.id = uid; + if (reason instanceof Error) { + warning.stack = reason.stack; + } process.emitWarning(warning); } else { hadListeners = true; diff --git a/test/message/unhandled_promise_trace_warnings.js b/test/message/unhandled_promise_trace_warnings.js new file mode 100644 index 00000000000000..48450fb21e2169 --- /dev/null +++ b/test/message/unhandled_promise_trace_warnings.js @@ -0,0 +1,5 @@ +// Flags: --trace-warnings +'use strict'; +require('../common'); +const p = Promise.reject(new Error('This was rejected')); +setImmediate(() => p.catch(() => {})); diff --git a/test/message/unhandled_promise_trace_warnings.out b/test/message/unhandled_promise_trace_warnings.out new file mode 100644 index 00000000000000..c2c7b91f47e11d --- /dev/null +++ b/test/message/unhandled_promise_trace_warnings.out @@ -0,0 +1,21 @@ +(node:*) Error: This was rejected + at * (*test*message*unhandled_promise_trace_warnings.js:*) + at * + at * + at * + at * + at * + at * + at * + at * + at * +(node:*) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1) + at getAsynchronousRejectionWarningObject (internal/process/promises.js:*) + at rejectionHandled (internal/process/promises.js:*) + at * + at Promise.then (native) + at Promise.catch (native) + at Immediate.setImmediate (*test*message*unhandled_promise_trace_warnings.js:*) + at * + at * + at *