Showing the changes to libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp (1 of 4 files). Show all
Unified · Split
| @@ -146,7 +146,7 @@ V8ScriptValue ScriptObjectV8Proxy::newQObject(ScriptEngineV8* engine, QObject* o · 145 unmodified lines | |||
| 146 | if (lookupV8 != enginePtr->_qobjectWrapperMapV8.end()) { | 146 | if (lookupV8 != enginePtr->_qobjectWrapperMapV8.end()) { |
| 147 | enginePtr->_qobjectWrapperMapV8.erase(lookupV8); | 147 | enginePtr->_qobjectWrapperMapV8.erase(lookupV8); |
| 148 | } | 148 | } |
| 149 | qDebug() << "ScriptObjectV8Proxy::newQObject object deleted, object count: " << enginePtr->_qobjectWrapperMapV8.size(); | 149 | //qDebug() << "ScriptObjectV8Proxy::newQObject object deleted, object count: " << enginePtr->_qobjectWrapperMapV8.size(); |
| 150 | }); | 150 | }); |
| 151 | //qDebug() << "ScriptObjectV8Proxy::newQObject object count: " << engine->_qobjectWrapperMapV8.size(); | 151 | //qDebug() << "ScriptObjectV8Proxy::newQObject object count: " << engine->_qobjectWrapperMapV8.size(); |
| 152 | } | 152 | } |
| @@ -218,19 +218,26 @@ QObject* ScriptObjectV8Proxy::unwrap(const V8ScriptValue& val) { · 65 unmodified lines | |||
| 218 | } | 218 | } |
| 219 | 219 | ||
| 220 | ScriptObjectV8Proxy::~ScriptObjectV8Proxy() { | 220 | ScriptObjectV8Proxy::~ScriptObjectV8Proxy() { |
| 221 | auto isolate = _engine->getIsolate(); | ||
| 222 | v8::Locker locker(isolate); | ||
| 223 | v8::Isolate::Scope isolateScope(isolate); | ||
| 224 | v8::HandleScope handleScope(isolate); | ||
| 225 | if(_object) qCDebug(scriptengine_v8) << "Deleting object proxy: " << name(); | ||
| 226 | // V8TODO: once WeakPersistent pointer is added we should check if it's valid before deleting | ||
| 227 | Q_ASSERT(!_v8Object.Get(isolate)->IsNullOrUndefined()); | ||
| 228 | // This prevents unwrap function from unwrapping proxy that was deleted | ||
| 229 | _v8Object.Get(isolate)->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToDeletedQObjectProxy)); | ||
| 230 | _v8Object.Reset(); | ||
| 231 | if (_ownsObject) { | 221 | if (_ownsObject) { |
| 222 | auto isolate = _engine->getIsolate(); | ||
| 223 | v8::Locker locker(isolate); | ||
| 224 | v8::Isolate::Scope isolateScope(isolate); | ||
| 225 | v8::HandleScope handleScope(isolate); | ||
| 226 | _v8Object.Reset(); | ||
| 232 | QObject* qobject = _object; | 227 | QObject* qobject = _object; |
| 233 | if(qobject) qobject->deleteLater(); | 228 | if(qobject) qobject->deleteLater(); |
| 229 | } else { | ||
| 230 | auto isolate = _engine->getIsolate(); | ||
| 231 | v8::Locker locker(isolate); | ||
| 232 | v8::Isolate::Scope isolateScope(isolate); | ||
| 233 | v8::HandleScope handleScope(isolate); | ||
| 234 | if (_object) | ||
| 235 | qCDebug(scriptengine_v8) << "Deleting object proxy: " << name(); | ||
| 236 | // V8TODO: once WeakPersistent pointer is added we should check if it's valid before deleting | ||
| 237 | Q_ASSERT(!_v8Object.Get(isolate)->IsNullOrUndefined()); | ||
| 238 | // This prevents unwrap function from unwrapping proxy that was deleted | ||
| 239 | _v8Object.Get(isolate)->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToDeletedQObjectProxy)); | ||
| 240 | _v8Object.Reset(); | ||
| 234 | } | 241 | } |
| 235 | } | 242 | } |
| 236 | 243 | ||
| @@ -382,6 +389,7 @@ void ScriptObjectV8Proxy::investigate() { · 145 unmodified lines | |||
| 382 | // Add all the methods objects as properties - this allows adding properties to a given method later. Is used by Script.request. | 389 | // Add all the methods objects as properties - this allows adding properties to a given method later. Is used by Script.request. |
| 383 | // 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. | 390 | // 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. |
| 384 | for (auto i = _methods.begin(); i != _methods.end(); i++) { | 391 | for (auto i = _methods.begin(); i != _methods.end(); i++) { |
| 392 | //V8TODO: lifetime may prevent garbage collection? | ||
| 385 | V8ScriptValue method = ScriptMethodV8Proxy::newMethod(_engine, qobject, V8ScriptValue(_engine, v8Object), | 393 | V8ScriptValue method = ScriptMethodV8Proxy::newMethod(_engine, qobject, V8ScriptValue(_engine, v8Object), |
| 386 | i.value().methods, i.value().numMaxParms); | 394 | i.value().methods, i.value().numMaxParms); |
| 387 | if(!propertiesObject->Set(_engine->getContext(), i.value().name.constGet(), method.get()).FromMaybe(false)) { | 395 | if(!propertiesObject->Set(_engine->getContext(), i.value().name.constGet(), method.get()).FromMaybe(false)) { |
| @@ -393,7 +401,9 @@ void ScriptObjectV8Proxy::investigate() { · 5 unmodified lines | |||
| 393 | void ScriptObjectV8Proxy::weakHandleCallback(const v8::WeakCallbackInfo<ScriptObjectV8Proxy>& info) { | 401 | void ScriptObjectV8Proxy::weakHandleCallback(const v8::WeakCallbackInfo<ScriptObjectV8Proxy>& info) { |
| 394 | //V8TODO: does the object need to be moved to script engine thread? | 402 | //V8TODO: does the object need to be moved to script engine thread? |
| 395 | //V8TODO: why does this never get called? | 403 | //V8TODO: why does this never get called? |
| 396 | qDebug(scriptengine_v8) << "ScriptObjectV8Proxy::weakHandleCallback"; | 404 | //qDebug(scriptengine_v8) << "ScriptObjectV8Proxy::weakHandleCallback"; |
| 405 | auto proxy = info.GetParameter(); | ||
| 406 | proxy->_v8Object.Reset(); | ||
| 397 | info.GetParameter()->_object->deleteLater(); | 407 | info.GetParameter()->_object->deleteLater(); |
| 398 | } | 408 | } |
| 399 | 409 | ||
| @@ -775,6 +785,7 @@ ScriptVariantV8Proxy::~ScriptVariantV8Proxy() { · 375 unmodified lines | |||
| 775 | } | 785 | } |
| 776 | 786 | ||
| 777 | V8ScriptValue ScriptVariantV8Proxy::newVariant(ScriptEngineV8* engine, const QVariant& variant, V8ScriptValue proto) { | 787 | V8ScriptValue ScriptVariantV8Proxy::newVariant(ScriptEngineV8* engine, const QVariant& variant, V8ScriptValue proto) { |
| 788 | qDebug() << "ScriptVariantV8Proxy::newVariant"; | ||
| 778 | auto isolate = engine->getIsolate(); | 789 | auto isolate = engine->getIsolate(); |
| 779 | v8::Locker locker(isolate); | 790 | v8::Locker locker(isolate); |
| 780 | v8::Isolate::Scope isolateScope(isolate); | 791 | v8::Isolate::Scope isolateScope(isolate); |
| @@ -960,12 +971,30 @@ QVariant ScriptVariantV8Proxy::unwrap(const V8ScriptValue& val) { · 179 unmodified lines | |||
| 960 | 971 | ||
| 961 | ScriptMethodV8Proxy::ScriptMethodV8Proxy(ScriptEngineV8* engine, QObject* object, V8ScriptValue lifetime, | 972 | ScriptMethodV8Proxy::ScriptMethodV8Proxy(ScriptEngineV8* engine, QObject* object, V8ScriptValue lifetime, |
| 962 | const QList<QMetaMethod>& metas, int numMaxParams) : | 973 | const QList<QMetaMethod>& metas, int numMaxParams) : |
| 963 | _numMaxParams(numMaxParams), _engine(engine), _object(object), _objectLifetime(lifetime), _metas(metas) { | 974 | _numMaxParams(numMaxParams), _engine(engine), _object(object), /*_objectLifetime(lifetime),*/ _metas(metas) { |
| 975 | auto isolate = engine->getIsolate(); | ||
| 976 | v8::Locker locker(isolate); | ||
| 977 | v8::Isolate::Scope isolateScope(isolate); | ||
| 978 | v8::HandleScope handleScope(isolate); | ||
| 979 | v8::Context::Scope contextScope(engine->getContext()); | ||
| 980 | _objectLifetime.Reset(isolate, lifetime.get()); | ||
| 981 | _objectLifetime.SetWeak(this, weakHandleCallback, v8::WeakCallbackType::kParameter); | ||
| 964 | } | 982 | } |
| 965 | 983 | ||
| 966 | ScriptMethodV8Proxy::~ScriptMethodV8Proxy() { | 984 | ScriptMethodV8Proxy::~ScriptMethodV8Proxy() { |
| 967 | qCDebug(scriptengine_v8) << "ScriptMethodV8Proxy destroyed"; | 985 | //qCDebug(scriptengine_v8) << "ScriptMethodV8Proxy destroyed"; |
| 968 | printf("ScriptMethodV8Proxy destroyed"); | 986 | auto isolate = _engine->getIsolate(); |
| 987 | v8::Locker locker(isolate); | ||
| 988 | v8::Isolate::Scope isolateScope(isolate); | ||
| 989 | v8::HandleScope handleScope(isolate); | ||
| 990 | _objectLifetime.Reset(); | ||
| 991 | } | ||
| 992 | |||
| 993 | void ScriptMethodV8Proxy::weakHandleCallback(const v8::WeakCallbackInfo<ScriptMethodV8Proxy>& info) { | ||
| 994 | //qDebug(scriptengine_v8) << "ScriptMethodV8Proxy::weakHandleCallback"; | ||
| 995 | auto proxy = info.GetParameter(); | ||
| 996 | proxy->_objectLifetime.Reset(); | ||
| 997 | info.GetParameter()->deleteLater(); | ||
| 969 | } | 998 | } |
| 970 | 999 | ||
| 971 | V8ScriptValue ScriptMethodV8Proxy::newMethod(ScriptEngineV8* engine, QObject* object, V8ScriptValue lifetime, | 1000 | V8ScriptValue ScriptMethodV8Proxy::newMethod(ScriptEngineV8* engine, QObject* object, V8ScriptValue lifetime, |
| @@ -980,6 +1009,7 @@ V8ScriptValue ScriptMethodV8Proxy::newMethod(ScriptEngineV8* engine, QObject* ob · 8 unmodified lines | |||
| 980 | auto methodData = methodDataTemplate->NewInstance(engine->getContext()).ToLocalChecked(); | 1009 | auto methodData = methodDataTemplate->NewInstance(engine->getContext()).ToLocalChecked(); |
| 981 | methodData->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToMethodProxy)); | 1010 | methodData->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToMethodProxy)); |
| 982 | // V8TODO it needs to be deleted somehow on object destruction | 1011 | // V8TODO it needs to be deleted somehow on object destruction |
| 1012 | // weak persistent callback would do this | ||
| 983 | methodData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(new ScriptMethodV8Proxy(engine, object, lifetime, metas, numMaxParams))); | 1013 | methodData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(new ScriptMethodV8Proxy(engine, object, lifetime, metas, numMaxParams))); |
| 984 | auto v8Function = v8::Function::New(engine->getContext(), callback, methodData, numMaxParams).ToLocalChecked(); | 1014 | auto v8Function = v8::Function::New(engine->getContext(), callback, methodData, numMaxParams).ToLocalChecked(); |
| 985 | return V8ScriptValue(engine, v8Function); | 1015 | return V8ScriptValue(engine, v8Function); |
| @@ -1068,6 +1098,7 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume · 82 unmodified lines | |||
| 1068 | int bestMeta = 0; | 1098 | int bestMeta = 0; |
| 1069 | int bestConversionPenaltyScore = 0; | 1099 | int bestConversionPenaltyScore = 0; |
| 1070 | 1100 | ||
| 1101 | |||
| 1071 | for (int i = 0; i < num_metas; i++) { | 1102 | for (int i = 0; i < num_metas; i++) { |
| 1072 | const QMetaMethod& meta = _metas[i]; | 1103 | const QMetaMethod& meta = _metas[i]; |
| 1073 | int methodNumArgs = meta.parameterCount(); | 1104 | int methodNumArgs = meta.parameterCount(); |
| @@ -1162,14 +1193,25 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume · 88 unmodified lines | |||
| 1162 | return; | 1193 | return; |
| 1163 | } else if (returnTypeId == scriptValueTypeId) { | 1194 | } else if (returnTypeId == scriptValueTypeId) { |
| 1164 | ScriptValue result; | 1195 | ScriptValue result; |
| 1165 | bool success = meta.invoke(qobject, Qt::DirectConnection, Q_RETURN_ARG(ScriptValue, result), qGenArgs[0], | 1196 | /*if (_metas.front().name() == "createGarbageCollectorDebuggingObject") { |
| 1197 | //qDebug() << "createGarbageCollectorDebuggingObject"; | ||
| 1198 | return; | ||
| 1199 | }*/ | ||
| 1200 | /*const char* typeName = meta.typeName(); | ||
| 1201 | QVariant qRetVal(returnTypeId, static_cast<void*>(NULL)); | ||
| 1202 | QGenericReturnArgument sRetVal(typeName, const_cast<void*>(qRetVal.constData())); | ||
| 1203 | bool success = meta.invoke(qobject, Qt::DirectConnection, sRetVal, qGenArgs[0], | ||
| 1166 | qGenArgs[1], qGenArgs[2], qGenArgs[3], qGenArgs[4], qGenArgs[5], qGenArgs[6], | 1204 | qGenArgs[1], qGenArgs[2], qGenArgs[3], qGenArgs[4], qGenArgs[5], qGenArgs[6], |
| 1167 | qGenArgs[7], qGenArgs[8], qGenArgs[9]); | 1205 | qGenArgs[7], qGenArgs[8], qGenArgs[9]);*/ |
| 1206 | bool success = meta.invoke(qobject, Qt::DirectConnection, Q_RETURN_ARG(ScriptValue, result), qGenArgs[0], | ||
| 1207 | qGenArgs[1], qGenArgs[2], qGenArgs[3], qGenArgs[4], qGenArgs[5], qGenArgs[6], | ||
| 1208 | qGenArgs[7], qGenArgs[8], qGenArgs[9]); | ||
| 1168 | if (!success) { | 1209 | if (!success) { |
| 1169 | isolate->ThrowError(v8::String::NewFromUtf8(isolate, QString("Unexpected: Native call of %1 failed").arg(fullName()).toStdString().c_str()).ToLocalChecked()); | 1210 | isolate->ThrowError(v8::String::NewFromUtf8(isolate, QString("Unexpected: Native call of %1 failed").arg(fullName()).toStdString().c_str()).ToLocalChecked()); |
| 1170 | return; | 1211 | return; |
| 1171 | } | 1212 | } |
| 1172 | V8ScriptValue v8Result = ScriptValueV8Wrapper::fullUnwrap(_engine, result); | 1213 | V8ScriptValue v8Result = ScriptValueV8Wrapper::fullUnwrap(_engine, result); |
| 1214 | //V8ScriptValue v8Result = _engine->castVariantToValue(qRetVal); | ||
| 1173 | arguments.GetReturnValue().Set(v8Result.get()); | 1215 | arguments.GetReturnValue().Set(v8Result.get()); |
| 1174 | return; | 1216 | return; |
| 1175 | } else { | 1217 | } else { |
| @@ -1396,14 +1438,34 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume · 220 unmodified lines | |||
| 1396 | return QVariant(); | 1438 | return QVariant(); |
| 1397 | }*/ | 1439 | }*/ |
| 1398 | 1440 | ||
| 1441 | ScriptSignalV8Proxy::ScriptSignalV8Proxy(ScriptEngineV8* engine, QObject* object, V8ScriptValue lifetime, const QMetaMethod& meta) : | ||
| 1442 | _engine(engine), _object(object), _meta(meta), _metaCallId(discoverMetaCallIdx()) { | ||
| 1443 | auto isolate = _engine->getIsolate(); | ||
| 1444 | v8::Locker locker(isolate); | ||
| 1445 | v8::Isolate::Scope isolateScope(isolate); | ||
| 1446 | v8::HandleScope handleScope(isolate); | ||
| 1447 | v8::Context::Scope contextScope(_engine->getContext()); | ||
| 1448 | _objectLifetime.Reset(isolate, lifetime.get()); | ||
| 1449 | _objectLifetime.SetWeak(this, weakHandleCallback, v8::WeakCallbackType::kParameter); | ||
| 1450 | _v8Context.Reset(isolate, _engine->getContext()); | ||
| 1451 | } | ||
| 1452 | |||
| 1399 | ScriptSignalV8Proxy::~ScriptSignalV8Proxy() { | 1453 | ScriptSignalV8Proxy::~ScriptSignalV8Proxy() { |
| 1400 | auto isolate = _engine->getIsolate(); | 1454 | auto isolate = _engine->getIsolate(); |
| 1401 | v8::Locker locker(isolate); | 1455 | v8::Locker locker(isolate); |
| 1402 | v8::Isolate::Scope isolateScope(isolate); | 1456 | v8::Isolate::Scope isolateScope(isolate); |
| 1403 | v8::HandleScope handleScope(isolate); | 1457 | v8::HandleScope handleScope(isolate); |
| 1458 | _objectLifetime.Reset(); | ||
| 1404 | _v8Context.Reset(); | 1459 | _v8Context.Reset(); |
| 1405 | } | 1460 | } |
| 1406 | 1461 | ||
| 1462 | void ScriptSignalV8Proxy::weakHandleCallback(const v8::WeakCallbackInfo<ScriptSignalV8Proxy>& info) { | ||
| 1463 | //qDebug(scriptengine_v8) << "ScriptSignalV8Proxy::weakHandleCallback"; | ||
| 1464 | auto proxy = info.GetParameter(); | ||
| 1465 | proxy->_objectLifetime.Reset(); | ||
| 1466 | proxy->deleteLater(); | ||
| 1467 | } | ||
| 1468 | |||
| 1407 | QString ScriptSignalV8Proxy::fullName() const { | 1469 | QString ScriptSignalV8Proxy::fullName() const { |
| 1408 | Q_ASSERT(_object); | 1470 | Q_ASSERT(_object); |
| 1409 | if (!_object) return ""; | 1471 | if (!_object) return ""; |