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

Reply via email to