Question

I want to call JSON.stringify method from the C++ side with modified arguments, but any solution that came to my mind results in a weird segfault with all frames being at "??".

I want to do the following: api::Console is a custom console implementation for debugging purposes and has therefore static methods like api::Console::handleLog or api::Console::handleDebug.

For handleDebug which is passed correctly to the console's ObjectTemplate, the following doesn't work, v8gl::context is the current execution context and is correctly usable in other api implementations:

v8::Handle<v8::Value> Console::handleDebug(const v8::Arguments& args) {

    if (args.Length() < 1) {
        return v8::Undefined();
    }

    v8::HandleScope scope;

    v8::Handle<v8::Object> global = v8gl::context->Global();
    v8::Handle<v8::Object> JSON = global->Get(v8::String::New("JSON"))->ToObject();
    v8::Handle<v8::Function> JSON_stringify = v8::Handle<v8::Function>::Cast(JSON->Get(v8::String::New("stringify")));


    for (signed a = 0; a < args.Length(); a++) {

        for (int m = 0; m < consoleMargin; m++) {
            fprintf(stdout, "\t");
        }

        v8::Handle<v8::Value> passargs[1];
        // alternative try was:
        // passargs[0] = v8::String::New("{foo:'bar'}");
        passargs[0] = v8::String::New(*v8::String::Utf8Value(args[a]->ToString()));


        v8::String::Utf8Value value(JSON_stringify->Call(JSON, 1, passargs));
        char* message = *value;

        fprintf(stdout, "%s\n", message);

    }


    return scope.Close(v8::Undefined());

}

The backtrace in gdb is somehow weird and I have no idea why:

(gdb) backtrace
#0  0x00000000004a0880 in v8::Context::Global() ()
#1  0x00000000004128ea in api::Console::handleDebug(v8::Arguments const&) ()
#2  0x00000000004b9eab in v8::internal::Builtin_HandleApiCall(v8::internal::(anonymous namespace)::BuiltinArguments<(v8::internal::BuiltinExtraArguments)1>, v8::internal::Isolate*) ()
#3  0x000004cd67f0618e in ?? ()
#4  0x000004cd67f12998 in ?? ()
#5  0x000004cd67f060e1 in ?? ()
# (... etc ...)

So my question is the following:

How do I cast correctly from the Local value"v8::Arguments& args" to "v8::Handle<v8::Value>*" for usage with the Call() method of v8::Function?

If I want to use the args[a] directly in the loop, compiler errors are thrown for the differing signature of v8::Function::Call, which is correct due to args being a Local Value. The signature of v8::Function::Call is the following:

v8::Local<v8::Value> v8::Function::Call(v8::Handle<v8::Object>, int, v8::Handle <v8::Value>*)

// Edit: Updated passargs[false index]

Was it helpful?

Solution

You have error there:

    v8::Handle<v8::Value> passargs[1];

    passargs[1/* SHOULD BE 0!!!*/] = 
         v8::String::New(*v8::String::Utf8Value(args[a]->ToString()));

So you try to access element out of array bounds.

BTW: v8::Local<> is inherited from v8::Handle<> so you don't need any magic to convert Local to Handle.

Edit: Most of v8 features require not only v8::HandleScope but also v8::Context::Scope seems you need to create context scope too. You can get valid context form args:

Local<Object> self = args.Holder();
Persistent<Context> context(self->CreationContext());

Then create handle scope and context scope:

Context::Scope work_in_context_scope(context);
HandleScope work_in_this_function_scope;

Then do you job.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top