diff --git a/libraries/script-engine/src/v8/ScriptEngineV8.cpp b/libraries/script-engine/src/v8/ScriptEngineV8.cpp index 206756fbe7..f58bc1e838 100644 --- a/libraries/script-engine/src/v8/ScriptEngineV8.cpp +++ b/libraries/script-engine/src/v8/ScriptEngineV8.cpp @@ -73,8 +73,16 @@ bool ScriptEngineV8::IS_THREADSAFE_INVOCATION(const QThread* thread, const QStri // engine-aware JS Error copier and factory V8ScriptValue ScriptEngineV8::makeError(const V8ScriptValue& _other, const QString& type) { if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) { + v8::Locker locker(_v8Isolate); + v8::Isolate::Scope isolateScope(_v8Isolate); + v8::HandleScope handleScope(_v8Isolate); + v8::Context::Scope contextScope(getContext()); return V8ScriptValue(this, v8::Null(_v8Isolate)); } + v8::Locker locker(_v8Isolate); + v8::Isolate::Scope isolateScope(_v8Isolate); + v8::HandleScope handleScope(_v8Isolate); + v8::Context::Scope contextScope(getContext()); return V8ScriptValue(this, v8::Null(_v8Isolate)); //V8TODO /* @@ -308,6 +316,8 @@ bool ScriptEngineV8::maybeEmitUncaughtException(const QString& debugHint) { return call; }*/ QString Lambda::toString() const { + v8::Locker locker(_engine->getIsolate()); + v8::Isolate::Scope isolateScope(_engine->getIsolate()); v8::HandleScope handleScope(_engine->getIsolate()); v8::Context::Scope contextScope(_engine->getContext()); v8::Local string; @@ -1118,6 +1128,7 @@ QString ScriptEngineV8::formatErrorMessageFromTryCatch(v8::TryCatch &tryCatch) { } ScriptContextV8Pointer ScriptEngineV8::pushContext(v8::Local context) { + v8::HandleScope handleScope(_v8Isolate); Q_ASSERT(!_contexts.isEmpty()); ScriptContextPointer parent = _contexts.last(); _contexts.append(std::make_shared(this, context, ScriptContextPointer())); @@ -1472,6 +1483,11 @@ ScriptValue ScriptEngineV8::newFunction(ScriptEngine::FunctionSignature fun, int return unwrapped ? unwrapped->toV8Value() : V8ScriptValue(); };*/ + v8::Locker locker(_v8Isolate); + v8::Isolate::Scope isolateScope(_v8Isolate); + v8::HandleScope handleScope(_v8Isolate); + v8::Context::Scope contextScope(getContext()); + auto v8FunctionCallback = [](const v8::FunctionCallbackInfo& info) { //V8TODO: is using GetCurrentContext ok, or context wrapper needs to be added? v8::HandleScope handleScope(info.GetIsolate()); @@ -1495,10 +1511,6 @@ ScriptValue ScriptEngineV8::newFunction(ScriptEngine::FunctionSignature fun, int //auto functionTemplate = v8::FunctionTemplate::New(_v8Isolate, v8FunctionCallback, v8::Local(), v8::Local(), length); //auto functionData = v8::Object::New(_v8Isolate); //functionData->setIn - v8::Locker locker(_v8Isolate); - v8::Isolate::Scope isolateScope(_v8Isolate); - v8::HandleScope handleScope(_v8Isolate); - v8::Context::Scope contextScope(getContext()); auto functionDataTemplate = v8::ObjectTemplate::New(_v8Isolate); functionDataTemplate->SetInternalFieldCount(2); auto functionData = functionDataTemplate->NewInstance(getContext()).ToLocalChecked(); diff --git a/libraries/script-engine/src/v8/ScriptEngineV8_cast.cpp b/libraries/script-engine/src/v8/ScriptEngineV8_cast.cpp index 1d51439456..45e6e93108 100644 --- a/libraries/script-engine/src/v8/ScriptEngineV8_cast.cpp +++ b/libraries/script-engine/src/v8/ScriptEngineV8_cast.cpp @@ -186,6 +186,7 @@ static bool JsonArrayFromScriptValue(const ScriptValue& src, QJsonArray& dest) { // QMetaType::QJsonArray void ScriptEngineV8::registerSystemTypes() { + // V8TODO: why is this commented out? //qScriptRegisterMetaType(this, ScriptValueToV8ScriptValue, ScriptValueFromV8ScriptValue); scriptRegisterMetaType(static_cast(this)); @@ -564,6 +565,7 @@ bool ScriptEngineV8::castValueToVariant(const V8ScriptValue& v8Val, QVariant& de bool ScriptEngineV8::convertJSArrayToVariant(v8::Local array, QVariant &dest) { v8::HandleScope handleScope(_v8Isolate); auto context = getContext(); + v8::Context::Scope contextScope(context); int length = array->Length(); QList properties; for (int i = 0; i < length; i++) { @@ -588,6 +590,7 @@ bool ScriptEngineV8::convertJSArrayToVariant(v8::Local array, QVarian bool ScriptEngineV8::convertJSObjectToVariant(v8::Local object, QVariant &dest) { v8::HandleScope handleScope(_v8Isolate); auto context = getContext(); + v8::Context::Scope contextScope(context); v8::Local names; if(!object->GetPropertyNames(context).ToLocal(&names)) { qDebug() << "ScriptEngineV8::convertJSObjectToVariant could not get property names"; diff --git a/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp b/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp index ac1fb6f77b..2c3f551ea6 100644 --- a/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp +++ b/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp @@ -138,8 +138,14 @@ V8ScriptValue ScriptObjectV8Proxy::newQObject(ScriptEngineV8* engine, QObject* o } ScriptObjectV8Proxy* ScriptObjectV8Proxy::unwrapProxy(const V8ScriptValue& val) { + auto isolate = val.getEngine()->getIsolate(); + v8::Locker locker(isolate); + v8::Isolate::Scope isolateScope(isolate); + v8::HandleScope handleScope(isolate); + v8::Local context = val.constGetContext(); + v8::Context::Scope contextScope(context); //V8TODO This shouldn't cause problems but I'm not sure if it's ok - v8::HandleScope handleScope(const_cast(val.constGetIsolate())); + //v8::HandleScope handleScope(const_cast(val.constGetIsolate())); auto v8Value = val.constGet(); if (!v8Value->IsObject()) { //qDebug(scriptengine) << "Cannot unwrap proxy - value is not an object"; @@ -158,8 +164,12 @@ ScriptObjectV8Proxy* ScriptObjectV8Proxy::unwrapProxy(const V8ScriptValue& val) } ScriptObjectV8Proxy* ScriptObjectV8Proxy::unwrapProxy(v8::Isolate* isolate, v8::Local &value) { - //V8TODO This shouldn't cause problems but I'm not sure if it's ok + v8::Locker locker(isolate); + v8::Isolate::Scope isolateScope(isolate); v8::HandleScope handleScope(isolate); + //V8TODO: shouldn't there be context scope here? + //v8::Local context = val.constGetContext(); + //v8::Context::Scope contextScope(context); if (!value->IsObject()) { //qDebug(scriptengine) << "Cannot unwrap proxy - value is not an object"; return nullptr; @@ -193,7 +203,10 @@ void ScriptObjectV8Proxy::investigate() { QObject* qobject = _object; Q_ASSERT(qobject); if (!qobject) return; - + + auto isolate = _engine->getIsolate(); + v8::Locker locker(isolate); + v8::Isolate::Scope isolateScope(isolate); v8::HandleScope handleScope(_engine->getIsolate()); v8::Context::Scope contextScope(_engine->getContext()); @@ -346,14 +359,18 @@ QString ScriptObjectV8Proxy::name() const { } ScriptObjectV8Proxy::QueryFlags ScriptObjectV8Proxy::queryProperty(const V8ScriptValue& object, const V8ScriptString& name, QueryFlags flags, uint* id) { - v8::HandleScope handleScope(_engine->getIsolate()); + auto isolate = _engine->getIsolate(); + v8::Locker locker(isolate); + v8::Isolate::Scope isolateScope(isolate); + v8::HandleScope handleScope(isolate); // V8TODO: this might be inefficient when there's large number of properties - //v8::Local context = _engine->getContext(); - v8::String::Utf8Value nameStr(_engine->getIsolate(), name.constGet()); + v8::Local context = _engine->getContext(); + v8::Context::Scope contextScope(context); + v8::String::Utf8Value nameStr(isolate, name.constGet()); // check for methods for (MethodDefMap::const_iterator trans = _methods.cbegin(); trans != _methods.cend(); ++trans) { - v8::String::Utf8Value methodNameStr(_engine->getIsolate(), trans.value().name.constGet()); + v8::String::Utf8Value methodNameStr(isolate, trans.value().name.constGet()); //qDebug(scriptengine) << "queryProperty : " << *nameStr << " method: " << *methodNameStr; if (!(trans.value().name == name)) continue; *id = trans.key() | METHOD_TYPE; @@ -407,6 +424,7 @@ ScriptValue::PropertyFlags ScriptObjectV8Proxy::propertyFlags(const V8ScriptValu void ScriptObjectV8Proxy::v8Get(v8::Local name, const v8::PropertyCallbackInfo& info) { v8::HandleScope handleScope(info.GetIsolate()); + //V8TODO: should there be a context scope here? v8::String::Utf8Value utf8Value(info.GetIsolate(), name); //qDebug(scriptengine) << "Get: " << *utf8Value; v8::Local objectV8 = info.This(); @@ -435,6 +453,7 @@ void ScriptObjectV8Proxy::v8Get(v8::Local name, const v8::PropertyCall void ScriptObjectV8Proxy::v8Set(v8::Local name, v8::Local value, const v8::PropertyCallbackInfo& info) { v8::HandleScope handleScope(info.GetIsolate()); + //V8TODO: should there be a context scope here? v8::String::Utf8Value utf8Value(info.GetIsolate(), name); //qDebug(scriptengine) << "Set: " << *utf8Value; v8::Local objectV8 = info.This(); @@ -464,14 +483,15 @@ void ScriptObjectV8Proxy::v8Set(v8::Local name, v8::Local v V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V8ScriptString& name, uint id) { - v8::Locker locker(_engine->getIsolate()); - v8::Isolate::Scope isolateScope(_engine->getIsolate()); - v8::HandleScope handleScope(_engine->getIsolate()); + auto isolate = _engine->getIsolate(); + v8::Locker locker(isolate); + v8::Isolate::Scope isolateScope(isolate); + v8::HandleScope handleScope(isolate); v8::Context::Scope contextScope(_engine->getContext()); QObject* qobject = _object; if (!qobject) { _engine->getIsolate()->ThrowError("Referencing deleted native object"); - return V8ScriptValue(_engine, v8::Null(_engine->getIsolate())); + return V8ScriptValue(_engine, v8::Null(isolate)); } const QMetaObject* metaObject = qobject->metaObject(); @@ -480,7 +500,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V case PROPERTY_TYPE: { int propId = id & ~TYPE_MASK; PropertyDefMap::const_iterator lookup = _props.find(propId); - if (lookup == _props.cend()) return V8ScriptValue(_engine, v8::Null(_engine->getIsolate())); + if (lookup == _props.cend()) return V8ScriptValue(_engine, v8::Null(isolate)); QMetaProperty prop = metaObject->property(propId); ScriptValue scriptThis = ScriptValue(new ScriptValueV8Wrapper(_engine, object)); @@ -493,7 +513,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V case METHOD_TYPE: { int methodId = id & ~TYPE_MASK; MethodDefMap::const_iterator lookup = _methods.find(methodId); - if (lookup == _methods.cend()) return V8ScriptValue(_engine, v8::Null(_engine->getIsolate())); + if (lookup == _methods.cend()) return V8ScriptValue(_engine, v8::Null(isolate)); const MethodDef& methodDef = lookup.value(); for (auto iter = methodDef.methods.begin(); iter != methodDef.methods.end(); iter++ ) { if((*iter).returnType() == QMetaType::UnknownType) { @@ -502,7 +522,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V } //V8TODO: is new method created during every call? It needs to be cached instead //bool isMethodDefined = false; v8::Local property; - if(_v8Object.Get(_engine->getIsolate())->GetInternalField(2).As()->Get(_engine->getContext(), name.constGet()).ToLocal(&property)) { + if(_v8Object.Get(isolate)->GetInternalField(2).As()->Get(_engine->getContext(), name.constGet()).ToLocal(&property)) { if (!property->IsUndefined()) { return V8ScriptValue(_engine, property); } @@ -514,7 +534,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V case SIGNAL_TYPE: { int signalId = id & ~TYPE_MASK; SignalDefMap::const_iterator defLookup = _signals.find(signalId); - if (defLookup == _signals.cend()) return V8ScriptValue(_engine, v8::Null(_engine->getIsolate())); + if (defLookup == _signals.cend()) return V8ScriptValue(_engine, v8::Null(isolate)); InstanceMap::const_iterator instLookup = _signalInstances.find(signalId); if (instLookup == _signalInstances.cend() || instLookup.value().isNull()) { @@ -532,13 +552,14 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V //return _engine->newQObject(proxy, ScriptEngine::ScriptOwnership, options); } } - return V8ScriptValue(_engine, v8::Null(_engine->getIsolate())); + return V8ScriptValue(_engine, v8::Null(isolate)); } void ScriptObjectV8Proxy::setProperty(V8ScriptValue& object, const V8ScriptString& name, uint id, const V8ScriptValue& value) { - v8::Locker locker(_engine->getIsolate()); - v8::Isolate::Scope isolateScope(_engine->getIsolate()); - v8::HandleScope handleScope(_engine->getIsolate()); + auto isolate = _engine->getIsolate(); + v8::Locker locker(isolate); + v8::Isolate::Scope isolateScope(isolate); + v8::HandleScope handleScope(isolate); v8::Context::Scope contextScope(_engine->getContext()); if (!(id & PROPERTY_TYPE)) return; QObject* qobject = _object; @@ -566,7 +587,7 @@ void ScriptObjectV8Proxy::setProperty(V8ScriptValue& object, const V8ScriptStrin if(!_engine->castValueToVariant(value, varValue, propTypeId)) { QByteArray propTypeName = QMetaType(propTypeId).name(); QByteArray valTypeName = _engine->valueType(value).toLatin1(); - _engine->getIsolate()->ThrowError(v8::String::NewFromUtf8(_engine->getIsolate(), QString("Cannot convert %1 to %2").arg(valTypeName, propTypeName).toStdString().c_str()).ToLocalChecked()); + isolate->ThrowError(v8::String::NewFromUtf8(isolate, QString("Cannot convert %1 to %2").arg(valTypeName, propTypeName).toStdString().c_str()).ToLocalChecked()); return; } prop.write(qobject, varValue); @@ -578,20 +599,21 @@ ScriptVariantV8Proxy::ScriptVariantV8Proxy(ScriptEngineV8* engine, const QVarian } V8ScriptValue ScriptVariantV8Proxy::newVariant(ScriptEngineV8* engine, const QVariant& variant, V8ScriptValue proto) { - v8::Locker locker(engine->getIsolate()); - v8::Isolate::Scope isolateScope(engine->getIsolate()); - v8::HandleScope handleScope(engine->getIsolate()); + auto isolate = engine->getIsolate(); + v8::Locker locker(isolate); + v8::Isolate::Scope isolateScope(isolate); + v8::HandleScope handleScope(isolate); v8::Context::Scope contextScope(engine->getContext()); ScriptObjectV8Proxy* protoProxy = ScriptObjectV8Proxy::unwrapProxy(proto); if (!protoProxy) { Q_ASSERT(protoProxy); //return engine->newVariant(variant); - return V8ScriptValue(engine, v8::Undefined(engine->getIsolate())); + return V8ScriptValue(engine, v8::Undefined(isolate)); } // V8TODO probably needs connection to be deleted // V8TODO what to do with proto variable? auto proxy = new ScriptVariantV8Proxy(engine, variant, proto, protoProxy); - auto variantDataTemplate = v8::ObjectTemplate::New(engine->getIsolate()); + auto variantDataTemplate = v8::ObjectTemplate::New(isolate); variantDataTemplate->SetInternalFieldCount(2); auto variantData = variantDataTemplate->NewInstance(engine->getContext()).ToLocalChecked(); variantData->SetAlignedPointerInInternalField(0, const_cast(internalPointsToQVariantProxy)); @@ -600,8 +622,12 @@ V8ScriptValue ScriptVariantV8Proxy::newVariant(ScriptEngineV8* engine, const QVa } ScriptVariantV8Proxy* ScriptVariantV8Proxy::unwrapProxy(const V8ScriptValue& val) { - // V8TODO V8ScriptValue should have link to engine instead maybe? - v8::HandleScope handleScope(const_cast(val.constGetIsolate())); + auto isolate = val.getEngine()->getIsolate(); + v8::Locker locker(isolate); + v8::Isolate::Scope isolateScope(isolate); + v8::HandleScope handleScope(isolate); + v8::Context::Scope contextScope(val.getEngine()->getContext()); + auto v8Value = val.constGet(); if (!v8Value->IsObject()) { return nullptr; @@ -633,11 +659,12 @@ ScriptMethodV8Proxy::~ScriptMethodV8Proxy() { V8ScriptValue ScriptMethodV8Proxy::newMethod(ScriptEngineV8* engine, QObject* object, V8ScriptValue lifetime, const QList& metas, int numMaxParams) { - v8::Locker locker(engine->getIsolate()); - v8::Isolate::Scope isolateScope(engine->getIsolate()); - v8::HandleScope handleScope(engine->getIsolate()); + auto isolate = engine->getIsolate(); + v8::Locker locker(isolate); + v8::Isolate::Scope isolateScope(isolate); + v8::HandleScope handleScope(isolate); v8::Context::Scope contextScope(engine->getContext()); - auto methodDataTemplate = v8::ObjectTemplate::New(engine->getIsolate()); + auto methodDataTemplate = v8::ObjectTemplate::New(isolate); methodDataTemplate->SetInternalFieldCount(2); auto methodData = methodDataTemplate->NewInstance(engine->getContext()).ToLocalChecked(); methodData->SetAlignedPointerInInternalField(0, const_cast(internalPointsToMethodProxy)); @@ -697,13 +724,13 @@ void ScriptMethodV8Proxy::callback(const v8::FunctionCallbackInfo& ar } void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo& arguments) { - v8::Locker locker(_engine->getIsolate()); - v8::Isolate::Scope isolateScope(_engine->getIsolate()); - v8::HandleScope handleScope(_engine->getIsolate()); - v8::Context::Scope contextScope(_engine->getContext()); - QObject* qobject = _object; v8::Isolate *isolate = arguments.GetIsolate(); Q_ASSERT(isolate == _engine->getIsolate()); + v8::Locker locker(isolate); + v8::Isolate::Scope isolateScope(isolate); + v8::HandleScope handleScope(isolate); + v8::Context::Scope contextScope(_engine->getContext()); + QObject* qobject = _object; if (!qobject) { isolate->ThrowError("Referencing deleted native object"); return; @@ -879,6 +906,7 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo& argume return; } +//V8TODO: was this used anywhere? /*QVariant ScriptMethodV8Proxy::extension(Extension extension, const QVariant& argument) { if (extension != Callable) return QVariant(); V8ScriptContext* context = qvariant_cast(argument); @@ -1066,21 +1094,17 @@ int ScriptSignalV8Proxy::qt_metacall(QMetaObject::Call call, int id, void** argu auto isolate = _engine->getIsolate(); v8::Locker locker(isolate); v8::Isolate::Scope isolateScope(isolate); - v8::HandleScope handleScope(isolate); - // V8TODO: should we use function creation context, or context in which connect happened? - - auto context = _engine->getContext(); - v8::Context::Scope contextScope(context); //V8ScriptValueList args(isolate, v8::Null(isolate)); - v8::Local args[Q_METAMETHOD_INVOKE_MAX_ARGS]; + // Moved to inside of the lock - could it cause crashes if left here? + /*v8::Local args[Q_METAMETHOD_INVOKE_MAX_ARGS]; int numArgs = _meta.parameterCount(); for (int arg = 0; arg < numArgs; ++arg) { int methodArgTypeId = _meta.parameterType(arg); Q_ASSERT(methodArgTypeId != QMetaType::UnknownType); QVariant argValue(methodArgTypeId, arguments[arg+1]); args[arg] = _engine->castVariantToValue(argValue).get(); - } + }*/ /*QList connections; withReadLock([&]{ @@ -1090,7 +1114,20 @@ int ScriptSignalV8Proxy::qt_metacall(QMetaObject::Call call, int id, void** argu // V8TODO: this may cause deadlocks on connect/disconnect, so the connect/disconnect procedure needs to be reworked. // It should probably add events to a separate list that would be processed before and after all the events for the signal. withReadLock([&]{ + // V8TODO: check all other lambda functions to make sure they have handle scope - could they cause crashes otherwise? + v8::HandleScope handleScope(isolate); + // V8TODO: should we use function creation context, or context in which connect happened? + auto context = _engine->getContext(); + v8::Context::Scope contextScope(context); + v8::Local args[Q_METAMETHOD_INVOKE_MAX_ARGS]; + int numArgs = _meta.parameterCount(); //for (ConnectionList::iterator iter = connections.begin(); iter != connections.end(); ++iter) { + for (int arg = 0; arg < numArgs; ++arg) { + int methodArgTypeId = _meta.parameterType(arg); + Q_ASSERT(methodArgTypeId != QMetaType::UnknownType); + QVariant argValue(methodArgTypeId, arguments[arg+1]); + args[arg] = _engine->castVariantToValue(argValue).get(); + } for (ConnectionList::iterator iter = _connections.begin(); iter != _connections.end(); ++iter) { Connection& conn = *iter; { @@ -1142,11 +1179,11 @@ int ScriptSignalV8Proxy::discoverMetaCallIdx() { } ScriptSignalV8Proxy::ConnectionList::iterator ScriptSignalV8Proxy::findConnection(V8ScriptValue thisObject, V8ScriptValue callback) { - v8::Locker locker(_engine->getIsolate()); - v8::Isolate::Scope isolateScope(_engine->getIsolate()); - v8::HandleScope handleScope(_engine->getIsolate()); - v8::Context::Scope contextScope(_engine->getContext()); auto iterOut = resultWithReadLock([&]{ + v8::Locker locker(_engine->getIsolate()); + v8::Isolate::Scope isolateScope(_engine->getIsolate()); + v8::HandleScope handleScope(_engine->getIsolate()); + v8::Context::Scope contextScope(_engine->getContext()); ConnectionList::iterator iter; for (iter = _connections.begin(); iter != _connections.end(); ++iter) { Connection& conn = *iter; diff --git a/libraries/script-engine/src/v8/ScriptProgramV8Wrapper.h b/libraries/script-engine/src/v8/ScriptProgramV8Wrapper.h index eb7a14bbfe..c61b83f231 100644 --- a/libraries/script-engine/src/v8/ScriptProgramV8Wrapper.h +++ b/libraries/script-engine/src/v8/ScriptProgramV8Wrapper.h @@ -52,7 +52,18 @@ public: // construction //inline ScriptProgramV8Wrapper(ScriptEngineV8* engine, V8ScriptProgram&& value) : // _engine(engine), _value(std::move(value)) {} inline ScriptProgramV8Wrapper(ScriptEngineV8* engine, QString source, QString url) : - _engine(engine), _source(source), _url(url), _value(engine, v8::Local()) {} + _engine(engine), _source(source), _url(url), _value(_engine) { + auto isolate = _engine->getIsolate(); + v8::Locker locker(isolate); + v8::Isolate::Scope isolateScope(isolate); + v8::HandleScope handleScope(isolate); + v8::Context::Scope contextScope(_engine->getContext()); + // V8TODO: In implicit copy assignment operator for 'V8ScriptValueTemplate' + // first required here /home/ksuprynowicz/overte/overte_v8/libraries/script-engine/src/v8/V8Types.h:45:5: + // warning: definition of implicit copy assignment operator for 'V8ScriptValueTemplate' is deprecated + // because it has a user-provided copy constructor + _value = V8ScriptProgram(engine, v8::Local()); + } static ScriptProgramV8Wrapper* unwrap(ScriptProgramPointer val); bool compile(); inline const V8ScriptProgram& toV8Value() const { return _value; } diff --git a/libraries/script-engine/src/v8/ScriptValueV8Wrapper.cpp b/libraries/script-engine/src/v8/ScriptValueV8Wrapper.cpp index ae212a04fc..5db23d080a 100644 --- a/libraries/script-engine/src/v8/ScriptValueV8Wrapper.cpp +++ b/libraries/script-engine/src/v8/ScriptValueV8Wrapper.cpp @@ -176,6 +176,7 @@ ScriptValue ScriptValueV8Wrapper::construct(const ScriptValue& arguments) { //return ScriptValue(new ScriptValueV8Wrapper(_engine, std::move(result))); } +// V8TODO: check how data() is used and if it needs fixing ScriptValue ScriptValueV8Wrapper::data() const { auto isolate = _engine->getIsolate(); v8::Locker locker(isolate); @@ -189,8 +190,10 @@ ScriptValue ScriptValueV8Wrapper::data() const { //bool createData = false; if (!v8Object->Get(_engine->getContext(), v8::String::NewFromUtf8(isolate, "__data").ToLocalChecked()).ToLocal(&data)) { data = v8::Undefined(isolate); + Q_ASSERT(false); //createData = true; - } /*else { + } + /*else { if (data->IsUndefined()) { createData = true; } @@ -284,8 +287,9 @@ ScriptValue ScriptValueV8Wrapper::property(const QString& name, const ScriptValu if (name == QString("x")) { printf("x"); } - 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))); - qDebug() << "Backtrace: " << _engine->currentContext()->backtrace(); + //This displays too many messages during correct operation, but is useful for debugging + //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))); + //qDebug() << "Backtrace: " << _engine->currentContext()->backtrace(); return _engine->undefinedValue(); /*v8::Local nullValue = v8::Null(_engine->getIsolate()); V8ScriptValue nullScriptValue(_engine->getIsolate(), std::move(nullValue)); @@ -536,8 +540,9 @@ bool ScriptValueV8Wrapper::equals(const ScriptValue& other) const { v8::HandleScope handleScope(isolate); v8::Context::Scope contextScope(_engine->getContext()); ScriptValueV8Wrapper* unwrappedOther = unwrap(other); - //V8TODO: does this work with different contexts/isolates? + //V8TODO: is this used with different isolates? // in such case conversion will probably be necessary + Q_ASSERT(_engine->getIsolate() == unwrappedOther->_engine->getIsolate()); if (!unwrappedOther) { return false; }else{ @@ -656,6 +661,7 @@ bool ScriptValueV8Wrapper::isVariant() const { v8::Isolate::Scope isolateScope(isolate); v8::HandleScope handleScope(isolate); v8::Context::Scope contextScope(_engine->getContext()); + Q_ASSERT(false); return false; //return _value.isVariant(); } diff --git a/libraries/script-engine/src/v8/V8Types.h b/libraries/script-engine/src/v8/V8Types.h index d11506521e..d494e8af26 100644 --- a/libraries/script-engine/src/v8/V8Types.h +++ b/libraries/script-engine/src/v8/V8Types.h @@ -34,6 +34,14 @@ public: _value.reset(new v8::UniquePersistent(_engine->getIsolate(), std::move(value))); }; + V8ScriptValueTemplate(ScriptEngineV8 *engine) : _engine(engine) { + v8::Locker locker(_engine->getIsolate()); + v8::Isolate::Scope isolateScope(_engine->getIsolate()); + v8::HandleScope handleScope(_engine->getIsolate()); + v8::Context::Scope(_engine->getContext()); + _value.reset(new v8::UniquePersistent(_engine->getIsolate(), v8::Local())); + }; + V8ScriptValueTemplate(const V8ScriptValueTemplate &copied) : _engine(copied.getEngine()) { v8::Locker locker(_engine->getIsolate()); v8::Isolate::Scope isolateScope(_engine->getIsolate());