aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAurindam Jana <aurindam.jana@digia.com>2013-09-10 17:32:00 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-19 21:40:56 +0200
commitcaddd0ef4ad9039c60c62a5110dd4452cca132d5 (patch)
tree296c4751ba781af26dbe23aacb7ff3b2e200b587
parent353a068c7716a34eb90d1441893f4c4a5b28f9de (diff)
QmlDebugging: Process commands in v4DebugService
Change-Id: I6371db756f72ee373884268fc49a5b16cb66fd34 Reviewed-by: Kai Koehne <kai.koehne@digia.com>
-rw-r--r--src/qml/debugger/qv4debugservice.cpp188
-rw-r--r--src/qml/debugger/qv4debugservice_p.h12
-rw-r--r--src/qml/qml/qqmlengine.cpp4
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