diff options
author | Aurindam Jana <aurindam.jana@digia.com> | 2013-09-10 17:32:00 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-19 21:40:56 +0200 |
commit | caddd0ef4ad9039c60c62a5110dd4452cca132d5 (patch) | |
tree | 296c4751ba781af26dbe23aacb7ff3b2e200b587 | |
parent | 353a068c7716a34eb90d1441893f4c4a5b28f9de (diff) |
QmlDebugging: Process commands in v4DebugService
Change-Id: I6371db756f72ee373884268fc49a5b16cb66fd34
Reviewed-by: Kai Koehne <kai.koehne@digia.com>
-rw-r--r-- | src/qml/debugger/qv4debugservice.cpp | 188 | ||||
-rw-r--r-- | src/qml/debugger/qv4debugservice_p.h | 12 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 4 |
3 files changed, 163 insertions, 41 deletions
diff --git a/src/qml/debugger/qv4debugservice.cpp b/src/qml/debugger/qv4debugservice.cpp index 10aefbfd13..ac239f31be 100644 --- a/src/qml/debugger/qv4debugservice.cpp +++ b/src/qml/debugger/qv4debugservice.cpp @@ -44,11 +44,20 @@ #include "qqmlengine.h" #include "qv4debugging_p.h" #include "qv4engine_p.h" +#include "qv4function_p.h" #include <private/qv8engine_p.h> const char *V4_CONNECT = "connect"; const char *V4_BREAK_ON_SIGNAL = "breakonsignal"; +const char *V4_ADD_BREAKPOINT = "addBreakpoint"; +const char *V4_REMOVE_BREAKPOINT = "removeBreakpoint"; +const char *V4_PAUSE = "interrupt"; +const char *V4_ALL = "all"; +const char *V4_BREAK = "break"; + +const char *V4_FILENAME = "filename"; +const char *V4_LINENUMBER = "linenumber"; QT_BEGIN_NAMESPACE @@ -65,22 +74,35 @@ class QV4DebugServicePrivate : public QQmlDebugServicePrivate Q_DECLARE_PUBLIC(QV4DebugService) public: - static QByteArray packMessage(const QString &type, const QString &message = QString()) + QV4DebugServicePrivate() : version(1) {} + + static QByteArray packMessage(const QByteArray &command, int querySequence, const QByteArray &message = QByteArray()) { QByteArray reply; QQmlDebugStream rs(&reply, QIODevice::WriteOnly); - QByteArray cmd("V4DEBUG"); - rs << cmd << type.toUtf8() << message.toUtf8(); + const QByteArray cmd("V4DEBUG"); + rs << cmd << QByteArray::number(++sequence) << QByteArray::number(querySequence) << command << message; return reply; } + void processCommand(const QByteArray &command, const QByteArray &data); + void addBreakpoint(const QByteArray &data); + void removeBreakpoint(const QByteArray &data); + QMutex initializeMutex; QWaitCondition initializeCondition; QV4DebuggerAgent debuggerAgent; QStringList breakOnSignals; + QMap<int, QV4::Debugging::Debugger *> debuggerMap; + static int debuggerIndex; + static int sequence; + const int version; }; +int QV4DebugServicePrivate::debuggerIndex = 0; +int QV4DebugServicePrivate::sequence = 0; + QV4DebugService::QV4DebugService(QObject *parent) : QQmlDebugService(*(new QV4DebugServicePrivate()), QStringLiteral("V4Debugger"), 1, parent) @@ -90,8 +112,7 @@ QV4DebugService::QV4DebugService(QObject *parent) // don't execute stateChanged, messageReceived in parallel QMutexLocker lock(&d->initializeMutex); - if (registerService() == Enabled - && QQmlDebugService::blockingMode()) { + if (registerService() == Enabled && blockingMode()) { // let's wait for first message ... d->initializeCondition.wait(&d->initializeMutex); } @@ -108,30 +129,36 @@ QV4DebugService *QV4DebugService::instance() void QV4DebugService::addEngine(const QQmlEngine *engine) { - // just make sure that the service is properly registered - if (engine) - v4ServiceInstance()->addEngine(QV8Engine::getV4(engine->handle())); -} - -void QV4DebugService::removeEngine(const QQmlEngine *engine) -{ - // just make sure that the service is properly registered - if (engine) - v4ServiceInstance()->removeEngine(QV8Engine::getV4(engine->handle())); -} - -void QV4DebugService::addEngine(const QV4::ExecutionEngine *engine) -{ Q_D(QV4DebugService); - if (engine) - d->debuggerAgent.addDebugger(engine->debugger); + if (engine) { + QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle()); + if (ee) { + ee->enableDebugger(); + QV4::Debugging::Debugger *debugger = ee->debugger; + d->debuggerMap.insert(d->debuggerIndex++, debugger); + d->debuggerAgent.addDebugger(debugger); + } + } } -void QV4DebugService::removeEngine(const QV4::ExecutionEngine *engine) +void QV4DebugService::removeEngine(const QQmlEngine *engine) { Q_D(QV4DebugService); - if (engine) - d->debuggerAgent.removeDebugger(engine->debugger); + if (engine){ + const QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle()); + if (ee) { + QV4::Debugging::Debugger *debugger = ee->debugger; + typedef QMap<int, QV4::Debugging::Debugger *>::const_iterator DebuggerMapIterator; + const DebuggerMapIterator end = d->debuggerMap.constEnd(); + for (DebuggerMapIterator i = d->debuggerMap.constBegin(); i != end; ++i) { + if (i.value() == debugger) { + d->debuggerMap.remove(i.key()); + break; + } + } + d->debuggerAgent.removeDebugger(debugger); + } + } } void QV4DebugService::signalEmitted(const QString &signal) @@ -170,36 +197,129 @@ void QV4DebugService::messageReceived(const QByteArray &message) Q_D(QV4DebugService); QMutexLocker lock(&d->initializeMutex); - QQmlDebugStream ds(message); + QQmlDebugStream ms(message); QByteArray header; - ds >> header; + ms >> header; if (header == "V4DEBUG") { + QByteArray sequenceValue; QByteArray command; QByteArray data; - ds >> command >> data; + ms >> sequenceValue >> command >> data; - if (command == V4_CONNECT) { - // wake up constructor in blocking mode - d->initializeCondition.wakeAll(); - } else if (command == V4_BREAK_ON_SIGNAL) { - QQmlDebugStream rs(data); + QQmlDebugStream ds(data); + + QByteArray versionValue; + QByteArray debuggerValue; + ds >> versionValue >> debuggerValue; // unused for now + + int querySequence = sequenceValue.toInt(); + if (command == V4_BREAK_ON_SIGNAL) { QByteArray signal; bool enabled; - rs >> signal >> enabled; + ds >> signal >> enabled; //Normalize to lower case. QString signalName(QString::fromUtf8(signal).toLower()); if (enabled) d->breakOnSignals.append(signalName); else d->breakOnSignals.removeOne(signalName); - sendMessage(QV4DebugServicePrivate::packMessage(QLatin1String(V4_BREAK_ON_SIGNAL))); + } else if (command == V4_ADD_BREAKPOINT) { + QMetaObject::invokeMethod(this, "addBreakpoint", Qt::QueuedConnection, + Q_ARG(QByteArray, data), Q_ARG(int, querySequence)); + } else if (command == V4_REMOVE_BREAKPOINT) { + QMetaObject::invokeMethod(this, "removeBreakpoint", Qt::QueuedConnection, + Q_ARG(QByteArray, data), Q_ARG(int, querySequence)); + } else if (command == V4_PAUSE) { + int id = ds.atEnd() ? debuggerValue.toInt() : -1; + QMetaObject::invokeMethod(this, "pause", Qt::QueuedConnection, Q_ARG(int, id), + Q_ARG(int, querySequence)); + } else if (command == V4_CONNECT) { + QByteArray response; + QQmlDebugStream rs(&response, QIODevice::WriteOnly); + rs << QByteArray::number(d->version) << QByteArray::number(1); + sendMessage(d->packMessage(command, sequenceValue.toInt(), response)); + + d->initializeCondition.wakeAll(); + } else { + QByteArray response; + QQmlDebugStream rs(&response, QIODevice::WriteOnly); + rs << QByteArray::number(d->version) << QByteArray::number(0); + sendMessage(d->packMessage(command, sequenceValue.toInt(), response)); } } } void QV4DebuggerAgent::debuggerPaused(QV4::Debugging::Debugger *debugger) { + QByteArray data; + QQmlDebugStream message(&data, QIODevice::WriteOnly); + + QV4::Debugging::Debugger::ExecutionState state = debugger->currentExecutionState(); + message << V4_FILENAME << state.fileName.toLatin1(); + message << V4_LINENUMBER << QByteArray().number(state.lineNumber); + + QV4DebugService::instance()->sendMessage(QV4DebugServicePrivate::packMessage(V4_BREAK, -1, data)); + + qDebug() << Q_FUNC_INFO; +} + +void QV4DebugService::pause(int debuggerId, int querySequence) +{ + Q_D(QV4DebugService); + + debuggerId == -1 ? d->debuggerAgent.pauseAll() + : d->debuggerAgent.pause(d->debuggerMap.value(debuggerId)); + QByteArray response; + QQmlDebugStream rs(&response, QIODevice::WriteOnly); + rs << QByteArray::number(d->version) << QByteArray::number(1); + sendMessage(d->packMessage(V4_PAUSE, querySequence, response)); +} + +void QV4DebugService::addBreakpoint(const QByteArray &data, int querySequence) +{ + Q_D(QV4DebugService); + + QQmlDebugStream ds(data); + QString fileName; + int lineNumber = -1; + while (!ds.atEnd()) { + QByteArray key; + QByteArray value; + ds >> key >> value; + if (key == V4_FILENAME) + fileName = QString::fromLatin1(value); + else if (key == V4_LINENUMBER) + lineNumber = value.toInt(); + } + d->debuggerAgent.addBreakPoint(fileName, lineNumber); + QByteArray response; + QQmlDebugStream rs(&response, QIODevice::WriteOnly); + rs << QByteArray::number(d->version) << QByteArray::number(1); + sendMessage(d->packMessage(V4_ADD_BREAKPOINT, querySequence, response)); +} + +void QV4DebugService::removeBreakpoint(const QByteArray &data, int querySequence) +{ + Q_D(QV4DebugService); + + QQmlDebugStream ds(data); + QString fileName; + int lineNumber = -1; + while (!ds.atEnd()) { + QByteArray key; + QByteArray value; + ds >> key >> value; + if (key == V4_FILENAME) + fileName = QString::fromLatin1(value); + else if (key == V4_LINENUMBER) + lineNumber = value.toInt(); + } + d->debuggerAgent.removeBreakPoint(fileName, lineNumber); + QByteArray response; + QQmlDebugStream rs(&response, QIODevice::WriteOnly); + rs << QByteArray::number(d->version) << QByteArray::number(1); + sendMessage(d->packMessage(V4_REMOVE_BREAKPOINT, querySequence, response)); } QT_END_NAMESPACE diff --git a/src/qml/debugger/qv4debugservice_p.h b/src/qml/debugger/qv4debugservice_p.h index c355a514e6..a89b009c7f 100644 --- a/src/qml/debugger/qv4debugservice_p.h +++ b/src/qml/debugger/qv4debugservice_p.h @@ -69,11 +69,8 @@ public: ~QV4DebugService(); static QV4DebugService *instance(); - static void addEngine(const QQmlEngine *engine); - static void removeEngine(const QQmlEngine *engine); - - void addEngine(const QV4::ExecutionEngine *engine); - void removeEngine(const QV4::ExecutionEngine *engine); + void addEngine(const QQmlEngine *engine); + void removeEngine(const QQmlEngine *engine); void signalEmitted(const QString &signal); @@ -81,6 +78,11 @@ protected: void stateChanged(State newState); void messageReceived(const QByteArray &); +private slots: + void pause(int debuggerId, int querySequence); + void addBreakpoint(const QByteArray &data, int querySequence); + void removeBreakpoint(const QByteArray &data, int querySequence); + private: Q_DISABLE_COPY(QV4DebugService) Q_DECLARE_PRIVATE(QV4DebugService) diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 274952cb12..33c9d87856 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -794,7 +794,7 @@ void QQmlEnginePrivate::init() QQmlEngineDebugService::isDebuggingEnabled()) { isDebugging = true; QQmlEngineDebugService::instance()->addEngine(q); - QV4DebugService::addEngine(q); + QV4DebugService::instance()->addEngine(q); QV8ProfilerService::initialize(); QQmlProfilerService::initialize(); QDebugMessageService::instance(); @@ -883,7 +883,7 @@ QQmlEngine::~QQmlEngine() Q_D(QQmlEngine); if (d->isDebugging) { QQmlEngineDebugService::instance()->remEngine(this); - QV4DebugService::removeEngine(this); + QV4DebugService::instance()->removeEngine(this); } // Emit onDestruction signals for the root context before |