Hi, all!
i just implemented a little v8::InvocationCallback function which i thought
might be useful to some of you... it fetches v8::StackTrace info from JS
space. What follows is the C++ code, sample JS usage, and sample output.
Sample JS code:
---------
function test2() {
var s = getStackTrace();
print(JSON.stringify(s,undefined,'\t'));
}
function test1() {
new test2();
}
test1();
---------
Output:
[
{
"column": 21,
"functionName": "test2",
"line": 3,
"scriptName": "stacktrace.js",
"isConstructor": true,
"isEval": false
},
{
"column": 5,
"functionName": "test1",
"line": 7,
"scriptName": "stacktrace.js",
"isConstructor": false,
"isEval": false
},
{
"column": 1,
"functionName": "",
"line": 9,
"scriptName": "stacktrace.js",
"isConstructor": false,
"isEval": false
}
]
The C++ code and API docs follow, but the impl uses one function specific to
my library to convert the argument to a uint value. That line will need to
be replaced...
/**
Implements the v8::InvocationCallback interface and has the following
JS interface:
Array stracktrace([unsigned int limit = some reasonable default])
Each element in the returned array represents a stack frame and
is a plain object with the following properties:
column = 1-based column number (note that this is different from most
editors,
but this is how v8 returns this value.)
line = 1-based line number
scriptName = name of the script
functionName = name of the function
isConstructor = true if this is a constructor call
isEval = true if this is part of an eval()
TODO:
- Add a toString() member which creates a conventional-looking
stacktrace string.
*/
v8::Handle<v8::Value> GetV8StackTrace( v8::Arguments const & argv )
{
uint32_t limit = (argv.Length() > 0) ?
convert::CastFromJS<uint32_t>(argv[0]) : 0;
if( limit == 0 ) limit = 8;
else if( limit > 100 ) limit = 100;
Local<StackTrace> const st = StackTrace::CurrentStackTrace( limit,
StackTrace::kDetailed );
int const fcountI = st->GetFrameCount();
// Who the hell designed the StackTrace API to return an int in
GetFrameCount() but take
// an unsigned int in GetFrame()???
uint32_t const fcount = static_cast<uint32_t>(fcountI);
Local<Array> jst = Array::New(fcount);
#define STR(X) v8::String::New(X)
for( uint32_t i = 0; (i < fcount) && (i<limit); ++i )
{
Local<StackFrame> const & sf( st->GetFrame(i) );
Local<Object> jsf = Object::New();
jsf->Set(STR("column"), convert::CastToJS(sf->GetColumn()));
jsf->Set(STR("functionName"), sf->GetFunctionName());
jsf->Set(STR("line"), convert::CastToJS(sf->GetLineNumber()));
jsf->Set(STR("scriptName"), sf->GetScriptName());
jsf->Set(STR("isConstructor"),
convert::CastToJS(sf->IsConstructor()));
jsf->Set(STR("isEval"), convert::CastToJS(sf->IsEval()));
jst->Set(i,jsf);
}
return jst;
#undef STR
}
Note that it doesn't use HandleScope and doesn't need to as long as it is
only called from JS space. If you need to call it from C++ code (which
itself was not called by v8) then you'll need to add a HandleScope and call
(return scope.Close(jst)) at the end instead of (return jst).
i'm getting crashes in v8 when i do:
eval("someCodeWhichCallsGetStackTrace");
but i don't yet know if the problem is in my lib or v8.
Happy Hacking!
--
----- stephan beal
http://wanderinghorse.net/home/stephan/
--
v8-users mailing list
[email protected]
http://groups.google.com/group/v8-users