Skip to content

Commit

Permalink
Parsing and testing stack traces from IE, FF, Chrome, Safari
Browse files Browse the repository at this point in the history
  • Loading branch information
Calamari committed Feb 5, 2014
0 parents commit a479524
Show file tree
Hide file tree
Showing 6 changed files with 309 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
20 changes: 20 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module.exports = function(grunt) {
var pkg = require('./package.json');

grunt.initConfig({
shell: { // grunt-shell-spawn
options: {
stdout: true,
stderr: true
},
mocha: {
command: './node_modules/.bin/mocha --reporter spec test/**/*.js',
}
}
});


grunt.loadNpmTasks('grunt-shell-spawn');

grunt.registerTask('test', ['shell:mocha']);
};
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('./lib/stacktrace-parser.js');
45 changes: 45 additions & 0 deletions lib/stacktrace-parser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@


var UNKNOWN_FUNCTION = '<unknown>';

var StackTraceParser = {
/**
* This parses the different stack traces and puts them into one format
* This borrows heavily from TraceKit (https://github.com/occ/TraceKit)
*/
parse: function(stackString) {
var chrome = /^\s*at (?:(?:(?:Anonymous function)?|((?:\[object object\])?\S+(?: \[as \S+\])?)) )?\(?((?:file|http|https):.*?):(\d+)(?::(\d+))?\)?\s*$/i,
gecko = /^(?:\s*(\S*)(?:\((.*?)\))?@)?((?:file|http|https).*?):(\d+)(?::(\d+))?\s*$/i,
lines = stackString.split('\n'),
stack = [],
parts,
element;

for (var i = 0, j = lines.length; i < j; ++i) {
if ((parts = gecko.exec(lines[i]))) {
element = {
'file': parts[3],
'methodName': parts[1] || UNKNOWN_FUNCTION,
'lineNumber': +parts[4],
'column': parts[5] ? +parts[5] : null
};
} else if ((parts = chrome.exec(lines[i]))) {
element = {
'file': parts[2],
'methodName': parts[1] || UNKNOWN_FUNCTION,
'lineNumber': +parts[3],
'column': parts[4] ? +parts[4] : null
};
} else {
continue;
}

stack.push(element);
}

return stack;
}
};


module.exports = StackTraceParser;
22 changes: 22 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"author": "Georg Tavonius <g.tavonius@gmail.com> (http://jaz-lounge.com)",
"name": "stacktrace-parser",
"description": "Parses every stack trace into a nicely formatted array of hashes.",
"version": "0.1.0",
"engines": {
"node": "~0.10"
},
"dependencies": {},
"devDependencies": {
"mocha": "*",
"should": "*",
"expect.js": "*",
"grunt-cli": "~0.1.13",
"grunt": "~0.4.2",
"grunt-shell-spawn": "~0.3.0"
},
"main": "index.js",
"scripts": {
"test": "make test"
}
}
220 changes: 220 additions & 0 deletions test/stacktrace_parser_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
var expect = require('expect.js'),

StackTraceParser = require('../lib/stacktrace-parser');

describe('StackTraceParser', function() {
var data = {
'Chrome & Chrome Mobile & Opera': [
{
from: "Error: with timeout\n at http://errwischt.com/stack_traces/test:76:15\n at wrapped (http://errwischt.com/bandage.js:51:25)",
to: [
{ file: 'http://errwischt.com/stack_traces/test',
methodName: '<unknown>',
lineNumber: 76,
column: 15 },
{ file: 'http://errwischt.com/bandage.js',
methodName: 'wrapped',
lineNumber: 51,
column: 25 }
]
},
{
from: "Error: with timeout and named func\n at timeoutWithName (http://errwischt.com/stack_traces/test:83:15)\n at wrapped (http://errwischt.com/bandage.js:51:25)",
to: [
{ file: 'http://errwischt.com/stack_traces/test',
methodName: 'timeoutWithName',
lineNumber: 83,
column: 15 },
{ file: 'http://errwischt.com/bandage.js',
methodName: 'wrapped',
lineNumber: 51,
column: 25 }
]
},
{
from: "TypeError: Object # has no method 'objectBreakDown'\n at HTMLDocument. (http://errwischt.com/stack_traces/test:91:19)\n at l (http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js:4:24882)\n at Object.c.fireWith [as resolveWith] (http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js:4:25702)\n at Function.x.extend.ready (http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js:4:2900)\n at HTMLDocument.S (http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js:4:553)",
to: [
{ file: 'http://errwischt.com/stack_traces/test',
methodName: 'HTMLDocument.',
lineNumber: 91,
column: 19 },
{ file: 'http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js',
methodName: 'l',
lineNumber: 4,
column: 24882 },
{ file: 'http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js',
methodName: 'Object.c.fireWith [as resolveWith]',
lineNumber: 4,
column: 25702 },
{ file: 'http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js',
methodName: 'Function.x.extend.ready',
lineNumber: 4,
column: 2900 },
{ file: 'http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js',
methodName: 'HTMLDocument.S',
lineNumber: 4,
column: 553 }
]
}
],
'Firefox': [
{
from: "timeoutWithName@http://errwischt.com/stack_traces/test:83\nwrapped@http://errwischt.com/bandage.js:51",
to: [
{ file: 'http://errwischt.com/stack_traces/test',
methodName: 'timeoutWithName',
lineNumber: 83,
column: null },
{ file: 'http://errwischt.com/bandage.js',
methodName: 'wrapped',
lineNumber: 51,
column: null }
]
},
{
from: "@http://errwischt.com/stack_traces/test:76\nwrapped@http://errwischt.com/bandage.js:51",
to: [
{ file: 'http://errwischt.com/stack_traces/test',
methodName: '<unknown>',
lineNumber: 76,
column: null },
{ file: 'http://errwischt.com/bandage.js',
methodName: 'wrapped',
lineNumber: 51,
column: null }
]
},
{
from: "@http://errwischt.com/stack_traces/test:97\nx.Callbacks/l@http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js:4\nx.Callbacks/c.fireWith@http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js:4\n.ready@http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js:4\nS@http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js:4",
to: [
{ file: 'http://errwischt.com/stack_traces/test',
methodName: '<unknown>',
lineNumber: 97,
column: null },
{ file: 'http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js',
methodName: 'x.Callbacks/l',
lineNumber: 4,
column: null },
{ file: 'http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js',
methodName: 'x.Callbacks/c.fireWith',
lineNumber: 4,
column: null },
{ file: 'http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js',
methodName: '.ready',
lineNumber: 4,
column: null },
{ file: 'http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js',
methodName: 'S',
lineNumber: 4,
column: null }
]
}
],
'Safari': [
{
from: "timeoutWithName@http://bandage.local:8181/stack_traces/test:83:55\nwrapped@http://bandage.local:8181/bandage.js:51:30",
to: [ { file: 'http://bandage.local:8181/stack_traces/test',
methodName: 'timeoutWithName',
lineNumber: 83,
column: 55 },
{ file: 'http://bandage.local:8181/bandage.js',
methodName: 'wrapped',
lineNumber: 51,
column: 30 } ]
},
{
from: "http://bandage.local:8181/stack_traces/test:76:40\nwrapped@http://bandage.local:8181/bandage.js:51:30",
to: [ { file: 'http://bandage.local:8181/stack_traces/test',
methodName: '<unknown>',
lineNumber: 76,
column: 40 },
{ file: 'http://bandage.local:8181/bandage.js',
methodName: 'wrapped',
lineNumber: 51,
column: 30 } ]
},
{
from: "http://bandage.local:8181/stack_traces/test:97:28\nl@http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js:4:24909\nfireWith@http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js:4:50440\nready@http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js:4:2933\nS@http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js:4:580",
to: [ { file: 'http://bandage.local:8181/stack_traces/test',
methodName: '<unknown>',
lineNumber: 97,
column: 28 },
{ file: 'http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js',
methodName: 'l',
lineNumber: 4,
column: 24909 },
{ file: 'http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js',
methodName: 'fireWith',
lineNumber: 4,
column: 50440 },
{ file: 'http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js',
methodName: 'ready',
lineNumber: 4,
column: 2933 },
{ file: 'http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js',
methodName: 'S',
lineNumber: 4,
column: 580 } ]
}
],
'Internet Explorer': [
{
from: "Error: with timeout and named func\n at timeoutWithName (http://bandage.jaz-lounge.com/stack_traces/test:83:9)\n at wrapped (http://bandage.jaz-lounge.com/bandage.js:51:13)",
to: [ { file: 'http://bandage.jaz-lounge.com/stack_traces/test',
methodName: 'timeoutWithName',
lineNumber: 83,
column: 9 },
{ file: 'http://bandage.jaz-lounge.com/bandage.js',
methodName: 'wrapped',
lineNumber: 51,
column: 13 } ]
},
{
from: "Error: with timeout\n at Anonymous function (http://bandage.jaz-lounge.com/stack_traces/test:76:9)\n at wrapped (http://bandage.jaz-lounge.com/bandage.js:51:13)",
to: [ { file: 'http://bandage.jaz-lounge.com/stack_traces/test',
methodName: '<unknown>',
lineNumber: 76,
column: 9 },
{ file: 'http://bandage.jaz-lounge.com/bandage.js',
methodName: 'wrapped',
lineNumber: 51,
column: 13 } ]
},
{
from: "TypeError: Object doesn't support property or method 'objectBreakDown'\n at Anonymous function (http://bandage.jaz-lounge.com/stack_traces/test:91:7)\n at l (http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js:4:24874)\n at fireWith (http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js:4:25638)\n at ready (http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js:4:2898)\n at S (http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js:4:551)",
to: [ { file: 'http://bandage.jaz-lounge.com/stack_traces/test',
methodName: '<unknown>',
lineNumber: 91,
column: 7 },
{ file: 'http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js',
methodName: 'l',
lineNumber: 4,
column: 24874 },
{ file: 'http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js',
methodName: 'fireWith',
lineNumber: 4,
column: 25638 },
{ file: 'http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js',
methodName: 'ready',
lineNumber: 4,
column: 2898 },
{ file: 'http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js',
methodName: 'S',
lineNumber: 4,
column: 551 } ]
}
]
};

Object.keys(data).forEach(function(browser) {
describe('can parse stack trace of ' + browser, function() {
data[browser].forEach(function(browserData) {
it(browserData.from, function() {
var result = StackTraceParser.parse(browserData.from);
expect(result.length).to.equal(browserData.to.length);
expect(result).to.eql(browserData.to);
});
});
});
});
});

0 comments on commit a479524

Please sign in to comment.