aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/debugger/qv4debugservice.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/debugger/qv4debugservice.cpp')
-rw-r--r--src/qml/debugger/qv4debugservice.cpp501
1 files changed, 226 insertions, 275 deletions
diff --git a/src/qml/debugger/qv4debugservice.cpp b/src/qml/debugger/qv4debugservice.cpp
index 81d4c7b70a..19c06bffeb 100644
--- a/src/qml/debugger/qv4debugservice.cpp
+++ b/src/qml/debugger/qv4debugservice.cpp
@@ -32,9 +32,7 @@
****************************************************************************/
#include "qv4debugservice_p.h"
-#include "qqmlconfigurabledebugservice_p_p.h"
#include "qqmlengine.h"
-#include "qv4debugging_p.h"
#include "qv4engine_p.h"
#include "qv4function_p.h"
#include "qqmldebugconnector_p.h"
@@ -44,7 +42,6 @@
#include <QtCore/QJsonArray>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
-#include <QtCore/QJsonValue>
const char *const V4_CONNECT = "connect";
const char *const V4_DISCONNECT = "disconnect";
@@ -63,41 +60,6 @@ QT_BEGIN_NAMESPACE
Q_GLOBAL_STATIC(QV4DebugService, v4ServiceInstance)
-class QV4DebugServicePrivate;
-
-class QV4DebuggerAgent : public QV4::Debugging::DebuggerAgent
-{
-public:
- QV4DebuggerAgent(QV4DebugServicePrivate *debugServicePrivate)
- : debugServicePrivate(debugServicePrivate)
- {}
-
- QV4::Debugging::Debugger *firstDebugger() const
- {
- // Currently only 1 single engine is supported, so:
- if (m_debuggers.isEmpty())
- return 0;
- else
- return m_debuggers.first();
- }
-
- bool isRunning() const
- {
- // Currently only 1 single engine is supported, so:
- if (QV4::Debugging::Debugger *debugger = firstDebugger())
- return debugger->state() == QV4::Debugging::Debugger::Running;
- else
- return false;
- }
-
-public slots:
- virtual void debuggerPaused(QV4::Debugging::Debugger *debugger, QV4::Debugging::PauseReason reason);
- virtual void sourcesCollected(QV4::Debugging::Debugger *debugger, QStringList sources, int requestSequenceNr);
-
-private:
- QV4DebugServicePrivate *debugServicePrivate;
-};
-
class V8CommandHandler;
class UnknownV8CommandHandler;
@@ -343,164 +305,8 @@ private:
QHash<QV4::Object *, int> objectRefs;
};
-class QV4DebugServicePrivate : public QQmlConfigurableDebugServicePrivate
-{
- Q_DECLARE_PUBLIC(QV4DebugService)
-
-public:
- QV4DebugServicePrivate();
- ~QV4DebugServicePrivate() { qDeleteAll(handlers); }
-
- static QByteArray packMessage(const QByteArray &command, const QByteArray &message = QByteArray())
- {
- QByteArray reply;
- QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
- static const QByteArray cmd("V8DEBUG");
- rs << cmd << command << message;
- return reply;
- }
-
- void send(QJsonObject v8Payload)
- {
- v8Payload[QLatin1String("seq")] = sequence++;
- QJsonDocument doc;
- doc.setObject(v8Payload);
-#ifdef NO_PROTOCOL_TRACING
- QByteArray responseData = doc.toJson(QJsonDocument::Compact);
-#else
- QByteArray responseData = doc.toJson(QJsonDocument::Indented);
-#endif
-
- TRACE_PROTOCOL(qDebug() << "sending response for:" << responseData.constData() << endl);
-
- emit q_func()->messageToClient(name, packMessage("v8message", responseData));
- }
-
- void processCommand(const QByteArray &command, const QByteArray &data);
-
- QV4DebuggerAgent debuggerAgent;
-
- QStringList breakOnSignals;
- QMap<int, QV4::Debugging::Debugger *> debuggerMap;
- static int debuggerIndex;
- static int sequence;
- const int version;
-
- V8CommandHandler *v8CommandHandler(const QString &command) const;
-
- void clearHandles(QV4::ExecutionEngine *engine)
- {
- theCollector.reset(new VariableCollector(engine));
- }
-
- QJsonObject buildFrame(const QV4::StackFrame &stackFrame, int frameNr,
- QV4::Debugging::Debugger *debugger)
- {
- QJsonObject frame;
- frame[QLatin1String("index")] = frameNr;
- frame[QLatin1String("debuggerFrame")] = false;
- frame[QLatin1String("func")] = theCollector->addFunctionRef(stackFrame.function);
- frame[QLatin1String("script")] = theCollector->addScriptRef(stackFrame.source);
- frame[QLatin1String("line")] = stackFrame.line - 1;
- if (stackFrame.column >= 0)
- frame[QLatin1String("column")] = stackFrame.column;
-
- QJsonArray properties;
- theCollector->setDestination(&properties);
- if (debugger->collectThisInContext(theCollector.data(), frameNr)) {
- QJsonObject obj;
- obj[QLatin1String("properties")] = properties;
- frame[QLatin1String("receiver")] = theCollector->addObjectRef(obj, false);
- }
-
- QJsonArray scopes;
- // Only type and index are used by Qt Creator, so we keep it easy:
- QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes = debugger->getScopeTypes(frameNr);
- for (int i = 0, ei = scopeTypes.count(); i != ei; ++i) {
- int type = encodeScopeType(scopeTypes[i]);
- if (type == -1)
- continue;
-
- QJsonObject scope;
- scope[QLatin1String("index")] = i;
- scope[QLatin1String("type")] = type;
- scopes.push_back(scope);
- }
- frame[QLatin1String("scopes")] = scopes;
-
- return frame;
- }
-
- int encodeScopeType(QV4::Heap::ExecutionContext::ContextType scopeType)
- {
- switch (scopeType) {
- case QV4::Heap::ExecutionContext::Type_GlobalContext:
- return 0;
- break;
- case QV4::Heap::ExecutionContext::Type_CatchContext:
- return 4;
- break;
- case QV4::Heap::ExecutionContext::Type_WithContext:
- return 2;
- break;
- case QV4::Heap::ExecutionContext::Type_SimpleCallContext:
- case QV4::Heap::ExecutionContext::Type_CallContext:
- return 1;
- break;
- case QV4::Heap::ExecutionContext::Type_QmlContext:
- default:
- return -1;
- }
- }
-
- QJsonObject buildScope(int frameNr, int scopeNr, QV4::Debugging::Debugger *debugger)
- {
- QJsonObject scope;
-
- QJsonArray properties;
- theCollector->collectScope(&properties, debugger, frameNr, scopeNr);
-
- QJsonObject anonymous;
- anonymous[QLatin1String("properties")] = properties;
-
- QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes = debugger->getScopeTypes(frameNr);
- scope[QLatin1String("type")] = encodeScopeType(scopeTypes[scopeNr]);
- scope[QLatin1String("index")] = scopeNr;
- scope[QLatin1String("frameIndex")] = frameNr;
- scope[QLatin1String("object")] = theCollector->addObjectRef(anonymous, true);
-
- return scope;
- }
-
- QJsonValue lookup(int refId) const { return theCollector->lookup(refId); }
-
- QJsonArray buildRefs()
- {
- return theCollector->retrieveRefsToInclude();
- }
-
- VariableCollector *collector() const
- {
- return theCollector.data();
- }
-
- void selectFrame(int frameNr)
- { theSelectedFrame = frameNr; }
-
- int selectedFrame() const
- { return theSelectedFrame; }
-
-private:
- QScopedPointer<VariableCollector> theCollector;
- int theSelectedFrame;
-
- void addHandler(V8CommandHandler* handler);
- QHash<QString, V8CommandHandler*> handlers;
- QScopedPointer<UnknownV8CommandHandler> unknownV8CommandHandler;
-};
-
-int QV4DebugServicePrivate::debuggerIndex = 0;
-int QV4DebugServicePrivate::sequence = 0;
+int QV4DebugService::debuggerIndex = 0;
+int QV4DebugService::sequence = 0;
class V8CommandHandler
{
@@ -514,22 +320,20 @@ public:
QString command() const { return cmd; }
- void handle(const QJsonObject &request, QQmlDebugService *s, QV4DebugServicePrivate *p)
+ void handle(const QJsonObject &request, QV4DebugService *s)
{
TRACE_PROTOCOL(qDebug() << "handling command" << command() << "...");
req = request;
seq = req.value(QStringLiteral("seq"));
debugService = s;
- debugServicePrivate = p;
handleRequest();
if (!response.isEmpty()) {
response[QLatin1String("type")] = QStringLiteral("response");
- debugServicePrivate->send(response);
+ debugService->send(response);
}
- debugServicePrivate = 0;
debugService = 0;
seq = QJsonValue();
req = QJsonObject();
@@ -549,12 +353,12 @@ protected:
void addRunning()
{
- response.insert(QStringLiteral("running"), debugServicePrivate->debuggerAgent.isRunning());
+ response.insert(QStringLiteral("running"), debugService->debuggerAgent.isRunning());
}
void addRefs()
{
- response.insert(QStringLiteral("refs"), debugServicePrivate->buildRefs());
+ response.insert(QStringLiteral("refs"), debugService->buildRefs());
}
void createErrorResponse(const QString &msg)
@@ -574,8 +378,7 @@ protected:
QString cmd;
QJsonObject req;
QJsonValue seq;
- QQmlDebugService *debugService;
- QV4DebugServicePrivate *debugServicePrivate;
+ QV4DebugService *debugService;
QJsonObject response;
};
@@ -646,7 +449,7 @@ public:
QString condition = args.value(QStringLiteral("condition")).toString();
// set the break point:
- int id = debugServicePrivate->debuggerAgent.addBreakPoint(fileName, line + 1, enabled, condition);
+ int id = debugService->debuggerAgent.addBreakPoint(fileName, line + 1, enabled, condition);
// response:
addCommand();
@@ -682,7 +485,7 @@ public:
}
// remove the break point:
- debugServicePrivate->debuggerAgent.removeBreakPoint(id);
+ debugService->debuggerAgent.removeBreakPoint(id);
// response:
addCommand();
@@ -710,12 +513,12 @@ public:
int toFrame = arguments.value(QStringLiteral("toFrame")).toInt(fromFrame + 10);
// no idea what the bottom property is for, so we'll ignore it.
- QV4::Debugging::Debugger *debugger = debugServicePrivate->debuggerAgent.firstDebugger();
+ QV4::Debugging::Debugger *debugger = debugService->debuggerAgent.firstDebugger();
QJsonArray frameArray;
QVector<QV4::StackFrame> frames = debugger->stackTrace(toFrame);
for (int i = fromFrame; i < toFrame && i < frames.size(); ++i)
- frameArray.push_back(debugServicePrivate->buildFrame(frames[i], i, debugger));
+ frameArray.push_back(debugService->buildFrame(frames[i], i, debugger));
// response:
addCommand();
@@ -744,17 +547,18 @@ public:
{
// decypher the payload:
QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- const int frameNr = arguments.value(QStringLiteral("number")).toInt(debugServicePrivate->selectedFrame());
+ const int frameNr = arguments.value(QStringLiteral("number")).toInt(
+ debugService->selectedFrame());
- QV4::Debugging::Debugger *debugger = debugServicePrivate->debuggerAgent.firstDebugger();
+ QV4::Debugging::Debugger *debugger = debugService->debuggerAgent.firstDebugger();
QVector<QV4::StackFrame> frames = debugger->stackTrace(frameNr + 1);
if (frameNr < 0 || frameNr >= frames.size()) {
createErrorResponse(QStringLiteral("frame command has invalid frame number"));
return;
}
- debugServicePrivate->selectFrame(frameNr);
- QJsonObject frame = debugServicePrivate->buildFrame(frames[frameNr], frameNr, debugger);
+ debugService->selectFrame(frameNr);
+ QJsonObject frame = debugService->buildFrame(frames[frameNr], frameNr, debugger);
// response:
addCommand();
@@ -775,10 +579,11 @@ public:
{
// decypher the payload:
QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- const int frameNr = arguments.value(QStringLiteral("frameNumber")).toInt(debugServicePrivate->selectedFrame());
+ const int frameNr = arguments.value(QStringLiteral("frameNumber")).toInt(
+ debugService->selectedFrame());
const int scopeNr = arguments.value(QStringLiteral("number")).toInt(0);
- QV4::Debugging::Debugger *debugger = debugServicePrivate->debuggerAgent.firstDebugger();
+ QV4::Debugging::Debugger *debugger = debugService->debuggerAgent.firstDebugger();
QVector<QV4::StackFrame> frames = debugger->stackTrace(frameNr + 1);
if (frameNr < 0 || frameNr >= frames.size()) {
createErrorResponse(QStringLiteral("scope command has invalid frame number"));
@@ -789,7 +594,7 @@ public:
return;
}
- QJsonObject scope = debugServicePrivate->buildScope(frameNr, scopeNr, debugger);
+ QJsonObject scope = debugService->buildScope(frameNr, scopeNr, debugger);
// response:
addCommand();
@@ -814,7 +619,7 @@ public:
QJsonObject body;
foreach (const QJsonValue &handle, handles)
- body[QString::number(handle.toInt())] = debugServicePrivate->lookup(handle.toInt());
+ body[QString::number(handle.toInt())] = debugService->lookup(handle.toInt());
// response:
addCommand();
@@ -836,7 +641,7 @@ public:
// decypher the payload:
QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- QV4::Debugging::Debugger *debugger = debugServicePrivate->debuggerAgent.firstDebugger();
+ QV4::Debugging::Debugger *debugger = debugService->debuggerAgent.firstDebugger();
if (arguments.empty()) {
debugger->resume(QV4::Debugging::Debugger::FullThrottle);
@@ -874,8 +679,8 @@ public:
virtual void handleRequest()
{
- debugServicePrivate->debuggerAgent.removeAllBreakPoints();
- debugServicePrivate->debuggerAgent.resumeAll();
+ debugService->debuggerAgent.removeAllBreakPoints();
+ debugService->debuggerAgent.resumeAll();
// response:
addCommand();
@@ -892,7 +697,7 @@ public:
virtual void handleRequest()
{
- bool wasEnabled = debugServicePrivate->debuggerAgent.breakOnThrow();
+ bool wasEnabled = debugService->debuggerAgent.breakOnThrow();
//decypher the payload:
QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
@@ -910,11 +715,11 @@ public:
}
// do it:
- debugServicePrivate->debuggerAgent.setBreakOnThrow(enabled);
+ debugService->debuggerAgent.setBreakOnThrow(enabled);
QJsonObject body;
body[QLatin1String("type")] = type;
- body[QLatin1String("enabled")] = debugServicePrivate->debuggerAgent.breakOnThrow();
+ body[QLatin1String("enabled")] = debugService->debuggerAgent.breakOnThrow();
// response:
addBody(body);
@@ -944,7 +749,7 @@ public:
}
// do it:
- debugServicePrivate->debuggerAgent.firstDebugger()->gatherSources(requestSequenceNr());
+ debugService->debuggerAgent.firstDebugger()->gatherSources(requestSequenceNr());
// response will be send by
}
@@ -990,10 +795,10 @@ public:
QString expression = arguments.value(QStringLiteral("expression")).toString();
const int frame = arguments.value(QStringLiteral("frame")).toInt(0);
- QV4::Debugging::Debugger *debugger = debugServicePrivate->debuggerAgent.firstDebugger();
+ QV4::Debugging::Debugger *debugger = debugService->debuggerAgent.firstDebugger();
Q_ASSERT(debugger->state() == QV4::Debugging::Debugger::Paused);
- VariableCollector *collector = debugServicePrivate->collector();
+ VariableCollector *collector = debugService->collector();
QJsonArray dest;
collector->setDestination(&dest);
debugger->evaluateExpression(frame, expression, collector);
@@ -1012,8 +817,22 @@ public:
};
} // anonymous namespace
-QV4DebugServicePrivate::QV4DebugServicePrivate() :
- QQmlConfigurableDebugServicePrivate(QStringLiteral("V8Debugger"), 1), debuggerAgent(this),
+void QV4DebugService::addHandler(V8CommandHandler* handler)
+{
+ handlers[handler->command()] = handler;
+}
+
+V8CommandHandler *QV4DebugService::v8CommandHandler(const QString &command) const
+{
+ V8CommandHandler *handler = handlers.value(command, 0);
+ if (handler)
+ return handler;
+ else
+ return unknownV8CommandHandler.data();
+}
+
+QV4DebugService::QV4DebugService(QObject *parent) :
+ QQmlConfigurableDebugService(QStringLiteral("V8Debugger"), 1, parent), debuggerAgent(this),
version(1), theSelectedFrame(0), unknownV8CommandHandler(new UnknownV8CommandHandler)
{
addHandler(new V8VersionRequest);
@@ -1030,26 +849,9 @@ QV4DebugServicePrivate::QV4DebugServicePrivate() :
addHandler(new V8EvaluateRequest);
}
-void QV4DebugServicePrivate::addHandler(V8CommandHandler* handler)
-{
- handlers[handler->command()] = handler;
-}
-
-V8CommandHandler *QV4DebugServicePrivate::v8CommandHandler(const QString &command) const
-{
- V8CommandHandler *handler = handlers.value(command, 0);
- if (handler)
- return handler;
- else
- return unknownV8CommandHandler.data();
-}
-
-QV4DebugService::QV4DebugService(QObject *parent)
- : QQmlConfigurableDebugService(*(new QV4DebugServicePrivate()), parent)
-{}
-
QV4DebugService::~QV4DebugService()
{
+ qDeleteAll(handlers);
}
QV4DebugService *QV4DebugService::instance()
@@ -1059,17 +861,16 @@ QV4DebugService *QV4DebugService::instance()
void QV4DebugService::engineAboutToBeAdded(QQmlEngine *engine)
{
- Q_D(QV4DebugService);
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
if (engine) {
QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
if (QQmlDebugConnector *server = QQmlDebugConnector::instance()) {
if (ee) {
ee->enableDebugger();
QV4::Debugging::Debugger *debugger = ee->debugger;
- d->debuggerMap.insert(d->debuggerIndex++, debugger);
- d->debuggerAgent.addDebugger(debugger);
- d->debuggerAgent.moveToThread(server->thread());
+ debuggerMap.insert(debuggerIndex++, debugger);
+ debuggerAgent.addDebugger(debugger);
+ debuggerAgent.moveToThread(server->thread());
moveToThread(server->thread());
}
}
@@ -1079,21 +880,20 @@ void QV4DebugService::engineAboutToBeAdded(QQmlEngine *engine)
void QV4DebugService::engineAboutToBeRemoved(QQmlEngine *engine)
{
- Q_D(QV4DebugService);
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
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) {
+ const DebuggerMapIterator end = debuggerMap.constEnd();
+ for (DebuggerMapIterator i = debuggerMap.constBegin(); i != end; ++i) {
if (i.value() == debugger) {
- d->debuggerMap.remove(i.key());
+ debuggerMap.remove(i.key());
break;
}
}
- d->debuggerAgent.removeDebugger(debugger);
+ debuggerAgent.removeDebugger(debugger);
}
}
QQmlConfigurableDebugService::engineAboutToBeRemoved(engine);
@@ -1104,13 +904,12 @@ void QV4DebugService::signalEmitted(const QString &signal)
//This function is only called by QQmlBoundSignal
//only if there is a slot connected to the signal. Hence, there
//is no need for additional check.
- Q_D(QV4DebugService);
//Parse just the name and remove the class info
//Normalize to Lower case.
QString signalName = signal.left(signal.indexOf(QLatin1Char('('))).toLower();
- foreach (const QString &signal, d->breakOnSignals) {
+ foreach (const QString &signal, breakOnSignals) {
if (signal == signalName) {
// TODO: pause debugger
break;
@@ -1120,8 +919,7 @@ void QV4DebugService::signalEmitted(const QString &signal)
void QV4DebugService::messageReceived(const QByteArray &message)
{
- Q_D(QV4DebugService);
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
QQmlDebugStream ms(message);
QByteArray header;
@@ -1136,10 +934,10 @@ void QV4DebugService::messageReceived(const QByteArray &message)
TRACE_PROTOCOL(qDebug() << "... type:" << type);
if (type == V4_CONNECT) {
- emit messageToClient(name(), d->packMessage(type));
+ emit messageToClient(name(), packMessage(type));
stopWaiting();
} else if (type == V4_PAUSE) {
- d->debuggerAgent.pauseAll();
+ debuggerAgent.pauseAll();
sendSomethingToSomebody(type);
} else if (type == V4_BREAK_ON_SIGNAL) {
QByteArray signal;
@@ -1148,9 +946,9 @@ void QV4DebugService::messageReceived(const QByteArray &message)
//Normalize to lower case.
QString signalName(QString::fromUtf8(signal).toLower());
if (enabled)
- d->breakOnSignals.append(signalName);
+ breakOnSignals.append(signalName);
else
- d->breakOnSignals.removeOne(signalName);
+ breakOnSignals.removeOne(signalName);
} else if (type == "v8request") {
handleV8Request(payload);
} else if (type == V4_DISCONNECT) {
@@ -1164,20 +962,40 @@ void QV4DebugService::messageReceived(const QByteArray &message)
void QV4DebugService::sendSomethingToSomebody(const char *type, int magicNumber)
{
- Q_D(QV4DebugService);
-
QByteArray response;
QQmlDebugStream rs(&response, QIODevice::WriteOnly);
rs << QByteArray(type)
- << QByteArray::number(d->version) << QByteArray::number(magicNumber);
- emit messageToClient(name(), d->packMessage(type, response));
+ << QByteArray::number(version) << QByteArray::number(magicNumber);
+ emit messageToClient(name(), packMessage(type, response));
+}
+
+QV4DebuggerAgent::QV4DebuggerAgent(QV4DebugService *debugService)
+ : debugService(debugService)
+{}
+
+QV4::Debugging::Debugger *QV4DebuggerAgent::firstDebugger() const
+{
+ // Currently only 1 single engine is supported, so:
+ if (m_debuggers.isEmpty())
+ return 0;
+ else
+ return m_debuggers.first();
+}
+
+bool QV4DebuggerAgent::isRunning() const
+{
+ // Currently only 1 single engine is supported, so:
+ if (QV4::Debugging::Debugger *debugger = firstDebugger())
+ return debugger->state() == QV4::Debugging::Debugger::Running;
+ else
+ return false;
}
void QV4DebuggerAgent::debuggerPaused(QV4::Debugging::Debugger *debugger, QV4::Debugging::PauseReason reason)
{
Q_UNUSED(reason);
- debugServicePrivate->clearHandles(debugger->engine());
+ debugService->clearHandles(debugger->engine());
QJsonObject event, body, script;
event.insert(QStringLiteral("type"), QStringLiteral("event"));
@@ -1212,7 +1030,7 @@ void QV4DebuggerAgent::debuggerPaused(QV4::Debugging::Debugger *debugger, QV4::D
body.insert(QStringLiteral("script"), script);
if (!body.isEmpty())
event.insert(QStringLiteral("body"), body);
- debugServicePrivate->send(event);
+ debugService->send(event);
}
void QV4DebuggerAgent::sourcesCollected(QV4::Debugging::Debugger *debugger, QStringList sources, int requestSequenceNr)
@@ -1232,13 +1050,11 @@ void QV4DebuggerAgent::sourcesCollected(QV4::Debugging::Debugger *debugger, QStr
response[QLatin1String("command")] = QStringLiteral("scripts");
response[QLatin1String("request_seq")] = requestSequenceNr;
response[QLatin1String("type")] = QStringLiteral("response");
- debugServicePrivate->send(response);
+ debugService->send(response);
}
void QV4DebugService::handleV8Request(const QByteArray &payload)
{
- Q_D(QV4DebugService);
-
TRACE_PROTOCOL(qDebug() << "v8request, payload:" << payload.constData());
QJsonDocument request = QJsonDocument::fromJson(payload);
@@ -1246,10 +1062,145 @@ void QV4DebugService::handleV8Request(const QByteArray &payload)
QJsonValue type = o.value(QStringLiteral("type"));
if (type.toString() == QStringLiteral("request")) {
QJsonValue command = o.value(QStringLiteral("command"));
- V8CommandHandler *h = d->v8CommandHandler(command.toString());
+ V8CommandHandler *h = v8CommandHandler(command.toString());
if (h)
- h->handle(o, this, d);
+ h->handle(o, this);
+ }
+}
+
+QByteArray QV4DebugService::packMessage(const QByteArray &command, const QByteArray &message)
+{
+ QByteArray reply;
+ QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
+ static const QByteArray cmd("V8DEBUG");
+ rs << cmd << command << message;
+ return reply;
+}
+
+void QV4DebugService::send(QJsonObject v8Payload)
+{
+ v8Payload[QLatin1String("seq")] = sequence++;
+ QJsonDocument doc;
+ doc.setObject(v8Payload);
+#ifdef NO_PROTOCOL_TRACING
+ QByteArray responseData = doc.toJson(QJsonDocument::Compact);
+#else
+ QByteArray responseData = doc.toJson(QJsonDocument::Indented);
+#endif
+
+ TRACE_PROTOCOL(qDebug() << "sending response for:" << responseData.constData() << endl);
+
+ emit messageToClient(name(), packMessage("v8message", responseData));
+}
+
+void QV4DebugService::clearHandles(QV4::ExecutionEngine *engine)
+{
+ theCollector.reset(new VariableCollector(engine));
+}
+
+QJsonObject QV4DebugService::buildFrame(const QV4::StackFrame &stackFrame, int frameNr,
+ QV4::Debugging::Debugger *debugger)
+{
+ QJsonObject frame;
+ frame[QLatin1String("index")] = frameNr;
+ frame[QLatin1String("debuggerFrame")] = false;
+ frame[QLatin1String("func")] = theCollector->addFunctionRef(stackFrame.function);
+ frame[QLatin1String("script")] = theCollector->addScriptRef(stackFrame.source);
+ frame[QLatin1String("line")] = stackFrame.line - 1;
+ if (stackFrame.column >= 0)
+ frame[QLatin1String("column")] = stackFrame.column;
+
+ QJsonArray properties;
+ theCollector->setDestination(&properties);
+ if (debugger->collectThisInContext(theCollector.data(), frameNr)) {
+ QJsonObject obj;
+ obj[QLatin1String("properties")] = properties;
+ frame[QLatin1String("receiver")] = theCollector->addObjectRef(obj, false);
}
+
+ QJsonArray scopes;
+ // Only type and index are used by Qt Creator, so we keep it easy:
+ QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes = debugger->getScopeTypes(frameNr);
+ for (int i = 0, ei = scopeTypes.count(); i != ei; ++i) {
+ int type = encodeScopeType(scopeTypes[i]);
+ if (type == -1)
+ continue;
+
+ QJsonObject scope;
+ scope[QLatin1String("index")] = i;
+ scope[QLatin1String("type")] = type;
+ scopes.push_back(scope);
+ }
+ frame[QLatin1String("scopes")] = scopes;
+
+ return frame;
+}
+
+int QV4DebugService::encodeScopeType(QV4::Heap::ExecutionContext::ContextType scopeType)
+{
+ switch (scopeType) {
+ case QV4::Heap::ExecutionContext::Type_GlobalContext:
+ return 0;
+ break;
+ case QV4::Heap::ExecutionContext::Type_CatchContext:
+ return 4;
+ break;
+ case QV4::Heap::ExecutionContext::Type_WithContext:
+ return 2;
+ break;
+ case QV4::Heap::ExecutionContext::Type_SimpleCallContext:
+ case QV4::Heap::ExecutionContext::Type_CallContext:
+ return 1;
+ break;
+ case QV4::Heap::ExecutionContext::Type_QmlContext:
+ default:
+ return -1;
+ }
+}
+
+QJsonObject QV4DebugService::buildScope(int frameNr, int scopeNr,
+ QV4::Debugging::Debugger *debugger)
+{
+ QJsonObject scope;
+
+ QJsonArray properties;
+ theCollector->collectScope(&properties, debugger, frameNr, scopeNr);
+
+ QJsonObject anonymous;
+ anonymous[QLatin1String("properties")] = properties;
+
+ QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes = debugger->getScopeTypes(frameNr);
+ scope[QLatin1String("type")] = encodeScopeType(scopeTypes[scopeNr]);
+ scope[QLatin1String("index")] = scopeNr;
+ scope[QLatin1String("frameIndex")] = frameNr;
+ scope[QLatin1String("object")] = theCollector->addObjectRef(anonymous, true);
+
+ return scope;
+}
+
+QJsonValue QV4DebugService::lookup(int refId) const
+{
+ return theCollector->lookup(refId);
+}
+
+QJsonArray QV4DebugService::buildRefs()
+{
+ return theCollector->retrieveRefsToInclude();
+}
+
+VariableCollector *QV4DebugService::collector() const
+{
+ return theCollector.data();
+}
+
+void QV4DebugService::selectFrame(int frameNr)
+{
+ theSelectedFrame = frameNr;
+}
+
+int QV4DebugService::selectedFrame() const
+{
+ return theSelectedFrame;
}
QT_END_NAMESPACE