Skip to content

Instantly share code, notes, and snippets.

@mshustov
Last active December 28, 2017 11:38
Show Gist options
  • Save mshustov/b296d17e8c315c294f3550e79747220b to your computer and use it in GitHub Desktop.
Save mshustov/b296d17e8c315c294f3550e79747220b to your computer and use it in GitHub Desktop.
parse error stack
// "error-stack-parser": "2.0.1",
// "stacktrace-gps": "3.0.2"
// additional sources https://github.com/stacktracejs/stacktrace.js/blob/master/stacktrace.js#L102-L116
import fs from 'fs';
import path from 'path';
import { SourceMapConsumer } from 'source-map';
import StackTraceGPS from 'stacktrace-gps';
import ErrorStackParser from 'error-stack-parser';
import mapValues from 'lodash/mapValues';
import update from 'lodash/update';
const blackList = ['/webpack-runtime.js'];
function formatFilename(name) {
return path.basename(name);
}
function normalizeAssetNames(assets) {
return Object.values(assets)
.map(i => i.js)
.filter(Boolean)
.filter(name => !blackList.includes(name))
.map(formatFilename);
}
function _getSources(filenames, publicPath) {
return filenames.reduce(function collectSources(acc, filename) {
const resolvedPath = path.join(publicPath, filename);
const sourceFile = fs.readFileSync(resolvedPath, 'utf-8');
acc[filename] = sourceFile;
return acc;
}, {});
}
function getFileSources(filenames, publicPath) {
return _getSources(filenames, publicPath);
}
function getSourceMapSources(filenames, publicPath) {
const sourceMapCache = _getSources(filenames, publicPath);
return mapValues(sourceMapCache, file => new SourceMapConsumer(file));
}
export function createSourceMapsCache(assets, publicPath) {
const filenames = normalizeAssetNames(assets);
const sourceCache = getFileSources(filenames, publicPath);
const filenamesMap = filenames.map(name => `${name}.map`);
const sourceMapConsumerCache = getSourceMapSources(filenamesMap, publicPath);
const gps = new StackTraceGPS({
offline: true,
sourceCache,
sourceMapConsumerCache
});
return {
formatError(errorObject) {
return Promise.resolve().then(function formatErrorStack() {
const parsedErrorStack = ErrorStackParser.parse(errorObject)
.filter(o => o.fileName)
.map(obj => update(obj, 'fileName', formatFilename))
.map(s => gps.pinpoint(s));
return Promise.all(parsedErrorStack).then(function formatError(stack) {
return {
name: errorObject.name,
message: errorObject.message,
stack: stack.join('\n')
};
});
});
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment