diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 27163ef3fae631f7e25a85a263ca3233654d79c0..8bb0d7fae7d0fcb9c84cc0a1794ccf220cce0c3d 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -87,10 +87,11 @@ QDataStream& operator>>(QDataStream& s, WatchData &data) QString value; QString type; bool hasChildren; - s >> data.exp >> data.name >> value >> type >> hasChildren; + s >> data.exp >> data.name >> value >> type >> hasChildren >> data.objectId; data.setType(type, false); data.setValue(value); data.setHasChildren(hasChildren); + data.setAllUnneeded(); return s; } @@ -526,7 +527,7 @@ void QmlEngine::updateWatchData(const WatchData &data) //watchHandler()->rebuildModel(); showStatusMessage(tr("Stopped."), 5000); - if (!data.name.isEmpty()) { + if (!data.name.isEmpty() && data.isValueNeeded()) { QByteArray reply; QDataStream rs(&reply, QIODevice::WriteOnly); rs << QByteArray("EXEC"); @@ -534,6 +535,10 @@ void QmlEngine::updateWatchData(const WatchData &data) sendMessage(reply); } + if (!data.name.isEmpty() && data.isChildrenNeeded() && watchHandler()->isExpandedIName(data.iname)) { + expandObject(data.iname, data.objectId); + } + { QByteArray reply; QDataStream rs(&reply, QIODevice::WriteOnly); @@ -543,6 +548,16 @@ void QmlEngine::updateWatchData(const WatchData &data) } } +void QmlEngine::expandObject(const QByteArray& iname, quint64 objectId) +{ + QByteArray reply; + QDataStream rs(&reply, QIODevice::WriteOnly); + rs << QByteArray("EXPAND"); + rs << iname << objectId; + sendMessage(reply); +} + + DebuggerEngine *createQmlEngine(const DebuggerStartParameters &sp) { return new QmlEngine(sp); @@ -599,11 +614,17 @@ void QmlEngine::messageReceived(const QByteArray &message) foreach (WatchData data, watches) { data.iname = watchHandler()->watcherName(data.exp); watchHandler()->insertData(data); + + if (watchHandler()->expandedINames().contains(data.iname)) + expandObject(data.iname, data.objectId); } foreach (WatchData data, locals) { data.iname = "local." + data.exp; watchHandler()->insertData(data); + + if (watchHandler()->expandedINames().contains(data.iname)) + expandObject(data.iname, data.objectId); } watchHandler()->endCycle(); @@ -614,6 +635,18 @@ void QmlEngine::messageReceived(const QByteArray &message) stream >> iname >> data; data.iname = iname; watchHandler()->insertData(data); + + } else if (command == "EXPANDED") { + QList<WatchData> result; + QByteArray iname; + stream >> iname >> result; + foreach (WatchData data, result) { + data.iname = iname + '.' + data.exp; + watchHandler()->insertData(data); + + if (watchHandler()->expandedINames().contains(data.iname)) + expandObject(data.iname, data.objectId); + } } else { qDebug() << Q_FUNC_INFO << "Unknown command: " << command; } diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h index dc4d9010af70dd6985ca019a099c781bc21f0788..49fe81caabfa5cf7886fb9f20576bd1ce8d7d8a1 100644 --- a/src/plugins/debugger/qml/qmlengine.h +++ b/src/plugins/debugger/qml/qmlengine.h @@ -128,6 +128,8 @@ signals: void sendMessage(const QByteArray &msg); private: + void expandObject(const QByteArray &iname, quint64 objectId); + #if 0 void createDockWidgets(); bool connectToViewer(); // using host, port from widgets diff --git a/src/plugins/debugger/watchdata.cpp b/src/plugins/debugger/watchdata.cpp index bf6b34e02daf0968c79802c9e3c2794bcaa862f4..dcd490e79c6dfd3546cdf84a6a07e192274154c3 100644 --- a/src/plugins/debugger/watchdata.cpp +++ b/src/plugins/debugger/watchdata.cpp @@ -25,6 +25,7 @@ WatchData::WatchData() : valueEditable(true), error(false), source(0), + objectId(0), state(InitialState), changed(false) { diff --git a/src/plugins/debugger/watchdata.h b/src/plugins/debugger/watchdata.h index cdc9067430f91a8125426d0d20f1c473186c6c60..0cd0dae433a8399fdd10e573deb4e356c6ad691f 100644 --- a/src/plugins/debugger/watchdata.h +++ b/src/plugins/debugger/watchdata.h @@ -130,6 +130,7 @@ public: public: int source; // Originated from dumper or symbol evaluation? (CDB only) + quint64 objectId; // Object id used for the QMLEngine int state; bool changed; }; diff --git a/src/tools/qml/qmlobserver/jsdebuggeragent.cpp b/src/tools/qml/qmlobserver/jsdebuggeragent.cpp index d79b18c4d4ebf27830a3c9e62065fe6fadd9227d..51ecea7dd6c5f61213eb936f13fc1e4e4e2f3fc4 100644 --- a/src/tools/qml/qmlobserver/jsdebuggeragent.cpp +++ b/src/tools/qml/qmlobserver/jsdebuggeragent.cpp @@ -52,13 +52,13 @@ QT_BEGIN_NAMESPACE -namespace { struct JSAgentWatchData { QByteArray exp; QString name; QString value; QString type; bool hasChildren; + quint64 objectId; static JSAgentWatchData fromScriptValue(const QString &expression, const QScriptValue &value) { @@ -67,6 +67,7 @@ struct JSAgentWatchData { data.name = expression; data.hasChildren = false; data.value = value.toString(); + data.objectId = value.objectId(); if (value.isArray()) { data.type = QLatin1String("Array"); data.value = QString::fromLatin1("[Array of length %1]").arg(value.property("length").toString()); @@ -113,9 +114,24 @@ struct JSAgentWatchData { QDataStream& operator<<(QDataStream& s, const JSAgentWatchData& data) { - return s << data.exp << data.name << data.value << data.type << data.hasChildren; + return s << data.exp << data.name << data.value << data.type << data.hasChildren << data.objectId; } +static QList<JSAgentWatchData> expandObject(const QScriptValue &object) +{ + QList<JSAgentWatchData> result; + QScriptValueIterator it(object); + while (it.hasNext()) { + it.next(); + result << JSAgentWatchData::fromScriptValue(it.name(), it.value()); + } + return result; +} + +void JSDebuggerAgent::recordKnownObjects(const QList<JSAgentWatchData>& list) +{ + foreach (const JSAgentWatchData &data, list) + knownObjectIds << data.objectId; } @@ -289,6 +305,7 @@ void JSDebuggerAgent::messageReceived(const QByteArray& message) ds >> id >> expr; JSAgentWatchData data = JSAgentWatchData::fromScriptValue(expr, engine()->evaluate(expr)); + knownObjectIds << data.objectId; // Clear any exceptions occurred during locals evaluation. engine()->clearExceptions(); @@ -297,6 +314,27 @@ void JSDebuggerAgent::messageReceived(const QByteArray& message) rs << QByteArray("RESULT") << id << data; sendMessage(reply); state = oldState; + } else if (command == "EXPAND") { + State oldState = state; + state = Stopped; + QByteArray requestId; + quint64 objectId; + ds >> requestId >> objectId; + QScriptValue v; + if (knownObjectIds.contains(objectId)) + v = engine()->objectById(objectId); + + QList<JSAgentWatchData> result = expandObject(v); + recordKnownObjects(result); + + // Clear any exceptions occurred during locals evaluation. + engine()->clearExceptions(); + + QByteArray reply; + QDataStream rs(&reply, QIODevice::WriteOnly); + rs << QByteArray("EXPANDED") << requestId << result; + sendMessage(reply); + state = oldState; } else { qDebug() << Q_FUNC_INFO << "Unknown command" << command; @@ -307,6 +345,7 @@ void JSDebuggerAgent::messageReceived(const QByteArray& message) void JSDebuggerAgent::stopped() { + knownObjectIds.clear(); state = Stopped; QList<QPair<QString, QPair<QString, qint32> > > backtrace; @@ -335,17 +374,14 @@ void JSDebuggerAgent::stopped() backtrace.append(qMakePair(functionName, qMakePair( QUrl(info.fileName()).toLocalFile(), info.lineNumber() ) ) ); } QList<JSAgentWatchData> watches; - foreach (const QString &expr, watchExpressions) { + foreach (const QString &expr, watchExpressions) watches << JSAgentWatchData::fromScriptValue(expr, engine()->evaluate(expr)); - } - QList<JSAgentWatchData> locals; QScriptValue activationObject = engine()->currentContext()->activationObject(); - QScriptValueIterator it(activationObject); - while (it.hasNext()) { - it.next(); - locals << JSAgentWatchData::fromScriptValue(it.name(), it.value()); - } + QList<JSAgentWatchData> locals = expandObject(activationObject); + + recordKnownObjects(watches); + recordKnownObjects(locals); // Clear any exceptions occurred during locals evaluation. engine()->clearExceptions(); diff --git a/src/tools/qml/qmlobserver/jsdebuggeragent.h b/src/tools/qml/qmlobserver/jsdebuggeragent.h index a374ce4d334d2d5fa3241785dce422ee68af950a..a842bf3c4a85b583a16606df2594ccdac09080cb 100644 --- a/src/tools/qml/qmlobserver/jsdebuggeragent.h +++ b/src/tools/qml/qmlobserver/jsdebuggeragent.h @@ -62,6 +62,8 @@ QT_BEGIN_NAMESPACE +class JSAgentWatchData; + class JSDebuggerAgent : public QDeclarativeDebugService , public QScriptEngineAgent { Q_OBJECT public: @@ -100,6 +102,7 @@ public slots: // void pauses(); private: + enum State { NoState, SteppingIntoState, @@ -114,10 +117,14 @@ private: void continueExec(); void stopped(); + + void recordKnownObjects(const QList<JSAgentWatchData> &); + QEventLoop loop; QHash <qint64, QString> filenames; QSet< QPair<QString, qint32> > breakpointList; QStringList watchExpressions; + QSet<qint64> knownObjectIds; Q_DISABLE_COPY(JSDebuggerAgent) };