'use strict';
|
|
|
|
var Promise = require('./core');
|
|
|
|
var DEFAULT_WHITELIST = [
|
|
ReferenceError,
|
|
TypeError,
|
|
RangeError
|
|
];
|
|
|
|
var enabled = false;
|
|
exports.disable = disable;
|
|
function disable() {
|
|
enabled = false;
|
|
Promise._Y = null;
|
|
Promise._Z = null;
|
|
}
|
|
|
|
exports.enable = enable;
|
|
function enable(options) {
|
|
options = options || {};
|
|
if (enabled) disable();
|
|
enabled = true;
|
|
var id = 0;
|
|
var displayId = 0;
|
|
var rejections = {};
|
|
Promise._Y = function (promise) {
|
|
if (
|
|
promise._V === 2 && // IS REJECTED
|
|
rejections[promise._1]
|
|
) {
|
|
if (rejections[promise._1].logged) {
|
|
onHandled(promise._1);
|
|
} else {
|
|
clearTimeout(rejections[promise._1].timeout);
|
|
}
|
|
delete rejections[promise._1];
|
|
}
|
|
};
|
|
Promise._Z = function (promise, err) {
|
|
if (promise._U === 0) { // not yet handled
|
|
promise._1 = id++;
|
|
rejections[promise._1] = {
|
|
displayId: null,
|
|
error: err,
|
|
timeout: setTimeout(
|
|
onUnhandled.bind(null, promise._1),
|
|
// For reference errors and type errors, this almost always
|
|
// means the programmer made a mistake, so log them after just
|
|
// 100ms
|
|
// otherwise, wait 2 seconds to see if they get handled
|
|
matchWhitelist(err, DEFAULT_WHITELIST)
|
|
? 100
|
|
: 2000
|
|
),
|
|
logged: false
|
|
};
|
|
}
|
|
};
|
|
function onUnhandled(id) {
|
|
if (
|
|
options.allRejections ||
|
|
matchWhitelist(
|
|
rejections[id].error,
|
|
options.whitelist || DEFAULT_WHITELIST
|
|
)
|
|
) {
|
|
rejections[id].displayId = displayId++;
|
|
if (options.onUnhandled) {
|
|
rejections[id].logged = true;
|
|
options.onUnhandled(
|
|
rejections[id].displayId,
|
|
rejections[id].error
|
|
);
|
|
} else {
|
|
rejections[id].logged = true;
|
|
logError(
|
|
rejections[id].displayId,
|
|
rejections[id].error
|
|
);
|
|
}
|
|
}
|
|
}
|
|
function onHandled(id) {
|
|
if (rejections[id].logged) {
|
|
if (options.onHandled) {
|
|
options.onHandled(rejections[id].displayId, rejections[id].error);
|
|
} else if (!rejections[id].onUnhandled) {
|
|
console.warn(
|
|
'Promise Rejection Handled (id: ' + rejections[id].displayId + '):'
|
|
);
|
|
console.warn(
|
|
' This means you can ignore any previous messages of the form "Possible Unhandled Promise Rejection" with id ' +
|
|
rejections[id].displayId + '.'
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function logError(id, error) {
|
|
console.warn('Possible Unhandled Promise Rejection (id: ' + id + '):');
|
|
var errStr = (error && (error.stack || error)) + '';
|
|
errStr.split('\n').forEach(function (line) {
|
|
console.warn(' ' + line);
|
|
});
|
|
}
|
|
|
|
function matchWhitelist(error, list) {
|
|
return list.some(function (cls) {
|
|
return error instanceof cls;
|
|
});
|
|
}
|