Skip to content

Instantly share code, notes, and snippets.

@fasterthanlime
Created December 23, 2014 14:57
Show Gist options
  • Save fasterthanlime/661c7d96644a7d5846b8 to your computer and use it in GitHub Desktop.
Save fasterthanlime/661c7d96644a7d5846b8 to your computer and use it in GitHub Desktop.
Pretty stack trace support for Duktape/ooc with TypeScript & sourcemaps
function lpad(input, len) {
var s = "" + input;
while (s.length < len) {
s = " " + s;
}
return s;
}
function rpad(input, len) {
var s = "" + input;
while (s.length < len) {
s = s + " ";
}
return s;
}
var sourcemap = require('source-map');
var fs = require('fs');
var input = fs.readFileSync("trace.txt") + "";
var lines = input.split("\n").map(function (x) { return x.trim(); });
console.log(lines[0]);
console.log(lines[1]);
var frames = lines.slice(3, lines.length);
var arrow = " ⇒ ";
for (var i = 0; i < frames.length - 1; i++) {
var frame = frames[i];
var matches = frame.match(/^(\w+)\s([\w\/]+):([0-9]+).*$/);
var prefix = lpad(i, 3) + " ☃ ";
if (matches) {
var func = matches[1];
var module = matches[2];
var line = parseInt(matches[3], 10);
var mapPath = "assets/js/" + module + ".js.map";
rawSourceMap = JSON.parse(fs.readFileSync(mapPath));
var smc = new sourcemap.SourceMapConsumer(rawSourceMap);
var pos = smc.originalPositionFor({line: line, column: 100000});
if (pos && pos.source) {
var source = pos.source.replace(/^(\.\.\/)+app\//, "");
console.log(prefix + rpad(pos.name + "()", 20) + arrow + source + ":" + pos.line);
} else {
var formatted = frame.replace(/^\w+\s*/, "");
console.log(prefix + rpad("???", 20) + arrow + formatted);
}
} else {
var formatted = frame.replace(/^\w+\s*/, "");
console.log(prefix + rpad("???", 20) + arrow + formatted);
}
}
console.log(frames[frames.length - 1]);
@fasterthanlime
Copy link
Author

I know the code is ugly :) plus most of the real intelligence is in Mozilla's "source-map" npm package. But honestly I don't need much more and it's working well. Huge return on investment for such easy to write throwaway code.

In case you're wondering about column: 100000: here's how the source-map package behaves: if you specify column: 0 (my first instinct, to get just the line number), it'll sometimes fail because lines are indented and sometimes there's no toke info until column 2, or 4, or 8, or.. you get the idea. However, having a column too big isn't a problem at all - token length isn't stored, so it just assumes tokens can be arbitrarily large. With this, I'm 99% sure it'll get the right line number (And if it fails, there's a fallback too).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment