|
|
|
@ -3,7 +3,8 @@ var path = require('path');
|
|
|
|
|
var fs = require('fs');
|
|
|
|
|
|
|
|
|
|
// Only install once if called multiple times
|
|
|
|
|
var alreadyInstalled = false;
|
|
|
|
|
var errorFormatterInstalled = false;
|
|
|
|
|
var uncaughtShimInstalled = false;
|
|
|
|
|
|
|
|
|
|
// If true, the caches are reset before a stack trace formatting operation
|
|
|
|
|
var emptyCacheBetweenOperations = false;
|
|
|
|
@ -20,6 +21,10 @@ var sourceMapCache = {};
|
|
|
|
|
// Regex for detecting source maps
|
|
|
|
|
var reSourceMap = /^data:application\/json[^,]+base64,/;
|
|
|
|
|
|
|
|
|
|
// Priority list of retrieve handlers
|
|
|
|
|
var retrieveFileHandlers = [];
|
|
|
|
|
var retrieveMapHandlers = [];
|
|
|
|
|
|
|
|
|
|
function isInBrowser() {
|
|
|
|
|
if (environment === "browser")
|
|
|
|
|
return true;
|
|
|
|
@ -32,7 +37,21 @@ function hasGlobalProcessEventEmitter() {
|
|
|
|
|
return ((typeof process === 'object') && (process !== null) && (typeof process.on === 'function'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function retrieveFile(path) {
|
|
|
|
|
function handlerExec(list) {
|
|
|
|
|
return function(arg) {
|
|
|
|
|
for (var i = 0; i < list.length; i++) {
|
|
|
|
|
var ret = list[i](arg);
|
|
|
|
|
if (ret) {
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var retrieveFile = handlerExec(retrieveFileHandlers);
|
|
|
|
|
|
|
|
|
|
retrieveFileHandlers.push(function(path) {
|
|
|
|
|
// Trim the path to make sure there is no extra whitespace.
|
|
|
|
|
path = path.trim();
|
|
|
|
|
if (path in fileContentsCache) {
|
|
|
|
@ -60,7 +79,7 @@ function retrieveFile(path) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return fileContentsCache[path] = contents;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Support URLs relative to a directory, but be careful about a protocol prefix
|
|
|
|
|
// in case we are in the browser (i.e. directories may start with "http://")
|
|
|
|
@ -106,7 +125,8 @@ function retrieveSourceMapURL(source) {
|
|
|
|
|
// there is no source map. The map field may be either a string or the parsed
|
|
|
|
|
// JSON object (ie, it must be a valid argument to the SourceMapConsumer
|
|
|
|
|
// constructor).
|
|
|
|
|
function retrieveSourceMap(source) {
|
|
|
|
|
var retrieveSourceMap = handlerExec(retrieveMapHandlers);
|
|
|
|
|
retrieveMapHandlers.push(function(source) {
|
|
|
|
|
var sourceMappingURL = retrieveSourceMapURL(source);
|
|
|
|
|
if (!sourceMappingURL) return null;
|
|
|
|
|
|
|
|
|
@ -131,7 +151,7 @@ function retrieveSourceMap(source) {
|
|
|
|
|
url: sourceMappingURL,
|
|
|
|
|
map: sourceMapData
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function mapSourcePosition(position) {
|
|
|
|
|
var sourceMap = sourceMapCache[position.source];
|
|
|
|
@ -393,7 +413,7 @@ function shimEmitUncaughtException () {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return origEmit.apply(this, arguments);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
exports.wrapCallSite = wrapCallSite;
|
|
|
|
@ -402,33 +422,50 @@ exports.mapSourcePosition = mapSourcePosition;
|
|
|
|
|
exports.retrieveSourceMap = retrieveSourceMap;
|
|
|
|
|
|
|
|
|
|
exports.install = function(options) {
|
|
|
|
|
if (!alreadyInstalled) {
|
|
|
|
|
alreadyInstalled = true;
|
|
|
|
|
Error.prepareStackTrace = prepareStackTrace;
|
|
|
|
|
options = options || {};
|
|
|
|
|
|
|
|
|
|
// Configure options
|
|
|
|
|
options = options || {};
|
|
|
|
|
var installHandler = 'handleUncaughtExceptions' in options ?
|
|
|
|
|
options.handleUncaughtExceptions : true;
|
|
|
|
|
|
|
|
|
|
if (options.environment) {
|
|
|
|
|
environment = options.environment;
|
|
|
|
|
if (["node", "browser", "auto"].indexOf(environment) === -1) {
|
|
|
|
|
throw new Error("environment " + environment + " was unknown. Available options are {auto, browser, node}")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Allow sources to be found by methods other than reading the files
|
|
|
|
|
// directly from disk.
|
|
|
|
|
if (options.retrieveFile) {
|
|
|
|
|
if (options.overrideRetrieveFile) {
|
|
|
|
|
retrieveFileHandlers.length = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
retrieveFileHandlers.unshift(options.retrieveFile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Allow source maps to be found by methods other than reading the files
|
|
|
|
|
// directly from disk.
|
|
|
|
|
if (options.retrieveSourceMap) {
|
|
|
|
|
if (options.overrideRetrieveSourceMap) {
|
|
|
|
|
retrieveMapHandlers.length = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
retrieveMapHandlers.unshift(options.retrieveSourceMap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Configure options
|
|
|
|
|
if (!emptyCacheBetweenOperations) {
|
|
|
|
|
emptyCacheBetweenOperations = 'emptyCacheBetweenOperations' in options ?
|
|
|
|
|
options.emptyCacheBetweenOperations : false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (options.environment) {
|
|
|
|
|
environment = options.environment;
|
|
|
|
|
if (["node", "browser", "auto"].indexOf(environment) === -1)
|
|
|
|
|
throw new Error("environment " + environment + " was unknown. Available options are {auto, browser, node}")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Allow sources to be found by methods other than reading the files
|
|
|
|
|
// directly from disk.
|
|
|
|
|
if (options.retrieveFile)
|
|
|
|
|
retrieveFile = options.retrieveFile;
|
|
|
|
|
// Install the error reformatter
|
|
|
|
|
if (!errorFormatterInstalled) {
|
|
|
|
|
errorFormatterInstalled = true;
|
|
|
|
|
Error.prepareStackTrace = prepareStackTrace;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Allow source maps to be found by methods other than reading the files
|
|
|
|
|
// directly from disk.
|
|
|
|
|
if (options.retrieveSourceMap)
|
|
|
|
|
retrieveSourceMap = options.retrieveSourceMap;
|
|
|
|
|
if (!uncaughtShimInstalled) {
|
|
|
|
|
var installHandler = 'handleUncaughtExceptions' in options ?
|
|
|
|
|
options.handleUncaughtExceptions : true;
|
|
|
|
|
|
|
|
|
|
// Provide the option to not install the uncaught exception handler. This is
|
|
|
|
|
// to support other uncaught exception handlers (in test frameworks, for
|
|
|
|
@ -438,6 +475,7 @@ exports.install = function(options) {
|
|
|
|
|
// generated JavaScript code will be shown above the stack trace instead of
|
|
|
|
|
// the original source code.
|
|
|
|
|
if (installHandler && hasGlobalProcessEventEmitter()) {
|
|
|
|
|
uncaughtShimInstalled = true;
|
|
|
|
|
shimEmitUncaughtException();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|