我想记录运行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”?
答案 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);
}