Debugger: Removing the deleted objects from objectReferenceHash
authorSimjees Abraham <simjees.abraham@nokia.com>
Tue, 22 May 2012 12:01:16 +0000 (14:01 +0200)
committerQt by Nokia <qt-info@nokia.com>
Thu, 24 May 2012 10:52:43 +0000 (12:52 +0200)
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 <aurindam.jana@nokia.com>

src/qml/debugger/qqmldebugservice.cpp
src/qml/debugger/qqmldebugservice_p.h
tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp

index 57d5a71..511c854 100644 (file)
@@ -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<QObject*> QQmlDebugService::objectForLocationInfo(const QString &filename,
     return objects;
 }
 
+void QQmlDebugService::removeInvalidObjectsFromHash()
+{
+    ObjectReferenceHash *hash = objectReferenceHash();
+    QHash<int, QObject *>::Iterator iter = hash->ids.begin();
+    while (iter != hash->ids.end()) {
+        QHash<QObject *, ObjectReference>::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;
index 6e99f93..4a0b52e 100644 (file)
@@ -87,6 +87,7 @@ public:
     static QObject *objectForId(int);
     static QList<QObject*> objectForLocationInfo(const QString &filename,
                                           int lineNumber, int columnNumber);
+    static void removeInvalidObjectsFromHash();
 
     static QString objectToString(QObject *obj);
 
index b0070b7..59623fe 100644 (file)
@@ -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<QQmlContext *>(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);