From b909ce4f50be282a65f04b1ef19469d5875868e1 Mon Sep 17 00:00:00 2001 From: Simjees Abraham Date: Tue, 22 May 2012 14:01:16 +0200 Subject: [PATCH] Debugger: Removing the deleted objects from objectReferenceHash The invalid entries from objectReferenceHash in QQmlDebugService is removed once the Qml object is destroyed. Task-number: QTCREATORBUG_7451 Change-Id: I8d2ccafe81a811ea319f13fd99fbde3c13e6b2be Reviewed-by: Aurindam Jana --- src/qml/debugger/qqmldebugservice.cpp | 20 ++++++ src/qml/debugger/qqmldebugservice_p.h | 1 + .../tst_qqmlenginedebugservice.cpp | 64 ++++++++++++++++++++ 3 files changed, 85 insertions(+), 0 deletions(-) diff --git a/src/qml/debugger/qqmldebugservice.cpp b/src/qml/debugger/qqmldebugservice.cpp index 57d5a71..511c854 100644 --- a/src/qml/debugger/qqmldebugservice.cpp +++ b/src/qml/debugger/qqmldebugservice.cpp @@ -199,6 +199,8 @@ QObject *QQmlDebugService::objectForId(int id) if (objIter->object == 0) { hash->ids.erase(iter); hash->objects.erase(objIter); + // run a loop to remove other invalid objects + removeInvalidObjectsFromHash(); return 0; } else { return *iter; @@ -237,6 +239,24 @@ QList QQmlDebugService::objectForLocationInfo(const QString &filename, return objects; } +void QQmlDebugService::removeInvalidObjectsFromHash() +{ + ObjectReferenceHash *hash = objectReferenceHash(); + QHash::Iterator iter = hash->ids.begin(); + while (iter != hash->ids.end()) { + QHash::Iterator objIter = + hash->objects.find(*iter); + Q_ASSERT(objIter != hash->objects.end()); + + if (objIter->object == 0) { + iter = hash->ids.erase(iter); + hash->objects.erase(objIter); + } else { + ++iter; + } + } +} + bool QQmlDebugService::isDebuggingEnabled() { return QQmlDebugServer::instance() != 0; diff --git a/src/qml/debugger/qqmldebugservice_p.h b/src/qml/debugger/qqmldebugservice_p.h index 6e99f93..4a0b52e 100644 --- a/src/qml/debugger/qqmldebugservice_p.h +++ b/src/qml/debugger/qqmldebugservice_p.h @@ -87,6 +87,7 @@ public: static QObject *objectForId(int); static QList objectForLocationInfo(const QString &filename, int lineNumber, int columnNumber); + static void removeInvalidObjectsFromHash(); static QString objectToString(QObject *obj); diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp index b0070b7..59623fe 100644 --- a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp +++ b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp @@ -131,6 +131,8 @@ private slots: void setMethodBody(); void queryObjectTree(); void setBindingInStates(); + + void regression_QTCREATORBUG_7451(); }; QmlDebugObjectReference tst_QQmlEngineDebugService::findRootObject( @@ -763,6 +765,68 @@ void tst_QQmlEngineDebugService::queryObjectsForLocation_data() QTest::newRow("recursive") << true; } +void tst_QQmlEngineDebugService::regression_QTCREATORBUG_7451() +{ + QmlDebugObjectReference rootObject = findRootObject(); + int contextId = rootObject.contextDebugId; + QQmlContext *context = qobject_cast(QQmlDebugService::objectForId(contextId)); + QQmlComponent component(context->engine()); + QByteArray content; + content.append("import QtQuick 2.0\n" + "Text {" + "y: 10\n" + "text: \"test\"\n" + "}"); + component.setData(content, rootObject.source.url); + QObject *object = component.create(context); + QVERIFY(object); + int idNew = QQmlDebugService::idForObject(object); + QVERIFY(idNew >= 0); + + const QString fileName = QFileInfo(rootObject.source.url.toString()).fileName(); + int lineNumber = rootObject.source.lineNumber; + int columnNumber = rootObject.source.columnNumber; + bool success = false; + + m_dbg->queryObjectsForLocation(fileName, lineNumber, + columnNumber, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + + foreach (QmlDebugObjectReference child, rootObject.children) { + success = false; + lineNumber = child.source.lineNumber; + columnNumber = child.source.columnNumber; + m_dbg->queryObjectsForLocation(fileName, lineNumber, + columnNumber, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + } + + delete object; + QObject *deleted = QQmlDebugService::objectForId(idNew); + QVERIFY(!deleted); + + lineNumber = rootObject.source.lineNumber; + columnNumber = rootObject.source.columnNumber; + success = false; + m_dbg->queryObjectsForLocation(fileName, lineNumber, + columnNumber, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + + foreach (QmlDebugObjectReference child, rootObject.children) { + success = false; + lineNumber = child.source.lineNumber; + columnNumber = child.source.columnNumber; + m_dbg->queryObjectsForLocation(fileName, lineNumber, + columnNumber, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + } +} + + void tst_QQmlEngineDebugService::queryExpressionResult() { QFETCH(QString, expr); -- 1.7.2.5