Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript Stack Trace in IE (or maybe just a simple Javascript error)

I came across this method to produce a Javascript stack trace (to fix an IE specific bug): http://pastie.org/253058.txt which sounds really useful, but when I call it, the stack trace I get is for the code of the script itself?!

Can this code be changed to produce a general stack trace? Or is there a better way to get a stack trace in IE?

(function () {

YOUR_NAMESPACE.getStackTrace = (function () {

var mode;
try {(0)()} catch (e) {
    mode = e.stack ? 'Firefox' : window.opera ? 'Opera' : 'Other';
}

switch (mode) {
    case 'Firefox' : return function () {
        try {(0)()} catch (e) {
            return e.stack.replace(/^.*?\n/,'').
                           replace(/(?:\n@:0)?\s+$/m,'').
                           replace(/^\(/gm,'{anonymous}(').
                           split("\n");
        }
    };

    case 'Opera' : return function () {
        try {(0)()} catch (e) {
            var lines = e.message.split("\n"),
                ANON = '{anonymous}',
                lineRE = /Line\s+(\d+).*?in\s+(http\S+)(?:.*?in\s+function\s+(\S+))?/i,
                i,j,len;

            for (i=4,j=0,len=lines.length; i<len; i+=2) {
                if (lineRE.test(lines[i])) {
                    lines[j++] = (RegExp.$3 ?
                        RegExp.$3 + '()@' + RegExp.$2 + RegExp.$1 :
                        ANON + RegExp.$2 + ':' + RegExp.$1) +
                        ' -- ' + lines[i+1].replace(/^\s+/,'');
                }
            }

            lines.splice(j,lines.length-j);
            return lines;
        }
    };

    default : return function () {
        var curr  = arguments.callee.caller,
            FUNC  = 'function', ANON = "{anonymous}",
            fnRE  = /function\s*([\w\-$]+)?\s*\(/i,
            stack = [],j=0,
            fn,args,i;

        while (curr) {
            fn    = fnRE.test(curr.toString()) ? RegExp.$1 || ANON : ANON;
            args  = stack.slice.call(curr.arguments);
            i     = args.length;

            while (i--) {
                switch (typeof args[i]) {
                    case 'string'  : args[i] = '"'+args[i].replace(/"/g,'\\"')+'"'; break;
                    case 'function': args[i] = FUNC; break;
                }
            }

            stack[j++] = fn + '(' + args.join() + ')';
            curr = curr.caller;
        }

        return stack;
    };
}

})();
like image 818
Gavin Avatar asked Oct 01 '09 08:10

Gavin


1 Answers

This getStackTrace() function creates the stack trace of the function from which you've called getStackTrace(). It does not create the stack trace of an error that you've caught. For example, you'd use it to try to figure out how a specific function is being called:

function foo() {
    // debug how this is being called
    alert(YOUR_NAMESPACE.getStackTrace());
}

Or to add some more detail to an error you raise:

function foo() {
    // signal something went wrong
    var error = new Error("error in foo");
    if (!error.stack)
        error.stack = YOUR_NAMESPACE.getStackTrace();
    throw error;
}

You can not use it like this:

try {
    foo();
} catch (e) {
    alert(YOUR_NAMESPACE.getStackTrace(e));
}

Here's a good rundown of what stack information you can get -- and from which browsers -- when an error occurs: Three Painful Ways to Obtain a Stack Trace in Javascript (Archive.org link replacing dead link)

like image 176
Justin Ludwig Avatar answered Sep 22 '22 13:09

Justin Ludwig