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 | 146 | if (lookupV8 != enginePtr->_qobjectWrapperMapV8.end()) { |
| 147 | 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 | 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 | 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 | 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 | 227 | QObject* qobject = _object; |
| 233 | 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 | 389 | // Add all the methods objects as properties - this allows adding properties to a given method later. Is used by Script.request. |
| 383 | 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 | 391 | for (auto i = _methods.begin(); i != _methods.end(); i++) { |
| 392 | + //V8TODO: lifetime may prevent garbage collection? | |
| 385 | 393 | V8ScriptValue method = ScriptMethodV8Proxy::newMethod(_engine, qobject, V8ScriptValue(_engine, v8Object), |
| 386 | 394 | i.value().methods, i.value().numMaxParms); |
| 387 | 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 | 401 | void ScriptObjectV8Proxy::weakHandleCallback(const v8::WeakCallbackInfo<ScriptObjectV8Proxy>& info) { |
| 394 | 402 | //V8TODO: does the object need to be moved to script engine thread? |
| 395 | 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 | 407 | info.GetParameter()->_object->deleteLater(); |
| 398 | 408 | } |
| 399 | 409 | |
| @@ -775,6 +785,7 @@ ScriptVariantV8Proxy::~ScriptVariantV8Proxy() { · 375 unmodified lines | ||
| 775 | 785 | } |
| 776 | 786 | |
| 777 | 787 | V8ScriptValue ScriptVariantV8Proxy::newVariant(ScriptEngineV8* engine, const QVariant& variant, V8ScriptValue proto) { |
| 788 | + qDebug() << "ScriptVariantV8Proxy::newVariant"; | |
| 778 | 789 | auto isolate = engine->getIsolate(); |
| 779 | 790 | v8::Locker locker(isolate); |
| 780 | 791 | v8::Isolate::Scope isolateScope(isolate); |
| @@ -960,12 +971,30 @@ QVariant ScriptVariantV8Proxy::unwrap(const V8ScriptValue& val) { · 179 unmodified lines | ||
| 960 | 971 | |
| 961 | 972 | ScriptMethodV8Proxy::ScriptMethodV8Proxy(ScriptEngineV8* engine, QObject* object, V8ScriptValue lifetime, |
| 962 | 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 | 984 | ScriptMethodV8Proxy::~ScriptMethodV8Proxy() { |
| 967 | − qCDebug(scriptengine_v8) << "ScriptMethodV8Proxy destroyed"; | |
| 968 | − printf("ScriptMethodV8Proxy destroyed"); | |
| 985 | + //qCDebug(scriptengine_v8) << "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 | 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 | 1009 | auto methodData = methodDataTemplate->NewInstance(engine->getContext()).ToLocalChecked(); |
| 981 | 1010 | methodData->SetAlignedPointerInInternalField(0, const_cast<void*>(internalPointsToMethodProxy)); |
| 982 | 1011 | // V8TODO it needs to be deleted somehow on object destruction |
| 1012 | + // weak persistent callback would do this | |
| 983 | 1013 | methodData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(new ScriptMethodV8Proxy(engine, object, lifetime, metas, numMaxParams))); |
| 984 | 1014 | auto v8Function = v8::Function::New(engine->getContext(), callback, methodData, numMaxParams).ToLocalChecked(); |
| 985 | 1015 | return V8ScriptValue(engine, v8Function); |
| @@ -1068,6 +1098,7 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume · 82 unmodified lines | ||
| 1068 | 1098 | int bestMeta = 0; |
| 1069 | 1099 | int bestConversionPenaltyScore = 0; |
| 1070 | 1100 | |
| 1101 | + | |
| 1071 | 1102 | for (int i = 0; i < num_metas; i++) { |
| 1072 | 1103 | const QMetaMethod& meta = _metas[i]; |
| 1073 | 1104 | int methodNumArgs = meta.parameterCount(); |
| @@ -1162,14 +1193,25 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume · 88 unmodified lines | ||
| 1162 | 1193 | return; |
| 1163 | 1194 | } else if (returnTypeId == scriptValueTypeId) { |
| 1164 | 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 | 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 | 1209 | if (!success) { |
| 1169 | 1210 | isolate->ThrowError(v8::String::NewFromUtf8(isolate, QString("Unexpected: Native call of %1 failed").arg(fullName()).toStdString().c_str()).ToLocalChecked()); |
| 1170 | 1211 | return; |
| 1171 | 1212 | } |
| 1172 | 1213 | V8ScriptValue v8Result = ScriptValueV8Wrapper::fullUnwrap(_engine, result); |
| 1214 | + //V8ScriptValue v8Result = _engine->castVariantToValue(qRetVal); | |
| 1173 | 1215 | arguments.GetReturnValue().Set(v8Result.get()); |
| 1174 | 1216 | return; |
| 1175 | 1217 | } else { |
| @@ -1396,14 +1438,34 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume · 220 unmodified lines | ||
| 1396 | 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 | 1453 | ScriptSignalV8Proxy::~ScriptSignalV8Proxy() { |
| 1400 | 1454 | auto isolate = _engine->getIsolate(); |
| 1401 | 1455 | v8::Locker locker(isolate); |
| 1402 | 1456 | v8::Isolate::Scope isolateScope(isolate); |
| 1403 | 1457 | v8::HandleScope handleScope(isolate); |
| 1458 | + _objectLifetime.Reset(); | |
| 1404 | 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 | 1469 | QString ScriptSignalV8Proxy::fullName() const { |
| 1408 | 1470 | Q_ASSERT(_object); |
| 1409 | 1471 | if (!_object) return ""; |