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
7676 QSharedPointer<ScriptObjectV8Proxy> proxy = lookup.value().lock();
7777 // V8TODO: is conversion to QVariant and back needed?
7878 if (proxy) {
79− return V8ScriptValue(engine->getIsolate(), proxy.get()->toV8Value());
79+ return V8ScriptValue(engine, proxy.get()->toV8Value());
8080 }
8181 //if (proxy) return engine->newObject(proxy.get(), engine->newVariant(QVariant::fromValue(proxy)));;
8282 }
@@ -111,7 +111,7 @@ V8ScriptValue ScriptObjectV8Proxy::newQObject(ScriptEngineV8* engine, QObject* o · 28 unmodified lines
111111 QSharedPointer<ScriptObjectV8Proxy> proxy = lookup.value().lock();
112112 //if (proxy) return qengine->newObject(proxy.get(), qengine->newVariant(QVariant::fromValue(proxy)));;
113113 if (proxy) {
114− return V8ScriptValue(engine->getIsolate(), proxy.get()->toV8Value());
114+ return V8ScriptValue(engine, proxy.get()->toV8Value());
115115 }
116116 }
117117 // 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
133133 });
134134 }
135135
136− return V8ScriptValue(engine->getIsolate(), proxy.get()->toV8Value());
136+ return V8ScriptValue(engine, proxy.get()->toV8Value());
137137 //return qengine->newObject(proxy.get(), qengine->newVariant(QVariant::fromValue(proxy)));
138138 }
139139
@@ -157,6 +157,25 @@ ScriptObjectV8Proxy* ScriptObjectV8Proxy::unwrapProxy(const V8ScriptValue& val) · 17 unmodified lines
157157 return reinterpret_cast<ScriptObjectV8Proxy*>(v8Object->GetAlignedPointerFromInternalField(1));
158158 }
159159
160+ScriptObjectV8Proxy* 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+
160179 QObject* ScriptObjectV8Proxy::unwrap(const V8ScriptValue& val) {
161180 ScriptObjectV8Proxy* proxy = unwrapProxy(val);
162181 return proxy ? proxy->toQObject() : nullptr;
@@ -209,7 +228,7 @@ void ScriptObjectV8Proxy::investigate() { · 46 unmodified lines
209228 }
210229
211230 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();
213232 propDef.flags = ScriptValue::Undeletable | ScriptValue::PropertyGetter | ScriptValue::PropertySetter |
214233 ScriptValue::QObjectMember;
215234 if (prop.isConstant()) propDef.flags |= ScriptValue::ReadOnly;
@@ -248,11 +267,11 @@ void ScriptObjectV8Proxy::investigate() { · 32 unmodified lines
248267 }
249268
250269 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);
252271 auto nameLookup = methodNames.find(name);
253272 if (isSignal) {
254273 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();
256275 signalDef.name = name;
257276 signalDef.signal = method;
258277 //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
280299 }
281300 }
282301 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();
284303 methodDef.name = name;
285304 methodDef.numMaxParms = parameterCount;
286305 methodDef.methods.append(method);
@@ -308,7 +327,8 @@ void ScriptObjectV8Proxy::investigate() { · 21 unmodified lines
308327 // Add all the methods objects as properties - this allows adding properties to a given method later. Is used by Script.request.
309328 // 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.
310329 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);
312332 if(!propertiesObject->Set(_engine->getContext(), i.value().name.constGet(), method.get()).FromMaybe(false)) {
313333 Q_ASSERT(false);
314334 }
@@ -389,13 +409,15 @@ void ScriptObjectV8Proxy::v8Get(v8::Local<v8::Name> name, const v8::PropertyCall · 74 unmodified lines
389409 v8::HandleScope handleScope(info.GetIsolate());
390410 v8::String::Utf8Value utf8Value(info.GetIsolate(), name);
391411 //qDebug(scriptengine) << "Get: " << *utf8Value;
392− V8ScriptValue object(info.GetIsolate(), info.This());
393− ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(object);
412+ v8::Local<v8::Value> objectV8 = info.This();
413+ ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(info.GetIsolate(), objectV8);
394414 if (!proxy) {
395415 qDebug(scriptengine) << "Proxy object not found when getting: " << *utf8Value;
396416 return;
397417 }
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));
399421 uint id;
400422 QueryFlags flags = proxy->queryProperty(object, nameString, HandlesReadAccess, &id);
401423 if (flags) {
@@ -415,18 +437,20 @@ void ScriptObjectV8Proxy::v8Set(v8::Local<v8::Name> name, v8::Local<v8::Value> v · 13 unmodified lines
415437 v8::HandleScope handleScope(info.GetIsolate());
416438 v8::String::Utf8Value utf8Value(info.GetIsolate(), name);
417439 //qDebug(scriptengine) << "Set: " << *utf8Value;
418− V8ScriptValue object(info.GetIsolate(), info.This());
419− ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(object);
440+ v8::Local<v8::Value> objectV8 = info.This();
441+ ScriptObjectV8Proxy *proxy = ScriptObjectV8Proxy::unwrapProxy(info.GetIsolate(), objectV8);
420442 if (!proxy) {
421443 qDebug(scriptengine) << "Proxy object not found when setting: " << *utf8Value;
422444 return;
423445 }
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));
425449 //V8ScriptString nameString(info.GetIsolate(), name->ToString(proxy->_engine->getContext()).ToLocalChecked());
426450 uint id;
427451 QueryFlags flags = proxy->queryProperty(object, nameString, HandlesWriteAccess, &id);
428452 if (flags) {
429− proxy->setProperty(object, nameString, id, V8ScriptValue(info.GetIsolate(), value));
453+ proxy->setProperty(object, nameString, id, V8ScriptValue(proxy->_engine, value));
430454 info.GetReturnValue().Set(value);
431455 } else {
432456 // 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
447471 QObject* qobject = _object;
448472 if (!qobject) {
449473 _engine->getIsolate()->ThrowError("Referencing deleted native object");
450− return V8ScriptValue(_engine->getIsolate(), v8::Null(_engine->getIsolate()));
474+ return V8ScriptValue(_engine, v8::Null(_engine->getIsolate()));
451475 }
452476
453477 const QMetaObject* metaObject = qobject->metaObject();
@@ -456,7 +480,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V · 2 unmodified lines
456480 case PROPERTY_TYPE: {
457481 int propId = id & ~TYPE_MASK;
458482 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()));
460484
461485 QMetaProperty prop = metaObject->property(propId);
462486 ScriptValue scriptThis = ScriptValue(new ScriptValueV8Wrapper(_engine, object));
@@ -469,7 +493,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V · 6 unmodified lines
469493 case METHOD_TYPE: {
470494 int methodId = id & ~TYPE_MASK;
471495 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()));
473497 const MethodDef& methodDef = lookup.value();
474498 for (auto iter = methodDef.methods.begin(); iter != methodDef.methods.end(); iter++ ) {
475499 if((*iter).returnType() == QMetaType::UnknownType) {
@@ -480,7 +504,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V · 4 unmodified lines
480504 v8::Local<v8::Value> property;
481505 if(_v8Object.Get(_engine->getIsolate())->GetInternalField(2).As<v8::Object>()->Get(_engine->getContext(), name.constGet()).ToLocal(&property)) {
482506 if (!property->IsUndefined()) {
483− return V8ScriptValue(_engine->getIsolate(), property);
507+ return V8ScriptValue(_engine, property);
484508 }
485509 }
486510 Q_ASSERT(false);
@@ -490,7 +514,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V · 3 unmodified lines
490514 case SIGNAL_TYPE: {
491515 int signalId = id & ~TYPE_MASK;
492516 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()));
494518
495519 InstanceMap::const_iterator instLookup = _signalInstances.find(signalId);
496520 if (instLookup == _signalInstances.cend() || instLookup.value().isNull()) {
@@ -508,7 +532,7 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V · 11 unmodified lines
508532 //return _engine->newQObject(proxy, ScriptEngine::ScriptOwnership, options);
509533 }
510534 }
511− return V8ScriptValue(_engine->getIsolate(), v8::Null(_engine->getIsolate()));
535+ return V8ScriptValue(_engine, v8::Null(_engine->getIsolate()));
512536 }
513537
514538 void 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
562586 if (!protoProxy) {
563587 Q_ASSERT(protoProxy);
564588 //return engine->newVariant(variant);
565− return V8ScriptValue(engine->getIsolate(), v8::Undefined(engine->getIsolate()));
589+ return V8ScriptValue(engine, v8::Undefined(engine->getIsolate()));
566590 }
567591 // V8TODO probably needs connection to be deleted
568592 // V8TODO what to do with proto variable?
@@ -572,7 +596,7 @@ V8ScriptValue ScriptVariantV8Proxy::newVariant(ScriptEngineV8* engine, const QVa · 3 unmodified lines
572596 auto variantData = variantDataTemplate->NewInstance(engine->getContext()).ToLocalChecked();
573597 variantData->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToQVariantProxy));
574598 variantData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(proxy));
575− return V8ScriptValue(engine->getIsolate(), variantData);
599+ return V8ScriptValue(engine, variantData);
576600 }
577601
578602 ScriptVariantV8Proxy* ScriptVariantV8Proxy::unwrapProxy(const V8ScriptValue& val) {
@@ -620,7 +644,7 @@ V8ScriptValue ScriptMethodV8Proxy::newMethod(ScriptEngineV8* engine, QObject* ob · 41 unmodified lines
620644 // V8TODO it needs to be deleted somehow on object destruction
621645 methodData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(new ScriptMethodV8Proxy(engine, object, lifetime, metas, numMaxParams)));
622646 auto v8Function = v8::Function::New(engine->getContext(), callback, methodData, numMaxParams).ToLocalChecked();
623− return V8ScriptValue(engine->getIsolate(), v8Function);
647+ return V8ScriptValue(engine, v8Function);
624648 }
625649
626650 QString ScriptMethodV8Proxy::fullName() const {
@@ -722,11 +746,11 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume · 95 unmodified lines
722746 Q_ASSERT(methodArgTypeId != QMetaType::UnknownType);
723747 v8::Local<v8::Value> argVal = arguments[arg];
724748 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))));
726750 qGenArgsVectors[i][arg] = Q_ARG(ScriptValue, qScriptArgLists[i].back());
727751 } else if (methodArgTypeId == QMetaType::QVariant) {
728752 QVariant varArgVal;
729− if (!_engine->castValueToVariant(V8ScriptValue(isolate, argVal), varArgVal, methodArgTypeId)) {
753+ if (!_engine->castValueToVariant(V8ScriptValue(_engine, argVal), varArgVal, methodArgTypeId)) {
730754 conversionFailures++;
731755 } else {
732756 qVarArgLists[i].append(varArgVal);
@@ -734,12 +758,12 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume · 1 unmodified line
734758 }
735759 } else {
736760 QVariant varArgVal;
737− if (!_engine->castValueToVariant(V8ScriptValue(isolate, argVal), varArgVal, methodArgTypeId)) {
761+ if (!_engine->castValueToVariant(V8ScriptValue(_engine, argVal), varArgVal, methodArgTypeId)) {
738762 conversionFailures++;
739763 } else {
740764 qVarArgLists[i].append(varArgVal);
741765 const QVariant& converted = qVarArgLists[i].back();
742− conversionPenaltyScore = _engine->computeCastPenalty(V8ScriptValue(isolate, argVal), methodArgTypeId);
766+ conversionPenaltyScore = _engine->computeCastPenalty(V8ScriptValue(_engine, argVal), methodArgTypeId);
743767
744768 // a lot of type conversion assistance thanks to https://stackoverflow.com/questions/28457819/qt-invoke-method-with-qvariant
745769 // 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
834858 v8::Local<v8::Value> argVal = arguments[arg];
835859 if (methodArgTypeId != scriptValueTypeId) {
836860 QVariant varArgVal;
837− if (!_engine->castValueToVariant(V8ScriptValue(isolate, argVal), varArgVal, methodArgTypeId)) {
861+ if (!_engine->castValueToVariant(V8ScriptValue(_engine, argVal), varArgVal, methodArgTypeId)) {
838862 QByteArray methodTypeName = QMetaType(methodArgTypeId).name();
839− QByteArray argTypeName = _engine->valueType(V8ScriptValue(isolate, argVal)).toLatin1();
863+ QByteArray argTypeName = _engine->valueType(V8ScriptValue(_engine, argVal)).toLatin1();
840864 QString errorMessage = QString("Native call of %1 failed: Cannot convert parameter %2 from %3 to %4")
841865 .arg(fullName()).arg(arg+1).arg(argTypeName, methodTypeName);
842866 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
10431067 v8::Locker locker(isolate);
10441068 v8::Isolate::Scope isolateScope(isolate);
10451069 v8::HandleScope handleScope(isolate);
1070+ // V8TODO: should we use function creation context, or context in which connect happened?
1071+
10461072 auto context = _engine->getContext();
10471073 v8::Context::Scope contextScope(context);
10481074
@@ -1063,20 +1089,29 @@ int ScriptSignalV8Proxy::qt_metacall(QMetaObject::Call call, int id, void** argu · 14 unmodified lines
10631089
10641090 for (ConnectionList::iterator iter = connections.begin(); iter != connections.end(); ++iter) {
10651091 Connection& conn = *iter;
1066− v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(conn.callback.get());
1067− v8::Local<v8::Value> v8This;
1068− if (conn.thisValue.get()->IsObject()) {
1069− v8This = conn.thisValue.get();
1070− } else {
1071− v8This = _engine->getContext()->Global();
1072− }
1092+ Q_ASSERT(!conn.callback.get().IsEmpty());
1093+ Q_ASSERT(!conn.callback.get()->IsUndefined());
1094+ Q_ASSERT(conn.callback.get()->IsFunction());
1095+ {
1096+ v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(conn.callback.get());
1097+ auto functionContext = callback->CreationContext();
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+ }
10731106
1074− v8::TryCatch tryCatch(isolate);
1075− callback->Call(_engine->getContext(), v8This, numArgs, args);
1076− if (tryCatch.HasCaught()) {
1077− qCDebug(scriptengine) << "Signal proxy " << fullName() << " connection call failed: \""
1078− << _engine->formatErrorMessageFromTryCatch(tryCatch)
1079− << "\nThis provided: " << conn.thisValue.get()->IsObject();
1107+ v8::TryCatch tryCatch(isolate);
1108+ callback->Call(_engine->getContext(), v8This, numArgs, args);
1109+ if (tryCatch.HasCaught()) {
1110+ qCDebug(scriptengine) << "Signal proxy " << fullName() << " connection call failed: \""
1111+ << _engine->formatErrorMessageFromTryCatch(tryCatch)
1112+ << "\nThis provided: " << conn.thisValue.get()->IsObject();
1113+ }
1114+ _engine->popContext();
10801115 }
10811116 }
10821117
@@ -1125,8 +1160,8 @@ void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) { · 42 unmodified lines
11251160 //v8::HandleScope handleScope(isolate);
11261161
11271162 // untangle the arguments
1128− V8ScriptValue callback(isolate, v8::Null(isolate));
1129− V8ScriptValue callbackThis(isolate, v8::Null(isolate));
1163+ V8ScriptValue callback(_engine, v8::Null(isolate));
1164+ V8ScriptValue callbackThis(_engine, v8::Null(isolate));
11301165 if (arg1.isFunction()) {
11311166 auto unwrappedArg0 = ScriptValueV8Wrapper::unwrap(arg0);
11321167 auto unwrappedArg1 = ScriptValueV8Wrapper::unwrap(arg1);
@@ -1158,6 +1193,9 @@ void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) { · 25 unmodified lines
11581193 }
11591194
11601195 // 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());
11611199 v8::Local<v8::Function> destFunction = v8::Local<v8::Function>::Cast(callback.get());
11621200 v8::Local<v8::String> destDataName = v8::String::NewFromUtf8(isolate, "__data__").ToLocalChecked();
11631201 v8::Local<v8::Value> destData;
@@ -1166,7 +1204,10 @@ void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) { · 2 unmodified lines
11661204 //Q_ASSERT(destFunction->InternalFieldCount() == 4);
11671205 //Q_ASSERT(destData.get()->IsArray());
11681206 //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()) {
11701211 v8::Local<v8::Array> destArray = v8::Local<v8::Array>::Cast(destData);
11711212 int length = destArray->Length();//destData.property("length").toInteger();
11721213 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
12321273 v8::Context::Scope contextScope(_engine->getContext());
12331274
12341275 // untangle the arguments
1235− V8ScriptValue callback(isolate, v8::Null(isolate));
1236− V8ScriptValue callbackThis(isolate, v8::Null(isolate));
1276+ V8ScriptValue callback(_engine, v8::Null(isolate));
1277+ V8ScriptValue callbackThis(_engine, v8::Null(isolate));
12371278 if (arg1.isFunction()) {
12381279 auto unwrappedArg0 = ScriptValueV8Wrapper::unwrap(arg0);
12391280 auto unwrappedArg1 = ScriptValueV8Wrapper::unwrap(arg1);
@@ -1277,7 +1318,10 @@ void ScriptSignalV8Proxy::disconnect(ScriptValue arg0, ScriptValue arg1) { · 37 unmodified lines
12771318 V8ScriptValue v8ThisObject = ScriptValueV8Wrapper::fullUnwrap(_engine, thisObject());
12781319 //V8ScriptValue destData = callback.data();
12791320 //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()) {
12811325 v8::Local<v8::Array> destArray = v8::Local<v8::Array>::Cast(destData);
12821326 int length = destArray->Length();//destData.property("length").toInteger();
12831327 v8::Local<v8::Array> newArray = v8::Array::New(isolate, length - 1);