OSDN Git Service

Delegate javascript debugging to Script and V8 debugger clients.
authorAurindam Jana <aurindam.jana@nokia.com>
Tue, 26 Jul 2011 14:22:49 +0000 (16:22 +0200)
committerAurindam Jana <aurindam.jana@nokia.com>
Wed, 3 Aug 2011 09:27:38 +0000 (11:27 +0200)
The appropriate client handles the debugging based on the service available at the server side.

Change-Id: I46b66036f700fc7e45e8b38cef7f1ce1445b1122
Reviewed-on: http://codereview.qt.nokia.com/2497
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Kai Koehne <kai.koehne@nokia.com>
26 files changed:
src/libs/qmljsdebugclient/qdeclarativedebugclient_p.h
src/plugins/debugger/gdb/codagdbadapter.cpp
src/plugins/debugger/qml/qml.pri
src/plugins/debugger/qml/qmladapter.cpp
src/plugins/debugger/qml/qmladapter.h
src/plugins/debugger/qml/qmldebuggerclient.cpp
src/plugins/debugger/qml/qmldebuggerclient.h
src/plugins/debugger/qml/qmlengine.cpp
src/plugins/debugger/qml/qmlengine.h
src/plugins/debugger/qml/qmlv8debuggerclient.cpp [new file with mode: 0644]
src/plugins/debugger/qml/qmlv8debuggerclient.h [new file with mode: 0644]
src/plugins/debugger/qml/qscriptdebuggerclient.cpp [new file with mode: 0644]
src/plugins/debugger/qml/qscriptdebuggerclient.h [new file with mode: 0644]
src/plugins/qt4projectmanager/qt-s60/codaruncontrol.cpp
src/plugins/qt4projectmanager/qt-s60/qt-s60.pri
src/shared/json/json.cpp [moved from src/shared/symbianutils/json.cpp with 97% similarity]
src/shared/json/json.h [moved from src/shared/symbianutils/json.h with 94% similarity]
src/shared/json/json.pri [new file with mode: 0644]
src/shared/json/json_global.h [new file with mode: 0644]
src/shared/symbianutils/codadevice.cpp
src/shared/symbianutils/codadevice.h
src/shared/symbianutils/codamessage.cpp
src/shared/symbianutils/codamessage.h
src/shared/symbianutils/symbianutils.pri
tests/auto/debugger/dumpers.pro
tests/auto/debugger/tst_dumpers.cpp

index bbbe19b..c87ccef 100644 (file)
@@ -88,7 +88,7 @@ public:
 
     Status status() const;
 
-    void sendMessage(const QByteArray &);
+    virtual void sendMessage(const QByteArray &);
 
 protected:
     virtual void statusChanged(Status);
index d28dda1..cedf750 100644 (file)
@@ -1349,7 +1349,7 @@ void CodaGdbAdapter::handleReadRegisters(const CodaCommandResult &result)
         logMessage("ERROR: " + result.errorString(), LogError);
         return;
     }
-    if (result.values.isEmpty() || result.values.front().type() != JsonValue::String) {
+    if (result.values.isEmpty() || result.values.front().type() != Json::JsonValue::String) {
         logMessage(_("Format error in register message: ") + result.toString(),
             LogError);
         return;
index e9621a0..0cec0d1 100644 (file)
@@ -1,4 +1,6 @@
 include($$PWD/../../../libs/qmljsdebugclient/qmljsdebugclient-lib.pri)
+include($$PWD/../../../shared/json/json.pri)
+DEFINES += JSON_INCLUDE_PRI
 
 HEADERS += \
     $$PWD/qmlengine.h \
@@ -6,10 +8,15 @@ HEADERS += \
     $$PWD/qmldebuggerclient.h \
     $$PWD/qmljsprivateapi.h \
     $$PWD/qmlcppengine.h \
-    $$PWD/scriptconsole.h
+    $$PWD/scriptconsole.h \
+    $$PWD/qscriptdebuggerclient.h \
+    $$PWD/qmlv8debuggerclient.h
+
 SOURCES += \
     $$PWD/qmlengine.cpp \
     $$PWD/qmladapter.cpp \
     $$PWD/qmldebuggerclient.cpp \
     $$PWD/qmlcppengine.cpp \
-    $$PWD/scriptconsole.cpp
+    $$PWD/scriptconsole.cpp \
+    $$PWD/qscriptdebuggerclient.cpp \
+    $$PWD/qmlv8debuggerclient.cpp
index d131c7b..4ec0e41 100644 (file)
 #include "qmladapter.h"
 
 #include "debuggerstartparameters.h"
-#include "qmldebuggerclient.h"
+#include "qscriptdebuggerclient.h"
+#include "qmlv8debuggerclient.h"
 #include "qmljsprivateapi.h"
 
-#include "debuggerengine.h"
+#include "qmlengine.h"
 
 #include <extensionsystem/pluginmanager.h>
 #include <utils/qtcassert.h>
@@ -61,13 +62,13 @@ public:
     }
 
     QWeakPointer<DebuggerEngine> m_engine;
-    Internal::QmlDebuggerClient *m_qmlClient;
+    QmlDebuggerClient *m_qmlClient;
 
     QTimer m_connectionTimer;
     int m_connectionAttempts;
     int m_maxConnectionAttempts;
     QDeclarativeDebugConnection *m_conn;
-    QList<QByteArray> sendBuffer;
+    QHash<QString, QmlDebuggerClient*> debugClients;
 };
 
 } // namespace Internal
@@ -149,16 +150,6 @@ void QmlAdapter::connectToViewer()
     }
 }
 
-void QmlAdapter::sendMessage(const QByteArray &msg)
-{
-    if (d->m_qmlClient->status() == QDeclarativeDebugClient::Enabled) {
-        flushSendBuffer();
-        d->m_qmlClient->sendMessage(msg);
-    } else {
-        d->sendBuffer.append(msg);
-    }
-}
-
 void QmlAdapter::connectionErrorOccurred(QAbstractSocket::SocketError socketError)
 {
     showConnectionStatusMessage(tr("Error: (%1) %2", "%1=error code, %2=error message")
@@ -177,8 +168,10 @@ void QmlAdapter::clientStatusChanged(QDeclarativeDebugClient::Status status)
 
     logServiceStatusChange(serviceName, status);
 
-    if (status == QDeclarativeDebugClient::Enabled)
-        flushSendBuffer();
+    if (status == QDeclarativeDebugClient::Enabled) {
+        d->m_qmlClient = d->debugClients.value(serviceName);
+        d->m_qmlClient->flushSendBuffer();
+    }
 }
 
 void QmlAdapter::connectionStateChanged()
@@ -202,7 +195,8 @@ void QmlAdapter::connectionStateChanged()
         showConnectionStatusMessage(tr("connected.\n"));
 
         if (!d->m_qmlClient)
-            createDebuggerClient();
+            createDebuggerClients();
+
         //reloadEngines();
         emit connected();
         break;
@@ -216,16 +210,23 @@ void QmlAdapter::connectionStateChanged()
     }
 }
 
-void QmlAdapter::createDebuggerClient()
+void QmlAdapter::createDebuggerClients()
 {
-    d->m_qmlClient = new Internal::QmlDebuggerClient(d->m_conn);
 
-    connect(d->m_qmlClient, SIGNAL(newStatus(QDeclarativeDebugClient::Status)),
+    Internal::QScriptDebuggerClient *client1 = new Internal::QScriptDebuggerClient(d->m_conn);
+    connect(client1, SIGNAL(newStatus(QDeclarativeDebugClient::Status)),
             this, SLOT(clientStatusChanged(QDeclarativeDebugClient::Status)));
-    connect(d->m_engine.data(), SIGNAL(sendMessage(QByteArray)),
-            this, SLOT(sendMessage(QByteArray)));
-    connect(d->m_qmlClient, SIGNAL(messageWasReceived(QByteArray)),
-            d->m_engine.data(), SLOT(messageReceived(QByteArray)));
+
+    Internal::QmlV8DebuggerClient *client2 = new Internal::QmlV8DebuggerClient(d->m_conn);
+    connect(client2, SIGNAL(newStatus(QDeclarativeDebugClient::Status)),
+            this, SLOT(clientStatusChanged(QDeclarativeDebugClient::Status)));
+
+    d->debugClients.insert(client1->name(),client1);
+    d->debugClients.insert(client2->name(),client2);
+
+
+    client1->setEngine((Internal::QmlEngine*)(d->m_engine.data()));
+    client2->setEngine((Internal::QmlEngine*)(d->m_engine.data()));
 
     //engine->startSuccessful();  // FIXME: AAA: port to new debugger states
 }
@@ -243,13 +244,13 @@ QDeclarativeDebugConnection *QmlAdapter::connection() const
 void QmlAdapter::showConnectionStatusMessage(const QString &message)
 {
     if (!d->m_engine.isNull())
-        d->m_engine.data()->showMessage(QLatin1String("QmlJSDebugger: ") + message, LogStatus);
+        d->m_engine.data()->showMessage(QLatin1String("QmlDebugger: ") + message, LogStatus);
 }
 
 void QmlAdapter::showConnectionErrorMessage(const QString &message)
 {
     if (!d->m_engine.isNull())
-        d->m_engine.data()->showMessage(QLatin1String("QmlJSDebugger: ") + message, LogError);
+        d->m_engine.data()->showMessage(QLatin1String("QmlDebugger: ") + message, LogError);
 }
 
 bool QmlAdapter::disableJsDebugging(bool block)
@@ -271,6 +272,15 @@ bool QmlAdapter::disableJsDebugging(bool block)
     return isBlocked;
 }
 
+Internal::QmlDebuggerClient *QmlAdapter::activeDebuggerClient()
+{
+    return d->m_qmlClient;
+}
+
+QHash<QString, Internal::QmlDebuggerClient*> QmlAdapter::debuggerClients()
+{
+    return d->debugClients;
+}
 void QmlAdapter::logServiceStatusChange(const QString &service,
                                         QDeclarativeDebugClient::Status newStatus)
 {
@@ -298,12 +308,4 @@ void QmlAdapter::logServiceActivity(const QString &service, const QString &logMe
         d->m_engine.data()->showMessage(QString("%1 %2").arg(service, logMessage), LogDebug);
 }
 
-void QmlAdapter::flushSendBuffer()
-{
-    QTC_ASSERT(d->m_qmlClient->status() == QDeclarativeDebugClient::Enabled, return);
-    foreach (const QByteArray &msg, d->sendBuffer)
-        d->m_qmlClient->sendMessage(msg);
-    d->sendBuffer.clear();
-}
-
 } // namespace Debugger
index e23020a..07b67ad 100644 (file)
@@ -70,6 +70,9 @@ public:
 
     bool disableJsDebugging(bool block);
 
+    Internal::QmlDebuggerClient *activeDebuggerClient();
+    QHash<QString, Internal::QmlDebuggerClient*> debuggerClients();
+
 public slots:
     void logServiceStatusChange(const QString &service, QDeclarativeDebugClient::Status newStatus);    
     void logServiceActivity(const QString &service, const QString &logMessage);
@@ -82,7 +85,6 @@ signals:
     void serviceConnectionError(const QString serviceName);
 
 private slots:
-    void sendMessage(const QByteArray &msg);
     void connectionErrorOccurred(QAbstractSocket::SocketError socketError);
     void clientStatusChanged(QDeclarativeDebugClient::Status status);
     void connectionStateChanged();
@@ -90,10 +92,9 @@ private slots:
 
 private:
     void connectToViewer();
-    void createDebuggerClient();
+    void createDebuggerClients();
     void showConnectionStatusMessage(const QString &message);
     void showConnectionErrorMessage(const QString &message);
-    void flushSendBuffer();
 
 private:
     QScopedPointer<Internal::QmlAdapterPrivate> d;
index 2563eca..68b1cc1 100644 (file)
 namespace Debugger {
 namespace Internal {
 
-QmlDebuggerClient::QmlDebuggerClient(QmlJsDebugClient::QDeclarativeDebugConnection* client)
-    : QDeclarativeDebugClient(QLatin1String("JSDebugger"), client)
+class QmlDebuggerClientPrivate
+{
+public:
+    QList<QByteArray> sendBuffer;
+};
+
+QmlDebuggerClient::QmlDebuggerClient(QmlJsDebugClient::QDeclarativeDebugConnection* client, QLatin1String clientName)
+    : QDeclarativeDebugClient(clientName, client),
+      d(new QmlDebuggerClientPrivate())
 {
 }
 
 QmlDebuggerClient::~QmlDebuggerClient()
 {
+    delete d;
 }
 
 void QmlDebuggerClient::statusChanged(Status status)
@@ -51,9 +59,21 @@ void QmlDebuggerClient::statusChanged(Status status)
     emit newStatus(status);
 }
 
-void QmlDebuggerClient::messageReceived(const QByteArray &data)
+void QmlDebuggerClient::sendMessage(const QByteArray &msg)
+{
+    if (status() == Enabled) {
+        QDeclarativeDebugClient::sendMessage(msg);
+    } else {
+        d->sendBuffer.append(msg);
+    }
+}
+
+void QmlDebuggerClient::flushSendBuffer()
 {
-    emit messageWasReceived(data);
+    QTC_ASSERT(status() == QDeclarativeDebugClient::Enabled, return);
+    foreach (const QByteArray &msg, d->sendBuffer)
+       QDeclarativeDebugClient::sendMessage(msg);
+    d->sendBuffer.clear();
 }
 
 } // Internal
index 191858e..a1ceeaf 100644 (file)
 **
 **************************************************************************/
 
-#ifndef QMLJSDEBUGGERCLIENT_H
-#define QMLJSDEBUGGERCLIENT_H
+#ifndef QMLDEBUGGERCLIENT_H
+#define QMLDEBUGGERCLIENT_H
 
 #include "qmljsprivateapi.h"
 
 namespace Debugger {
 namespace Internal {
 
+class WatchData;
+class BreakHandler;
+class BreakpointModelId;
+class QmlEngine;
+class QmlDebuggerClientPrivate;
+
 class QmlDebuggerClient : public QDeclarativeDebugClient
 {
     Q_OBJECT
 
 public:
-    QmlDebuggerClient(QmlJsDebugClient::QDeclarativeDebugConnection *client);
+    QmlDebuggerClient(QmlJsDebugClient::QDeclarativeDebugConnection* client, QLatin1String clientName);
     virtual ~QmlDebuggerClient();
 
+    virtual void executeStep() = 0;
+    virtual void executeStepOut() = 0;
+    virtual void executeNext() = 0;
+    virtual void executeStepI() = 0;
+
+    virtual void continueInferior() = 0;
+    virtual void interruptInferior() = 0;
+
+    virtual void activateFrame(int index) = 0;
+
+    virtual void insertBreakpoints(BreakHandler *handler, BreakpointModelId *id) = 0;
+    virtual void removeBreakpoints(BreakpointModelId *id) = 0;
+    virtual void setBreakpoints() = 0;
+
+    virtual void assignValueInDebugger(const QByteArray expr, const quint64 &id,
+                                       const QString &property, const QString value) = 0;
+
+    virtual void updateWatchData(const WatchData *data) = 0;
+    virtual void executeDebuggerCommand(const QString &command) = 0;
+
+    virtual void synchronizeWatchers(const QStringList &watchers) = 0;
+
+    virtual void expandObject(const QByteArray &iname, quint64 objectId) = 0;
+    virtual void sendPing() = 0;
+
+    virtual void setEngine(QmlEngine *engine) = 0;
+
+    void flushSendBuffer();
+
 signals:
     void newStatus(QDeclarativeDebugClient::Status status);
-    void messageWasReceived(const QByteArray &data);
 
 protected:
     virtual void statusChanged(Status status);
-    virtual void messageReceived(const QByteArray &data);
+    void sendMessage(const QByteArray &msg);
+
+private:
+    QmlDebuggerClientPrivate *d;
+    friend class QmlDebuggerClientPrivate;
 };
 
 } // Internal
-} // QmlJSInspector
+} // Debugger
 
-#endif // QMLJSDEBUGGERCLIENT_H
+#endif // QMLDEBUGGERCLIENT_H
index ecac3a1..7b7aa9e 100644 (file)
@@ -89,70 +89,6 @@ using namespace ProjectExplorer;
 namespace Debugger {
 namespace Internal {
 
-struct JSAgentBreakpointData
-{
-    QByteArray functionName;
-    QByteArray fileUrl;
-    qint32 lineNumber;
-};
-
-struct JSAgentStackData
-{
-    QByteArray functionName;
-    QByteArray fileUrl;
-    qint32 lineNumber;
-};
-
-uint qHash(const JSAgentBreakpointData &b)
-{
-    return b.lineNumber ^ qHash(b.fileUrl);
-}
-
-QDataStream &operator<<(QDataStream &s, const JSAgentBreakpointData &data)
-{
-    return s << data.functionName << data.fileUrl << data.lineNumber;
-}
-
-QDataStream &operator<<(QDataStream &s, const JSAgentStackData &data)
-{
-    return s << data.functionName << data.fileUrl << data.lineNumber;
-}
-
-QDataStream &operator>>(QDataStream &s, JSAgentBreakpointData &data)
-{
-    return s >> data.functionName >> data.fileUrl >> data.lineNumber;
-}
-
-QDataStream &operator>>(QDataStream &s, JSAgentStackData &data)
-{
-    return s >> data.functionName >> data.fileUrl >> data.lineNumber;
-}
-
-bool operator==(const JSAgentBreakpointData &b1, const JSAgentBreakpointData &b2)
-{
-    return b1.lineNumber == b2.lineNumber && b1.fileUrl == b2.fileUrl;
-}
-
-typedef QSet<JSAgentBreakpointData> JSAgentBreakpoints;
-typedef QList<JSAgentStackData> JSAgentStackFrames;
-
-
-static QDataStream &operator>>(QDataStream &s, WatchData &data)
-{
-    data = WatchData();
-    QByteArray name;
-    QByteArray value;
-    QByteArray type;
-    bool hasChildren = false;
-    s >> data.exp >> name >> value >> type >> hasChildren >> data.id;
-    data.name = QString::fromUtf8(name);
-    data.setType(type, false);
-    data.setValue(QString::fromUtf8(value));
-    data.setHasChildren(hasChildren);
-    data.setAllUnneeded();
-    return s;
-}
-
 class QmlEnginePrivate
 {
 public:
@@ -160,7 +96,6 @@ public:
 
 private:
     friend class QmlEngine;
-    int m_ping;
     QmlAdapter m_adapter;
     ApplicationLauncher m_applicationLauncher;
     Utils::FileInProjectFinder fileFinder;
@@ -168,7 +103,7 @@ private:
 };
 
 QmlEnginePrivate::QmlEnginePrivate(QmlEngine *q)
-    : m_ping(0), m_adapter(q)
+    : m_adapter(q)
 {}
 
 
@@ -466,8 +401,6 @@ void QmlEngine::shutdownEngine()
 
 void QmlEngine::setupEngine()
 {
-    d->m_ping = 0;
-
     connect(&d->m_applicationLauncher, SIGNAL(bringToForegroundRequested(qint64)),
             runControl(), SLOT(bringApplicationToForeground(qint64)),
             Qt::UniqueConnection);
@@ -478,12 +411,8 @@ void QmlEngine::setupEngine()
 void QmlEngine::continueInferior()
 {
     QTC_ASSERT(state() == InferiorStopOk, qDebug() << state());
-    QByteArray reply;
-    QDataStream rs(&reply, QIODevice::WriteOnly);
-    QByteArray cmd = "CONTINUE";
-    rs << cmd;
-    logMessage(LogSend, cmd);
-    sendMessage(reply);
+    logMessage(LogSend, "CONTINUE");
+    d->m_adapter.activeDebuggerClient()->continueInferior();
     resetLocation();
     notifyInferiorRunRequested();
     notifyInferiorRunOk();
@@ -491,23 +420,15 @@ void QmlEngine::continueInferior()
 
 void QmlEngine::interruptInferior()
 {
-    QByteArray reply;
-    QDataStream rs(&reply, QIODevice::WriteOnly);
-    QByteArray cmd = "INTERRUPT";
-    rs << cmd;
-    logMessage(LogSend, cmd);
-    sendMessage(reply);
-    notifyInferiorStopOk();
+    logMessage(LogSend, "INTERRUPT");
+    d->m_adapter.activeDebuggerClient()->interruptInferior();
+
 }
 
 void QmlEngine::executeStep()
 {
-    QByteArray reply;
-    QDataStream rs(&reply, QIODevice::WriteOnly);
-    QByteArray cmd = "STEPINTO";
-    rs << cmd;
-    logMessage(LogSend, cmd);
-    sendMessage(reply);
+    logMessage(LogSend, "STEPINTO");
+    d->m_adapter.activeDebuggerClient()->executeStep();
     resetLocation();
     notifyInferiorRunRequested();
     notifyInferiorRunOk();
@@ -515,12 +436,8 @@ void QmlEngine::executeStep()
 
 void QmlEngine::executeStepI()
 {
-    QByteArray reply;
-    QDataStream rs(&reply, QIODevice::WriteOnly);
-    QByteArray cmd = "STEPINTO";
-    rs << cmd;
-    logMessage(LogSend, cmd);
-    sendMessage(reply);
+    logMessage(LogSend, "STEPINTO");
+    d->m_adapter.activeDebuggerClient()->executeStepI();
     resetLocation();
     notifyInferiorRunRequested();
     notifyInferiorRunOk();
@@ -528,12 +445,8 @@ void QmlEngine::executeStepI()
 
 void QmlEngine::executeStepOut()
 {
-    QByteArray reply;
-    QDataStream rs(&reply, QIODevice::WriteOnly);
-    QByteArray cmd = "STEPOUT";
-    rs << cmd;
-    logMessage(LogSend, cmd);
-    sendMessage(reply);
+    logMessage(LogSend, "STEPOUT");
+    d->m_adapter.activeDebuggerClient()->executeStepOut();
     resetLocation();
     notifyInferiorRunRequested();
     notifyInferiorRunOk();
@@ -541,12 +454,8 @@ void QmlEngine::executeStepOut()
 
 void QmlEngine::executeNext()
 {
-    QByteArray reply;
-    QDataStream rs(&reply, QIODevice::WriteOnly);
-    QByteArray cmd = "STEPOVER";
-    rs << cmd;
-    logMessage(LogSend, cmd);
-    sendMessage(reply);
+    logMessage(LogSend, "STEPOVER");
+    d->m_adapter.activeDebuggerClient()->executeNext();
     resetLocation();
     notifyInferiorRunRequested();
     notifyInferiorRunOk();
@@ -577,13 +486,8 @@ void QmlEngine::executeJumpToLine(const ContextData &data)
 
 void QmlEngine::activateFrame(int index)
 {
-    QByteArray reply;
-    QDataStream rs(&reply, QIODevice::WriteOnly);
-    QByteArray cmd = "ACTIVATE_FRAME";
-    rs << cmd
-       << index;
-    logMessage(LogSend, QString("%1 %2").arg(QString(cmd), QString::number(index)));
-    sendMessage(reply);
+    logMessage(LogSend, QString("%1 %2").arg(QString("ACTIVATE_FRAME"), QString::number(index)));
+    d->m_adapter.activeDebuggerClient()->activateFrame(index);
     gotoLocation(stackHandler()->frames().value(index));
 }
 
@@ -602,40 +506,46 @@ void QmlEngine::attemptBreakpointSynchronization()
             handler->setEngine(id, this);
     }
 
-    JSAgentBreakpoints breakpoints;
+    QStringList breakPointsStr;
     foreach (BreakpointModelId id, handler->engineBreakpointIds(this)) {
         if (handler->state(id) == BreakpointRemoveRequested) {
             handler->notifyBreakpointRemoveProceeding(id);
+            if (d->m_adapter.activeDebuggerClient())
+                d->m_adapter.activeDebuggerClient()->removeBreakpoints(&id);
+            else {
+                foreach (QmlDebuggerClient *client, d->m_adapter.debuggerClients()) {
+                    client->removeBreakpoints(&id);
+                }
+            }
             handler->notifyBreakpointRemoveOk(id);
         } else {
             if (handler->state(id) == BreakpointInsertRequested) {
                 handler->notifyBreakpointInsertProceeding(id);
             }
-            JSAgentBreakpointData bp;
-            bp.fileUrl = QUrl::fromLocalFile(handler->fileName(id)).toString().toUtf8();
-            bp.lineNumber = handler->lineNumber(id);
-            bp.functionName = handler->functionName(id).toUtf8();
-            breakpoints.insert(bp);
+            if (d->m_adapter.activeDebuggerClient())
+                d->m_adapter.activeDebuggerClient()->insertBreakpoints(handler,&id);
+            else {
+                foreach (QmlDebuggerClient *client, d->m_adapter.debuggerClients()) {
+                    client->insertBreakpoints(handler,&id);
+                }
+            }
             if (handler->state(id) == BreakpointInsertProceeding) {
                 handler->notifyBreakpointInsertOk(id);
             }
+            breakPointsStr << QString("('%1' '%2' %3)").arg(QString(handler->functionName(id).toUtf8()),
+                                      QString(QUrl::fromLocalFile(handler->fileName(id)).toString().toUtf8()), QString::number(handler->lineNumber(id)));
         }
     }
 
-    QByteArray reply;
-    QDataStream rs(&reply, QIODevice::WriteOnly);
-    QByteArray cmd = "BREAKPOINTS";
-    rs << cmd
-       << breakpoints;
+    logMessage(LogSend, QString("%1 [%2]").arg(QString("BREAKPOINTS"), breakPointsStr.join(", ")));
 
-    QStringList breakPointsStr;
-    foreach (const JSAgentBreakpointData &bp, breakpoints) {
-        breakPointsStr << QString("('%1' '%2' %3)").arg(QString(bp.functionName),
-                                  QString(bp.fileUrl), QString::number(bp.lineNumber));
+    if (d->m_adapter.activeDebuggerClient()) {
+        d->m_adapter.activeDebuggerClient()->setBreakpoints();
+    }
+    else {
+        foreach (QmlDebuggerClient *client, d->m_adapter.debuggerClients())
+            client->setBreakpoints();
     }
-    logMessage(LogSend, QString("%1 [%2]").arg(QString(cmd), breakPointsStr.join(", ")));
-
-    sendMessage(reply);
 }
 
 bool QmlEngine::acceptsBreakpoint(BreakpointModelId id) const
@@ -682,25 +592,15 @@ bool QmlEngine::setToolTipExpression(const QPoint &mousePos,
 //
 //////////////////////////////////////////////////////////////////////
 
-void QmlEngine::assignValueInDebugger(const WatchData *,
+void QmlEngine::assignValueInDebugger(const WatchData *data,
     const QString &expression, const QVariant &valueV)
 {
-    QRegExp inObject("@([0-9a-fA-F]+)->(.+)");
-    if (inObject.exactMatch(expression)) {
-        bool ok = false;
-        quint64 objectId = inObject.cap(1).toULongLong(&ok, 16);
-        QString property = inObject.cap(2);
-        if (ok && objectId > 0 && !property.isEmpty()) {
-            QByteArray reply;
-            QDataStream rs(&reply, QIODevice::WriteOnly);
-            QByteArray cmd = "SET_PROPERTY";
-            rs << cmd;
-            rs << expression.toUtf8() << objectId << property << valueV.toString();
-            logMessage(LogSend, QString("%1 %2 %3 %4 %5").arg(
-                                 QString(cmd), QString::number(objectId), QString(property),
-                                 valueV.toString()));
-            sendMessage(reply);
-        }
+    quint64 objectId =  data->id;
+    if (objectId > 0 && !expression.isEmpty()) {
+        logMessage(LogSend, QString("%1 %2 %3 %4 %5").arg(
+                             QString("SET_PROPERTY"), QString::number(objectId), QString(expression),
+                             valueV.toString()));
+        d->m_adapter.activeDebuggerClient()->assignValueInDebugger(expression.toUtf8(), objectId, expression, valueV.toString());
     }
 }
 
@@ -712,19 +612,14 @@ void QmlEngine::updateWatchData(const WatchData &data,
     showStatusMessage(tr("Stopped."), 5000);
 
     if (!data.name.isEmpty() && data.isValueNeeded()) {
-        QByteArray reply;
-        QDataStream rs(&reply, QIODevice::WriteOnly);
-        QByteArray cmd = "EXEC";
-        rs << cmd;
-        rs << data.iname << data.name;
-        logMessage(LogSend, QString("%1 %2 %3").arg(QString(cmd), QString(data.iname),
+        logMessage(LogSend, QString("%1 %2 %3").arg(QString("EXEC"), QString(data.iname),
                                                           QString(data.name)));
-        sendMessage(reply);
+         d->m_adapter.activeDebuggerClient()->updateWatchData(&data);
     }
 
     if (!data.name.isEmpty() && data.isChildrenNeeded()
             && watchHandler()->isExpandedIName(data.iname)) {
-        expandObject(data.iname, data.id);
+        d->m_adapter.activeDebuggerClient()->expandObject(data.iname, data.id);
     }
 
     synchronizeWatchers();
@@ -735,39 +630,17 @@ void QmlEngine::updateWatchData(const WatchData &data,
 
 void QmlEngine::synchronizeWatchers()
 {
+    QStringList watchedExpressions = watchHandler()->watchedExpressions();
     // send watchers list
-    QByteArray reply;
-    QDataStream rs(&reply, QIODevice::WriteOnly);
-    QByteArray cmd = "WATCH_EXPRESSIONS";
-    rs << cmd;
-    rs << watchHandler()->watchedExpressions();
     logMessage(LogSend, QString("%1 %2").arg(
-                   QString(cmd), watchHandler()->watchedExpressions().join(", ")));
-    sendMessage(reply);
-}
-
-void QmlEngine::expandObject(const QByteArray &iname, quint64 objectId)
-{
-    QByteArray reply;
-    QDataStream rs(&reply, QIODevice::WriteOnly);
-    QByteArray cmd = "EXPAND";
-    rs << cmd;
-    rs << iname << objectId;
-    logMessage(LogSend, QString("%1 %2 %3").arg(QString(cmd), QString(iname),
-                                                      QString::number(objectId)));
-    sendMessage(reply);
-}
-
-void QmlEngine::sendPing()
-{
-    d->m_ping++;
-    QByteArray reply;
-    QDataStream rs(&reply, QIODevice::WriteOnly);
-    QByteArray cmd = "PING";
-    rs << cmd;
-    rs << d->m_ping;
-    logMessage(LogSend, QString("%1 %2").arg(QString(cmd), QString::number(d->m_ping)));
-    sendMessage(reply);
+                   QString("WATCH_EXPRESSIONS"), watchedExpressions.join(", ")));
+    if (d->m_adapter.activeDebuggerClient()) {
+        d->m_adapter.activeDebuggerClient()->synchronizeWatchers(watchedExpressions);
+    }
+    else {
+        foreach (QmlDebuggerClient *client, d->m_adapter.debuggerClients())
+            client->synchronizeWatchers(watchedExpressions);
+    }
 }
 
 unsigned QmlEngine::debuggerCapabilities() const
@@ -794,209 +667,12 @@ QString QmlEngine::toFileInProject(const QUrl &fileUrl)
     return d->fileFinder.findFile(fileUrl);
 }
 
-void QmlEngine::messageReceived(const QByteArray &message)
+void QmlEngine::inferiorSpontaneousStop()
 {
-    QByteArray rwData = message;
-    QDataStream stream(&rwData, QIODevice::ReadOnly);
-
-    QByteArray command;
-    stream >> command;
-
-    if (command == "STOPPED") {
-        //qDebug() << command << this << state();
-        if (state() == InferiorRunOk)
-            notifyInferiorSpontaneousStop();
-
-        QString logString = QString::fromLatin1(command);
-
-        JSAgentStackFrames stackFrames;
-        QList<WatchData> watches;
-        QList<WatchData> locals;
-        stream >> stackFrames >> watches >> locals;
-
-        logString += QString::fromLatin1(" (%1 stack frames) (%2 watches)  (%3 locals)").
-                     arg(stackFrames.size()).arg(watches.size()).arg(locals.size());
-
-        StackFrames ideStackFrames;
-        for (int i = 0; i != stackFrames.size(); ++i) {
-            StackFrame frame;
-            frame.line = stackFrames.at(i).lineNumber;
-            frame.function = stackFrames.at(i).functionName;
-            frame.file = toFileInProject(QUrl(stackFrames.at(i).fileUrl));
-            frame.usable = QFileInfo(frame.file).isReadable();
-            frame.level = i + 1;
-            ideStackFrames << frame;
-        }
-
-        if (ideStackFrames.size() && ideStackFrames.back().function == "<global>")
-            ideStackFrames.takeLast();
-        stackHandler()->setFrames(ideStackFrames);
-
-        watchHandler()->beginCycle();
-        bool needPing = false;
-
-        foreach (WatchData data, watches) {
-            data.iname = watchHandler()->watcherName(data.exp);
-            watchHandler()->insertData(data);
-
-            if (watchHandler()->expandedINames().contains(data.iname)) {
-                needPing = true;
-                expandObject(data.iname, data.id);
-            }
-        }
-
-        foreach (WatchData data, locals) {
-            data.iname = "local." + data.exp;
-            watchHandler()->insertData(data);
-
-            if (watchHandler()->expandedINames().contains(data.iname)) {
-                needPing = true;
-                expandObject(data.iname, data.id);
-            }
-        }
-
-        if (needPing) {
-            sendPing();
-        } else {
-            watchHandler()->endCycle();
-        }
-
-        bool becauseOfException;
-        stream >> becauseOfException;
-
-        logString += becauseOfException ? " exception" : " no_exception";
-
-        if (becauseOfException) {
-            QString error;
-            stream >> error;
-
-            logString += QLatin1Char(' ');
-            logString += error;
-            logMessage(LogReceive, logString);
-
-            QString msg = stackFrames.isEmpty()
-                ? tr("<p>An uncaught exception occurred:</p><p>%1</p>")
-                    .arg(Qt::escape(error))
-                : tr("<p>An uncaught exception occurred in <i>%1</i>:</p><p>%2</p>")
-                    .arg(stackFrames.value(0).fileUrl, Qt::escape(error));
-            showMessageBox(QMessageBox::Information, tr("Uncaught Exception"), msg);
-        } else {
-            //
-            // Make breakpoint non-pending
-            //
-            QString file;
-            QString function;
-            int line = -1;
-
-            if (!ideStackFrames.isEmpty()) {
-                file = ideStackFrames.at(0).file;
-                line = ideStackFrames.at(0).line;
-                function = ideStackFrames.at(0).function;
-            }
-
-            BreakHandler *handler = breakHandler();
-            foreach (BreakpointModelId id, handler->engineBreakpointIds(this)) {
-                QString processedFilename = handler->fileName(id);
-                if (processedFilename == file && handler->lineNumber(id) == line) {
-                    QTC_CHECK(handler->state(id) == BreakpointInserted);
-                    BreakpointResponse br = handler->response(id);
-                    br.fileName = file;
-                    br.lineNumber = line;
-                    br.functionName = function;
-                    handler->setResponse(id, br);
-                }
-            }
-
-            logMessage(LogReceive, logString);
-        }
-
-        if (!ideStackFrames.isEmpty())
-            gotoLocation(ideStackFrames.value(0));
-
-    } else if (command == "RESULT") {
-        WatchData data;
-        QByteArray iname;
-        stream >> iname >> data;
-
-        logMessage(LogReceive, QString("%1 %2 %3").arg(QString(command),
-                                                             QString(iname), QString(data.value)));
-        data.iname = iname;
-        if (iname.startsWith("watch.")) {
-            watchHandler()->insertData(data);
-        } else if(iname == "console") {
-            showMessage(data.value, ScriptConsoleOutput);
-        } else {
-            qWarning() << "QmlEngine: Unexcpected result: " << iname << data.value;
-        }
-    } else if (command == "EXPANDED") {
-        QList<WatchData> result;
-        QByteArray iname;
-        stream >> iname >> result;
-
-        logMessage(LogReceive, QString("%1 %2 (%3 x watchdata)").arg(
-                             QString(command), QString(iname), QString::number(result.size())));
-        bool needPing = false;
-        foreach (WatchData data, result) {
-            data.iname = iname + '.' + data.exp;
-            watchHandler()->insertData(data);
-
-            if (watchHandler()->expandedINames().contains(data.iname)) {
-                needPing = true;
-                expandObject(data.iname, data.id);
-            }
-        }
-        if (needPing)
-            sendPing();
-    } else if (command == "LOCALS") {
-        QList<WatchData> locals;
-        QList<WatchData> watches;
-        int frameId;
-        stream >> frameId >> locals;
-        if (!stream.atEnd()) { // compatibility with jsdebuggeragent from 2.1, 2.2
-            stream >> watches;
-        }
-
-        logMessage(LogReceive, QString("%1 %2 (%3 x locals) (%4 x watchdata)").arg(
-                             QString(command), QString::number(frameId),
-                             QString::number(locals.size()),
-                             QString::number(watches.size())));
-        watchHandler()->beginCycle();
-        bool needPing = false;
-        foreach (WatchData data, watches) {
-            data.iname = watchHandler()->watcherName(data.exp);
-            watchHandler()->insertData(data);
-
-            if (watchHandler()->expandedINames().contains(data.iname)) {
-                needPing = true;
-                expandObject(data.iname, data.id);
-            }
-        }
-
-        foreach (WatchData data, locals) {
-            data.iname = "local." + data.exp;
-            watchHandler()->insertData(data);
-            if (watchHandler()->expandedINames().contains(data.iname)) {
-                needPing = true;
-                expandObject(data.iname, data.id);
-            }
-        }
-        if (needPing)
-            sendPing();
-        else
-            watchHandler()->endCycle();
-
-    } else if (command == "PONG") {
-        int ping;
-        stream >> ping;
-
-        logMessage(LogReceive, QString("%1 %2").arg(QString(command), QString::number(ping)));
-
-        if (ping == d->m_ping)
-            watchHandler()->endCycle();
-    } else {
-        qDebug() << Q_FUNC_INFO << "Unknown command: " << command;
-        logMessage(LogReceive, QString("%1 UNKNOWN COMMAND!!").arg(QString(command)));
-    }
+    if (state() == InferiorRunOk)
+        notifyInferiorSpontaneousStop();
+    else
+        notifyInferiorStopOk();
 }
 
 void QmlEngine::disconnected()
@@ -1016,14 +692,9 @@ void QmlEngine::wrongSetupMessageBoxFinished(int result)
 
 void QmlEngine::executeDebuggerCommand(const QString& command)
 {
-    QByteArray reply;
-    QDataStream rs(&reply, QIODevice::WriteOnly);
-    QByteArray cmd = "EXEC";
-    QByteArray console = "console";
-    rs << cmd << console << command;
-    logMessage(LogSend, QString("%1 %2 %3").arg(QString(cmd), QString(console),
+    logMessage(LogSend, QString("%1 %2 %3").arg(QString("EXEC"), QString("console"),
                                                       QString(command)));
-    sendMessage(reply);
+    d->m_adapter.activeDebuggerClient()->executeDebuggerCommand(command);
 }
 
 
@@ -1034,7 +705,7 @@ QString QmlEngine::qmlImportPath() const
 
 void QmlEngine::logMessage(LogDirection direction, const QString &message)
 {
-    QString msg = "JSDebugger";
+    QString msg = "QmlDebugger";
     if (direction == LogSend) {
         msg += " sending ";
     } else {
index 904a301..2658de7 100644 (file)
@@ -49,6 +49,11 @@ class QmlEngine : public DebuggerEngine
     Q_OBJECT
 
 public:
+    enum LogDirection {
+        LogSend,
+        LogReceive
+    };
+
     QmlEngine(const DebuggerStartParameters &startParameters,
         DebuggerEngine *masterEngine);
     ~QmlEngine();
@@ -62,9 +67,12 @@ public:
                      int timeout = -1) const;
     void filterApplicationMessage(const QString &msg, int channel);
     virtual bool acceptsWatchesWhileRunning() const;
+    QString toFileInProject(const QUrl &fileUrl);
+    void inferiorSpontaneousStop();
+
+    void logMessage(LogDirection direction, const QString &str);
 
 public slots:
-    void messageReceived(const QByteArray &message);
     void disconnected();
 
 private slots:
@@ -120,7 +128,6 @@ private:
     unsigned int debuggerCapabilities() const;
 
 signals:
-    void sendMessage(const QByteArray &msg);
     void tooltipRequested(const QPoint &mousePos,
         TextEditor::ITextEditor *editor, int cursorPos);
 
@@ -135,9 +142,6 @@ private slots:
     void synchronizeWatchers();
 
 private:
-    void expandObject(const QByteArray &iname, quint64 objectId);
-    void sendPing();
-
     void closeConnection();
     void startApplicationLauncher();
     void stopApplicationLauncher();
@@ -148,13 +152,6 @@ private:
         const QString &oldBasePath, const QString &newBasePath) const;
     QString qmlImportPath() const;
 
-    enum LogDirection {
-        LogSend,
-        LogReceive
-    };
-    void logMessage(LogDirection direction, const QString &str);
-    QString toFileInProject(const QUrl &fileUrl);
-
 private:
     friend class QmlCppEngine;
     QmlEnginePrivate *d;
diff --git a/src/plugins/debugger/qml/qmlv8debuggerclient.cpp b/src/plugins/debugger/qml/qmlv8debuggerclient.cpp
new file mode 100644 (file)
index 0000000..38c523a
--- /dev/null
@@ -0,0 +1,624 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at info@qt.nokia.com.
+**
+**************************************************************************/
+
+#include "qmlv8debuggerclient.h"
+
+#include "watchdata.h"
+#include "watchhandler.h"
+#include "breakpoint.h"
+#include "breakhandler.h"
+#include "debuggerconstants.h"
+#include "qmlengine.h"
+#include "stackhandler.h"
+#include "debuggercore.h"
+
+#include <extensionsystem/pluginmanager.h>
+#include <utils/qtcassert.h>
+
+#include <QtCore/QVariant>
+#include <QtCore/QFileInfo>
+#include <QtGui/QTextDocument>
+#include <QtGui/QMessageBox>
+
+#define INITIALPARAMS "seq" << ':' << ++d->sequence << ',' << "type" << ':' << "request"
+
+using namespace Json;
+
+namespace Debugger {
+namespace Internal {
+
+class QmlV8DebuggerClientPrivate
+{
+public:
+    explicit QmlV8DebuggerClientPrivate(QmlV8DebuggerClient *) :
+        sequence(0), ping(0), engine(0)
+    {
+
+    }
+
+    int sequence;
+    int ping;
+    QmlEngine *engine;
+    QHash<BreakpointModelId,int> breakpoints;
+    QHash<int,BreakpointModelId> breakpointsSync;
+    QHash<int,QByteArray> locals;
+    QHash<int,QByteArray> watches;
+    QByteArray frames;
+};
+
+QmlV8DebuggerClient::QmlV8DebuggerClient(QmlJsDebugClient::QDeclarativeDebugConnection* client)
+    : QmlDebuggerClient(client, QLatin1String("V8Debugger")),
+      d(new QmlV8DebuggerClientPrivate(this))
+{
+}
+
+QmlV8DebuggerClient::~QmlV8DebuggerClient()
+{
+    delete d;
+}
+
+QByteArray QmlV8DebuggerClient::packMessage(QByteArray& message)
+{
+    QByteArray reply;
+    QDataStream rs(&reply, QIODevice::WriteOnly);
+    QByteArray cmd = "V8DEBUG";
+    rs << cmd << message;
+    return reply;
+}
+
+void QmlV8DebuggerClient::executeStep()
+{
+    QByteArray request;
+
+    JsonInputStream(request) << '{' << INITIALPARAMS ;
+    JsonInputStream(request) << ',' << "command" << ':' << "continue";
+
+    JsonInputStream(request) << ',' << "arguments" << ':';
+    JsonInputStream(request) << '{' << "stepaction" << ':' << "in";
+    JsonInputStream(request) << '}';
+
+    JsonInputStream(request) << '}';
+
+
+    sendMessage(packMessage(request));
+}
+
+void QmlV8DebuggerClient::executeStepOut()
+{
+    QByteArray request;
+
+    JsonInputStream(request) << '{' << INITIALPARAMS ;
+    JsonInputStream(request) << ',' << "command" << ':' << "continue";
+
+    JsonInputStream(request) << ',' << "arguments" << ':';
+    JsonInputStream(request) << '{' << "stepaction" << ':' << "out";
+    JsonInputStream(request) << '}';
+
+    JsonInputStream(request) << '}';
+
+
+    sendMessage(packMessage(request));
+
+}
+
+void QmlV8DebuggerClient::executeNext()
+{
+    QByteArray request;
+
+    JsonInputStream(request) << '{' << INITIALPARAMS ;
+    JsonInputStream(request) << ',' << "command" << ':' << "continue";
+
+    JsonInputStream(request) << ',' << "arguments" << ':';
+    JsonInputStream(request) << '{' << "stepaction" << ':' << "next";
+    JsonInputStream(request) << '}';
+
+    JsonInputStream(request) << '}';
+
+
+    sendMessage(packMessage(request));
+
+}
+
+void QmlV8DebuggerClient::executeStepI()
+{
+    QByteArray request;
+
+    JsonInputStream(request) << '{' << INITIALPARAMS ;
+    JsonInputStream(request) << ',' << "command" << ':' << "continue";
+
+    JsonInputStream(request) << ',' << "arguments" << ':';
+    JsonInputStream(request) << '{' << "stepaction" << ':' << "in";
+    JsonInputStream(request) << '}';
+
+    JsonInputStream(request) << '}';
+
+
+    sendMessage(packMessage(request));
+
+}
+
+void QmlV8DebuggerClient::continueInferior()
+{
+    QByteArray request;
+
+    JsonInputStream(request) << '{' << INITIALPARAMS ;
+    JsonInputStream(request) << ',' << "command" << ':' << "continue";
+    JsonInputStream(request) << '}';
+
+
+    sendMessage(packMessage(request));
+
+}
+
+void QmlV8DebuggerClient::interruptInferior()
+{
+    QByteArray request;
+
+    JsonInputStream(request) << '{' << INITIALPARAMS ;
+    JsonInputStream(request) << ',' << "command" << ':' << "interrupt";
+
+    JsonInputStream(request) << '}';
+
+    sendMessage(packMessage(request));
+
+}
+
+void QmlV8DebuggerClient::activateFrame(int index)
+{
+    setLocals(index);
+}
+
+void QmlV8DebuggerClient::insertBreakpoints(BreakHandler *handler, BreakpointModelId *id)
+{
+    QByteArray request;
+
+    JsonInputStream(request) << '{' << INITIALPARAMS ;
+    JsonInputStream(request) << ',' << "command" << ':' << "setbreakpoint";
+    JsonInputStream(request) << ',' << "arguments" << ':' << '{';
+    if (handler->breakpointData(*id).type == BreakpointByFileAndLine) {
+        JsonInputStream(request) << "type" << ':' << "script";
+        JsonInputStream(request) << ',' << "target" << ':' << QFileInfo(handler->fileName(*id)).fileName().toUtf8();
+        JsonInputStream(request) << ',' << "line" << ':' << handler->lineNumber(*id) - 1;
+    } else if (handler->breakpointData(*id).type == BreakpointByFunction) {
+        JsonInputStream(request) << "type" << ':' << "function";
+        JsonInputStream(request) << ',' << "target" << ':' << handler->functionName(*id).toUtf8();
+    }
+    JsonInputStream(request) << '}';
+    JsonInputStream(request) << '}';
+
+    d->breakpointsSync.insert(d->sequence,*id);
+    sendMessage(packMessage(request));
+
+}
+
+void QmlV8DebuggerClient::removeBreakpoints(BreakpointModelId *id)
+{
+    QList<int> breakpoints = d->breakpoints.values(*id);
+    d->breakpoints.remove(*id);
+
+    foreach (int bp, breakpoints) {
+        QByteArray request;
+
+        JsonInputStream(request) << '{' << INITIALPARAMS ;
+        JsonInputStream(request) << ',' << "command" << ':' << "clearbreakpoint";
+
+        JsonInputStream(request) << ',' << "arguments" << ':';
+        JsonInputStream(request) << '{' << "breakpoint" << ':' << bp;
+        JsonInputStream(request) << '}';
+
+        JsonInputStream(request) << '}';
+
+        sendMessage(packMessage(request));
+    }
+}
+
+void QmlV8DebuggerClient::setBreakpoints()
+{
+}
+
+void QmlV8DebuggerClient::assignValueInDebugger(const QByteArray expr, const quint64 &id,
+                                                const QString &property, const QString value)
+{
+    //TODO::
+}
+
+void QmlV8DebuggerClient::updateWatchData(const WatchData *data)
+{
+    if (!data->iname.startsWith("watch."))
+        return;
+
+    QByteArray request;
+
+    JsonInputStream(request) << '{' << INITIALPARAMS ;
+    JsonInputStream(request) << ',' << "command" << ':' << "evaluate";
+
+    JsonInputStream(request) << ',' << "arguments" << ':';
+    JsonInputStream(request) << '{' << "expression" << ':' << data->exp;
+    JsonInputStream(request) << ',' << "frame" << ':' << d->engine->stackHandler()->currentFrame().level;
+    JsonInputStream(request) << '}';
+
+    JsonInputStream(request) << '}';
+
+    d->watches.insert(d->sequence,data->iname);
+
+    sendMessage(packMessage(request));
+
+}
+
+void QmlV8DebuggerClient::executeDebuggerCommand(const QString &command)
+{
+    QByteArray request;
+
+    JsonInputStream(request) << '{' << INITIALPARAMS ;
+    JsonInputStream(request) << ',' << "command" << ':' << "evaluate";
+
+    JsonInputStream(request) << ',' << "arguments" << ':';
+    JsonInputStream(request) << '{' << "expression" << ':' << command;
+    JsonInputStream(request) << ',' << "global" << ':' << true;
+    JsonInputStream(request) << '}';
+
+    JsonInputStream(request) << '}';
+
+    sendMessage(packMessage(request));
+
+}
+
+void QmlV8DebuggerClient::synchronizeWatchers(const QStringList &watchers)
+{
+    //TODO:: send watchers list
+}
+
+void QmlV8DebuggerClient::expandObject(const QByteArray &iname, quint64 objectId)
+{
+    d->locals.insert(objectId,iname);
+    QList<int> ids;
+    ids.append(objectId);
+
+    QByteArray request;
+
+    JsonInputStream(request) << '{' << INITIALPARAMS ;
+    JsonInputStream(request) << ',' << "command" << ':' << "lookup";
+
+    JsonInputStream(request) << ',' << "arguments" << ':';
+    JsonInputStream(request) << '{' << "handles" << ':' << ids;
+    JsonInputStream(request) << '}';
+
+    JsonInputStream(request) << '}';
+
+    sendMessage(packMessage(request));
+
+}
+
+void QmlV8DebuggerClient::sendPing()
+{
+    QByteArray request;
+
+    JsonInputStream(request) << '{' << INITIALPARAMS ;
+    JsonInputStream(request) << ',' << "command" << ':' << "ping" << '}';
+
+    d->ping = d->sequence;
+    sendMessage(packMessage(request));
+}
+
+void QmlV8DebuggerClient::backtrace()
+{
+    QByteArray request;
+
+    JsonInputStream(request) << '{' << INITIALPARAMS ;
+    JsonInputStream(request) << ',' << "command" << ':' << "backtrace";
+    JsonInputStream(request) << '}';
+
+    sendMessage(packMessage(request));
+}
+
+void QmlV8DebuggerClient::messageReceived(const QByteArray &data)
+{
+    QDataStream ds(data);
+    QByteArray command;
+    ds >> command;
+
+    if (command == "V8DEBUG") {
+        QByteArray response;
+        ds >> response;
+
+        JsonValue value(response);
+        QString type = value.findChild("type").toVariant().toString();
+
+        if (type == "response") {
+
+            if (!value.findChild("success").toVariant().toBool()) {
+                //TODO:: Error
+                qDebug() << Q_FUNC_INFO << value.toString(true,2);
+                return;
+            }
+
+            QString debugCommand(value.findChild("command").toVariant().toString());
+            if (debugCommand == "pong") {
+                //DO NOTHING
+            } else if (debugCommand == "backtrace") {
+                setStackFrames(response);
+
+            } else if (debugCommand == "lookup") {
+                expandLocal(response);
+
+            } else if (debugCommand == "setbreakpoint") {
+                int sequence = value.findChild("request_seq").toVariant().toInt();
+                int breakpoint = value.findChild("body").findChild("breakpoint").toVariant().toInt();
+                d->breakpoints.insertMulti(d->breakpointsSync.take(sequence),breakpoint);
+
+            } else if (debugCommand == "evaluate") {
+                setExpression(response);
+
+            } else {
+                //TODO::
+                //qDebug() << Q_FUNC_INFO << value.toString(true,2);
+            }
+
+        } else if (type == "event") {
+            QString event(value.findChild("event").toVariant().toString());
+
+            if (event == "break") {
+                d->engine->inferiorSpontaneousStop();
+                backtrace();
+            }
+        }
+    }
+}
+
+void QmlV8DebuggerClient::setStackFrames(QByteArray &message)
+{
+    d->frames = message;
+    JsonValue response(message);
+
+    JsonValue refs = response.findChild("refs");
+    JsonValue body = response.findChild("body");
+
+    int totalFrames = body.findChild("totalFrames").toVariant().toInt();
+    JsonValue stackFrames = body.findChild("frames");
+
+    StackFrames ideStackFrames;
+    for (int i = 0; i != totalFrames; ++i) {
+
+        JsonValue stackFrame = stackFrames.childAt(i);
+
+        StackFrame frame;
+
+        int frameIndex = stackFrame.findChild("index").toVariant().toInt();
+        frame.level = frameIndex;
+
+        frame.line = stackFrame.findChild("line").toVariant().toInt() + 1;
+
+        int index = indexInRef(refs,stackFrame.findChild("func").findChild("ref").toVariant().toInt());
+        if (index != -1) {
+            JsonValue func = refs.childAt(index);
+            frame.function = func.findChild("name").toVariant().toString();
+        }
+
+        index = indexInRef(refs,stackFrame.findChild("script").findChild("ref").toVariant().toInt());
+        if (index != -1) {
+            JsonValue script = refs.childAt(index);
+            frame.file = d->engine->toFileInProject(script.findChild("name").toVariant().toString());
+            frame.usable = QFileInfo(frame.file).isReadable();
+        }
+        ideStackFrames << frame;
+    }
+
+    d->engine->stackHandler()->setFrames(ideStackFrames);
+
+    QString fileName;
+    QString file;
+    QString function;
+    int line = -1;
+
+    if (!ideStackFrames.isEmpty()) {
+        file = ideStackFrames.at(0).file;
+        fileName = QFileInfo(file).fileName();
+        line = ideStackFrames.at(0).line;
+        function = ideStackFrames.at(0).function;
+    }
+
+    BreakHandler *handler = d->engine->breakHandler();
+    foreach (BreakpointModelId id, handler->engineBreakpointIds(d->engine)) {
+        QString processedFilename = QFileInfo(handler->fileName(id)).fileName();
+        if (processedFilename == fileName && handler->lineNumber(id) == line) {
+            QTC_ASSERT(handler->state(id) == BreakpointInserted,/**/);
+            BreakpointResponse br = handler->response(id);
+            br.fileName = file;
+            br.lineNumber = line;
+            br.functionName = function;
+            handler->setResponse(id, br);
+        }
+    }
+
+    if (!ideStackFrames.isEmpty()) {
+        setLocals(0);
+        d->engine->gotoLocation(ideStackFrames.value(0));
+    }
+
+}
+
+void QmlV8DebuggerClient::setLocals(int frameIndex)
+{
+    JsonValue response(d->frames);
+
+    JsonValue refs = response.findChild("refs");
+    JsonValue body = response.findChild("body");
+
+    int totalFrames = body.findChild("totalFrames").toVariant().toInt();
+    JsonValue stackFrames = body.findChild("frames");
+
+
+    for (int i = 0; i != totalFrames; ++i) {
+
+        JsonValue stackFrame = stackFrames.childAt(i);
+        int index = stackFrame.findChild("index").toVariant().toInt();
+        if (index != frameIndex)
+            continue;
+
+        JsonValue locals = stackFrame.findChild("locals");
+
+        d->engine->watchHandler()->beginCycle();
+
+        int localsCount = locals.childCount();
+        for (int j = 0; j != localsCount; ++j) {
+            JsonValue local = locals.childAt(j);
+
+            WatchData data;
+            data.exp = local.findChild("name").toVariant().toByteArray();
+            data.name = data.exp;
+            data.iname = "local." + data.exp;
+            JsonValue val = refs.childAt(indexInRef(refs,local.findChild("value").findChild("ref").toVariant().toInt()));
+            data.type = val.findChild("type").toVariant().toByteArray();
+
+            if (data.type == "object") {
+                data.hasChildren = true;
+                data.value = val.findChild("className").toVariant().toByteArray();
+
+            } else if (data.type == "function" || data.type == "undefined") {
+                data.hasChildren = false;
+                data.value = val.findChild("text").toVariant().toByteArray();
+
+            } else {
+                data.hasChildren = false;
+                data.value = val.findChild("value").toVariant().toByteArray();
+            }
+
+            data.id = val.findChild("handle").toVariant().toInt();
+
+            d->engine->watchHandler()->insertData(data);
+
+            if (d->engine->watchHandler()->expandedINames().contains(data.iname)) {
+                expandObject(data.iname, data.id);
+            }
+        }
+
+        d->engine->watchHandler()->endCycle();
+    }
+}
+
+void QmlV8DebuggerClient::expandLocal(QByteArray &message)
+{
+    JsonValue response(message);
+
+    JsonValue refs = response.findChild("refs");
+    JsonValue body = response.findChild("body");
+    JsonValue details = body.childAt(0);
+
+    int id = QString(details.name()).toInt();
+    QByteArray prepend = d->locals.take(id);
+
+    JsonValue properties = details.findChild("properties");
+    int propertiesCount = properties.childCount();
+
+    for (int k = 0; k != propertiesCount; ++k) {
+        JsonValue property = properties.childAt(k);
+        setPropertyValue(refs,property,prepend);
+    }
+}
+
+void QmlV8DebuggerClient::setExpression(QByteArray &message)
+{
+    JsonValue response(message);
+    JsonValue body = response.findChild("body");
+
+    int seq = response.findChild("request_seq").toVariant().toInt();
+
+    if (!d->watches.contains(seq)) {
+        d->engine->showMessage(body.findChild("text").toVariant().toString(), ScriptConsoleOutput);
+        return;
+    }
+    //TODO::
+//    JsonValue refs = response.findChild("refs");
+//    JsonValue body = response.findChild("body");
+//    JsonValue details = body.childAt(0);
+
+//    int id = QString(details.name()).toInt();
+//    QByteArray prepend = d->locals.take(id);
+
+//    JsonValue properties = details.findChild("properties");
+//    int propertiesCount = properties.childCount();
+
+//    for (int k = 0; k != propertiesCount; ++k) {
+//        JsonValue property = properties.childAt(k);
+//        setPropertyValue(refs,property,prepend);
+//    }
+}
+
+void QmlV8DebuggerClient::setPropertyValue(JsonValue &refs, JsonValue &property, QByteArray &prepend)
+{
+    WatchData data;
+    data.exp = property.findChild("name").toVariant().toByteArray();
+    data.name = data.exp;
+    data.iname = prepend + '.' + data.exp;
+    JsonValue val = refs.childAt(indexInRef(refs,property.findChild("ref").toVariant().toInt()));
+    data.type = val.findChild("type").toVariant().toByteArray();
+
+    if (data.type == "object") {
+        data.hasChildren = true;
+        data.value = val.findChild("className").toVariant().toByteArray();
+
+    } else if (data.type == "function") {
+        data.hasChildren = false;
+        data.value = val.findChild("text").toVariant().toByteArray();
+
+    } else {
+        data.hasChildren = false;
+        data.value = val.findChild("value").toVariant().toByteArray();
+    }
+
+    data.id = val.findChild("handle").toVariant().toInt();
+
+    d->engine->watchHandler()->insertData(data);
+
+    if (d->engine->watchHandler()->expandedINames().contains(data.iname)) {
+        expandObject(data.iname, data.id);
+    }
+}
+
+int QmlV8DebuggerClient::indexInRef(const JsonValue &refs, int refIndex)
+{
+    for (int i = 0; i != refs.childCount(); ++i) {
+        JsonValue ref = refs.childAt(i);
+        int index = ref.findChild("handle").toVariant().toInt();
+        if (index == refIndex)
+            return i;
+    }
+    return -1;
+}
+
+void QmlV8DebuggerClient::setEngine(QmlEngine *engine)
+{
+    d->engine = engine;
+}
+
+} // Internal
+} // Debugger
diff --git a/src/plugins/debugger/qml/qmlv8debuggerclient.h b/src/plugins/debugger/qml/qmlv8debuggerclient.h
new file mode 100644 (file)
index 0000000..870f07b
--- /dev/null
@@ -0,0 +1,106 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at info@qt.nokia.com.
+**
+**************************************************************************/
+
+#ifndef QMLV8DEBUGGERCLIENT_H
+#define QMLV8DEBUGGERCLIENT_H
+
+#include "qmldebuggerclient.h"
+#include "stackframe.h"
+#include "watchdata.h"
+#include "qmlengine.h"
+#include "json.h"
+
+namespace Debugger {
+namespace Internal {
+
+class QmlV8DebuggerClientPrivate;
+
+class QmlV8DebuggerClient : public QmlDebuggerClient
+{
+    Q_OBJECT
+
+public:
+    explicit QmlV8DebuggerClient(QmlJsDebugClient::QDeclarativeDebugConnection *client);
+    ~QmlV8DebuggerClient();
+
+    void executeStep();
+    void executeStepOut();
+    void executeNext();
+    void executeStepI();
+
+    void continueInferior();
+    void interruptInferior();
+
+    void activateFrame(int index);
+
+    void insertBreakpoints(BreakHandler *handler, BreakpointModelId *id);
+    void removeBreakpoints(BreakpointModelId *id);
+    void setBreakpoints();
+
+    void assignValueInDebugger(const QByteArray expr, const quint64 &id,
+                                       const QString &property, const QString value);
+
+    void updateWatchData(const WatchData *data);
+    void executeDebuggerCommand(const QString &command);
+
+    void synchronizeWatchers(const QStringList &watchers);
+
+    void expandObject(const QByteArray &iname, quint64 objectId);
+    void sendPing();
+
+    void setEngine(QmlEngine *engine);
+
+signals:
+    void notifyDebuggerStopped();
+
+protected:
+    void messageReceived(const QByteArray &data);
+
+private:
+    void backtrace();
+    void setStackFrames(QByteArray &);
+    void setLocals(int frameIndex);
+    void setExpression(QByteArray &message);
+    void expandLocal(QByteArray &message);
+    void setPropertyValue(Json::JsonValue &refs, Json::JsonValue &property, QByteArray &prepend);
+    int indexInRef(const Json::JsonValue &refs, int refIndex);
+    QByteArray packMessage(QByteArray& message);
+
+private:
+    QmlV8DebuggerClientPrivate *d;
+    friend class QmlV8DebuggerClientPrivate;
+};
+
+} // Internal
+} // Debugger
+
+#endif // QMLV8DEBUGGERCLIENT_H
diff --git a/src/plugins/debugger/qml/qscriptdebuggerclient.cpp b/src/plugins/debugger/qml/qscriptdebuggerclient.cpp
new file mode 100644 (file)
index 0000000..51cd2cf
--- /dev/null
@@ -0,0 +1,511 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at info@qt.nokia.com.
+**
+**************************************************************************/
+#include "qscriptdebuggerclient.h"
+
+#include "watchdata.h"
+#include "watchhandler.h"
+#include "breakpoint.h"
+#include "breakhandler.h"
+#include "debuggerconstants.h"
+#include "qmlengine.h"
+#include "stackhandler.h"
+#include "debuggercore.h"
+
+#include <QTextDocument>
+#include <QFileInfo>
+#include <QMessageBox>
+#include <extensionsystem/pluginmanager.h>
+#include <utils/qtcassert.h>
+
+namespace Debugger {
+namespace Internal {
+
+struct JSAgentBreakpointData
+{
+    QByteArray functionName;
+    QByteArray fileUrl;
+    qint32 lineNumber;
+};
+
+struct JSAgentStackData
+{
+    QByteArray functionName;
+    QByteArray fileUrl;
+    qint32 lineNumber;
+};
+
+uint qHash(const JSAgentBreakpointData &b)
+{
+    return b.lineNumber ^ qHash(b.fileUrl);
+}
+
+QDataStream &operator<<(QDataStream &s, const JSAgentBreakpointData &data)
+{
+    return s << data.functionName << data.fileUrl << data.lineNumber;
+}
+
+QDataStream &operator<<(QDataStream &s, const JSAgentStackData &data)
+{
+    return s << data.functionName << data.fileUrl << data.lineNumber;
+}
+
+QDataStream &operator>>(QDataStream &s, JSAgentBreakpointData &data)
+{
+    return s >> data.functionName >> data.fileUrl >> data.lineNumber;
+}
+
+QDataStream &operator>>(QDataStream &s, JSAgentStackData &data)
+{
+    return s >> data.functionName >> data.fileUrl >> data.lineNumber;
+}
+
+bool operator==(const JSAgentBreakpointData &b1, const JSAgentBreakpointData &b2)
+{
+    return b1.lineNumber == b2.lineNumber && b1.fileUrl == b2.fileUrl;
+}
+
+typedef QSet<JSAgentBreakpointData> JSAgentBreakpoints;
+typedef QList<JSAgentStackData> JSAgentStackFrames;
+
+
+static QDataStream &operator>>(QDataStream &s, WatchData &data)
+{
+    data = WatchData();
+    QByteArray name;
+    QByteArray value;
+    QByteArray type;
+    bool hasChildren = false;
+    s >> data.exp >> name >> value >> type >> hasChildren >> data.id;
+    data.name = QString::fromUtf8(name);
+    data.setType(type, false);
+    data.setValue(QString::fromUtf8(value));
+    data.setHasChildren(hasChildren);
+    data.setAllUnneeded();
+    return s;
+}
+
+class QScriptDebuggerClientPrivate
+{
+public:
+    explicit QScriptDebuggerClientPrivate(QScriptDebuggerClient *) :
+        ping(0), engine(0)
+    {
+
+    }
+
+    int ping;
+    QmlEngine *engine;
+    JSAgentBreakpoints breakpoints;
+};
+
+QScriptDebuggerClient::QScriptDebuggerClient(QmlJsDebugClient::QDeclarativeDebugConnection* client)
+    : QmlDebuggerClient(client, QLatin1String("JSDebugger")),
+      d(new QScriptDebuggerClientPrivate(this))
+{
+}
+
+QScriptDebuggerClient::~QScriptDebuggerClient()
+{
+    delete d;
+}
+
+void QScriptDebuggerClient::executeStep()
+{
+    QByteArray reply;
+    QDataStream rs(&reply, QIODevice::WriteOnly);
+    QByteArray cmd = "STEPINTO";
+    rs << cmd;
+    sendMessage(reply);
+}
+
+void QScriptDebuggerClient::executeStepOut()
+{
+    QByteArray reply;
+    QDataStream rs(&reply, QIODevice::WriteOnly);
+    QByteArray cmd = "STEPOUT";
+    rs << cmd;
+    sendMessage(reply);
+}
+
+void QScriptDebuggerClient::executeNext()
+{
+    QByteArray reply;
+    QDataStream rs(&reply, QIODevice::WriteOnly);
+    QByteArray cmd = "STEPOVER";
+    rs << cmd;
+    sendMessage(reply);
+}
+
+void QScriptDebuggerClient::executeStepI()
+{
+    QByteArray reply;
+    QDataStream rs(&reply, QIODevice::WriteOnly);
+    QByteArray cmd = "STEPINTO";
+    rs << cmd;
+    sendMessage(reply);
+}
+
+void QScriptDebuggerClient::continueInferior()
+{
+    QByteArray reply;
+    QDataStream rs(&reply, QIODevice::WriteOnly);
+    QByteArray cmd = "CONTINUE";
+    rs << cmd;
+    sendMessage(reply);
+}
+
+void QScriptDebuggerClient::interruptInferior()
+{
+    QByteArray reply;
+    QDataStream rs(&reply, QIODevice::WriteOnly);
+    QByteArray cmd = "INTERRUPT";
+    rs << cmd;
+    sendMessage(reply);
+}
+
+void QScriptDebuggerClient::activateFrame(int index)
+{
+    QByteArray reply;
+    QDataStream rs(&reply, QIODevice::WriteOnly);
+    QByteArray cmd = "ACTIVATE_FRAME";
+    rs << cmd
+       << index;
+    sendMessage(reply);
+}
+
+void QScriptDebuggerClient::insertBreakpoints(BreakHandler *handler, BreakpointModelId *id)
+{
+    JSAgentBreakpointData bp;
+    bp.fileUrl = QUrl::fromLocalFile(handler->fileName(*id)).toString().toUtf8();
+    bp.lineNumber = handler->lineNumber(*id);
+    bp.functionName = handler->functionName(*id).toUtf8();
+    d->breakpoints.insert(bp);
+}
+
+void QScriptDebuggerClient::removeBreakpoints(BreakpointModelId */*id*/)
+{
+
+}
+
+void QScriptDebuggerClient::setBreakpoints()
+{
+    QByteArray reply;
+    QDataStream rs(&reply, QIODevice::WriteOnly);
+    QByteArray cmd = "BREAKPOINTS";
+    rs << cmd
+       << d->breakpoints;
+
+    QStringList breakPointsStr;
+    foreach (const JSAgentBreakpointData &bp, d->breakpoints) {
+        breakPointsStr << QString("('%1' '%2' %3)").arg(QString(bp.functionName),
+                                                        QString(bp.fileUrl), QString::number(bp.lineNumber));
+    }
+
+    sendMessage(reply);
+
+    d->breakpoints.clear();
+}
+
+void QScriptDebuggerClient::assignValueInDebugger(const QByteArray expr, const quint64 &id,
+                                                  const QString &property, const QString value)
+{
+    QByteArray reply;
+    QDataStream rs(&reply, QIODevice::WriteOnly);
+    QByteArray cmd = "SET_PROPERTY";
+    rs << cmd;
+    rs << expr << id << property << value;
+    sendMessage(reply);
+}
+
+void QScriptDebuggerClient::updateWatchData(const WatchData *data)
+{
+    QByteArray reply;
+    QDataStream rs(&reply, QIODevice::WriteOnly);
+    QByteArray cmd = "EXEC";
+    rs << cmd;
+    rs << data->iname << data->name;
+    sendMessage(reply);
+}
+
+void QScriptDebuggerClient::executeDebuggerCommand(const QString &command)
+{
+    QByteArray reply;
+    QDataStream rs(&reply, QIODevice::WriteOnly);
+    QByteArray cmd = "EXEC";
+    QByteArray console = "console";
+    rs << cmd << console << command;
+    sendMessage(reply);
+}
+
+void QScriptDebuggerClient::synchronizeWatchers(const QStringList &watchers)
+{
+    // send watchers list
+    QByteArray reply;
+    QDataStream rs(&reply, QIODevice::WriteOnly);
+    QByteArray cmd = "WATCH_EXPRESSIONS";
+    rs << cmd;
+    rs << watchers;
+    sendMessage(reply);
+}
+
+void QScriptDebuggerClient::expandObject(const QByteArray &iname, quint64 objectId)
+{
+    QByteArray reply;
+    QDataStream rs(&reply, QIODevice::WriteOnly);
+    QByteArray cmd = "EXPAND";
+    rs << cmd;
+    rs << iname << objectId;
+    sendMessage(reply);
+}
+
+void QScriptDebuggerClient::sendPing()
+{
+    d->ping++;
+    QByteArray reply;
+    QDataStream rs(&reply, QIODevice::WriteOnly);
+    QByteArray cmd = "PING";
+    rs << cmd;
+    rs << d->ping;
+    sendMessage(reply);
+}
+
+void QScriptDebuggerClient::messageReceived(const QByteArray &data)
+{
+    QByteArray rwData = data;
+    QDataStream stream(&rwData, QIODevice::ReadOnly);
+
+    QByteArray command;
+    stream >> command;
+
+    if (command == "STOPPED") {
+        d->engine->inferiorSpontaneousStop();
+
+        QString logString = QString::fromLatin1(command);
+
+        JSAgentStackFrames stackFrames;
+        QList<WatchData> watches;
+        QList<WatchData> locals;
+        stream >> stackFrames >> watches >> locals;
+
+        logString += QString::fromLatin1(" (%1 stack frames) (%2 watches)  (%3 locals)").
+                arg(stackFrames.size()).arg(watches.size()).arg(locals.size());
+
+        StackFrames ideStackFrames;
+        for (int i = 0; i != stackFrames.size(); ++i) {
+            StackFrame frame;
+            frame.line = stackFrames.at(i).lineNumber;
+            frame.function = stackFrames.at(i).functionName;
+            frame.file = d->engine->toFileInProject(QUrl(stackFrames.at(i).fileUrl));
+            frame.usable = QFileInfo(frame.file).isReadable();
+            frame.level = i + 1;
+            ideStackFrames << frame;
+        }
+
+        if (ideStackFrames.size() && ideStackFrames.back().function == "<global>")
+            ideStackFrames.takeLast();
+        d->engine->stackHandler()->setFrames(ideStackFrames);
+
+        d->engine->watchHandler()->beginCycle();
+        bool needPing = false;
+
+        foreach (WatchData data, watches) {
+            data.iname = d->engine->watchHandler()->watcherName(data.exp);
+            d->engine->watchHandler()->insertData(data);
+
+            if (d->engine->watchHandler()->expandedINames().contains(data.iname)) {
+                needPing = true;
+                expandObject(data.iname,data.id);
+            }
+        }
+
+        foreach (WatchData data, locals) {
+            data.iname = "local." + data.exp;
+            d->engine->watchHandler()->insertData(data);
+
+            if (d->engine->watchHandler()->expandedINames().contains(data.iname)) {
+                needPing = true;
+                expandObject(data.iname,data.id);
+            }
+        }
+
+        if (needPing) {
+            sendPing();
+        } else {
+            d->engine->watchHandler()->endCycle();
+        }
+
+        bool becauseOfException;
+        stream >> becauseOfException;
+
+        logString += becauseOfException ? " exception" : " no_exception";
+
+        if (becauseOfException) {
+            QString error;
+            stream >> error;
+
+            logString += QLatin1Char(' ');
+            logString += error;
+            d->engine->logMessage(QmlEngine::LogReceive, logString);
+
+            QString msg = stackFrames.isEmpty()
+                    ? tr("<p>An uncaught exception occurred:</p><p>%1</p>")
+                      .arg(Qt::escape(error))
+                    : tr("<p>An uncaught exception occurred in <i>%1</i>:</p><p>%2</p>")
+                      .arg(stackFrames.value(0).fileUrl, Qt::escape(error));
+            showMessageBox(QMessageBox::Information, tr("Uncaught Exception"), msg);
+        } else {
+            //
+            // Make breakpoint non-pending
+            //
+            QString file;
+            QString function;
+            int line = -1;
+
+            if (!ideStackFrames.isEmpty()) {
+                file = ideStackFrames.at(0).file;
+                line = ideStackFrames.at(0).line;
+                function = ideStackFrames.at(0).function;
+            }
+
+            BreakHandler *handler = d->engine->breakHandler();
+            foreach (BreakpointModelId id, handler->engineBreakpointIds(d->engine)) {
+                QString processedFilename = handler->fileName(id);
+                if (processedFilename == file && handler->lineNumber(id) == line) {
+                    QTC_ASSERT(handler->state(id) == BreakpointInserted,/**/);
+                    BreakpointResponse br = handler->response(id);
+                    br.fileName = file;
+                    br.lineNumber = line;
+                    br.functionName = function;
+                    handler->setResponse(id, br);
+                }
+            }
+
+            d->engine->logMessage(QmlEngine::LogReceive, logString);
+        }
+
+        if (!ideStackFrames.isEmpty())
+            d->engine->gotoLocation(ideStackFrames.value(0));
+
+    } else if (command == "RESULT") {
+        WatchData data;
+        QByteArray iname;
+        stream >> iname >> data;
+
+        d->engine->logMessage(QmlEngine::LogReceive, QString("%1 %2 %3").arg(QString(command),
+                                                                             QString(iname), QString(data.value)));
+        data.iname = iname;
+        if (iname.startsWith("watch.")) {
+            d->engine->watchHandler()->insertData(data);
+        } else if (iname == "console") {
+            d->engine->showMessage(data.value, ScriptConsoleOutput);
+        } else {
+            qWarning() << "QmlEngine: Unexcpected result: " << iname << data.value;
+        }
+    } else if (command == "EXPANDED") {
+        QList<WatchData> result;
+        QByteArray iname;
+        stream >> iname >> result;
+
+        d->engine->logMessage(QmlEngine::LogReceive, QString("%1 %2 (%3 x watchdata)").arg(
+                                  QString(command), QString(iname), QString::number(result.size())));
+        bool needPing = false;
+        foreach (WatchData data, result) {
+            data.iname = iname + '.' + data.exp;
+            d->engine->watchHandler()->insertData(data);
+
+            if (d->engine->watchHandler()->expandedINames().contains(data.iname)) {
+                needPing = true;
+                expandObject(data.iname, data.id);
+            }
+        }
+        if (needPing)
+            sendPing();
+    } else if (command == "LOCALS") {
+        QList<WatchData> locals;
+        QList<WatchData> watches;
+        int frameId;
+        stream >> frameId >> locals;
+        if (!stream.atEnd()) { // compatibility with jsdebuggeragent from 2.1, 2.2
+            stream >> watches;
+        }
+
+        d->engine->logMessage(QmlEngine::LogReceive, QString("%1 %2 (%3 x locals) (%4 x watchdata)").arg(
+                                  QString(command), QString::number(frameId),
+                                  QString::number(locals.size()),
+                                  QString::number(watches.size())));
+        d->engine->watchHandler()->beginCycle();
+        bool needPing = false;
+        foreach (WatchData data, watches) {
+            data.iname = d->engine->watchHandler()->watcherName(data.exp);
+            d->engine->watchHandler()->insertData(data);
+
+            if (d->engine->watchHandler()->expandedINames().contains(data.iname)) {
+                needPing = true;
+                expandObject(data.iname, data.id);
+            }
+        }
+
+        foreach (WatchData data, locals) {
+            data.iname = "local." + data.exp;
+            d->engine->watchHandler()->insertData(data);
+            if (d->engine->watchHandler()->expandedINames().contains(data.iname)) {
+                needPing = true;
+                expandObject(data.iname, data.id);
+            }
+        }
+        if (needPing)
+            sendPing();
+        else
+            d->engine->watchHandler()->endCycle();
+
+    } else if (command == "PONG") {
+        int ping;
+        stream >> ping;
+
+        d->engine->logMessage(QmlEngine::LogReceive, QString("%1 %2").arg(QString(command), QString::number(ping)));
+
+        if (ping == d->ping)
+            d->engine->watchHandler()->endCycle();
+    } else {
+        qDebug() << Q_FUNC_INFO << "Unknown command: " << command;
+        d->engine->logMessage(QmlEngine::LogReceive, QString("%1 UNKNOWN COMMAND!!").arg(QString(command)));
+    }
+
+}
+
+void QScriptDebuggerClient::setEngine(QmlEngine *engine)
+{
+    d->engine = engine;
+}
+
+} // Internal
+} // Debugger
diff --git a/src/plugins/debugger/qml/qscriptdebuggerclient.h b/src/plugins/debugger/qml/qscriptdebuggerclient.h
new file mode 100644 (file)
index 0000000..d8b6935
--- /dev/null
@@ -0,0 +1,95 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at info@qt.nokia.com.
+**
+**************************************************************************/
+
+#ifndef QSCRIPTDEBUGGERCLIENT_H
+#define QSCRIPTDEBUGGERCLIENT_H
+
+#include "qmldebuggerclient.h"
+#include "stackframe.h"
+#include "watchdata.h"
+#include "qmlengine.h"
+
+namespace Debugger {
+namespace Internal {
+
+class QScriptDebuggerClientPrivate;
+
+class QScriptDebuggerClient : public QmlDebuggerClient
+{
+    Q_OBJECT
+
+public:
+    QScriptDebuggerClient(QmlJsDebugClient::QDeclarativeDebugConnection *client);
+    ~QScriptDebuggerClient();
+
+    void executeStep();
+    void executeStepOut();
+    void executeNext();
+    void executeStepI();
+
+    void continueInferior();
+    void interruptInferior();
+
+    void activateFrame(int index);
+
+    void insertBreakpoints(BreakHandler *handler, BreakpointModelId *id);
+    void removeBreakpoints(BreakpointModelId *id);
+    void setBreakpoints();
+
+    void assignValueInDebugger(const QByteArray expr, const quint64 &id,
+                                       const QString &property, const QString value);
+
+    void updateWatchData(const WatchData *data);
+    void executeDebuggerCommand(const QString &command);
+
+    void synchronizeWatchers(const QStringList &watchers);
+
+    void expandObject(const QByteArray &iname, quint64 objectId);
+    void sendPing();
+
+    void setEngine(QmlEngine *engine);
+
+signals:
+    void notifyDebuggerStopped();
+
+protected:
+    void messageReceived(const QByteArray &data);
+
+private:
+    QScriptDebuggerClientPrivate *d;
+    friend class QScriptDebuggerClientPrivate;
+};
+
+} // Internal
+} // Debugger
+
+#endif // QSCRIPTDEBUGGERCLIENT_H
index fb90db4..39f7ee0 100644 (file)
@@ -344,7 +344,7 @@ void CodaRunControl::handleDebugSessionEnded(const CodaCommandResult &result)
 
 void CodaRunControl::handleFindProcesses(const CodaCommandResult &result)
 {
-    if (result.values.size() && result.values.at(0).type() == JsonValue::Array && result.values.at(0).children().count()) {
+    if (result.values.size() && result.values.at(0).type() == Json::JsonValue::Array && result.values.at(0).children().count()) {
         //there are processes running. Cannot run mine
         appendMessage(tr("The process is already running on the device. Please first close it.\n"), Utils::ErrorMessageFormat);
         finishRunControl();
@@ -367,7 +367,7 @@ void CodaRunControl::handleCreateProcess(const CodaCommandResult &result)
     if (ok) {
         if (m_codaFlags & OptionsUseDebugSession) {
             if (result.values.size()) {
-                JsonValue id = result.values.at(0).findChild("ID");
+                Json::JsonValue id = result.values.at(0).findChild("ID");
                 if (id.isValid()) {
                     m_state = StateProcessRunning;
                     m_runningProcessId = id.data();
index 7369cb0..6faede1 100644 (file)
@@ -77,3 +77,6 @@ FORMS += $$PWD/s60createpackagestep.ui \
     $$PWD/s60publishingbuildsettingspageovi.ui \
     $$PWD/s60publishingresultspageovi.ui \
     $$PWD/s60publishingsissettingspageovi.ui
+
+include(../../../shared/json/json.pri)
+DEFINES += JSON_INCLUDE_PRI
similarity index 97%
rename from src/shared/symbianutils/json.cpp
rename to src/shared/json/json.cpp
index 7ac1c8c..a73881c 100644 (file)
 
 #include <ctype.h>
 
-//#define DEBUG_JASON
 #ifdef DEBUG_JASON
 #define JDEBUG(s) qDebug() << s
 #else
 #define JDEBUG(s)
 #endif
 
-namespace Coda {
+using namespace Json;
 
 static void skipSpaces(const char *&from, const char *to)
 {
@@ -530,11 +529,23 @@ JsonInputStream &JsonInputStream::operator<<(const QVector<QByteArray> &ba)
     return *this;
 }
 
+JsonInputStream &JsonInputStream::operator<<(const QList<int> &in)
+{
+    m_target.append('[');
+    const int count = in.size();
+    for (int i = 0 ; i < count; i++) {
+        if (i)
+            m_target.append(',');
+        m_target.append(QByteArray::number(in.at(i)));
+    }
+    m_target.append(']');
+    return *this;
+}
+
 JsonInputStream &JsonInputStream::operator<<(bool b)
 {
     m_target.append(b ? "true" : "false");
     return *this;
 }
 
-} // namespace Coda
 
similarity index 94%
rename from src/shared/symbianutils/json.h
rename to src/shared/json/json.h
index 50e3e15..318a7c3 100644 (file)
 **
 **************************************************************************/
 
-#ifndef SYMBIANUTILS_JSON_H
-#define SYMBIANUTILS_JSON_H
+#ifndef JSON_H
+#define JSON_H
 
-#include "symbianutils_global.h"
+#include "json_global.h"
 
 #include <QtCore/QByteArray>
 #include <QtCore/QStringList>
 #include <QtCore/QVector>
 
-namespace Coda {
+namespace Json {
 
-class SYMBIANUTILS_EXPORT JsonValue
+class JSON_EXPORT JsonValue
 {
 public:
     JsonValue() : m_type(Invalid) {}
@@ -106,7 +106,7 @@ private:
  * Note that strings get double quotes and JSON-escaping, characters should be
  * used for the array/hash delimiters.
  * */
-class SYMBIANUTILS_EXPORT JsonInputStream {
+class JSON_EXPORT JsonInputStream {
 public:
     explicit JsonInputStream(QByteArray &a) : m_target(a) {}
 
@@ -121,6 +121,9 @@ public:
     // Format as array
     JsonInputStream &operator<<(const QVector<QByteArray> &ba);
 
+    //Format as array
+    JsonInputStream &operator<<(const QList<int> &in);
+
     JsonInputStream &operator<<(bool b);
 
     JsonInputStream &operator<<(int i)
@@ -137,6 +140,6 @@ private:
     QByteArray &m_target;
 };
 
-} // namespace Coda
+} //namespace Json
 
-#endif // SYMBIANUTILS_JSON_H
+#endif // JSON_H
diff --git a/src/shared/json/json.pri b/src/shared/json/json.pri
new file mode 100644 (file)
index 0000000..088fc4c
--- /dev/null
@@ -0,0 +1,7 @@
+INCLUDEPATH *= $$PWD
+
+# Input
+HEADERS += $$PWD/json_global.h \
+    $$PWD/json.h
+
+SOURCES += $$PWD/json.cpp
diff --git a/src/shared/json/json_global.h b/src/shared/json/json_global.h
new file mode 100644 (file)
index 0000000..2d67787
--- /dev/null
@@ -0,0 +1,46 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at info@qt.nokia.com.
+**
+**************************************************************************/
+
+#ifndef JSON_GLOBAL_H
+#define JSON_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#if defined(JSON_BUILD_LIB)
+#    define JSON_EXPORT Q_DECL_EXPORT
+#elif defined(JSON_BUILD_STATIC_LIB) || defined(JSON_INCLUDE_PRI)
+#    define JSON_EXPORT
+#else
+#    define JSON_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // SYMBIANUTILS_GLOBAL_H
index c125ac7..80a3346 100644 (file)
@@ -112,6 +112,7 @@ static inline QByteArray encodeUsbSerialMessage(const QByteArray &dataIn)
     return frame;
 }
 
+using namespace Json;
 namespace Coda {
 // ------------- CodaCommandError
 
index 3469268..4700008 100644 (file)
@@ -71,7 +71,7 @@ struct SYMBIANUTILS_EXPORT CodaCommandError {
     operator bool() const { return isError(); }
     QString toString() const;
     void write(QTextStream &str) const;
-    bool parse(const QVector<JsonValue> &values);
+    bool parse(const QVector<Json::JsonValue> &values);
 
     quint64 timeMS; // Since 1.1.1970
     qint64 code;
@@ -94,7 +94,7 @@ struct SYMBIANUTILS_EXPORT CodaCommandResult {
     explicit CodaCommandResult(Type t = SuccessReply);
     explicit CodaCommandResult(char typeChar, Services service,
                                  const QByteArray &request,
-                                 const QVector<JsonValue> &values,
+                                 const QVector<Json::JsonValue> &values,
                                  const QVariant &cookie);
 
     QString toString() const;
@@ -107,7 +107,7 @@ struct SYMBIANUTILS_EXPORT CodaCommandResult {
     Services service;
     QByteArray request;
     CodaCommandError commandError;
-    QVector<JsonValue> values;
+    QVector<Json::JsonValue> values;
     QVariant cookie;
 };
 
@@ -394,7 +394,7 @@ public:
     static CodaStatResponse parseStat(const CodaCommandResult &r);
 
 signals:
-    void genericCodaEvent(int service, const QByteArray &name, const QVector<JsonValue> &value);
+    void genericCodaEvent(int service, const QByteArray &name, const QVector<Json::JsonValue> &value);
     void codaEvent(const Coda::CodaEvent &knownEvent);
     void unknownEvent(uchar protocolId, const QByteArray& data);
     void serialPong(const QString &codaVersion);
index 1506e6c..9eba08a 100644 (file)
@@ -43,6 +43,7 @@ static const char *serviceNamesC[] =
   "DebugSessionControl",
   "UnknownService"};
 
+using namespace Json;
 namespace Coda {
 
 SYMBIANUTILS_EXPORT QString joinByteArrays(const QVector<QByteArray> &a, char sep)
index f61fdeb..b58cd29 100644 (file)
@@ -34,6 +34,7 @@
 #define CODAMESSAGE_H
 
 #include "symbianutils_global.h"
+#include "json_global.h"
 
 #include <QtCore/QStringList>
 #include <QtCore/QVector>
@@ -42,10 +43,12 @@ QT_BEGIN_NAMESPACE
 class QTextStream;
 QT_END_NAMESPACE
 
-namespace Coda {
-
+namespace Json {
 class JsonValue;
 class JsonInputStream;
+}
+
+namespace Coda {
 
 enum Services {
     LocatorService,
@@ -101,7 +104,7 @@ struct SYMBIANUTILS_EXPORT RunControlContext {
     unsigned threadId() const;
 
     void clear();
-    bool parse(const JsonValue &v);
+    bool parse(const Json::JsonValue &v);
     void format(QTextStream &str) const;
     QString toString() const;
 
@@ -122,7 +125,7 @@ struct SYMBIANUTILS_EXPORT RunControlContext {
 struct SYMBIANUTILS_EXPORT ModuleLoadEventInfo {
     ModuleLoadEventInfo();
     void clear();
-    bool parse(const JsonValue &v);
+    bool parse(const Json::JsonValue &v);
     void format(QTextStream &str) const;
 
     QByteArray name;
@@ -154,7 +157,7 @@ struct SYMBIANUTILS_EXPORT Breakpoint {
     bool thumb;
 };
 
-SYMBIANUTILS_EXPORT JsonInputStream &operator<<(JsonInputStream &str, const Breakpoint &b);
+Json::JsonInputStream &operator<<(Json::JsonInputStream &str, const Breakpoint &b);
 
 // Event hierarchy
 class SYMBIANUTILS_EXPORT CodaEvent
@@ -179,7 +182,7 @@ public:
     Type type() const;
     virtual QString toString() const;
 
-    static CodaEvent *parseEvent(Services s, const QByteArray &name, const QVector<JsonValue> &val);
+    static CodaEvent *parseEvent(Services s, const QByteArray &name, const QVector<Json::JsonValue> &val);
 
 protected:
     explicit CodaEvent(Type type = None);
@@ -252,7 +255,7 @@ public:
     const RunControlContexts &contexts() const { return m_contexts; }
     virtual QString toString() const;
 
-    static CodaRunControlContextAddedEvent *parseEvent(const QVector<JsonValue> &val);
+    static CodaRunControlContextAddedEvent *parseEvent(const QVector<Json::JsonValue> &val);
 
 private:
     const RunControlContexts m_contexts;
index 7bb782f..6511d4d 100644 (file)
@@ -10,14 +10,12 @@ HEADERS += $$PWD/symbianutils_global.h \
     $$PWD/symbiandevicemanager.h \
     $$PWD/codadevice.h \
     $$PWD/codamessage.h \
-    $$PWD/json.h \
     $$PWD/virtualserialdevice.h
 
 SOURCES += $$PWD/codautils.cpp \
     $$PWD/symbiandevicemanager.cpp \
     $$PWD/codadevice.cpp \
     $$PWD/codamessage.cpp \
-    $$PWD/json.cpp \
     $$PWD/virtualserialdevice.cpp
 
 DEFINES += HAS_SERIALPORT
@@ -25,3 +23,5 @@ win32:SOURCES += $$PWD/virtualserialdevice_win.cpp
 unix:SOURCES += $$PWD/virtualserialdevice_posix.cpp
 
 macx:LIBS += -framework IOKit -framework CoreFoundation
+include(../../shared/json/json.pri)
+DEFINES += JSON_INCLUDE_PRI
index 705a963..96ba211 100644 (file)
@@ -1,5 +1,7 @@
 include(../qttest.pri)
 include($$IDE_SOURCE_TREE/src/libs/symbianutils/symbianutils.pri)
+include($$IDE_SOURCE_TREE/src/shared/json/json.pri)
+DEFINES += JSON_INCLUDE_PRI
 
 DEBUGGERDIR = $$IDE_SOURCE_TREE/src/plugins/debugger
 UTILSDIR    = $$IDE_SOURCE_TREE/src/libs
index 9471b23..81eaeb8 100644 (file)
@@ -162,7 +162,7 @@ public:
 
     void testJson(const char* input)
     {
-        QCOMPARE('\n' + QString::fromLatin1(Coda::JsonValue(input).toString(false)),
+        QCOMPARE('\n' + QString::fromLatin1(Json::JsonValue(input).toString(false)),
             '\n' + QString(input));
     }