113 lines
2.8 KiB
JavaScript
113 lines
2.8 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
var Promise = require('./core');
|
||
|
|
||
|
var DEFAULT_WHITELIST = [
|
||
|
ReferenceError,
|
||
|
TypeError,
|
||
|
RangeError
|
||
|
];
|
||
|
|
||
|
var enabled = false;
|
||
|
exports.disable = disable;
|
||
|
function disable() {
|
||
|
enabled = false;
|
||
|
Promise._l = null;
|
||
|
Promise._m = null;
|
||
|
}
|
||
|
|
||
|
exports.enable = enable;
|
||
|
function enable(options) {
|
||
|
options = options || {};
|
||
|
if (enabled) disable();
|
||
|
enabled = true;
|
||
|
var id = 0;
|
||
|
var displayId = 0;
|
||
|
var rejections = {};
|
||
|
Promise._l = function (promise) {
|
||
|
if (
|
||
|
promise._i === 2 && // IS REJECTED
|
||
|
rejections[promise._o]
|
||
|
) {
|
||
|
if (rejections[promise._o].logged) {
|
||
|
onHandled(promise._o);
|
||
|
} else {
|
||
|
clearTimeout(rejections[promise._o].timeout);
|
||
|
}
|
||
|
delete rejections[promise._o];
|
||
|
}
|
||
|
};
|
||
|
Promise._m = function (promise, err) {
|
||
|
if (promise._h === 0) { // not yet handled
|
||
|
promise._o = id++;
|
||
|
rejections[promise._o] = {
|
||
|
displayId: null,
|
||
|
error: err,
|
||
|
timeout: setTimeout(
|
||
|
onUnhandled.bind(null, promise._o),
|
||
|
// 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;
|
||
|
});
|
||
|
}
|