Skip to content

Commit

Permalink
lib,src: throw on unhanded promise rejections
Browse files Browse the repository at this point in the history
  • Loading branch information
Fishrock123 committed Apr 28, 2017
1 parent b2c7a51 commit 1f9635d
Show file tree
Hide file tree
Showing 17 changed files with 406 additions and 271 deletions.
217 changes: 0 additions & 217 deletions deps/npm/node_modules/request/node_modules/form-data/Readme.md

This file was deleted.

4 changes: 2 additions & 2 deletions lib/internal/bootstrap_node.js
Original file line number Diff line number Diff line change
Expand Up @@ -304,13 +304,13 @@

function setupProcessFatal() {

process._fatalException = function(er) {
process._fatalException = function(er, fromPromise) {
var caught;

if (process.domain && process.domain._errorHandler)
caught = process.domain._errorHandler(er) || caught;

if (!caught)
if (!caught && !fromPromise)
caught = process.emit('uncaughtException', er);

// If someone handled it, then great. otherwise, die in C++ land
Expand Down
52 changes: 8 additions & 44 deletions lib/internal/process/promises.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,88 +2,52 @@

const promiseRejectEvent = process._promiseRejectEvent;
const hasBeenNotifiedProperty = new WeakMap();
const promiseToGuidProperty = new WeakMap();
const pendingUnhandledRejections = [];
let lastPromiseId = 1;

exports.setup = setupPromises;

function getAsynchronousRejectionWarningObject(uid) {
return new Error('Promise rejection was handled ' +
`asynchronously (rejection id: ${uid})`);
}

function setupPromises(scheduleMicrotasks) {
const promiseInternals = {};

process._setupPromises(function(event, promise, reason) {
if (event === promiseRejectEvent.unhandled)
unhandledRejection(promise, reason);
else if (event === promiseRejectEvent.handled)
rejectionHandled(promise);
else
require('assert').fail(null, null, 'unexpected PromiseRejectEvent');
});
}, function getPromiseReason(data) {
return data[data.indexOf('[[PromiseValue]]') + 1];
}, promiseInternals);

function unhandledRejection(promise, reason) {
hasBeenNotifiedProperty.set(promise, false);
promiseToGuidProperty.set(promise, lastPromiseId++);
addPendingUnhandledRejection(promise, reason);
}

function rejectionHandled(promise) {
const hasBeenNotified = hasBeenNotifiedProperty.get(promise);
if (hasBeenNotified !== undefined) {
hasBeenNotifiedProperty.delete(promise);
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);
}
promiseInternals.untrackPromise(promise);
process.nextTick(function() {
if (!process.emit('rejectionHandled', promise)) {
if (warning === null)
warning = getAsynchronousRejectionWarningObject(uid);
warning.name = 'PromiseRejectionHandledWarning';
warning.id = uid;
process.emitWarning(warning);
}
process.emit('rejectionHandled', promise);
});
}

}
}

function emitWarning(uid, reason) {
const warning = new Error('Unhandled promise rejection ' +
`(rejection id: ${uid}): ${reason}`);
warning.name = 'UnhandledPromiseRejectionWarning';
warning.id = uid;
if (reason instanceof Error) {
warning.stack = reason.stack;
}
process.emitWarning(warning);
if (!deprecationWarned) {
deprecationWarned = true;
process.emitWarning(
'Unhandled promise rejections are deprecated. In the future, ' +
'promise rejections that are not handled will terminate the ' +
'Node.js process with a non-zero exit code.',
'DeprecationWarning', 'DEP0018');
}
}
var deprecationWarned = false;
function emitPendingUnhandledRejections() {
let hadListeners = false;
while (pendingUnhandledRejections.length > 0) {
const promise = pendingUnhandledRejections.shift();
const reason = pendingUnhandledRejections.shift();
if (hasBeenNotifiedProperty.get(promise) === false) {
hasBeenNotifiedProperty.set(promise, true);
const uid = promiseToGuidProperty.get(promise);
if (!process.emit('unhandledRejection', reason, promise)) {
emitWarning(uid, reason);
promiseInternals.trackPromise(promise);
} else {
hadListeners = true;
}
Expand Down
2 changes: 2 additions & 0 deletions node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@
'src/stream_wrap.cc',
'src/tcp_wrap.cc',
'src/timer_wrap.cc',
'src/track-promise.cc',
'src/tracing/agent.cc',
'src/tracing/node_trace_buffer.cc',
'src/tracing/node_trace_writer.cc',
Expand Down Expand Up @@ -230,6 +231,7 @@
'src/node_revert.h',
'src/node_i18n.h',
'src/pipe_wrap.h',
'src/track-promise.h',
'src/tty_wrap.h',
'src/tcp_wrap.h',
'src/udp_wrap.h',
Expand Down
6 changes: 5 additions & 1 deletion src/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ namespace node {
V(zero_return_string, "ZERO_RETURN") \

#define ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V) \
V(array_from, v8::Function) \
V(as_external, v8::External) \
V(async_hooks_destroy_function, v8::Function) \
V(async_hooks_init_function, v8::Function) \
Expand All @@ -264,7 +265,10 @@ namespace node {
V(module_load_list_array, v8::Array) \
V(pipe_constructor_template, v8::FunctionTemplate) \
V(process_object, v8::Object) \
V(promise_reject_function, v8::Function) \
V(promise_unhandled_rejection_function, v8::Function) \
V(promise_unhandled_rejection, v8::Function) \
V(promise_unhandled_reject_map, v8::NativeWeakMap) \
V(promise_unhandled_reject_keys, v8::Set) \
V(push_values_to_array_function, v8::Function) \
V(script_context_constructor_template, v8::FunctionTemplate) \
V(script_data_constructor_function, v8::Function) \
Expand Down
Loading

0 comments on commit 1f9635d

Please sign in to comment.