#include "V8Executor.h" #include "JSValueHelper.h" V8Executor::V8Executor() : platform(v8::platform::NewDefaultPlatform()) { v8::V8::InitializePlatform(platform.get()); v8::V8::Initialize(); create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator(); m_isolate = v8::Isolate::New(create_params); m_isolate_scope = new v8::Isolate::Scope(m_isolate); v8::Isolate *isolate = v8::Isolate::GetCurrent(); v8::HandleScope scope(isolate); v8::Local global = v8::ObjectTemplate::New(isolate); v8::Local context = v8::Context::New(isolate, nullptr, global); context->Enter(); m_global_context = new v8::Global(isolate, context); } V8Executor::~V8Executor() { { v8::HandleScope scope(m_isolate); v8::Local context = m_global_context->Get(m_isolate); context->Exit(); } m_global_context->Reset(); delete m_global_context; delete m_isolate_scope; m_isolate->Dispose(); v8::V8::Dispose(); v8::V8::ShutdownPlatform(); delete create_params.array_buffer_allocator; } QString V8Executor::loadJS(QString script, QString source) { std::string exception; v8::HandleScope scope(m_isolate); v8::Local ret = innerExec(script.toUtf8().constData(), source.toUtf8().constData(), &exception); std::string result = ToString(ret); return QString::fromUtf8(result.c_str()); } void V8Executor::injectGlobalJSObject(QString name, QObject *target) { v8::HandleScope handleScope(v8::Isolate::GetCurrent()); v8::Local local = ObjectToJS(target); v8::Isolate *isolate = m_isolate; v8::HandleScope handle_scope(isolate); v8::Local context = isolate->GetEnteredOrMicrotaskContext(); v8::Local object = context->Global(); v8::Maybe result = object->Set(context, NewV8String(name.toUtf8().constData()), local); result.ToChecked(); } v8::Local V8Executor::innerExec(const char *script, const char *source, std::string *exception_str) { v8::Isolate *isolate = m_isolate; v8::EscapableHandleScope handle_scope(isolate); v8::Local result = Undefined(isolate); v8::Local context = isolate->GetEnteredOrMicrotaskContext(); v8::Context::Scope context_scope(context); v8::ScriptOrigin origin(NewV8String(source)); if (script) { v8::Local jsSource = NewV8String(script); v8::TryCatch try_catch(isolate); try_catch.SetVerbose(true); v8::MaybeLocal maybeScript = v8::Script::Compile(context, jsSource, &origin); if (!maybeScript.IsEmpty()) { v8::Local js_script = maybeScript.ToLocalChecked(); v8::MaybeLocal res = js_script->Run(context); if (!res.IsEmpty()) { result = res.ToLocalChecked(); } } v8::Local exception = try_catch.Exception(); if (!exception.IsEmpty()) { if (exception->IsObject()) { v8::Local exc = v8::Local::Cast(exception); v8::Local stack = exc->Get(context, NewV8String("stack")).FromMaybe(exception); *exception_str = ToString(stack); } else { *exception_str = ToString(exception); } } } return handle_scope.Escape(result); }