関数呼び出しハンドラにデータを提供しようとしていますが、ガベージ コレクションを適切に行うことができません。
tpl->SetCallHandler(callFn, external);
" "を含む行をコメントアウトすると、 ObjWeakCallbackが呼び出されます。ただし、関数が収集されることはありません (少なくともFnWeakCallbackは何があっても呼び出されません)。
プロセスごとに複数の分離に備える必要があるため、静的データはオプションではないことに注意してください。
isolate->setData
もオプションではありません。私は何かを完全に見逃していますか?内部v8::Function
にデータを保存する適切な方法は何ですか?
編集:私の意図をよりよく説明するために質問を言い換えましょう...
関数テンプレートを作成したいと思います (JS 側でコンストラクターとして使用する必要があるため)。void* をコール ハンドラに送信する方法が必要ですが、このデータはガベージ コレクション可能でなければなりません。
私がこれまでに試したことに関するいくつかのメモ:
の使用
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;
}