From 97137c7b138782f929d6140f8fcfccc152f5a520 Mon Sep 17 00:00:00 2001 From: ksuprynowicz Date: Mon, 5 Dec 2022 00:22:15 +0100 Subject: [PATCH] More fixes for V8 --- .../src/v8/ScriptContextV8Wrapper.cpp | 17 +- .../script-engine/src/v8/ScriptEngineV8.cpp | 185 +++++++++++++----- .../script-engine/src/v8/ScriptEngineV8.h | 1 + .../src/v8/ScriptEngineV8_cast.cpp | 52 ++++- .../src/v8/ScriptObjectV8Proxy.cpp | 18 +- .../src/v8/ScriptProgramV8Wrapper.cpp | 1 + .../src/v8/ScriptProgramV8Wrapper.h | 2 +- .../src/v8/ScriptValueV8Wrapper.cpp | 2 +- libraries/shared/src/Transform.h | 4 +- 9 files changed, 212 insertions(+), 70 deletions(-) diff --git a/libraries/script-engine/src/v8/ScriptContextV8Wrapper.cpp b/libraries/script-engine/src/v8/ScriptContextV8Wrapper.cpp index 3a37c82bd7..950193166d 100644 --- a/libraries/script-engine/src/v8/ScriptContextV8Wrapper.cpp +++ b/libraries/script-engine/src/v8/ScriptContextV8Wrapper.cpp @@ -147,11 +147,18 @@ ScriptValue ScriptContextV8Wrapper::thisObject() const { ScriptValue ScriptContextV8Wrapper::throwError(const QString& text) { 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))); + // V8TODO: I have no idea how to do this yet because it happens on another thread + if(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))); + } else { + qWarning() << "throwError on a different thread not implemented yet, error value: " << text; + return _engine->undefinedValue(); + } } ScriptValue ScriptContextV8Wrapper::throwValue(const ScriptValue& value) { diff --git a/libraries/script-engine/src/v8/ScriptEngineV8.cpp b/libraries/script-engine/src/v8/ScriptEngineV8.cpp index ed5291cf55..6dc619871c 100644 --- a/libraries/script-engine/src/v8/ScriptEngineV8.cpp +++ b/libraries/script-engine/src/v8/ScriptEngineV8.cpp @@ -370,7 +370,7 @@ v8::Platform* ScriptEngineV8::getV8Platform() { } ScriptEngineV8::ScriptEngineV8(ScriptManager* scriptManager) : - _scriptManager(scriptManager) + _scriptManager(scriptManager), _isEvaluating(false) //V8TODO //_arrayBufferClass(new ArrayBufferClass(this)) { @@ -514,21 +514,34 @@ void ScriptEngineV8::registerGlobalObject(const QString& name, QObject* object) #ifdef THREAD_DEBUGGING qCDebug(scriptengine) << "ScriptEngineV8::registerGlobalObject() called on thread [" << QThread::currentThread() << "] name:" << name; #endif - v8::HandleScope handleScope(_v8Isolate); - Q_ASSERT(_v8Isolate->IsCurrent()); - v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); - v8::Local v8GlobalObject = getContext()->Global(); - v8::Local v8Name = v8::String::NewFromUtf8(_v8Isolate, name.toStdString().c_str()).ToLocalChecked(); + bool is_isolate_exit_needed = false; + if(!_v8Isolate->IsCurrent() && !_v8Locker) { + // V8TODO: Theoretically only script thread should access this, so it should be safe + _v8Locker.reset(new v8::Locker(_v8Isolate)); + _v8Isolate->Enter(); + is_isolate_exit_needed = true; + } + { + v8::HandleScope handleScope(_v8Isolate); + Q_ASSERT(_v8Isolate->IsCurrent()); + v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); + v8::Local v8GlobalObject = getContext()->Global(); + v8::Local v8Name = v8::String::NewFromUtf8(_v8Isolate, name.toStdString().c_str()).ToLocalChecked(); - // V8TODO: Is IsEmpty check enough or IsValid is needed too? - if (!v8GlobalObject->Get(getContext(), v8Name).IsEmpty()) { - if (object) { - V8ScriptValue value = ScriptObjectV8Proxy::newQObject(this, object, ScriptEngine::QtOwnership); - v8GlobalObject->Set(getContext(), v8Name, value.get()); - } else { - v8GlobalObject->Set(getContext(), v8Name, v8::Null(_v8Isolate)); + // V8TODO: Is IsEmpty check enough or IsValid is needed too? + if (!v8GlobalObject->Get(getContext(), v8Name).IsEmpty()) { + if (object) { + V8ScriptValue value = ScriptObjectV8Proxy::newQObject(this, object, ScriptEngine::QtOwnership); + v8GlobalObject->Set(getContext(), v8Name, value.get()); + } else { + v8GlobalObject->Set(getContext(), v8Name, v8::Null(_v8Isolate)); + } } } + if (is_isolate_exit_needed) { + _v8Isolate->Exit(); + _v8Locker.reset(nullptr); + } } void ScriptEngineV8::registerFunction(const QString& name, ScriptEngine::FunctionSignature functionSignature, int numArguments) { @@ -548,13 +561,26 @@ void ScriptEngineV8::registerFunction(const QString& name, ScriptEngine::Functio qCDebug(scriptengine) << "ScriptEngineV8::registerFunction() called on thread [" << QThread::currentThread() << "] name:" << name; #endif - //auto scriptFun = static_cast(newFunction(functionSignature, numArguments).ptr())->toV8Value().constGet(); - v8::HandleScope handleScope(_v8Isolate); - v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); - auto scriptFun = newFunction(functionSignature, numArguments); + bool is_isolate_exit_needed = false; + if(!_v8Isolate->IsCurrent() && !_v8Locker) { + // V8TODO: Theoretically only script thread should access this, so it should be safe + _v8Locker.reset(new v8::Locker(_v8Isolate)); + _v8Isolate->Enter(); + is_isolate_exit_needed = true; + } + { + //auto scriptFun = static_cast(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(); - globalObject().setProperty(name, scriptFun); + //getContext()->Global().Set(); + globalObject().setProperty(name, scriptFun); + } + if (is_isolate_exit_needed) { + _v8Isolate->Exit(); + _v8Locker.reset(nullptr); + } } void ScriptEngineV8::registerFunction(const QString& parent, const QString& name, ScriptEngine::FunctionSignature functionSignature, int numArguments) { @@ -572,12 +598,25 @@ void ScriptEngineV8::registerFunction(const QString& parent, const QString& name qCDebug(scriptengine) << "ScriptEngineV8::registerFunction() called on thread [" << QThread::currentThread() << "] parent:" << parent << "name:" << name; #endif - v8::HandleScope handleScope(_v8Isolate); - v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); - ScriptValue object = globalObject().property(parent); - if (object.isValid()) { - ScriptValue scriptFun = newFunction(functionSignature, numArguments); - object.setProperty(name, scriptFun); + bool is_isolate_exit_needed = false; + if(!_v8Isolate->IsCurrent() && !_v8Locker) { + // V8TODO: Theoretically only script thread should access this, so it should be safe + _v8Locker.reset(new v8::Locker(_v8Isolate)); + _v8Isolate->Enter(); + is_isolate_exit_needed = true; + } + { + v8::HandleScope handleScope(_v8Isolate); + v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); + ScriptValue object = globalObject().property(parent); + if (object.isValid()) { + ScriptValue scriptFun = newFunction(functionSignature, numArguments); + object.setProperty(name, scriptFun); + } + } + if (is_isolate_exit_needed) { + _v8Isolate->Exit(); + _v8Locker.reset(nullptr); } } @@ -599,10 +638,18 @@ void ScriptEngineV8::registerGetterSetter(const QString& name, ScriptEngine::Fun qCDebug(scriptengine) << "ScriptEngineV8::registerGetterSetter() called on thread [" << QThread::currentThread() << "] name:" << name << "parent:" << parent; #endif - v8::HandleScope handleScope(_v8Isolate); - v8::Context::Scope contextScope(getContext()); + bool is_isolate_exit_needed = false; + if(!_v8Isolate->IsCurrent() && !_v8Locker) { + // V8TODO: Theoretically only script thread should access this, so it should be safe + _v8Locker.reset(new v8::Locker(_v8Isolate)); + _v8Isolate->Enter(); + is_isolate_exit_needed = true; + } + { + v8::HandleScope handleScope(_v8Isolate); + v8::Context::Scope contextScope(getContext()); - /*auto getterFunction = [](v8::Local property, const v8::PropertyCallbackInfo& info) { + /*auto getterFunction = [](v8::Local property, const v8::PropertyCallbackInfo& info) { //V8TODO: is using GetCurrentContext ok, or context wrapper needs to be added? v8::HandleScope handleScope(info.GetIsolate()); auto context = info.GetIsolate()->GetCurrentContext(); @@ -636,35 +683,44 @@ void ScriptEngineV8::registerGetterSetter(const QString& name, ScriptEngine::Fun ScriptValueV8Wrapper* unwrapped = ScriptValueV8Wrapper::unwrap(result); };*/ - ScriptValue setterFunction = newFunction(setter, 1); - ScriptValue getterFunction = newFunction(getter); - V8ScriptValue unwrappedGetter = ScriptValueV8Wrapper::fullUnwrap(this, setterFunction); - V8ScriptValue unwrappedSetter = ScriptValueV8Wrapper::fullUnwrap(this, getterFunction); - v8::PropertyDescriptor propertyDescriptor(unwrappedGetter.get(), unwrappedSetter.get()); + ScriptValue setterFunction = newFunction(setter, 1); + ScriptValue getterFunction = newFunction(getter); + V8ScriptValue unwrappedGetter = ScriptValueV8Wrapper::fullUnwrap(this, setterFunction); + V8ScriptValue unwrappedSetter = ScriptValueV8Wrapper::fullUnwrap(this, getterFunction); + v8::PropertyDescriptor propertyDescriptor(unwrappedGetter.get(), unwrappedSetter.get()); - //V8TODO: Getters/setters are probably done in a different way in V8. Maybe object template is needed? - if (!parent.isNull() && !parent.isEmpty()) { - ScriptValue object = globalObject().property(parent); - if (object.isValid()) { - V8ScriptValue v8parent = ScriptValueV8Wrapper::fullUnwrap(this, object); - Q_ASSERT(v8parent.get()->IsObject()); - v8::Local v8object = v8::Local::Cast(v8parent.get()); - v8::Local v8propertyName = v8::String::NewFromUtf8(_v8Isolate, name.toStdString().c_str()).ToLocalChecked(); - if(!v8object->DefineProperty(getContext(), v8propertyName, propertyDescriptor).FromMaybe(false)) { - qCDebug(scriptengine) << "DefineProperty failed for registerGetterSetter \"" << name << "\" for parent: \"" << parent << "\""; + //V8TODO: Getters/setters are probably done in a different way in V8. Maybe object template is needed? + if (!parent.isNull() && !parent.isEmpty()) { + ScriptValue object = globalObject().property(parent); + if (object.isValid()) { + V8ScriptValue v8parent = ScriptValueV8Wrapper::fullUnwrap(this, object); + Q_ASSERT(v8parent.get()->IsObject()); + v8::Local v8object = v8::Local::Cast(v8parent.get()); + v8::Local v8propertyName = + v8::String::NewFromUtf8(_v8Isolate, name.toStdString().c_str()).ToLocalChecked(); + if (!v8object->DefineProperty(getContext(), v8propertyName, propertyDescriptor).FromMaybe(false)) { + qCDebug(scriptengine) << "DefineProperty failed for registerGetterSetter \"" << name << "\" for parent: \"" + << parent << "\""; + } + //object.setProperty(name, setterFunction, ScriptValue::PropertySetter); + //object.setProperty(name, getterFunction, ScriptValue::PropertyGetter); + } else { + qCDebug(scriptengine) << "Parent object \"" << parent << "\" for registerGetterSetter \"" << name + << "\" is not valid: "; } - //object.setProperty(name, setterFunction, ScriptValue::PropertySetter); - //object.setProperty(name, getterFunction, ScriptValue::PropertyGetter); } else { - qCDebug(scriptengine) << "Parent object \"" << parent << "\" for registerGetterSetter \"" << name << "\" is not valid: "; + v8::Local v8propertyName = + v8::String::NewFromUtf8(_v8Isolate, name.toStdString().c_str()).ToLocalChecked(); + if (!getContext()->Global()->DefineProperty(getContext(), v8propertyName, propertyDescriptor).FromMaybe(false)) { + qCDebug(scriptengine) << "DefineProperty failed for registerGetterSetter \"" << name << "\" for global object"; + } + //globalObject().setProperty(name, setterFunction, ScriptValue::PropertySetter); + //globalObject().setProperty(name, getterFunction, ScriptValue::PropertyGetter); } - } else { - v8::Local v8propertyName = v8::String::NewFromUtf8(_v8Isolate, name.toStdString().c_str()).ToLocalChecked(); - if(!getContext()->Global()->DefineProperty(getContext(), v8propertyName, propertyDescriptor).FromMaybe(false)) { - qCDebug(scriptengine) << "DefineProperty failed for registerGetterSetter \"" << name << "\" for global object"; - } - //globalObject().setProperty(name, setterFunction, ScriptValue::PropertySetter); - //globalObject().setProperty(name, getterFunction, ScriptValue::PropertyGetter); + } + if (is_isolate_exit_needed) { + _v8Isolate->Exit(); + _v8Locker.reset(nullptr); } } @@ -674,10 +730,13 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure, if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) { return nullValue(); } + Q_ASSERT(!isEvaluating()); + _isEvaluating = true; v8::HandleScope handleScope(_v8Isolate); v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); ScriptProgramV8Wrapper* unwrappedProgram = ScriptProgramV8Wrapper::unwrap(_program); if (unwrappedProgram == nullptr) { + _isEvaluating = false; return nullValue(); } const V8ScriptProgram& program = unwrappedProgram->toV8Value(); @@ -687,10 +746,12 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure, ScriptValueV8Wrapper* unwrappedClosure = ScriptValueV8Wrapper::unwrap(_closure); if (unwrappedClosure == nullptr) { + _isEvaluating = false; return nullValue(); } const V8ScriptValue& closure = unwrappedClosure->toV8Value(); if (!closure.constGet()->IsObject()) { + _isEvaluating = false; return nullValue(); } const v8::Local closureObject = v8::Local::Cast(closure.constGet()); @@ -698,6 +759,7 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure, v8::Local oldGlobal; v8::Local closureGlobal; if (!closureObject->Get(closure.constGetContext() ,v8::String::NewFromUtf8(_v8Isolate, "global").ToLocalChecked()).ToLocal(&closureGlobal)) { + _isEvaluating = false; return nullValue(); } @@ -721,6 +783,7 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure, v8::Local thiz; // V8TODO: not sure if "this" doesn't exist or is empty in some cases if (!closureObject->Get(closure.constGetContext() ,v8::String::NewFromUtf8(_v8Isolate, "this").ToLocalChecked()).ToLocal(&thiz)) { + _isEvaluating = false; return nullValue(); } //thiz = closure.property("this"); @@ -776,6 +839,7 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure, }*/ //_v8Context.Get(_v8Isolate)->Enter(); + _isEvaluating = false; return result; } @@ -801,6 +865,8 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f // Compile and check syntax // V8TODO: Could these all be replaced with checkSyntax function from wrapper? Q_ASSERT(!_v8Isolate->IsDead()); + Q_ASSERT(!isEvaluating()); + _isEvaluating = true; v8::HandleScope handleScope(_v8Isolate); v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); v8::TryCatch tryCatch(getIsolate()); @@ -830,6 +896,7 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f auto err = makeError(newValue(errorMessage)); raiseException(err); maybeEmitUncaughtException("compile"); + _isEvaluating = false; return err; } qCDebug(scriptengine) << "Script compilation succesful: " << fileName; @@ -863,9 +930,11 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f //V8TODO //raiseException(errorValue); //maybeEmitUncaughtException("evaluate"); + _isEvaluating = false; return errorValue; } V8ScriptValue resultValue(_v8Isolate, result); + _isEvaluating = false; return ScriptValue(new ScriptValueV8Wrapper(this, std::move(resultValue))); } @@ -910,6 +979,8 @@ Q_INVOKABLE ScriptValue ScriptEngineV8::evaluate(const ScriptProgramPointer& pro Q_ARG(const ScriptProgramPointer&, program)); return result; } + Q_ASSERT(!isEvaluating()); + _isEvaluating = true; v8::HandleScope handleScope(_v8Isolate); v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); ScriptProgramV8Wrapper* unwrapped = ScriptProgramV8Wrapper::unwrap(program); @@ -917,6 +988,7 @@ Q_INVOKABLE ScriptValue ScriptEngineV8::evaluate(const ScriptProgramPointer& pro auto err = makeError(newValue("could not unwrap program")); raiseException(err); maybeEmitUncaughtException("compile"); + _isEvaluating = false; return err; } ScriptSyntaxCheckResultPointer syntaxCheck = unwrapped->checkSyntax(); @@ -924,6 +996,7 @@ Q_INVOKABLE ScriptValue ScriptEngineV8::evaluate(const ScriptProgramPointer& pro auto err = makeError(newValue(syntaxCheck->errorMessage())); raiseException(err); maybeEmitUncaughtException("compile"); + _isEvaluating = false; return err; } @@ -945,9 +1018,11 @@ Q_INVOKABLE ScriptValue ScriptEngineV8::evaluate(const ScriptProgramPointer& pro ScriptValue errorValue(new ScriptValueV8Wrapper(this, V8ScriptValue(_v8Isolate, runError->Get()))); raiseException(errorValue); maybeEmitUncaughtException("evaluate"); + _isEvaluating = false; return errorValue; } V8ScriptValue resultValue(_v8Isolate, result); + _isEvaluating = false; return ScriptValue(new ScriptValueV8Wrapper(this, std::move(resultValue))); } @@ -1019,6 +1094,8 @@ ScriptProgramPointer ScriptEngineV8::newProgram(const QString& sourceCode, const //V8TODO: is it used between isolates? //V8TODO: should it be compiled on creation? //V8ScriptProgram result(sourceCode, fileName); + v8::HandleScope handleScope(_v8Isolate); + v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); return std::make_shared(this, sourceCode, fileName); } @@ -1132,8 +1209,8 @@ bool ScriptEngineV8::hasUncaughtException() const { } bool ScriptEngineV8::isEvaluating() const { - //V8TODO //return QScriptEngine::isEvaluating(); + return _isEvaluating; return false; } diff --git a/libraries/script-engine/src/v8/ScriptEngineV8.h b/libraries/script-engine/src/v8/ScriptEngineV8.h index f0161e1d8a..cdda68f47a 100644 --- a/libraries/script-engine/src/v8/ScriptEngineV8.h +++ b/libraries/script-engine/src/v8/ScriptEngineV8.h @@ -228,6 +228,7 @@ protected: //V8TODO //ArrayBufferClass* _arrayBufferClass; + bool _isEvaluating; }; // Lambda helps create callable V8ScriptValues out of std::functions: diff --git a/libraries/script-engine/src/v8/ScriptEngineV8_cast.cpp b/libraries/script-engine/src/v8/ScriptEngineV8_cast.cpp index 10ad3e3936..c483f08df2 100644 --- a/libraries/script-engine/src/v8/ScriptEngineV8_cast.cpp +++ b/libraries/script-engine/src/v8/ScriptEngineV8_cast.cpp @@ -433,6 +433,48 @@ bool ScriptEngineV8::castValueToVariant(const V8ScriptValue& v8Val, QVariant& de case QMetaType::QObjectStar: dest = QVariant::fromValue(ScriptObjectV8Proxy::unwrap(v8Val)); break; + case QMetaType::QVariant: + if (val->IsUndefined()) { + dest = QVariant(); + break; + } + if (val->IsNull()) { + dest = QVariant::fromValue(nullptr); + break; + } + if (val->IsBoolean()) { + //V8TODO is it right isolate? What if value from different script engine is used here + dest = QVariant::fromValue(val->BooleanValue(_v8Isolate)); + break; + } + if (val->IsString()) { + //V8TODO is it right context? What if value from different script engine is used here + v8::String::Utf8Value string(_v8Isolate, val); + Q_ASSERT(*string != nullptr); + dest = QVariant::fromValue(QString(*string)); + //dest = QVariant::fromValue(val->ToString(_v8Context.Get(_v8Isolate)).ToLocalChecked()->); + break; + } + if (val->IsNumber()) { + dest = QVariant::fromValue(val->ToNumber(_v8Context.Get(_v8Isolate)).ToLocalChecked()->Value()); + break; + } + { + QObject* obj = ScriptObjectV8Proxy::unwrap(v8Val); + if (obj) { + dest = QVariant::fromValue(obj); + break; + } + } + { + QVariant var = ScriptVariantV8Proxy::unwrap(v8Val); + if (var.isValid()) { + dest = var; + break; + } + } + // V8TODO maybe export as JSON and then convert from JSON to QVariant? + Q_ASSERT(false); default: // check to see if this is a pointer to a QObject-derived object if (QMetaType::typeFlags(destTypeId) & (QMetaType::PointerToQObject | QMetaType::TrackingPointerToQObject)) { @@ -458,10 +500,14 @@ bool ScriptEngineV8::castValueToVariant(const V8ScriptValue& v8Val, QVariant& de break; } } - // last chance, just convert it to a variant + // last chance, just convert it to a variant (impossible on V8) // V8TODO - qDebug() << "Converting: " << *v8::String::Utf8Value(_v8Isolate, val->ToDetailString(getConstContext()).ToLocalChecked()) - << "to variant. Destination type: " << QMetaType::typeName(destTypeId); + QString errorMessage = QString() + "Converting: " + QString(*v8::String::Utf8Value(_v8Isolate, val->ToDetailString(getConstContext()).ToLocalChecked())) + + "to variant. Destination type: " + QMetaType::typeName(destTypeId); + qDebug() << errorMessage; + if(destTypeId == QMetaType::QVariant) { + Q_ASSERT(false); + } //dest = val->ToVariant(); break; } diff --git a/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp b/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp index 47ff561d87..bbd5200b7d 100644 --- a/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp +++ b/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp @@ -657,6 +657,10 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo& argume int bestMeta = 0; int bestConversionPenaltyScore = 0; + if(fullName() == "SettingsScriptingInterface::getValue") { + printf("SettingsScriptingInterface::getValue"); + } + for (int i = 0; i < num_metas; i++) { const QMetaMethod& meta = _metas[i]; int methodNumArgs = meta.parameterCount(); @@ -783,21 +787,25 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo& argume int methodArgTypeId = meta.parameterType(arg); Q_ASSERT(methodArgTypeId != QMetaType::UnknownType); v8::Local argVal = arguments[arg]; - if (methodArgTypeId != scriptValueTypeId && methodArgTypeId != QMetaType::QVariant) { + if (methodArgTypeId != scriptValueTypeId) { QVariant varArgVal; if (!_engine->castValueToVariant(V8ScriptValue(isolate, argVal), varArgVal, methodArgTypeId)) { QByteArray methodTypeName = QMetaType(methodArgTypeId).name(); QByteArray argTypeName = _engine->valueType(V8ScriptValue(isolate, argVal)).toLatin1(); - isolate->ThrowError(v8::String::NewFromUtf8(isolate, QString("Native call of %1 failed: Cannot convert parameter %2 from %3 to %4") - .arg(fullName()).arg(arg+1).arg(argTypeName, methodTypeName).toStdString().c_str()).ToLocalChecked()); + QString errorMessage = QString("Native call of %1 failed: Cannot convert parameter %2 from %3 to %4") + .arg(fullName()).arg(arg+1).arg(argTypeName, methodTypeName); + qDebug(scriptengine) << errorMessage; + isolate->ThrowError(v8::String::NewFromUtf8(isolate, errorMessage.toStdString().c_str()).ToLocalChecked()); //context->throwError(V8ScriptContext::TypeError, QString("Native call of %1 failed: Cannot convert parameter %2 from %3 to %4") // .arg(fullName()).arg(arg+1).arg(argTypeName, methodTypeName)); return; } } } - - isolate->ThrowError(v8::String::NewFromUtf8(isolate, QString("Native call of %1 failed: could not locate an overload with the requested arguments").arg(fullName()).toStdString().c_str()).ToLocalChecked()); + QString errorMessage = QString("Native call of %1 failed: could not locate an overload with the requested arguments").arg(fullName()); + qDebug(scriptengine) << errorMessage; + isolate->ThrowError(v8::String::NewFromUtf8(isolate, errorMessage.toStdString().c_str()).ToLocalChecked()); + // V8TODO: it happens sometimes for some reason Q_ASSERT(false); // really shouldn't have gotten here -- it didn't work before and it's working now? return; } diff --git a/libraries/script-engine/src/v8/ScriptProgramV8Wrapper.cpp b/libraries/script-engine/src/v8/ScriptProgramV8Wrapper.cpp index 54ea3f6723..7baca34b12 100644 --- a/libraries/script-engine/src/v8/ScriptProgramV8Wrapper.cpp +++ b/libraries/script-engine/src/v8/ScriptProgramV8Wrapper.cpp @@ -35,6 +35,7 @@ bool ScriptProgramV8Wrapper::compile() { auto isolate = _engine->getIsolate(); v8::HandleScope handleScope(isolate); auto context = _engine->getContext(); + v8::Context::Scope contextScope(context); int errorColumnNumber = 0; int errorLineNumber = 0; QString errorMessage = ""; diff --git a/libraries/script-engine/src/v8/ScriptProgramV8Wrapper.h b/libraries/script-engine/src/v8/ScriptProgramV8Wrapper.h index 03313292b6..ff98a3177e 100644 --- a/libraries/script-engine/src/v8/ScriptProgramV8Wrapper.h +++ b/libraries/script-engine/src/v8/ScriptProgramV8Wrapper.h @@ -50,7 +50,7 @@ public: // construction _engine(engine), _value(value) {}*/ //inline ScriptProgramV8Wrapper(ScriptEngineV8* engine, V8ScriptProgram&& value) : // _engine(engine), _value(std::move(value)) {} - inline ScriptProgramV8Wrapper(ScriptEngineV8* engine, QString source, QString url) : + inline ScriptProgramV8Wrapper(ScriptEngineV8* engine, QString source, QString url) : _engine(engine), _source(source), _url(url), _value(engine->getIsolate(), v8::Local()) {} static ScriptProgramV8Wrapper* unwrap(ScriptProgramPointer val); bool compile(); diff --git a/libraries/script-engine/src/v8/ScriptValueV8Wrapper.cpp b/libraries/script-engine/src/v8/ScriptValueV8Wrapper.cpp index 7ab42d5123..f59f5b4657 100644 --- a/libraries/script-engine/src/v8/ScriptValueV8Wrapper.cpp +++ b/libraries/script-engine/src/v8/ScriptValueV8Wrapper.cpp @@ -183,7 +183,7 @@ ScriptValue ScriptValueV8Wrapper::property(const QString& name, const ScriptValu return ScriptValue(new ScriptValueV8Wrapper(_engine, std::move(result))); } } - qCritical() << "Failed to get property, parent of value: " << name << " is not a V8 object, reported type: " << QString(*v8::String::Utf8Value(isolate, _value.constGet()->TypeOf(isolate))); + qDebug() << "Failed to get property, parent of value: " << name << " is not a V8 object, reported type: " << QString(*v8::String::Utf8Value(isolate, _value.constGet()->TypeOf(isolate))); return _engine->undefinedValue(); /*v8::Local nullValue = v8::Null(_engine->getIsolate()); V8ScriptValue nullScriptValue(_engine->getIsolate(), std::move(nullValue)); diff --git a/libraries/shared/src/Transform.h b/libraries/shared/src/Transform.h index 90bfc1aaa6..f0d67aa0c0 100644 --- a/libraries/shared/src/Transform.h +++ b/libraries/shared/src/Transform.h @@ -26,7 +26,9 @@ class QJsonValue; inline bool isValidScale(glm::vec3 scale) { bool result = scale.x != 0.0f && scale.y != 0.0f && scale.z != 0.0f; - assert(result); + // V8TODO: commented out for now + qWarning() << "Scale is equal to 0"; + // assert(result); return result; }