2014-09-04 145 views
2

我想在运行js脚本时调用每个函数的日志。 所以我想为所有在JavaScript这样的功能的回调:v8:无法在函数调用中获取调用函数名称

global->Set(v8::String::NewFromUtf8(isolate, "print"), v8::FunctionTemplate::New(isolate, LogName)); 
global->Set(v8::String::NewFromUtf8(isolate, "eval"), v8::FunctionTemplate::New(isolate, LogName)); 
global->Set(v8::String::NewFromUtf8(isolate, "unescape"), v8::FunctionTemplate::New(isolate, LogName)); 

我这样定义我的功能:

void LogName(const v8::FunctionCallbackInfo<v8::Value>& args) { 
    v8::String::Utf8Value str_caller(args.Callee()); 
    printf("%s", str_caller); 
} 

这时候UNESCAPE被称为印刷:功能UNESCAPE() {[本地代码]}

但是,如果这样做:

object = v8::Handle<v8::Object>::Cast(context->Global()->Get(v8::String::NewFromUtf8(isolate, "String"))); 
object->Set(v8::String::NewFromUtf8(isolate, "fromCharCode"), v8::FunctionTemplate::New(isolate, LogName)->GetFunction()); 

这是对在调用String.fromCharCode时r:function(){[native code]}

为什么在第二个示例中,我没有函数名称,例如“fromCharCode”?

回答

1

我还是V8的新手,但遇到了同样的问题。到目前为止我只找到一个解决方案。我不知道它是否理想,但没有其他解决方案,所以在这里...

请注意获取名称的作用是将FunctionTemplate值添加到ObjectTemplate的位置(大概是这样在创建上下文时用作全局模板参数)。另外请注意,在那些不起作用的情况下,您正在尝试为该现有上下文的全局对象添加一个函数,这是在获取被调用者名称失败时(返回空字符串)。

到目前为止,我发现的唯一解决方案是为您为全局范围创建的ObjectTemplate保留一个持久句柄,在注册新函数时添加FunctionTemplate,然后创建一个新的Context那个修改过的ObjectTemplate。在此之后,调用该函数将根据需要返回被调用者名称。

要尽量说明这与一些代码:

Isolate *gIsolate; 
Persistent<ObjectTemplate> gTemplate; 
Persistent<Context> gContext; 

// Adds a new function to the global object template 
void AddFunction(const char *name, FunctionCallback func) 
{ 
    // Get global template 
    Local<ObjectTemplate> global = ObjectTemplate::New(gIsolate, gTemplate); 

    // Add new function to it 
    global->Set(String::NewFromUtf8(gIsolate, name), FunctionTemplate::New(gIsolate, func)); 
} 

void FirstTimeInit() 
{ 
    gIsolate = Isolate::New(); 
    HandleScope handle_scope(gIsolate); 
    Handle<ObjectTemplate> global = ObjectTemplate::New(gIsolate); 

    // Store global template in persistent handle 
    gTemplate.Reset(gIsolate, global); 

    // Register starting functions 
    AddFunction("print", LogName); 
    AddFunction("eval", LogName); 
    AddFunction("unescape", LogName); 

    // Create context 
    Handle<Context> context = Context::New(gIsolate, NULL, global); 

    gContext.Reset(gIsolate, context); 
} 

void AddOtherFunction() 
{ 
    AddFunction("fromCharCode", LogName); 

    Local<ObjectTemplate> global = ObjectTemplate::New(gIsolate, gTemplate); 

    // Create a new context from the modified global template 
    Local<Context> newContext = Context::New(gIsolate, nil, global); 

    // Update persistent context handle to reference the new one 
    gContext.Reset(gIsolate, newContext); 
}