History

Script engine thread safety improvements

ksuprynowicz committed 3 years ago

Commit 044cd501 parent 6bd8a8d21 files · +374 −204Browse files

Showing the changes to libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp (1 of 21 files). Show all

Unified · Split

libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp+93−49
@@ -76,7 +76,7 @@ V8ScriptValue ScriptObjectV8Proxy::newQObject(ScriptEngineV8* engine, QObject* o · 75 unmodified lines
76 QSharedPointer<ScriptObjectV8Proxy> proxy = lookup.value().lock();76 QSharedPointer<ScriptObjectV8Proxy> proxy = lookup.value().lock();
77 // V8TODO: is conversion to QVariant and back needed?77 // V8TODO: is conversion to QVariant and back needed?
78 if (proxy) {78 if (proxy) {
79 return V8ScriptValue(engine->getIsolate(), proxy.get()->toV8Value());79 return V8ScriptValue(engine, proxy.get()->toV8Value());
80 }80 }
81 //if (proxy) return engine->newObject(proxy.get(), engine->newVariant(QVariant::fromValue(proxy)));;81 //if (proxy) return engine->newObject(proxy.get(), engine->newVariant(QVariant::fromValue(proxy)));;
82 }82 }
@@ -111,7 +111,7 @@ V8ScriptValue ScriptObjectV8Proxy::newQObject(ScriptEngineV8* engine, QObject* o · 28 unmodified lines
111 QSharedPointer<ScriptObjectV8Proxy> proxy = lookup.value().lock();111 QSharedPointer<ScriptObjectV8Proxy> proxy = lookup.value().lock();
112 //if (proxy) return qengine->newObject(proxy.get(), qengine->newVariant(QVariant::fromValue(proxy)));;112 //if (proxy) return qengine->newObject(proxy.get(), qengine->newVariant(QVariant::fromValue(proxy)));;
113 if (proxy) {113 if (proxy) {
114 return V8ScriptValue(engine->getIsolate(), proxy.get()->toV8Value());114 return V8ScriptValue(engine, proxy.get()->toV8Value());
115 }115 }
116 }116 }
117 // V8TODO add a V8 callback that removes pointer for the script engine owned ob from the map so that it gets deleted117 // V8TODO add a V8 callback that removes pointer for the script engine owned ob from the map so that it gets deleted
@@ -133,7 +133,7 @@ V8ScriptValue ScriptObjectV8Proxy::newQObject(ScriptEngineV8* engine, QObject* o · 15 unmodified lines
133 });133 });
134 }134 }
135 135
136 return V8ScriptValue(engine->getIsolate(), proxy.get()->toV8Value());136 return V8ScriptValue(engine, proxy.get()->toV8Value());
137 //return qengine->newObject(proxy.get(), qengine->newVariant(QVariant::fromValue(proxy)));137 //return qengine->newObject(proxy.get(), qengine->newVariant(QVariant::fromValue(proxy)));
138}138}
139 139
@@ -157,6 +157,25 @@ ScriptObjectV8Proxy* ScriptObjectV8Proxy::unwrapProxy(const V8ScriptValue& val) · 17 unmodified lines
157 return reinterpret_cast<ScriptObjectV8Proxy*>(v8Object->GetAlignedPointerFromInternalField(1));157 return reinterpret_cast<ScriptObjectV8Proxy*>(v8Object->GetAlignedPointerFromInternalField(1));
158}158}
159 159
160ScriptObjectV8Proxy* ScriptObjectV8Proxy::unwrapProxy(v8::Isolate* isolate, v8::Local<v8::Value> &value) {
161 //V8TODO This shouldn't cause problems but I'm not sure if it's ok
162 v8::HandleScope handleScope(isolate);
163 if (!value->IsObject()) {
164 //qDebug(scriptengine) << "Cannot unwrap proxy - value is not an object";
165 return nullptr;
166 }
167 v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::Cast(value);
168 if (v8Object->InternalFieldCount() != 3) {
169 //qDebug(scriptengine) << "Cannot unwrap proxy - wrong number of internal fields";
170 return nullptr;
171 }
172 if (v8Object->GetAlignedPointerFromInternalField(0) != internalPointsToQObjectProxy) {
173 qDebug(scriptengine) << "Cannot unwrap proxy - internal fields don't point to object proxy";
174 return nullptr;
175 }
176 return reinterpret_cast<ScriptObjectV8Proxy*>(v8Object->GetAlignedPointerFromInternalField(1));
177}
178
160QObject* ScriptObjectV8Proxy::unwrap(const V8ScriptValue& val) {179QObject* ScriptObjectV8Proxy::unwrap(const V8ScriptValue& val) {
161 ScriptObjectV8Proxy* proxy = unwrapProxy(val);180 ScriptObjectV8Proxy* proxy = unwrapProxy(val);
162 return proxy ? proxy->toQObject() : nullptr;181 return proxy ? proxy->toQObject() : nullptr;
@@ -209,7 +228,7 @@ void ScriptObjectV8Proxy::investigate() { · 46 unmodified lines
209 }228 }
210 229
211 auto v8Name = v8::String::NewFromUtf8(_engine->getIsolate(), prop.name()).ToLocalChecked();230 auto v8Name = v8::String::NewFromUtf8(_engine->getIsolate(), prop.name()).ToLocalChecked();
212 PropertyDef& propDef = _props.insert(idx, PropertyDef(_engine->getIsolate(), v8Name)).value();231 PropertyDef& propDef = _props.insert(idx, PropertyDef(_engine, v8Name)).value();
213 propDef.flags = ScriptValue::Undeletable | ScriptValue::PropertyGetter | ScriptValue::PropertySetter |232 propDef.flags = ScriptValue::Undeletable | ScriptValue::PropertyGetter | ScriptValue::PropertySetter |
214 ScriptValue::QObjectMember;233 ScriptValue::QObjectMember;
215 if (prop.isConstant()) propDef.flags |= ScriptValue::ReadOnly;234 if (prop.isConstant()) propDef.flags |= ScriptValue::ReadOnly;
@@ -248,11 +267,11 @@ void ScriptObjectV8Proxy::investigate() { · 32 unmodified lines
248 }267 }
249 268
250 auto nameString = v8::String::NewFromUtf8(_engine->getIsolate(), szName.data(), v8::NewStringType::kNormal, szName.length()).ToLocalChecked();269 auto nameString = v8::String::NewFromUtf8(_engine->getIsolate(), szName.data(), v8::NewStringType::kNormal, szName.length()).ToLocalChecked();
251 V8ScriptString name(_engine->getIsolate(), nameString);270 V8ScriptString name(_engine, nameString);
252 auto nameLookup = methodNames.find(name);271 auto nameLookup = methodNames.find(name);
253 if (isSignal) {272 if (isSignal) {
254 if (nameLookup == methodNames.end()) {273 if (nameLookup == methodNames.end()) {
255 SignalDef& signalDef = _signals.insert(idx, SignalDef(_engine->getIsolate(), name.get())).value();274 SignalDef& signalDef = _signals.insert(idx, SignalDef(_engine, name.get())).value();
256 signalDef.name = name;275 signalDef.name = name;
257 signalDef.signal = method;276 signalDef.signal = method;
258 //qDebug(scriptengine) << "Utf8Value 1: " << QString(*v8::String::Utf8Value(const_cast<v8::Isolate*>(_engine->getIsolate()), nameString));277 //qDebug(scriptengine) << "Utf8Value 1: " << QString(*v8::String::Utf8Value(const_cast<v8::Isolate*>(_engine->getIsolate()), nameString));
@@ -280,7 +299,7 @@ void ScriptObjectV8Proxy::investigate() { · 21 unmodified lines
280 }299 }
281 }300 }
282 if (nameLookup == methodNames.end()) {301 if (nameLookup == methodNames.end()) {
283 MethodDef& methodDef = _methods.insert(idx, MethodDef(_engine->getIsolate(), name.get())).value();302 MethodDef& methodDef = _methods.insert(idx, MethodDef(_engine, name.get())).value();
284 methodDef.name = name;303 methodDef.name = name;
285 methodDef.numMaxParms = parameterCount;304 methodDef.numMaxParms = parameterCount;
286 methodDef.methods.append(method);305 methodDef.methods.append(method);
@@ -308,7 +327,8 @@ void ScriptObjectV8Proxy::investigate() { · 21 unmodified lines
308 // Add all the methods objects as properties - this allows adding properties to a given method later. Is used by Script.request.327 // Add all the methods objects as properties - this allows adding properties to a given method later. Is used by Script.request.
309 // V8TODO: Should these be deleted when the script-owned object is destroyed? It needs checking if script-owned objects will be garbage-collected, or will self-referencing prevent it.328 // V8TODO: Should these be deleted when the script-owned object is destroyed? It needs checking if script-owned objects will be garbage-collected, or will self-referencing prevent it.
310 for (auto i = _methods.begin(); i != _methods.end(); i++) {329 for (auto i = _methods.begin(); i != _methods.end(); i++) {
311 V8ScriptValue method = ScriptMethodV8Proxy::newMethod(_engine, qobject, V8ScriptValue(_engine->getIsolate(), v8Object), i.value().methods, i.value().numMaxParms);330 V8ScriptValue method = ScriptMethodV8Proxy::newMethod(_engine, qobject, V8ScriptValue(_engine, v8Object),
331 i.value().methods, i.value().numMaxParms);
312 if(!propertiesObject->Set(_engine->getContext(), i.value().name.constGet(), method.get()).FromMaybe(false)) {332 if(!propertiesObject->Set(_engine->getContext(), i.value().name.constGet(), method.get()).FromMaybe(false)) {
313 Q_ASSERT(false);333 Q_ASSERT(false);
314 }334 }
@@ -389,13 +409,15 @@ void ScriptObjectV8Proxy::v8Get(v8::Local<v8::Name> name, const v8::PropertyCall · 74 unmodified lines
389 v8::HandleScope handleScope(info.GetIsolate());409 v8::HandleScope handleScope(info.GetIsolate());
390 v8::String::Utf8Value utf8Value(info.GetIsolate(), name);410 v8::String::Utf8Value utf8Value(info.GetIsolate(), name);
391 //qDebug(scriptengine) << "Get: " << *utf8Value;411 //qDebug(scriptengine) << "Get: " << *utf8Value;
392 V8ScriptValue object(info.GetIsolate(), info.This());412 v8::Local<v8::Value> objectV8 = info.This();
393 ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(object);413 ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(info.GetIsolate(), objectV8);
394 if (!proxy) {414 if (!proxy) {
395 qDebug(scriptengine) << "Proxy object not found when getting: " << *utf8Value;415 qDebug(scriptengine) << "Proxy object not found when getting: " << *utf8Value;
396 return;416 return;
397 }417 }
398 V8ScriptString nameString(info.GetIsolate(), v8::Local<v8::String>::Cast(name));418 V8ScriptValue object(proxy->_engine, objectV8);
419 Q_ASSERT(name->IsString());
420 V8ScriptString nameString(proxy->_engine, v8::Local<v8::String>::Cast(name));
399 uint id;421 uint id;
400 QueryFlags flags = proxy->queryProperty(object, nameString, HandlesReadAccess, &id);422 QueryFlags flags = proxy->queryProperty(object, nameString, HandlesReadAccess, &id);
401 if (flags) {423 if (flags) {
@@ -415,18 +437,20 @@ void ScriptObjectV8Proxy::v8Set(v8::Local<v8::Name> name, v8::Local<v8::Value> v · 13 unmodified lines
415 v8::HandleScope handleScope(info.GetIsolate());437 v8::HandleScope handleScope(info.GetIsolate());
416 v8::String::Utf8Value utf8Value(info.GetIsolate(), name);438 v8::String::Utf8Value utf8Value(info.GetIsolate(), name);
417 //qDebug(scriptengine) << "Set: " << *utf8Value;439 //qDebug(scriptengine) << "Set: " << *utf8Value;
418 V8ScriptValue object(info.GetIsolate(), info.This());440 v8::Local<v8::Value> objectV8 = info.This();
419 ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(object);441 ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(info.GetIsolate(), objectV8);
420 if (!proxy) {442 if (!proxy) {
421 qDebug(scriptengine) << "Proxy object not found when setting: " << *utf8Value;443 qDebug(scriptengine) << "Proxy object not found when setting: " << *utf8Value;
422 return;444 return;
423 }445 }
424 V8ScriptString nameString(info.GetIsolate(), v8::Local<v8::String>::Cast(name));446 V8ScriptValue object(proxy->_engine, objectV8);
447 Q_ASSERT(name->IsString());
448 V8ScriptString nameString(proxy->_engine, v8::Local<v8::String>::Cast(name));
425 //V8ScriptString nameString(info.GetIsolate(), name->ToString(proxy->_engine->getContext()).ToLocalChecked());449 //V8ScriptString nameString(info.GetIsolate(), name->ToString(proxy->_engine->getContext()).ToLocalChecked());
426 uint id;450 uint id;
427 QueryFlags flags = proxy->queryProperty(object, nameString, HandlesWriteAccess, &id);451 QueryFlags flags = proxy->queryProperty(object, nameString, HandlesWriteAccess, &id);
428 if (flags) {452 if (flags) {
429 proxy->setProperty(object, nameString, id, V8ScriptValue(info.GetIsolate(), value));453 proxy->setProperty(object, nameString, id, V8ScriptValue(proxy->_engine, value));
430 info.GetReturnValue().Set(value);454 info.GetReturnValue().Set(value);
431 } else {455 } else {
432 // V8TODO: Should it be v8::Object or v8::Local<v8::Object>?456 // V8TODO: Should it be v8::Object or v8::Local<v8::Object>?
@@ -447,7 +471,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V · 14 unmodified lines
447 QObject* qobject = _object;471 QObject* qobject = _object;
448 if (!qobject) {472 if (!qobject) {
449 _engine->getIsolate()->ThrowError("Referencing deleted native object");473 _engine->getIsolate()->ThrowError("Referencing deleted native object");
450 return V8ScriptValue(_engine->getIsolate(), v8::Null(_engine->getIsolate()));474 return V8ScriptValue(_engine, v8::Null(_engine->getIsolate()));
451 }475 }
452 476
453 const QMetaObject* metaObject = qobject->metaObject();477 const QMetaObject* metaObject = qobject->metaObject();
@@ -456,7 +480,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V · 2 unmodified lines
456 case PROPERTY_TYPE: {480 case PROPERTY_TYPE: {
457 int propId = id & ~TYPE_MASK;481 int propId = id & ~TYPE_MASK;
458 PropertyDefMap::const_iterator lookup = _props.find(propId);482 PropertyDefMap::const_iterator lookup = _props.find(propId);
459 if (lookup == _props.cend()) return V8ScriptValue(_engine->getIsolate(), v8::Null(_engine->getIsolate()));483 if (lookup == _props.cend()) return V8ScriptValue(_engine, v8::Null(_engine->getIsolate()));
460 484
461 QMetaProperty prop = metaObject->property(propId);485 QMetaProperty prop = metaObject->property(propId);
462 ScriptValue scriptThis = ScriptValue(new ScriptValueV8Wrapper(_engine, object));486 ScriptValue scriptThis = ScriptValue(new ScriptValueV8Wrapper(_engine, object));
@@ -469,7 +493,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V · 6 unmodified lines
469 case METHOD_TYPE: {493 case METHOD_TYPE: {
470 int methodId = id & ~TYPE_MASK;494 int methodId = id & ~TYPE_MASK;
471 MethodDefMap::const_iterator lookup = _methods.find(methodId);495 MethodDefMap::const_iterator lookup = _methods.find(methodId);
472 if (lookup == _methods.cend()) return V8ScriptValue(_engine->getIsolate(), v8::Null(_engine->getIsolate()));496 if (lookup == _methods.cend()) return V8ScriptValue(_engine, v8::Null(_engine->getIsolate()));
473 const MethodDef& methodDef = lookup.value();497 const MethodDef& methodDef = lookup.value();
474 for (auto iter = methodDef.methods.begin(); iter != methodDef.methods.end(); iter++ ) {498 for (auto iter = methodDef.methods.begin(); iter != methodDef.methods.end(); iter++ ) {
475 if((*iter).returnType() == QMetaType::UnknownType) {499 if((*iter).returnType() == QMetaType::UnknownType) {
@@ -480,7 +504,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V · 4 unmodified lines
480 v8::Local<v8::Value> property;504 v8::Local<v8::Value> property;
481 if(_v8Object.Get(_engine->getIsolate())->GetInternalField(2).As<v8::Object>()->Get(_engine->getContext(), name.constGet()).ToLocal(&property)) {505 if(_v8Object.Get(_engine->getIsolate())->GetInternalField(2).As<v8::Object>()->Get(_engine->getContext(), name.constGet()).ToLocal(&property)) {
482 if (!property->IsUndefined()) {506 if (!property->IsUndefined()) {
483 return V8ScriptValue(_engine->getIsolate(), property);507 return V8ScriptValue(_engine, property);
484 }508 }
485 }509 }
486 Q_ASSERT(false);510 Q_ASSERT(false);
@@ -490,7 +514,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V · 3 unmodified lines
490 case SIGNAL_TYPE: {514 case SIGNAL_TYPE: {
491 int signalId = id & ~TYPE_MASK;515 int signalId = id & ~TYPE_MASK;
492 SignalDefMap::const_iterator defLookup = _signals.find(signalId);516 SignalDefMap::const_iterator defLookup = _signals.find(signalId);
493 if (defLookup == _signals.cend()) return V8ScriptValue(_engine->getIsolate(), v8::Null(_engine->getIsolate()));517 if (defLookup == _signals.cend()) return V8ScriptValue(_engine, v8::Null(_engine->getIsolate()));
494 518
495 InstanceMap::const_iterator instLookup = _signalInstances.find(signalId);519 InstanceMap::const_iterator instLookup = _signalInstances.find(signalId);
496 if (instLookup == _signalInstances.cend() || instLookup.value().isNull()) {520 if (instLookup == _signalInstances.cend() || instLookup.value().isNull()) {
@@ -508,7 +532,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V · 11 unmodified lines
508 //return _engine->newQObject(proxy, ScriptEngine::ScriptOwnership, options);532 //return _engine->newQObject(proxy, ScriptEngine::ScriptOwnership, options);
509 }533 }
510 }534 }
511 return V8ScriptValue(_engine->getIsolate(), v8::Null(_engine->getIsolate()));535 return V8ScriptValue(_engine, v8::Null(_engine->getIsolate()));
512}536}
513 537
514void ScriptObjectV8Proxy::setProperty(V8ScriptValue& object, const V8ScriptString& name, uint id, const V8ScriptValue& value) {538void ScriptObjectV8Proxy::setProperty(V8ScriptValue& object, const V8ScriptString& name, uint id, const V8ScriptValue& value) {
@@ -562,7 +586,7 @@ V8ScriptValue ScriptVariantV8Proxy::newVariant(ScriptEngineV8* engine, const QVa · 47 unmodified lines
562 if (!protoProxy) {586 if (!protoProxy) {
563 Q_ASSERT(protoProxy);587 Q_ASSERT(protoProxy);
564 //return engine->newVariant(variant);588 //return engine->newVariant(variant);
565 return V8ScriptValue(engine->getIsolate(), v8::Undefined(engine->getIsolate()));589 return V8ScriptValue(engine, v8::Undefined(engine->getIsolate()));
566 }590 }
567 // V8TODO probably needs connection to be deleted591 // V8TODO probably needs connection to be deleted
568 // V8TODO what to do with proto variable?592 // V8TODO what to do with proto variable?
@@ -572,7 +596,7 @@ V8ScriptValue ScriptVariantV8Proxy::newVariant(ScriptEngineV8* engine, const QVa · 3 unmodified lines
572 auto variantData = variantDataTemplate->NewInstance(engine->getContext()).ToLocalChecked();596 auto variantData = variantDataTemplate->NewInstance(engine->getContext()).ToLocalChecked();
573 variantData->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToQVariantProxy));597 variantData->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToQVariantProxy));
574 variantData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(proxy));598 variantData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(proxy));
575 return V8ScriptValue(engine->getIsolate(), variantData);599 return V8ScriptValue(engine, variantData);
576}600}
577 601
578ScriptVariantV8Proxy* ScriptVariantV8Proxy::unwrapProxy(const V8ScriptValue& val) {602ScriptVariantV8Proxy* ScriptVariantV8Proxy::unwrapProxy(const V8ScriptValue& val) {
@@ -620,7 +644,7 @@ V8ScriptValue ScriptMethodV8Proxy::newMethod(ScriptEngineV8* engine, QObject* ob · 41 unmodified lines
620 // V8TODO it needs to be deleted somehow on object destruction644 // V8TODO it needs to be deleted somehow on object destruction
621 methodData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(new ScriptMethodV8Proxy(engine, object, lifetime, metas, numMaxParams)));645 methodData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(new ScriptMethodV8Proxy(engine, object, lifetime, metas, numMaxParams)));
622 auto v8Function = v8::Function::New(engine->getContext(), callback, methodData, numMaxParams).ToLocalChecked();646 auto v8Function = v8::Function::New(engine->getContext(), callback, methodData, numMaxParams).ToLocalChecked();
623 return V8ScriptValue(engine->getIsolate(), v8Function);647 return V8ScriptValue(engine, v8Function);
624}648}
625 649
626QString ScriptMethodV8Proxy::fullName() const {650QString ScriptMethodV8Proxy::fullName() const {
@@ -722,11 +746,11 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume · 95 unmodified lines
722 Q_ASSERT(methodArgTypeId != QMetaType::UnknownType);746 Q_ASSERT(methodArgTypeId != QMetaType::UnknownType);
723 v8::Local<v8::Value> argVal = arguments[arg];747 v8::Local<v8::Value> argVal = arguments[arg];
724 if (methodArgTypeId == scriptValueTypeId) {748 if (methodArgTypeId == scriptValueTypeId) {
725 qScriptArgLists[i].append(ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(isolate, argVal))));749 qScriptArgLists[i].append(ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine, argVal))));
726 qGenArgsVectors[i][arg] = Q_ARG(ScriptValue, qScriptArgLists[i].back());750 qGenArgsVectors[i][arg] = Q_ARG(ScriptValue, qScriptArgLists[i].back());
727 } else if (methodArgTypeId == QMetaType::QVariant) {751 } else if (methodArgTypeId == QMetaType::QVariant) {
728 QVariant varArgVal;752 QVariant varArgVal;
729 if (!_engine->castValueToVariant(V8ScriptValue(isolate, argVal), varArgVal, methodArgTypeId)) {753 if (!_engine->castValueToVariant(V8ScriptValue(_engine, argVal), varArgVal, methodArgTypeId)) {
730 conversionFailures++;754 conversionFailures++;
731 } else {755 } else {
732 qVarArgLists[i].append(varArgVal);756 qVarArgLists[i].append(varArgVal);
@@ -734,12 +758,12 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume · 1 unmodified line
734 }758 }
735 } else {759 } else {
736 QVariant varArgVal;760 QVariant varArgVal;
737 if (!_engine->castValueToVariant(V8ScriptValue(isolate, argVal), varArgVal, methodArgTypeId)) {761 if (!_engine->castValueToVariant(V8ScriptValue(_engine, argVal), varArgVal, methodArgTypeId)) {
738 conversionFailures++;762 conversionFailures++;
739 } else {763 } else {
740 qVarArgLists[i].append(varArgVal);764 qVarArgLists[i].append(varArgVal);
741 const QVariant& converted = qVarArgLists[i].back();765 const QVariant& converted = qVarArgLists[i].back();
742 conversionPenaltyScore = _engine->computeCastPenalty(V8ScriptValue(isolate, argVal), methodArgTypeId);766 conversionPenaltyScore = _engine->computeCastPenalty(V8ScriptValue(_engine, argVal), methodArgTypeId);
743 767
744 // a lot of type conversion assistance thanks to https://stackoverflow.com/questions/28457819/qt-invoke-method-with-qvariant768 // a lot of type conversion assistance thanks to https://stackoverflow.com/questions/28457819/qt-invoke-method-with-qvariant
745 // A const_cast is needed because calling data() would detach the QVariant.769 // A const_cast is needed because calling data() would detach the QVariant.
@@ -834,9 +858,9 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume · 88 unmodified lines
834 v8::Local<v8::Value> argVal = arguments[arg];858 v8::Local<v8::Value> argVal = arguments[arg];
835 if (methodArgTypeId != scriptValueTypeId) {859 if (methodArgTypeId != scriptValueTypeId) {
836 QVariant varArgVal;860 QVariant varArgVal;
837 if (!_engine->castValueToVariant(V8ScriptValue(isolate, argVal), varArgVal, methodArgTypeId)) {861 if (!_engine->castValueToVariant(V8ScriptValue(_engine, argVal), varArgVal, methodArgTypeId)) {
838 QByteArray methodTypeName = QMetaType(methodArgTypeId).name();862 QByteArray methodTypeName = QMetaType(methodArgTypeId).name();
839 QByteArray argTypeName = _engine->valueType(V8ScriptValue(isolate, argVal)).toLatin1();863 QByteArray argTypeName = _engine->valueType(V8ScriptValue(_engine, argVal)).toLatin1();
840 QString errorMessage = QString("Native call of %1 failed: Cannot convert parameter %2 from %3 to %4")864 QString errorMessage = QString("Native call of %1 failed: Cannot convert parameter %2 from %3 to %4")
841 .arg(fullName()).arg(arg+1).arg(argTypeName, methodTypeName);865 .arg(fullName()).arg(arg+1).arg(argTypeName, methodTypeName);
842 qDebug(scriptengine) << errorMessage << "\n Backtrace:" << _engine->currentContext()->backtrace();866 qDebug(scriptengine) << errorMessage << "\n Backtrace:" << _engine->currentContext()->backtrace();
@@ -1043,6 +1067,8 @@ int ScriptSignalV8Proxy::qt_metacall(QMetaObject::Call call, int id, void** argu · 200 unmodified lines
1043 v8::Locker locker(isolate);1067 v8::Locker locker(isolate);
1044 v8::Isolate::Scope isolateScope(isolate);1068 v8::Isolate::Scope isolateScope(isolate);
1045 v8::HandleScope handleScope(isolate);1069 v8::HandleScope handleScope(isolate);
1070 // V8TODO: should we use function creation context, or context in which connect happened?
1071
1046 auto context = _engine->getContext();1072 auto context = _engine->getContext();
1047 v8::Context::Scope contextScope(context);1073 v8::Context::Scope contextScope(context);
1048 1074
@@ -1063,20 +1089,29 @@ int ScriptSignalV8Proxy::qt_metacall(QMetaObject::Call call, int id, void** argu · 14 unmodified lines
1063 1089
1064 for (ConnectionList::iterator iter = connections.begin(); iter != connections.end(); ++iter) {1090 for (ConnectionList::iterator iter = connections.begin(); iter != connections.end(); ++iter) {
1065 Connection& conn = *iter;1091 Connection& conn = *iter;
1066 v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(conn.callback.get());1092 Q_ASSERT(!conn.callback.get().IsEmpty());
1067 v8::Local<v8::Value> v8This;1093 Q_ASSERT(!conn.callback.get()->IsUndefined());
1068 if (conn.thisValue.get()->IsObject()) {1094 Q_ASSERT(conn.callback.get()->IsFunction());
1069 v8This = conn.thisValue.get();1095 {
1070 } else {1096 v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(conn.callback.get());
1071 v8This = _engine->getContext()->Global();1097 auto functionContext = callback->CreationContext();
1072 }1098 _engine->pushContext(functionContext);
1099 v8::Context::Scope functionContextScope(functionContext);
1100 v8::Local<v8::Value> v8This;
1101 if (conn.thisValue.get()->IsObject()) {
1102 v8This = conn.thisValue.get();
1103 } else {
1104 v8This = _engine->getContext()->Global();
1105 }
1073 1106
1074 v8::TryCatch tryCatch(isolate);1107 v8::TryCatch tryCatch(isolate);
1075 callback->Call(_engine->getContext(), v8This, numArgs, args);1108 callback->Call(_engine->getContext(), v8This, numArgs, args);
1076 if (tryCatch.HasCaught()) {1109 if (tryCatch.HasCaught()) {
1077 qCDebug(scriptengine) << "Signal proxy " << fullName() << " connection call failed: \""1110 qCDebug(scriptengine) << "Signal proxy " << fullName() << " connection call failed: \""
1078 << _engine->formatErrorMessageFromTryCatch(tryCatch)1111 << _engine->formatErrorMessageFromTryCatch(tryCatch)
1079 << "\nThis provided: " << conn.thisValue.get()->IsObject();1112 << "\nThis provided: " << conn.thisValue.get()->IsObject();
1113 }
1114 _engine->popContext();
1080 }1115 }
1081 }1116 }
1082 1117
@@ -1125,8 +1160,8 @@ void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) { · 42 unmodified lines
1125 //v8::HandleScope handleScope(isolate);1160 //v8::HandleScope handleScope(isolate);
1126 1161
1127 // untangle the arguments1162 // untangle the arguments
1128 V8ScriptValue callback(isolate, v8::Null(isolate));1163 V8ScriptValue callback(_engine, v8::Null(isolate));
1129 V8ScriptValue callbackThis(isolate, v8::Null(isolate));1164 V8ScriptValue callbackThis(_engine, v8::Null(isolate));
1130 if (arg1.isFunction()) {1165 if (arg1.isFunction()) {
1131 auto unwrappedArg0 = ScriptValueV8Wrapper::unwrap(arg0);1166 auto unwrappedArg0 = ScriptValueV8Wrapper::unwrap(arg0);
1132 auto unwrappedArg1 = ScriptValueV8Wrapper::unwrap(arg1);1167 auto unwrappedArg1 = ScriptValueV8Wrapper::unwrap(arg1);
@@ -1158,6 +1193,9 @@ void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) { · 25 unmodified lines
1158 }1193 }
1159 1194
1160 // add a reference to ourselves to the destination callback1195 // add a reference to ourselves to the destination callback
1196 Q_ASSERT(!callback.get().IsEmpty());
1197 Q_ASSERT(!callback.get()->IsUndefined());
1198 Q_ASSERT(callback.get()->IsFunction());
1161 v8::Local<v8::Function> destFunction = v8::Local<v8::Function>::Cast(callback.get());1199 v8::Local<v8::Function> destFunction = v8::Local<v8::Function>::Cast(callback.get());
1162 v8::Local<v8::String> destDataName = v8::String::NewFromUtf8(isolate, "__data__").ToLocalChecked();1200 v8::Local<v8::String> destDataName = v8::String::NewFromUtf8(isolate, "__data__").ToLocalChecked();
1163 v8::Local<v8::Value> destData;1201 v8::Local<v8::Value> destData;
@@ -1166,7 +1204,10 @@ void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) { · 2 unmodified lines
1166 //Q_ASSERT(destFunction->InternalFieldCount() == 4);1204 //Q_ASSERT(destFunction->InternalFieldCount() == 4);
1167 //Q_ASSERT(destData.get()->IsArray());1205 //Q_ASSERT(destData.get()->IsArray());
1168 //v8::Local<v8::Value> destData = destFunction->GetInternalField(3);1206 //v8::Local<v8::Value> destData = destFunction->GetInternalField(3);
1169 if (destFunction->Get(destFunctionContext, destDataName).ToLocal(&destData) && destData->IsArray()) {1207 if (!destFunction->Get(destFunctionContext, destDataName).ToLocal(&destData)) {
1208 Q_ASSERT(false);
1209 }
1210 if (destData->IsArray()) {
1170 v8::Local<v8::Array> destArray = v8::Local<v8::Array>::Cast(destData);1211 v8::Local<v8::Array> destArray = v8::Local<v8::Array>::Cast(destData);
1171 int length = destArray->Length();//destData.property("length").toInteger();1212 int length = destArray->Length();//destData.property("length").toInteger();
1172 v8::Local<v8::Array> newArray = v8::Array::New(isolate, length + 1);1213 v8::Local<v8::Array> newArray = v8::Array::New(isolate, length + 1);
@@ -1232,8 +1273,8 @@ void ScriptSignalV8Proxy::disconnect(ScriptValue arg0, ScriptValue arg1) { · 59 unmodified lines
1232 v8::Context::Scope contextScope(_engine->getContext());1273 v8::Context::Scope contextScope(_engine->getContext());
1233 1274
1234 // untangle the arguments1275 // untangle the arguments
1235 V8ScriptValue callback(isolate, v8::Null(isolate));1276 V8ScriptValue callback(_engine, v8::Null(isolate));
1236 V8ScriptValue callbackThis(isolate, v8::Null(isolate));1277 V8ScriptValue callbackThis(_engine, v8::Null(isolate));
1237 if (arg1.isFunction()) {1278 if (arg1.isFunction()) {
1238 auto unwrappedArg0 = ScriptValueV8Wrapper::unwrap(arg0);1279 auto unwrappedArg0 = ScriptValueV8Wrapper::unwrap(arg0);
1239 auto unwrappedArg1 = ScriptValueV8Wrapper::unwrap(arg1);1280 auto unwrappedArg1 = ScriptValueV8Wrapper::unwrap(arg1);
@@ -1277,7 +1318,10 @@ void ScriptSignalV8Proxy::disconnect(ScriptValue arg0, ScriptValue arg1) { · 37 unmodified lines
1277 V8ScriptValue v8ThisObject = ScriptValueV8Wrapper::fullUnwrap(_engine, thisObject());1318 V8ScriptValue v8ThisObject = ScriptValueV8Wrapper::fullUnwrap(_engine, thisObject());
1278 //V8ScriptValue destData = callback.data();1319 //V8ScriptValue destData = callback.data();
1279 //Q_ASSERT(destData->IsArray());1320 //Q_ASSERT(destData->IsArray());
1280 if (destFunction->Get(destFunctionContext, destDataName).ToLocal(&destData) && destData->IsArray()) {1321 if (!destFunction->Get(destFunctionContext, destDataName).ToLocal(&destData)) {
1322 Q_ASSERT(false);
1323 }
1324 if (destData->IsArray()) {
1281 v8::Local<v8::Array> destArray = v8::Local<v8::Array>::Cast(destData);1325 v8::Local<v8::Array> destArray = v8::Local<v8::Array>::Cast(destData);
1282 int length = destArray->Length();//destData.property("length").toInteger();1326 int length = destArray->Length();//destData.property("length").toInteger();
1283 v8::Local<v8::Array> newArray = v8::Array::New(isolate, length - 1);1327 v8::Local<v8::Array> newArray = v8::Array::New(isolate, length - 1);