
Wednesday January 23, 2008
Improved Callstack information in JavaScript
In this post I blogged about a simple function to get the call stack in JavaScript. Here is an improved variant of the same function:
/**
* This function returns an array of objects that contain the information about call stack.
*/
function callstack() {
function StackFrame(funcName, funcSource, flName, lnNumber) {
this.functionName = funcName;
this.functionSource = funcSource;
this.fileName = flName;
this.lineNumber = lnNumber;
}
StackFrame.prototype.toString = function() {
return 'at ' + this.functionName + '(' + this.fileName + ':' + this.lineNumber + ')' ;
};
StackFrame.prototype.toHtml = function() {
return '<table border="0">' +
'<tr valign="top"><td><b>Name: </b></td><td>' + this.functionName + '</td></tr>' +
'<tr valign="top"><td><b>File: </b></td><td>' + this.fileName + '</td></tr>' +
'<tr valign="top"><td><b>Line: </b></td><td>' + this.lineNumber + '</td></tr>' +
'<tr valign="top"><td><b>Source:</b></td><td>' +
( this.functionSource ?
'<pre>' + this.functionSource.toString().replace(/\</g, '<').replace(/\>/g, '>') + '</pre>' :
'unavailable') + '</td></tr>' +
'</table>'
;
};
var stackFrameStrings = new Error().stack.split('\n');
// remove first two stack frames
stackFrameStrings.splice(0,2);
var stackFrames = [];
for (var i in stackFrameStrings) {
// a stack frame string split into parts
var stackFrame = stackFrameStrings[i].split('@');
if (stackFrame && stackFrame.length == 2) {
stackFrames.push(
// Stackframe object
new StackFrame(stackFrame[0],
eval(stackFrame[0].replace(callstack.sansParenthesisRE,'')),
stackFrame[1].match(callstack.fileNameLineNumberRE)[1], // first group
stackFrame[1].match(callstack.fileNameLineNumberRE)[2] // second group
)
);
}
}
return stackFrames;
}
callstack.sansParenthesisRE = /[(][^)]*[)]/;
callstack.fileNameLineNumberRE = /(.*):(\d+)$/;
Here is how it canbe used. The callstack function code above is assumed to be stored in a file named Utilities.js .
<html>
<head>
<title>Callstack</title>
<script src='Utilities.js'></script>
<script>
function called() {
var cs = callstack();
document.write(cs[0].toHtml());
document.write(cs[1].toHtml());
document.write(cs[2].toHtml());
}
function caller() {
called();
}
</script>
</head>
<body onload="caller();">
</body>
</html>
Here is the output as displayed in the browser (FireFox):
| Name: | called() |
| File: | file:///languages/javascript/Callstack.html |
| Line: | 7 |
| Source: | function called() { var cs = callstack(); document.write(cs[0].toHtml()); document.write(cs[1].toHtml()); document.write(cs[2].toHtml()); } |
| Name: | caller() |
| File: | file:///languages/javascript/Callstack.html |
| Line: | 13 |
| Source: | function caller() { called(); } |
| Name: | onload([object Event]) |
| File: | file:///languages/javascript/Callstack.html |
| Line: | 1 |
| Source: | function onload(event) { caller(); } |
Posted by sandipchitale
( Jan 23 2008, 07:46:59 AM PST ) Permalink
Trackback URL: http://blogs.sun.com/scblog/entry/improved_callstack_information_in_javascript