Added context scopes

This commit is contained in:
ksuprynowicz 2022-10-08 20:05:49 +02:00
parent 2b06c09318
commit a4c6930a50
10 changed files with 300 additions and 95 deletions

View file

@ -7506,8 +7506,9 @@ void Application::registerScriptEngineWithApplicationServices(const ScriptManage
scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter,
LocationScriptingInterface::locationSetter, "Window");
// register `location` on the global object.
scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter,
LocationScriptingInterface::locationSetter);
//V8TODO causes a crash
//scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter,
// LocationScriptingInterface::locationSetter);
scriptEngine->registerFunction("OverlayWindow", clientScript ? QmlWindowClass::constructor : QmlWindowClass::restricted_constructor);
#if !defined(Q_OS_ANDROID) && !defined(DISABLE_QML)

View file

@ -119,6 +119,7 @@ public:
virtual void setProcessEventsInterval(int interval) = 0;
virtual QThread* thread() const = 0;
virtual void setThread(QThread* thread) = 0;
Q_INVOKABLE virtual void enterIsolateOnThisThread() = 0;
virtual ScriptValue undefinedValue() = 0;
virtual ScriptValue uncaughtException() const = 0;
virtual QStringList uncaughtExceptionBacktrace() const = 0;

View file

@ -825,7 +825,9 @@ void ScriptManager::run() {
// (because we're a client script)
hifi::scripting::setLocalAccessSafeThread(true);
}
_engine->enterIsolateOnThisThread();
auto filenameParts = _fileNameString.split("/");
auto name = filenameParts.size() > 0 ? filenameParts[filenameParts.size() - 1] : "unknown";
PROFILE_SET_THREAD_NAME("Script: " + name);

View file

@ -38,12 +38,23 @@ v8::Local<v8::Context> ScriptContextV8Wrapper::toV8Value() const {
}
int ScriptContextV8Wrapper::argumentCount() const {
Q_ASSERT(_functionCallbackInfo);
return _functionCallbackInfo->Length();
/*auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());*/
//Q_ASSERT(_functionCallbackInfo);A
// V8TODO
return Q_METAMETHOD_INVOKE_MAX_ARGS;
// This was wrong, in function registration it seems to be used as maximum number od arguments instead?
// Is it also used for something else?
//return _functionCallbackInfo->Length();
}
ScriptValue ScriptContextV8Wrapper::argument(int index) const {
v8::HandleScope handleScope(_engine->getIsolate());
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
Q_ASSERT(_functionCallbackInfo);
v8::Local<v8::Value> result = (*_functionCallbackInfo)[index];
//V8ScriptValue result = _context->argument(index);
@ -52,7 +63,9 @@ ScriptValue ScriptContextV8Wrapper::argument(int index) const {
QStringList ScriptContextV8Wrapper::backtrace() const {
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(isolate, 40);
QStringList backTrace;
//V8TODO nicer formatting
@ -93,20 +106,29 @@ ScriptContextPointer ScriptContextV8Wrapper::parentContext() const {
ScriptValue ScriptContextV8Wrapper::thisObject() const {
Q_ASSERT(_functionCallbackInfo);
v8::HandleScope handleScope(_engine->getIsolate());
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
v8::Local<v8::Value> result = _functionCallbackInfo->This();
return ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine->getIsolate(), result)));
return ScriptValue();
}
ScriptValue ScriptContextV8Wrapper::throwError(const QString& text) {
v8::HandleScope handleScope(_engine->getIsolate());
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
V8ScriptValue result(_engine->getIsolate(), _engine->getIsolate()->ThrowError(v8::String::NewFromUtf8(_engine->getIsolate(), text.toStdString().c_str()).ToLocalChecked()));
return ScriptValue(new ScriptValueV8Wrapper(_engine, std::move(result)));
}
ScriptValue ScriptContextV8Wrapper::throwValue(const ScriptValue& value) {
v8::HandleScope handleScope(_engine->getIsolate());
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
ScriptValueV8Wrapper* unwrapped = ScriptValueV8Wrapper::unwrap(value);
if (!unwrapped) {
return _engine->undefinedValue();

View file

@ -113,6 +113,8 @@ ScriptValue ScriptEngineV8::makeError(const ScriptValue& _other, const QString&
if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) {
return nullValue();
}
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
return nullValue();
//V8TODO
@ -136,6 +138,8 @@ ScriptValue ScriptEngineV8::cheskScriptSyntax(ScriptProgramPointer program) {
if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) {
return nullValue();
}
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
ScriptSyntaxCheckResultPointer syntaxCheck = program->checkSyntax();
//V8TODO
if (syntaxCheck->state() != ScriptSyntaxCheckResult::Valid) {
@ -190,6 +194,8 @@ ScriptValue ScriptEngineV8::cloneUncaughtException(const QString& extraDetail) {
if (!hasUncaughtException()) {
return nullValue();
}
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
return nullValue();
//V8TODO
/*
@ -284,6 +290,8 @@ bool ScriptEngineV8::maybeEmitUncaughtException(const QString& debugHint) {
ScriptValue ScriptEngineV8::newLambdaFunction(std::function<V8ScriptValue(V8ScriptContext*, ScriptEngineV8*)> operation,
const V8ScriptValue& data,
const ValueOwnership& ownership) {
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
auto lambda = new Lambda(this, operation, data);
auto object = newQObject(lambda, ownership);
//V8TODO?
@ -294,6 +302,7 @@ ScriptValue ScriptEngineV8::newLambdaFunction(std::function<V8ScriptValue(V8Scri
}
QString Lambda::toString() const {
v8::HandleScope handleScope(_engine->getIsolate());
v8::Context::Scope contextScope(_engine->getContext());
v8::Local<v8::String> string;
QString qString("");
if (_data.constGet()->ToString(_engine->getContext()).ToLocal(&string)) {
@ -373,30 +382,14 @@ ScriptEngineV8::ScriptEngineV8(ScriptManager* scriptManager) :
v8::Isolate::CreateParams isolateParams;
isolateParams.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
_v8Isolate = v8::Isolate::New(isolateParams);
_v8Isolate->Enter();
v8::HandleScope handleScope(_v8Isolate);
v8::Local<v8::Context> context = v8::Context::New(_v8Isolate);
Q_ASSERT(!context.IsEmpty());
_v8Context = v8::UniquePersistent<v8::Context>(_v8Isolate, context);
registerSystemTypes();
_currentThread = QThread::currentThread();
// V8TODO: port to V8
/*
if (_scriptManager) {
connect(this, &QScriptEngine::signalHandlerException, this, [this](const V8ScriptValue& exception) {
if (hasUncaughtException()) {
// the engine's uncaughtException() seems to produce much better stack traces here
emit _scriptManager->unhandledException(cloneUncaughtException("signalHandlerException"));
clearExceptions();
} else {
// ... but may not always be available -- so if needed we fallback to the passed exception
V8ScriptValue thrown = makeError(exception);
emit _scriptManager->unhandledException(ScriptValue(new ScriptValueV8Wrapper(this, std::move(thrown))));
}
}, Qt::DirectConnection);
moveToThread(scriptManager->thread());
}*/
// V8TODO: dispose of isolate on ScriptEngineV8 destruction
//v8::UniquePersistent<v8::Value> null = v8::UniquePersistent<v8::Value>(_v8Isolate, v8::Null(_v8Isolate));
//_nullValue = ScriptValue(new ScriptValueV8Wrapper(this, std::move(null)));
@ -410,6 +403,25 @@ ScriptEngineV8::ScriptEngineV8(ScriptManager* scriptManager) :
// V8TODO:
//QScriptEngine::setProcessEventsInterval(MSECS_PER_SECOND);
//_currentThread = QThread::currentThread();
if (_scriptManager) {
// V8TODO: port to V8
/*connect(this, &QScriptEngine::signalHandlerException, this, [this](const V8ScriptValue& exception) {
if (hasUncaughtException()) {
// the engine's uncaughtException() seems to produce much better stack traces here
emit _scriptManager->unhandledException(cloneUncaughtException("signalHandlerException"));
clearExceptions();
} else {
// ... but may not always be available -- so if needed we fallback to the passed exception
V8ScriptValue thrown = makeError(exception);
emit _scriptManager->unhandledException(ScriptValue(new ScriptValueV8Wrapper(this, std::move(thrown))));
}
}, Qt::DirectConnection);*/
//moveToThread(scriptManager->thread());
setThread(scriptManager->thread());
}
}
void ScriptEngineV8::registerEnum(const QString& enumName, QMetaEnum newEnum) {
@ -417,6 +429,8 @@ void ScriptEngineV8::registerEnum(const QString& enumName, QMetaEnum newEnum) {
qCCritical(scriptengine) << "registerEnum called on invalid enum with name " << enumName;
return;
}
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
for (int i = 0; i < newEnum.keyCount(); i++) {
const char* keyName = newEnum.key(i);
@ -426,8 +440,7 @@ void ScriptEngineV8::registerEnum(const QString& enumName, QMetaEnum newEnum) {
}
void ScriptEngineV8::registerValue(const QString& valueName, V8ScriptValue value) {
//V8TODO
/*if (QThread::currentThread() != QScriptEngine::thread()) {
if (QThread::currentThread() != thread()) {
#ifdef THREAD_DEBUGGING
qCDebug(scriptengine) << "*** WARNING *** ScriptEngineV8::registerValue() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]";
#endif
@ -435,8 +448,9 @@ void ScriptEngineV8::registerValue(const QString& valueName, V8ScriptValue value
Q_ARG(const QString&, valueName),
Q_ARG(V8ScriptValue, value));
return;
}*/
}
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
QStringList pathToValue = valueName.split(".");
int partsToGo = pathToValue.length();
v8::Local<v8::Object> partObject = _v8Context.Get(_v8Isolate)->Global();
@ -470,8 +484,7 @@ void ScriptEngineV8::registerValue(const QString& valueName, V8ScriptValue value
}
void ScriptEngineV8::registerGlobalObject(const QString& name, QObject* object) {
//V8TODO
/*if (QThread::currentThread() != QScriptEngine::thread()) {
if (QThread::currentThread() != thread()) {
#ifdef THREAD_DEBUGGING
qCDebug(scriptengine) << "*** WARNING *** ScriptEngineV8::registerGlobalObject() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name;
#endif
@ -482,8 +495,10 @@ void ScriptEngineV8::registerGlobalObject(const QString& name, QObject* object)
}
#ifdef THREAD_DEBUGGING
qCDebug(scriptengine) << "ScriptEngineV8::registerGlobalObject() called on thread [" << QThread::currentThread() << "] name:" << name;
#endif*/
#endif
v8::HandleScope handleScope(_v8Isolate);
Q_ASSERT(_v8Isolate->IsCurrent());
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
v8::Local<v8::Object> v8GlobalObject = getContext()->Global();
v8::Local<v8::String> v8Name = v8::String::NewFromUtf8(_v8Isolate, name.toStdString().c_str()).ToLocalChecked();
@ -499,22 +514,23 @@ void ScriptEngineV8::registerGlobalObject(const QString& name, QObject* object)
}
void ScriptEngineV8::registerFunction(const QString& name, ScriptEngine::FunctionSignature functionSignature, int numArguments) {
//V8TODO
/*if (QThread::currentThread() != QScriptEngine::thread()) {
if (QThread::currentThread() != thread()) {
#ifdef THREAD_DEBUGGING
qCDebug(scriptengine) << "*** WARNING *** ScriptEngineV8::registerFunction() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name;
#endif
QMetaObject::invokeMethod(this, "registerFunction",
Q_ARG(const QString&, name),
Q_ARG(QScriptEngine::FunctionSignature, functionSignature),
Q_ARG(ScriptEngine::FunctionSignature, functionSignature),
Q_ARG(int, numArguments));
return;
}
#ifdef THREAD_DEBUGGING
qCDebug(scriptengine) << "ScriptEngineV8::registerFunction() called on thread [" << QThread::currentThread() << "] name:" << name;
#endif*/
#endif
//auto scriptFun = static_cast<ScriptValueV8Wrapper*>(newFunction(functionSignature, numArguments).ptr())->toV8Value().constGet();
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
auto scriptFun = newFunction(functionSignature, numArguments);
//getContext()->Global().Set();
@ -522,21 +538,22 @@ void ScriptEngineV8::registerFunction(const QString& name, ScriptEngine::Functio
}
void ScriptEngineV8::registerFunction(const QString& parent, const QString& name, ScriptEngine::FunctionSignature functionSignature, int numArguments) {
//V8TODO
/*if (QThread::currentThread() != QScriptEngine::thread()) {
if (QThread::currentThread() != thread()) {
#ifdef THREAD_DEBUGGING
qCDebug(scriptengine) << "*** WARNING *** ScriptEngineV8::registerFunction() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] parent:" << parent << "name:" << name;
#endif
QMetaObject::invokeMethod(this, "registerFunction",
Q_ARG(const QString&, name),
Q_ARG(QScriptEngine::FunctionSignature, functionSignature),
Q_ARG(ScriptEngine::FunctionSignature, functionSignature),
Q_ARG(int, numArguments));
return;
}
#ifdef THREAD_DEBUGGING
qCDebug(scriptengine) << "ScriptEngineV8::registerFunction() called on thread [" << QThread::currentThread() << "] parent:" << parent << "name:" << name;
#endif*/
#endif
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
ScriptValue object = globalObject().property(parent);
if (object.isValid()) {
ScriptValue scriptFun = ScriptEngine::newFunction(functionSignature, numArguments);
@ -546,8 +563,7 @@ void ScriptEngineV8::registerFunction(const QString& parent, const QString& name
void ScriptEngineV8::registerGetterSetter(const QString& name, ScriptEngine::FunctionSignature getter,
ScriptEngine::FunctionSignature setter, const QString& parent) {
//V8TODO
/*if (QThread::currentThread() != QScriptEngine::thread()) {
if (QThread::currentThread() != thread()) {
#ifdef THREAD_DEBUGGING
qCDebug(scriptengine) << "*** WARNING *** ScriptEngineV8::registerGetterSetter() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
" name:" << name << "parent:" << parent;
@ -561,7 +577,10 @@ void ScriptEngineV8::registerGetterSetter(const QString& name, ScriptEngine::Fun
}
#ifdef THREAD_DEBUGGING
qCDebug(scriptengine) << "ScriptEngineV8::registerGetterSetter() called on thread [" << QThread::currentThread() << "] name:" << name << "parent:" << parent;
#endif*/
#endif
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
ScriptValue setterFunction = newFunction(setter, 1);
ScriptValue getterFunction = newFunction(getter);
@ -585,6 +604,7 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure,
return nullValue();
}
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
ScriptProgramV8Wrapper* unwrappedProgram = ScriptProgramV8Wrapper::unwrap(_program);
if (unwrappedProgram == nullptr) {
return nullValue();
@ -684,7 +704,7 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure,
setGlobalObject(oldGlobal);
}*/
_v8Context.Get(_v8Isolate)->Enter();
//_v8Context.Get(_v8Isolate)->Enter();
return result;
}
@ -695,7 +715,7 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f
//V8TODO
/*if (QThread::currentThread() != QScriptEngine::thread()) {
if (QThread::currentThread() != thread()) {
ScriptValue result;
#ifdef THREAD_DEBUGGING
qCDebug(scriptengine) << "*** WARNING *** ScriptEngineV8::evaluate() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
@ -706,10 +726,11 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f
Q_ARG(const QString&, sourceCode),
Q_ARG(const QString&, fileName));
return result;
}*/
}
// Compile and check syntax
// V8TODO: Could these all be replaced with checkSyntax function from wrapper?
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
v8::TryCatch tryCatch(getIsolate());
v8::ScriptOrigin scriptOrigin(getIsolate(), v8::String::NewFromUtf8(getIsolate(), fileName.toStdString().c_str()).ToLocalChecked());
v8::Local<v8::Script> script;
@ -775,8 +796,7 @@ Q_INVOKABLE ScriptValue ScriptEngineV8::evaluate(const ScriptProgramPointer& pro
return undefinedValue(); // bail early
}
//V8TODO
/*if (QThread::currentThread() != QScriptEngine::thread()) {
if (QThread::currentThread() != thread()) {
ScriptValue result;
#ifdef THREAD_DEBUGGING
qCDebug(scriptengine) << "*** WARNING *** ScriptEngineV8::evaluate() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
@ -786,8 +806,9 @@ Q_INVOKABLE ScriptValue ScriptEngineV8::evaluate(const ScriptProgramPointer& pro
Q_RETURN_ARG(ScriptValue, result),
Q_ARG(const ScriptProgramPointer&, program));
return result;
}*/
}
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
ScriptProgramV8Wrapper* unwrapped = ScriptProgramV8Wrapper::unwrap(program);
if (!unwrapped) {
auto err = makeError(newValue("could not unwrap program"));
@ -843,6 +864,7 @@ void ScriptEngineV8::updateMemoryCost(const qint64& deltaSize) {
ScriptValue ScriptEngineV8::globalObject() const {
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
V8ScriptValue global(_v8Isolate, getConstContext()->Global());// = QScriptEngine::globalObject(); // can't cache the value as it may change
return ScriptValue(new ScriptValueV8Wrapper(const_cast<ScriptEngineV8*>(this), std::move(global)));
}
@ -852,12 +874,15 @@ ScriptManager* ScriptEngineV8::manager() const {
}
ScriptValue ScriptEngineV8::newArray(uint length) {
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
V8ScriptValue result(_v8Isolate, v8::Array::New(_v8Isolate, static_cast<int>(length)));
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
}
ScriptValue ScriptEngineV8::newArrayBuffer(const QByteArray& message) {
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
//V8TODO: this will leak memory
std::shared_ptr<v8::BackingStore> backingStore(v8::ArrayBuffer::NewBackingStore(_v8Isolate, message.size()));
std::memcpy(backingStore.get()->Data(), message.constData(), message.size());
@ -873,12 +898,16 @@ ScriptValue ScriptEngineV8::newArrayBuffer(const QByteArray& message) {
}
ScriptValue ScriptEngineV8::newObject() {
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
V8ScriptValue result(_v8Isolate, v8::Object::New(_v8Isolate));
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
}
ScriptValue ScriptEngineV8::newMethod(QObject* object, V8ScriptValue lifetime,
const QList<QMetaMethod>& metas, int numMaxParams) {
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
V8ScriptValue result(ScriptMethodV8Proxy::newMethod(this, object, lifetime, metas, numMaxParams));
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
}
@ -893,33 +922,43 @@ ScriptProgramPointer ScriptEngineV8::newProgram(const QString& sourceCode, const
ScriptValue ScriptEngineV8::newQObject(QObject* object,
ScriptEngine::ValueOwnership ownership,
const ScriptEngine::QObjectWrapOptions& options) {
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
V8ScriptValue result = ScriptObjectV8Proxy::newQObject(this, object, ownership, options);
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
}
ScriptValue ScriptEngineV8::newValue(bool value) {
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
V8ScriptValue result(_v8Isolate, v8::Boolean::New(_v8Isolate, value));
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
}
ScriptValue ScriptEngineV8::newValue(int value) {
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
V8ScriptValue result(_v8Isolate, v8::Integer::New(_v8Isolate, value));
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
}
ScriptValue ScriptEngineV8::newValue(uint value) {
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
V8ScriptValue result(_v8Isolate, v8::Uint32::New(_v8Isolate, value));
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
}
ScriptValue ScriptEngineV8::newValue(double value) {
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
V8ScriptValue result(_v8Isolate, v8::Number::New(_v8Isolate, value));
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
}
ScriptValue ScriptEngineV8::newValue(const QString& value) {
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
v8::Local<v8::String> valueV8 = v8::String::NewFromUtf8(_v8Isolate, value.toStdString().c_str(), v8::NewStringType::kNormal).ToLocalChecked();
V8ScriptValue result(_v8Isolate, valueV8);
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
@ -927,6 +966,7 @@ ScriptValue ScriptEngineV8::newValue(const QString& value) {
ScriptValue ScriptEngineV8::newValue(const QLatin1String& value) {
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
v8::Local<v8::String> valueV8 = v8::String::NewFromUtf8(_v8Isolate, value.latin1(), v8::NewStringType::kNormal).ToLocalChecked();
V8ScriptValue result(_v8Isolate, valueV8);
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
@ -934,12 +974,15 @@ ScriptValue ScriptEngineV8::newValue(const QLatin1String& value) {
ScriptValue ScriptEngineV8::newValue(const char* value) {
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
v8::Local<v8::String> valueV8 = v8::String::NewFromUtf8(_v8Isolate, value, v8::NewStringType::kNormal).ToLocalChecked();
V8ScriptValue result(_v8Isolate, valueV8);
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
}
ScriptValue ScriptEngineV8::newVariant(const QVariant& value) {
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
V8ScriptValue result = castVariantToValue(value);
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result)));
}
@ -1005,12 +1048,14 @@ ScriptValue ScriptEngineV8::newFunction(ScriptEngine::FunctionSignature fun, int
//V8TODO: is using GetCurrentContext ok, or context wrapper needs to be added?
v8::HandleScope handleScope(info.GetIsolate());
auto context = info.GetIsolate()->GetCurrentContext();
v8::Context::Scope contextScope(context);
auto object = v8::Local<v8::Object>::Cast(info.Data());
auto function = reinterpret_cast<ScriptEngine::FunctionSignature>
(info.Data()->ToObject(context).ToLocalChecked()->GetAlignedPointerFromInternalField(0));
(object->GetAlignedPointerFromInternalField(0));
ScriptContext *scriptContext = reinterpret_cast<ScriptContext*>
(info.Data()->ToObject(context).ToLocalChecked()->GetAlignedPointerFromInternalField(1));;
(object->GetAlignedPointerFromInternalField(1));;
ScriptEngineV8 *scriptEngine = reinterpret_cast<ScriptEngineV8*>
(info.Data()->ToObject(context).ToLocalChecked()->GetAlignedPointerFromInternalField(2));;
(object->GetAlignedPointerFromInternalField(2));;
ScriptValue result = function(scriptContext, scriptEngine);
ScriptValueV8Wrapper* unwrapped = ScriptValueV8Wrapper::unwrap(result);
info.GetReturnValue().Set(unwrapped->toV8Value().constGet());
@ -1019,6 +1064,7 @@ ScriptValue ScriptEngineV8::newFunction(ScriptEngine::FunctionSignature fun, int
//auto functionData = v8::Object::New(_v8Isolate);
//functionData->setIn
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
auto functionDataTemplate = v8::ObjectTemplate::New(_v8Isolate);
functionDataTemplate->SetInternalFieldCount(3);
auto functionData = functionDataTemplate->NewInstance(getContext()).ToLocalChecked();
@ -1044,6 +1090,7 @@ void ScriptEngineV8::setObjectName(const QString& name) {
//V8TODO
bool ScriptEngineV8::setProperty(const char* name, const QVariant& value) {
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
v8::Local<v8::Object> global = getContext()->Global();
auto v8Name = v8::String::NewFromUtf8(getIsolate(), name).ToLocalChecked();
V8ScriptValue v8Value = castVariantToValue(value);
@ -1056,13 +1103,23 @@ void ScriptEngineV8::setProcessEventsInterval(int interval) {
}
QThread* ScriptEngineV8::thread() const {
return _currentThread;
return QObject::thread();
}
void ScriptEngineV8::setThread(QThread* thread) {
qDebug() << "Moved script engine " << objectName() << " to different thread";
_v8Isolate->Exit();
moveToThread(thread);
QMetaObject::invokeMethod(this, "enterIsolateOnThisThread");
}
void ScriptEngineV8::enterIsolateOnThisThread() {
Q_ASSERT(thread() == QThread::currentThread());
_v8Isolate->Enter();
qDebug() << "Script engine " << objectName() << " entered isolate on a new thread";
}
ScriptValue ScriptEngineV8::uncaughtException() const {
//V8TODO
//V8ScriptValue result = QScriptEngine::uncaughtException();
@ -1088,12 +1145,16 @@ bool ScriptEngineV8::raiseException(const ScriptValue& exception) {
}
ScriptValue ScriptEngineV8::create(int type, const void* ptr) {
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
QVariant variant(type, ptr);
V8ScriptValue scriptValue = castVariantToValue(variant);
return ScriptValue(new ScriptValueV8Wrapper(this, std::move(scriptValue)));
}
QVariant ScriptEngineV8::convert(const ScriptValue& value, int typeId) {
v8::HandleScope handleScope(_v8Isolate);
v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate));
ScriptValueV8Wrapper* unwrapped = ScriptValueV8Wrapper::unwrap(value);
if (unwrapped == nullptr) {
return QVariant();

View file

@ -114,12 +114,12 @@ public: // ScriptEngine implementation
const QString& parent = QString("")) override;
Q_INVOKABLE virtual void registerGlobalObject(const QString& name, QObject* object) override;
virtual void setDefaultPrototype(int metaTypeId, const ScriptValue& prototype) override;
// Already implemented by QObject
virtual void setObjectName(const QString& name) override;
virtual bool setProperty(const char* name, const QVariant& value) override;
virtual void setProcessEventsInterval(int interval) override;
virtual QThread* thread() const override;
virtual void setThread(QThread* thread) override;
Q_INVOKABLE virtual void enterIsolateOnThisThread() override;
virtual ScriptValue undefinedValue() override;
virtual ScriptValue uncaughtException() const override;
virtual QStringList uncaughtExceptionBacktrace() const override;
@ -219,7 +219,7 @@ protected:
ScriptValue _nullValue;
ScriptValue _undefinedValue;
mutable ScriptContextQtPointer _currContext;
QThread *_currentThread;
//QThread *_currentThread;
//V8TODO
//ArrayBufferClass* _arrayBufferClass;

View file

@ -139,7 +139,7 @@ ScriptObjectV8Proxy* ScriptObjectV8Proxy::unwrapProxy(const V8ScriptValue& val)
if (!v8Value->IsObject()) {
return nullptr;
}
v8::Local<v8::Object> v8Object = v8Value->ToObject(val.constGetContext()).ToLocalChecked();
v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::Cast(v8Value);
if (v8Object->InternalFieldCount() != 2) {
return nullptr;
}
@ -167,6 +167,7 @@ void ScriptObjectV8Proxy::investigate() {
if (!qobject) return;
v8::HandleScope handleScope(_engine->getIsolate());
v8::Context::Scope contextScope(_engine->getContext());
auto objectTemplate = _v8ObjectTemplate.Get(_engine->getIsolate());
objectTemplate->SetInternalFieldCount(3);
@ -228,13 +229,17 @@ void ScriptObjectV8Proxy::investigate() {
break;
}
V8ScriptString name(_engine->getIsolate(), v8::String::NewFromUtf8(_engine->getIsolate(), szName.data(), v8::NewStringType::kNormal, szName.length()).ToLocalChecked());
auto nameString = v8::String::NewFromUtf8(_engine->getIsolate(), szName.data(), v8::NewStringType::kNormal, szName.length()).ToLocalChecked();
V8ScriptString name(_engine->getIsolate(), nameString);
auto nameLookup = methodNames.find(name);
if (isSignal) {
if (nameLookup == methodNames.end()) {
SignalDef& signalDef = _signals.insert(idx, SignalDef(_engine->getIsolate(), name.get())).value();
signalDef.name = name;
signalDef.signal = method;
qDebug(scriptengine) << "Utf8Value 1: " << QString(*v8::String::Utf8Value(const_cast<v8::Isolate*>(_engine->getIsolate()), nameString));
qDebug(scriptengine) << "Utf8Value 2: " << QString(*v8::String::Utf8Value(const_cast<v8::Isolate*>(_engine->getIsolate()), name.constGet()));
qDebug(scriptengine) << "toQString: " << name.toQString();
methodNames.insert(name, idx);
} else {
int originalMethodId = nameLookup.value();
@ -474,7 +479,7 @@ ScriptVariantV8Proxy* ScriptVariantV8Proxy::unwrapProxy(const V8ScriptValue& val
if (!v8Value->IsObject()) {
return nullptr;
}
v8::Local<v8::Object> v8Object = v8Value->ToObject(val.constGetContext()).ToLocalChecked();
v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::Cast(v8Value);
if (v8Object->InternalFieldCount() != 2) {
return nullptr;
}

View file

@ -18,10 +18,8 @@ V8ScriptValueIterator::V8ScriptValueIterator(ScriptEngineV8* engine, v8::Local<v
v8::HandleScope handleScope(isolate);
_context.Reset(isolate, _engine->getContext());
auto context = _context.Get(isolate);
v8::Local<v8::Object> v8Object;
if (!object->ToObject(context).ToLocal(&v8Object)) {
Q_ASSERT(false);
}
Q_ASSERT(object->IsObject());
v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::Cast(object);
_object.Reset(isolate, v8Object);
_propertyNames.Reset(isolate, v8Object->GetOwnPropertyNames(context).ToLocalChecked());
_length = _propertyNames.Get(isolate)->Length();

View file

@ -60,7 +60,10 @@ V8ScriptValue ScriptValueV8Wrapper::fullUnwrap(ScriptEngineV8* engine, const Scr
}
ScriptValue ScriptValueV8Wrapper::call(const ScriptValue& thisObject, const ScriptValueList& args) {
v8::HandleScope handleScope(_engine->getIsolate());
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
V8ScriptValue v8This = fullUnwrap(thisObject);
//V8ScriptValueList qArgs;
Q_ASSERT(args.length() <= Q_METAMETHOD_INVOKE_MAX_ARGS);
@ -85,7 +88,10 @@ ScriptValue ScriptValueV8Wrapper::call(const ScriptValue& thisObject, const Scri
}
ScriptValue ScriptValueV8Wrapper::call(const ScriptValue& thisObject, const ScriptValue& arguments) {
v8::HandleScope handleScope(_engine->getIsolate());
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
V8ScriptValue v8This = fullUnwrap(thisObject);
V8ScriptValue v8Args = fullUnwrap(arguments);
// V8TODO should there be a v8 try-catch here?
@ -106,7 +112,10 @@ ScriptValue ScriptValueV8Wrapper::call(const ScriptValue& thisObject, const Scri
}
ScriptValue ScriptValueV8Wrapper::construct(const ScriptValueList& args) {
v8::HandleScope handleScope(_engine->getIsolate());
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
Q_ASSERT(args.length() <= Q_METAMETHOD_INVOKE_MAX_ARGS);
//V8TODO I'm not sure how else to do this since v8::Local should probably be on stack, not heap
v8::Local<v8::Value> v8Args[Q_METAMETHOD_INVOKE_MAX_ARGS];
@ -129,7 +138,10 @@ ScriptValue ScriptValueV8Wrapper::construct(const ScriptValueList& args) {
}
ScriptValue ScriptValueV8Wrapper::construct(const ScriptValue& arguments) {
v8::HandleScope handleScope(_engine->getIsolate());
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
// V8TODO I'm not sure in what format arguments are yet, backtrace will show how it is used
Q_ASSERT(false);
return _engine->undefinedValue();
@ -157,13 +169,17 @@ ScriptValueIteratorPointer ScriptValueV8Wrapper::newIterator() const {
}
ScriptValue ScriptValueV8Wrapper::property(const QString& name, const ScriptValue::ResolveFlags& mode) const {
v8::HandleScope handleScope(_engine->getIsolate());
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
if (!_value.constGet()->IsObject()) {
//V8TODO: what about flags?
v8::Local<v8::Value> resultLocal;
v8::Local<v8::String> key = v8::String::NewFromUtf8(_engine->getIsolate(), name.toStdString().c_str(),v8::NewStringType::kNormal).ToLocalChecked();
if (_value.constGet()->ToObject(_value.constGetContext()).ToLocalChecked()
->Get(_value.constGetContext(), key).ToLocal(&resultLocal)) {
v8::Local<v8::Value> resultLocal;
v8::Local<v8::String> key = v8::String::NewFromUtf8(_engine->getIsolate(), name.toStdString().c_str(),v8::NewStringType::kNormal).ToLocalChecked();
Q_ASSERT(_value.constGet()->IsObject());
const v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(_value.constGet());
if (object->Get(_value.constGetContext(), key).ToLocal(&resultLocal)) {
V8ScriptValue result(_engine->getIsolate(), resultLocal);
return ScriptValue(new ScriptValueV8Wrapper(_engine, std::move(result)));
}
@ -176,12 +192,16 @@ ScriptValue ScriptValueV8Wrapper::property(const QString& name, const ScriptValu
}
ScriptValue ScriptValueV8Wrapper::property(quint32 arrayIndex, const ScriptValue::ResolveFlags& mode) const {
v8::HandleScope handleScope(_engine->getIsolate());
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
if (!_value.constGet()->IsObject()) {
//V8TODO: what about flags?
v8::Local<v8::Value> resultLocal;
if (_value.constGet()->ToObject(_value.constGetContext()).ToLocalChecked()
->Get(_value.constGetContext(), arrayIndex).ToLocal(&resultLocal)) {
v8::Local<v8::Value> resultLocal;
Q_ASSERT(_value.constGet()->IsObject());
const v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(_value.constGet());
if (object->Get(_value.constGetContext(), arrayIndex).ToLocal(&resultLocal)) {
V8ScriptValue result(_engine->getIsolate(), resultLocal);
return ScriptValue(new ScriptValueV8Wrapper(_engine, std::move(result)));
}
@ -192,17 +212,28 @@ ScriptValue ScriptValueV8Wrapper::property(quint32 arrayIndex, const ScriptValue
}
void ScriptValueV8Wrapper::setData(const ScriptValue& value) {
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
V8ScriptValue unwrapped = fullUnwrap(value);
(**_value.get()) = (**unwrapped.get());
}
void ScriptValueV8Wrapper::setProperty(const QString& name, const ScriptValue& value, const ScriptValue::PropertyFlags& flags) {
v8::HandleScope handleScope(_engine->getIsolate());
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
V8ScriptValue unwrapped = fullUnwrap(value);
if(_value.constGet()->IsObject()) {
v8::Local<v8::String> key = v8::String::NewFromUtf8(_engine->getIsolate(), name.toStdString().c_str(),v8::NewStringType::kNormal).ToLocalChecked();
v8::Maybe<bool> retVal = _value.get()->ToObject(_value.getContext()).ToLocalChecked()
->Set(_value.getContext(), key, unwrapped.constGet());
v8::Local<v8::String> key = v8::String::NewFromUtf8(isolate, name.toStdString().c_str(),v8::NewStringType::kNormal).ToLocalChecked();
Q_ASSERT(_value.get()->IsObject());
auto object = v8::Local<v8::Object>::Cast(_value.get());
// V8TODO: What if velue context and current context is different?
//v8::Maybe<bool> retVal = object->Set(_value.getContext(), key, unwrapped.constGet());
//v8::Maybe<bool> retVal = object->Set(_engine->getContext(), key, unwrapped.constGet());
v8::Maybe<bool> retVal = object->Set(isolate->GetCurrentContext(), key, unwrapped.constGet());
if (retVal.IsJust() ? !retVal.FromJust() : true){
qDebug(scriptengine) << "Failed to set property";
}
@ -214,10 +245,14 @@ void ScriptValueV8Wrapper::setProperty(const QString& name, const ScriptValue& v
}
void ScriptValueV8Wrapper::setProperty(quint32 arrayIndex, const ScriptValue& value, const ScriptValue::PropertyFlags& flags) {
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
V8ScriptValue unwrapped = fullUnwrap(value);
if(_value.constGet()->IsObject()) {
v8::Maybe<bool> retVal(_value.get()->ToObject(_value.getContext()).ToLocalChecked()
->Set(_value.getContext(), arrayIndex, unwrapped.constGet()));
auto object = v8::Local<v8::Object>::Cast(_value.get());
v8::Maybe<bool> retVal(object->Set(_value.getContext(), arrayIndex, unwrapped.constGet()));
if (retVal.IsJust() ? !retVal.FromJust() : true){
qDebug(scriptengine) << "Failed to set property";
}
@ -229,11 +264,15 @@ void ScriptValueV8Wrapper::setProperty(quint32 arrayIndex, const ScriptValue& va
}
void ScriptValueV8Wrapper::setPrototype(const ScriptValue& prototype) {
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
ScriptValueV8Wrapper* unwrappedPrototype = unwrap(prototype);
if (unwrappedPrototype) {
if(unwrappedPrototype->toV8Value().constGet()->IsObject() && _value.constGet()->IsObject()) {
v8::Maybe<bool> retVal = _value.get()->ToObject(_value.getContext()).ToLocalChecked()
->SetPrototype(_value.getContext(), unwrappedPrototype->toV8Value().constGet());
auto object = v8::Local<v8::Object>::Cast(_value.get());
v8::Maybe<bool> retVal = object->SetPrototype(_value.getContext(), unwrappedPrototype->toV8Value().constGet());
if (retVal.IsJust() ? !retVal.FromJust() : true){
qDebug(scriptengine) << "Failed to assign prototype";
}
@ -244,18 +283,27 @@ void ScriptValueV8Wrapper::setPrototype(const ScriptValue& prototype) {
}
bool ScriptValueV8Wrapper::strictlyEquals(const ScriptValue& other) const {
v8::HandleScope handleScope(_engine->getIsolate());
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
ScriptValueV8Wrapper* unwrappedOther = unwrap(other);
return unwrappedOther ? _value.constGet()->StrictEquals(unwrappedOther->toV8Value().constGet()) : false;
}
bool ScriptValueV8Wrapper::toBool() const {
v8::HandleScope handleScope(_engine->getIsolate());
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
return _value.constGet()->ToBoolean(_engine->getIsolate())->Value();
}
qint32 ScriptValueV8Wrapper::toInt32() const {
v8::HandleScope handleScope(_engine->getIsolate());
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
v8::Local<v8::Integer> *integer;
if (!_value.constGet()->ToInteger(_value.constGetContext()).ToLocal(integer)) {
Q_ASSERT(false);
@ -264,7 +312,10 @@ qint32 ScriptValueV8Wrapper::toInt32() const {
}
double ScriptValueV8Wrapper::toInteger() const {
v8::HandleScope handleScope(_engine->getIsolate());
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
v8::Local<v8::Integer> *integer;
if (!_value.constGet()->ToInteger(_value.constGetContext()).ToLocal(integer)) {
Q_ASSERT(false);
@ -273,7 +324,10 @@ double ScriptValueV8Wrapper::toInteger() const {
}
double ScriptValueV8Wrapper::toNumber() const {
v8::HandleScope handleScope(_engine->getIsolate());
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
v8::Local<v8::Number> *number;
if (!_value.constGet()->ToNumber(_value.constGetContext()).ToLocal(number)) {
Q_ASSERT(false);
@ -282,14 +336,20 @@ double ScriptValueV8Wrapper::toNumber() const {
}
QString ScriptValueV8Wrapper::toString() const {
v8::HandleScope handleScope(_engine->getIsolate());
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
v8::String::Utf8Value string(_engine->getIsolate(), _value.constGet());
Q_ASSERT(*string != nullptr);
return QString(*string);
}
quint16 ScriptValueV8Wrapper::toUInt16() const {
v8::HandleScope handleScope(_engine->getIsolate());
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
v8::Local<v8::Uint32> *integer;
if (!_value.constGet()->ToUint32(_value.constGetContext()).ToLocal(integer)) {
Q_ASSERT(false);
@ -298,7 +358,10 @@ quint16 ScriptValueV8Wrapper::toUInt16() const {
}
quint32 ScriptValueV8Wrapper::toUInt32() const {
v8::HandleScope handleScope(_engine->getIsolate());
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
v8::Local<v8::Uint32> *integer;
if (!_value.constGet()->ToUint32(_value.constGetContext()).ToLocal(integer)) {
Q_ASSERT(false);
@ -327,7 +390,10 @@ QObject* ScriptValueV8Wrapper::toQObject() const {
}
bool ScriptValueV8Wrapper::equals(const ScriptValue& other) const {
v8::HandleScope handleScope(_engine->getIsolate());
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
ScriptValueV8Wrapper* unwrappedOther = unwrap(other);
//V8TODO: does this work with different contexts/isolates?
// in such case conversion will probably be necessary
@ -343,51 +409,95 @@ bool ScriptValueV8Wrapper::equals(const ScriptValue& other) const {
}
bool ScriptValueV8Wrapper::isArray() const {
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
return _value.constGet()->IsArray();
}
bool ScriptValueV8Wrapper::isBool() const {
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
return _value.constGet()->IsBoolean();
}
bool ScriptValueV8Wrapper::isError() const {
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
//V8TODO
return false;
//return _value.constGet()->IsError();
}
bool ScriptValueV8Wrapper::isFunction() const {
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
return _value.constGet()->IsFunction();
}
bool ScriptValueV8Wrapper::isNumber() const {
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
return _value.constGet()->IsNumber();
}
bool ScriptValueV8Wrapper::isNull() const {
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
return _value.constGet()->IsNull();
}
bool ScriptValueV8Wrapper::isObject() const {
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
return _value.constGet()->IsObject();
}
bool ScriptValueV8Wrapper::isString() const {
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
return _value.constGet()->IsString();
}
bool ScriptValueV8Wrapper::isUndefined() const {
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
return _value.constGet()->IsUndefined();
}
bool ScriptValueV8Wrapper::isValid() const {
//V8TODO
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
return true;
//return _value.constGet()->IsValid();
}
bool ScriptValueV8Wrapper::isVariant() const {
//V8TODO
auto isolate = _engine->getIsolate();
Q_ASSERT(isolate->IsCurrent());
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
return false;
//return _value.isVariant();
}

View file

@ -27,18 +27,21 @@ public:
V8ScriptValueTemplate(v8::Isolate *isolate, const v8::Local<T> value) : _isolate(isolate) {
//_value.reset(_isolate, value);
v8::HandleScope handleScope(_isolate);
Q_ASSERT(isolate->IsCurrent());
Q_ASSERT(!isolate->GetCurrentContext().IsEmpty());
_context.Reset(isolate, isolate->GetCurrentContext());
_value.reset(new v8::UniquePersistent<T>(_isolate, std::move(value)));
};
v8::Local<T> get() {
v8::EscapableHandleScope handleScope(_isolate);
return _value.get()->Get(_isolate);
return handleScope.Escape(_value.get()->Get(_isolate));
};
const v8::Local<T> constGet() const {
v8::EscapableHandleScope handleScope(_isolate);
return _value.get()->Get(_isolate);
return handleScope.Escape(_value.get()->Get(_isolate));
};
V8ScriptValueTemplate<T>&& copy() const {
Q_ASSERT(_isolate->IsCurrent());
v8::HandleScope handleScope(_isolate);
return new V8ScriptValueTemplate(_isolate, v8::Local<T>::New(_isolate, constGet()));};
const v8::Local<v8::Context> constGetContext() const {
@ -72,6 +75,8 @@ public:
V8ScriptString() = delete;
V8ScriptString(v8::Isolate *isolate, const v8::Local<v8::String> value) : V8ScriptValueTemplate<v8::String>(isolate, value) {};
const QString toQString() const {
Q_ASSERT(constGet()->IsString());
Q_ASSERT(constGetIsolate()->IsCurrent());
return QString(*v8::String::Utf8Value(const_cast<v8::Isolate*>(constGetIsolate()), constGet()));
};
bool operator==(const V8ScriptString& string) const {