防止 v8::Local 值被垃圾回收

Prevent v8::Local value from being garbage collected

我有一个函数将参数值存储到 C++ class 的 std::vector<v8::Local<v8::Value>> 属性 公开为 ObjectWrap,如下所示:

NAN_METHOD(MyObject::Write) {
  MyObject* obj = Nan::ObjectWrap::Unwrap<MyObject>(info.This());
  obj->data.push_back(info[0]);
}

但是,当我尝试从另一个 C++ 函数中读回值 时,该值丢失了,变成了 undefined.

我正在将一个数字传递给 MyObject::Write,我可以确认 info[0]->IsNumber() returns true,然后再将其推送到矢量,但是当读回它时,值 它不是 一个数字,实际上 returns false 对于我使用 v8::Value 中的 Is<Type> 方法测试的所有类型,但仍然 returns true BooleanValue().

我的猜测是变量在 MyObject::Write returns 之后被垃圾回收,但是我不知道如何防止这种情况发生。


我目前正在尝试将该值初始化为 Persistent 值。我尝试了以下尝试但没有成功:

Nan::CopyablePersistentTraits<v8::Value>::CopyablePersistent p;
Nan::Persistent<v8::Value> persistent(info[0]);
Nan::CopyablePersistentTraits::Copy(persistent, p);

并且:

v8::Isolate *isolate = info.GetIsolate();
v8::Persistent<v8::Value, v8::CopyablePersistentTraits<v8::Value>> persistent(isolate, info[0]);

但是出现大量 C++ 错误。

如果您计划在 C++ 中存储 v8 值,则需要使它们持久化而不是本地化,这样它们就独立于句柄范围,并且在释放句柄范围时不会被垃圾回收。

Nan has version-independant wrappers for v8::Persistent and Co. 因为使用内部 std::vector<>,你还需要用 Nan::CopyablePersistentTraits 初始化 Nan::Persistent 所以它变得可复制(或为它制作一个自己的引用计数容器)。

我 运行 遇到了自己解决这个烂摊子的问题。这里有很多我们都错过的模板内容。这是我发现最易读的解决方案:

// Define the copyable persistent
v8::CopyablePersistentTraits<v8::Value>::CopyablePersistent p;

// Create the local value
auto val = v8::Local<v8::Value>::New(
    v8::Isolate::GetCurrent(), //< Isolate required
    v8::Integer::New(v8::Isolate::GetCurrent(), v) //< Isolate required
);

// Reset() is a TEMPLATE FUNCTION, you have to template it with the same
// template type parameter as the v8::Local you are passing
p.Reset<v8::Value>(v8::Isolate::GetCurrent(), val); //< Isolate required

"info" 我假设您指的是 v8::FunctionCallbackInfo 参考。如果是这样,上面的代码将折叠为以下内容:

void SomeFunc(v8::FunctionCallbackInfo<v8::Value>& info) {
    v8::CopyablePersistentTraits<v8::Value>::CopyablePersistent p;
    p.Reset<v8::Value>(info[0]);
}

因为持久性现在是可复制的,所以您可以做一些事情,例如将它存储在标准库容器中。这是我的用例。这是在向量中存储值的示例:

std::vector<v8::CopyablePersistentTraits<v8::Value>::CopyablePersistent> vect;

void AccumulateData(v8::FunctionCallbackInfo<v8::Value>& info) {
    v8::CopyablePersistentTraits<v8::Value>::CopyablePersistent p;
    p.Reset<v8::Value>(info[0]);
    vect.push_back(p);
}

我希望这对那里的人有所帮助。