v8:无法在functioncallback中调用函数名

时间:2014-09-04 13:16:31

标签: v8

我想记录运行js脚本时调用的每个函数。 所以我想对javascript中的所有函数进行回调,如下所示:

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时会打印:function unescape(){[native code]}

但如果这样做:

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时会打印:function(){[native code]}

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

1 个答案:

答案 0 :(得分:1)

我对V8还不熟悉,但遇到了同样的问题。到目前为止,我找到了一个解决方案。我不确定它是否理想,但没有其他解决方案,所以这里......

请注意,获取名称的函数是将FunctionTemplate值添加到ObjectTemplate的位置(可能在创建Context时用作全局模板参数)。还要注意那些不能正常工作的你试图将函数添加到现有Context的全局Object中,这就是获取Callee名称失败时(返回一个空字符串)。

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

试图通过一些代码来说明这一点:

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);
}