Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
207 views
Welcome To Ask or Share your Answers For Others

1 Answer

The problem is that the unique_ptr for the platform is getting destroyed once the scope ends. Moving it into the parent scope fixes it.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...