Senica Gonzalez
Senica Gonzalez

Reputation: 8182

Javascript: debug stack trace with source maps

This may be a bit of an odd question, I can't seem to search the right phrase to pull up any relevant answers.

We have an app that runs on clients machines and is minified. We generate source maps, but they are not exposed to production versions.

I have a window.onerror that I use a catch all for sloppy code that finds it's way in unbeknownst to me. Thankfully, this is almost never utilized. Recently, I've been getting an undefined error popping up occasionally so someone has found a way to do something not intended. Chrome does a nice job recording row and column number in the stack trace which we log to a logging server when onerror catches one of these buggers, but that's all I have to debug with and looking through a min file is less than appealing. And undefined is not a function is not very helpful either :)

Question: is there a tool out there - maybe in nodejs - that can take a min file, source map, and a stack trace string and produce relevant files, line numbers, and column numbers?

I realize that the browser does this for you at runtime, but in this case I don't have that luxury as I'm trying to figure out what the error actually is after the fact.

Upvotes: 20

Views: 7169

Answers (4)

Joe Coder
Joe Coder

Reputation: 4525

There is a very popular project called source-map-support which does this easily.

Client-side JavaScript

<script src="browser-source-map-support.js"></script>
<script>sourceMapSupport.install();</script>

NodeJS (programmatic)

require('source-map-support').install();

NodeJS (CLI)

node -r source-map-support/register compiled.js

Upvotes: 2

Jimb Esser
Jimb Esser

Reputation: 11

I found https://github.com/thlorenz/stack-mapper easy to use to do this automatically. If you are looking to do this interactively, you can use stack-mapper in a web browser with a tool like this one: https://github.com/Jimbly/stackwalker - just load your .map file, paste the (minified) callstack or single error location and then you can click through the stack and see the original code on the right.

Upvotes: 0

AlignedDev
AlignedDev

Reputation: 8232

stacktrace.js looks to be another useful tool to achieve this.

Example from their website:

var error = new Error('BOOM!');
StackTrace.fromError(error).then(callback).catch(errback)
=> Promise(Array[StackFrame], Error);

Upvotes: 4

Senica Gonzalez
Senica Gonzalez

Reputation: 8182

Found this: https://github.com/thlorenz/stack-mapper

I use uglify which seems to produce the correct mapping that this needs and it looks like it will work for the case I suggested above.

Edit Actually, this one works a lot better and is much simpler to use https://github.com/mozilla/source-map/.

Example Usage:

var fs = require('fs');
var smc = require('source-map');

var stack = "TypeError: undefined is not a function\r\nat h/min/min.js?1404839824760:9:23048";
stack = stack.split(/\r\n/g);
var error = stack.shift(); // First line is the actual error

var errors = [];
var file = null;

stack.forEach(function(line){
    var _trace = line.split('/').pop();
    var trace = {};
    trace.filename = _trace.split('?').shift();
    _trace = _trace.split(':');
    trace.line = parseInt(_trace[1], 10);
    trace.column = parseInt(_trace[2], 10);
    errors.push(trace);

    if(!file)
        file = trace.filename.split('.').shift();

    trace.filename = __dirname + '/../min/' + trace.filename;
});

// This does not account for multiple files in stack trace right now
var map = fs.readFileSync(__dirname + '/../src/' + file + '.js.map');
map = JSON.parse(map);
var sm = new smc.SourceMapConsumer(map);
console.log(sm.originalPositionFor(errors[0]));

Upvotes: 11

Related Questions