我正在尝试向函数调用处理程序提供数据,但我无法正确地垃圾收集它。
如果我注释掉包含“ tpl->SetCallHandler(callFn, external);
”的行,则调用ObjWeakCallback。但是,该函数永远不会被收集(至少FnWeakCallback永远不会被调用,无论如何)。
请注意,静态数据不是一个选项,因为这需要为每个进程的多个隔离做好准备。
isolate->setData
也不是一种选择。我完全错过了什么吗?在里面存储数据的正确方法是什么v8::Function
,有吗?
编辑:让我重新表述这个问题以更好地描述我的意图......
我想创建一个函数模板(因为我需要将它用作 JS 端的构造函数)。我需要某种方式将 void* 发送到它的调用处理程序,但这些数据必须是可回收的。
到目前为止我一直在尝试的一些注意事项:
using
Function::New(isolate, callHandler, External::New(isolate, data))
有效,但不提供 JS 端构造函数能力(无法为创建的对象设置 SetInternalFieldCount)FunctionTemplate::New(isolate, callHandler, External::New(isolate, data))
提供将数据传递给调用处理程序的能力,但永远不会被垃圾收集(<not> 下面的工作示例)我尝试使用普通函数并返回一个新创建的
Object
,但随后以下假设new Fn() instanceof Fn
失败
#include <v8.h>
#include <iostream>
// made static, just to simplify the example and prevent crashes
// the persistents would normally be wrapped inside a "baton" together with required data
v8::Persistent<v8::Value> p_obj;
v8::Persistent<v8::Value> p_fn;
void FnWeakCallback(const v8::WeakCallbackData<v8::Value, int>& data) {
int* number = data.GetParameter();
std::cout << "GC fn " << number << '\n';
delete number;
p_fn.Reset();
}
void ObjWeakCallback(const v8::WeakCallbackData<v8::Value, int>& data) {
int* number = data.GetParameter();
std::cout << "GC obj " << number << '\n';
delete number;
p_obj.Reset();
}
void callFn(const v8::FunctionCallbackInfo<v8::Value>& info) {
std::cout << "called\n";
}
void test(v8::Isolate* isolate) {
v8::HandleScope scope(isolate);
auto external = v8::External::New(isolate, new int{ 1 });
p_obj.Reset(isolate, external);
p_obj.SetWeak(new int{ 1 }, ObjWeakCallback);
auto tpl = v8::FunctionTemplate::New(isolate);
tpl->SetCallHandler(callFn, external); // <======
tpl->InstanceTemplate()->SetInternalFieldCount(1);
auto fn = tpl->GetFunction();
p_fn.Reset(isolate, fn);
p_fn.SetWeak(new int{ 2 }, FnWeakCallback);
}
int main() {
v8::V8::SetFlagsFromString("--expose-gc", 11);
auto isolate = v8::Isolate::GetCurrent();
v8::HandleScope handle_scope(isolate);
auto context = v8::Context::New(isolate);
context->Enter();
test(isolate);
isolate->RequestGarbageCollectionForTesting(v8::Isolate::kFullGarbageCollection);
context->Exit();
return 0;
}