Calling on V8 experts. I am embedding V8 in a project of mine and I am running into issues modularizing my code. The simplest example of this is compiling and running a small script that prints "Hello World!" from a C++ function. The working version is as follows:
void testV8(const v8::FunctionCallbackInfo<v8::Value>& args) {
printf("Hello World!
");
}
void working() {
v8::Isolate* isolate = nullptr;
std::string code = "testV8();";
{
// Basic initialization
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize();
v8::Isolate::CreateParams initOptions;
initOptions.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
isolate = v8::Isolate::New(initOptions);
isolate->Enter();
// Create context
v8::HandleScope handleScope(isolate);
auto global = v8::ObjectTemplate::New(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate, nullptr, global);
// Enter context
v8::Context::Scope contextScope(context);
// Bind function
v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(isolate, &testV8);
auto name = v8::String::NewFromUtf8(isolate, "testV8").ToLocalChecked();
context->Global()->Set(context, name, ft->GetFunction(context).ToLocalChecked());
// Run script
auto execCode = v8::String::NewFromUtf8(isolate, code.c_str()).ToLocalChecked();
v8::Local<v8::Script> script;
if (v8::Script::Compile(context, execCode).ToLocal(&script)) {
v8::Local<v8::Value> result;
script->Run(context).ToLocal(&result);
}
}
}
When I try to split the code up into manageable scopes (mimicking wrapper classes I want to build later), I get a crash upon script compilation:
void testV8(const v8::FunctionCallbackInfo<v8::Value>& args) {
printf("Hello World!
");
}
void failing() {
v8::Isolate* isolate = nullptr;
std::string code = "testV8();";
v8::Persistent<v8::Context> persistentContext;
{
// Basic initialization
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize();
v8::Isolate::CreateParams initOptions;
initOptions.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
isolate = v8::Isolate::New(initOptions);
isolate->Enter();
// Create context
v8::HandleScope handleScope(isolate);
auto global = v8::ObjectTemplate::New(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate, nullptr, global);
// Save context
persistentContext.Reset(isolate, context);
}
{
// Rebuild scopes and enter context
v8::Locker locker(isolate);
v8::HandleScope handleScope(isolate);
v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate, persistentContext);
v8::Context::Scope contextScope(context);
// Bind function
v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(isolate, &testV8);
auto name = v8::String::NewFromUtf8(isolate, "testV8").ToLocalChecked();
context->Global()->Set(context, name, ft->GetFunction(context).ToLocalChecked());
}
{
// Rebuild scopes and enter context
v8::Locker locker(isolate);
v8::HandleScope handleScope(isolate);
v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate, persistentContext);
v8::Context::Scope contextScope(context);
// Run script
auto execCode = v8::String::NewFromUtf8(isolate, code.c_str()).ToLocalChecked();
v8::Local<v8::Script> script;
if (v8::Script::Compile(context, execCode).ToLocal(&script)) {
v8::Local<v8::Value> result;
script->Run(context).ToLocal(&result);
}
}
}
Building on xCode and running on this code on a Macbook. I can't tell if I'm doing anything wrong or if there is some bug with the contexts. Research online leads me to believe that using persistent contexts this way is fine to keep the same context alive between scopes. What's going wrong here?
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…