Встроенный контекст V8 и сбой компиляции скрипта - PullRequest
0 голосов
/ 11 марта 2020

Вызов экспертов V8. Я встраиваю V8 в мой проект и сталкиваюсь с проблемами модульности моего кода. Простейшим примером этого является компиляция и запуск небольшого скрипта, который печатает «Hello World!» из функции C ++. Рабочая версия выглядит следующим образом:

void testV8(const v8::FunctionCallbackInfo<v8::Value>& args) {
    printf("Hello World!\n");
}

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);
        }
    }
}

Когда я пытаюсь разделить код на управляемые области (имитируя классы-оболочки, которые я хочу создать позже), я получаю cra sh после компиляции скрипта:

void testV8(const v8::FunctionCallbackInfo<v8::Value>& args) {
    printf("Hello World!\n");
}

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);
        }
    }
}

Сборка на xCode и запуск этого кода на Macbook. Я не могу сказать, делаю ли я что-то неправильно или есть какая-то ошибка с контекстами. Исследования в Интернете заставляют меня поверить, что использование постоянных контекстов таким способом - это хорошая возможность поддерживать один и тот же контекст между областями видимости. Что здесь не так?

1 Ответ

0 голосов
/ 13 марта 2020

Проблема в том, что unique_ptr для платформы разрушается, когда заканчивается область. Перемещение в родительскую область исправляет это.

...