8

I need to get a full call stack when an exception occurs in JavaScript on Internet Explorer 8. Function calls may occur between frames whose number is large.

Call stack necessary to send logs to the developers. I cannot use a debugger, because the end user does not have to deal with this problem.

The current solution for JavaScripts provided it can generate callstack (http://eriwen.com/javascript/js-stack-trace/). It is based on arguments.callee.caller. But the caller returns zero ( undefined ) if the function was called from outside the current frame. Thus callstack obtained is incomplete.

Can I get the name of a frame from which the function was called in this case?

Solution based on Active Scripts Technology gives an object of type ScriptEngine: IHTMLDocument:: get_Script (IDispatch ** p)

But casting object "script" to the interface IActiveScript fails.

*Can I get out of IE8 the link to be used for a given context ScriptEngine, to extract the necessary information to construct the callstack?

Wayne Koorts
  • 10,861
  • 13
  • 46
  • 72
RostislavS
  • 81
  • 3
  • I sure hope you get a good answer to this and post something to the community, we need it! FYI, js-stack-trace will also give an erroneous stack trace if any of the functions in the stack are called more than once because "the value of caller attribute is a function, not a stack frame, so the bottom of the stack trace will be missing if some function is called recursively." (http://blog.yoursway.com/2009/07/3-painful-ways-to-obtain-stack-trace-in.html) – Hemlock Dec 28 '10 at 13:32
  • Thanks, Hemlock. Some more explanation for the interaction of Internet Explorer and Java Script Engine is given here: http://blogs.msdn.com/b/jaiprakash/archive/2007/01/22/jscript-exceptions-not-handled-thrown-across-frames-if-thrown-from-a-expando-method.aspx but this does not solve the problem :( – RostislavS Jan 12 '11 at 14:12
  • 2
    Avoid cross-frame communication would be the easiest solution. – Raynos Feb 02 '11 at 19:04

1 Answers1

2

I've found some way, which may be usefull. It utilizes the idea of callbacks.

Define next simple function at every frame:

function getCaller() { return arguments.callee.caller; }

and next functions only for top frame:

function populateStack(fn) {
    var perFrames = [];
    for (var i = 0; i < windows.length; i++) {
        var win = windows[i];
        var func = (win == this) ? fn : win.getCaller();
        var localStack = [];
        while (func) {
            localStack.push(getFuncName(func));
            func = func.caller;
        }
        perFrames.push(getWinName(win) + ": " + localStack.join(", "));
    }
    alert(perFrames.join("\n"));
}

function getWinName(win) {
    var m = win.location.toString().match(/^.*\/(.*)$/);
    return m[1];
}

function getFuncName(func) {
    var m = func.toString().match(/^function\s*(\w*)\(/);
    return m[1] || "anonymous";
}

windows should be an array at the top frame containing all window objects (i.e. frames). Usage:

window.top.populateStack.call(window, arguments.callee);

I've spent a pair of hours, trying to restore exact order, in which functions was called, but have found no solution. Only partial order (functions are correctly sorted within frames) is available in that code.

If you have several servers with different versions of code, then you may add a code, which will analyze function bodies and through that obtain more information about call order.

Hope, this helps :-)

kirilloid
  • 14,011
  • 6
  • 38
  • 52
  • Thanks, kirilloid. Maybe it's the only solution for this moment. – RostislavS Feb 07 '11 at 06:43
  • Interesting bug in IE8: [JScript exceptions not handled/thrown across frames if thrown from a expando method](http://blogs.msdn.com/b/jaiprakash/archive/2007/01/22/jscript-exceptions-not-handled-thrown-across-frames-if-thrown-from-a-expando-method.aspx). This article calls into question the efficiency of the system of exceptions in IE8 (in IE9.b seems to be fixed) – RostislavS Feb 07 '11 at 06:43