aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp')
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp292
1 files changed, 151 insertions, 141 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
index 168a08865c..5866163ca6 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
@@ -40,13 +40,12 @@
#include "qv4debugservice.h"
#include "qv4debugjob.h"
#include "qqmlengine.h"
-#include "qqmldebugpacket.h"
#include <private/qv4engine_p.h>
-#include <private/qv4isel_moth_p.h>
#include <private/qv4function_p.h>
#include <private/qqmldebugconnector_p.h>
#include <private/qv8engine_p.h>
+#include <private/qversionedpacket_p.h>
#include <QtCore/QJsonArray>
#include <QtCore/QJsonDocument>
@@ -68,19 +67,21 @@ const char *const V4_PAUSE = "interrupt";
QT_BEGIN_NAMESPACE
-class V8CommandHandler;
-class UnknownV8CommandHandler;
+class V4CommandHandler;
+class UnknownV4CommandHandler;
+
+using QQmlDebugPacket = QVersionedPacket<QQmlDebugConnector>;
int QV4DebugServiceImpl::sequence = 0;
-class V8CommandHandler
+class V4CommandHandler
{
public:
- V8CommandHandler(const QString &command)
+ V4CommandHandler(const QString &command)
: cmd(command)
{}
- virtual ~V8CommandHandler()
+ virtual ~V4CommandHandler()
{}
QString command() const { return cmd; }
@@ -99,7 +100,7 @@ public:
debugService->send(response);
}
- debugService = 0;
+ debugService = nullptr;
seq = QJsonValue();
req = QJsonObject();
response = QJsonObject();
@@ -121,21 +122,6 @@ protected:
response.insert(QStringLiteral("running"), debugService->debuggerAgent.isRunning());
}
- QV4DataCollector *saneCollector(QV4Debugger *debugger)
- {
- QV4DataCollector *collector = debugger->collector();
- collector->setNamesAsObjects(debugService->clientRequiresNamesAsObjects());
- collector->setRedundantRefs(debugService->clientRequiresRedundantRefs());
- return collector;
- }
-
- // TODO: drop this method once we don't need to support redundantRefs anymore.
- void addRefs(const QJsonArray &refs)
- {
- Q_ASSERT(debugService->clientRequiresRedundantRefs());
- response.insert(QStringLiteral("refs"), refs);
- }
-
void createErrorResponse(const QString &msg)
{
QJsonValue command = req.value(QLatin1String("command"));
@@ -157,10 +143,10 @@ protected:
QJsonObject response;
};
-class UnknownV8CommandHandler: public V8CommandHandler
+class UnknownV4CommandHandler: public V4CommandHandler
{
public:
- UnknownV8CommandHandler(): V8CommandHandler(QString()) {}
+ UnknownV4CommandHandler(): V4CommandHandler(QString()) {}
void handleRequest() override
{
@@ -172,10 +158,10 @@ public:
};
namespace {
-class V8VersionRequest: public V8CommandHandler
+class V4VersionRequest: public V4CommandHandler
{
public:
- V8VersionRequest(): V8CommandHandler(QStringLiteral("version")) {}
+ V4VersionRequest(): V4CommandHandler(QStringLiteral("version")) {}
void handleRequest() override
{
@@ -188,98 +174,137 @@ public:
QLatin1String("this is not V8, this is V4 in Qt " QT_VERSION_STR));
body.insert(QStringLiteral("UnpausedEvaluate"), true);
body.insert(QStringLiteral("ContextEvaluate"), true);
+ body.insert(QStringLiteral("ChangeBreakpoint"), true);
addBody(body);
}
};
-class V8SetBreakPointRequest: public V8CommandHandler
+class V4BreakPointRequest: public V4CommandHandler
{
public:
- V8SetBreakPointRequest(): V8CommandHandler(QStringLiteral("setbreakpoint")) {}
+ V4BreakPointRequest(const QString &name): V4CommandHandler(name) {}
- void handleRequest() override
+ void handleRequest() final
{
+ // Other types are currently not supported
+ m_type = QStringLiteral("scriptRegExp");
+
// decypher the payload:
- QJsonObject args = req.value(QLatin1String("arguments")).toObject();
- if (args.isEmpty())
+ m_args = req.value(QLatin1String("arguments")).toObject();
+ if (m_args.isEmpty()) {
+ createErrorResponse(QStringLiteral("breakpoint request with empty arguments object"));
return;
+ }
+
+ const int id = handleBreakPointRequest();
+ if (id < 0) {
+ createErrorResponse(m_error);
+ } else {
+ // response:
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ QJsonObject body;
+ body.insert(QStringLiteral("type"), m_type);
+ body.insert(QStringLiteral("breakpoint"), id);
+ addBody(body);
+ }
+ }
+
+protected:
+ virtual int handleBreakPointRequest() = 0;
- QString type = args.value(QLatin1String("type")).toString();
+ QJsonObject m_args;
+ QString m_type;
+ QString m_error;
+};
+
+class V4SetBreakPointRequest: public V4BreakPointRequest
+{
+public:
+ V4SetBreakPointRequest(): V4BreakPointRequest(QStringLiteral("setbreakpoint")) {}
+
+ int handleBreakPointRequest() final
+ {
+ // decypher the payload:
+ const QString type = m_args.value(QLatin1String("type")).toString();
if (type != QLatin1String("scriptRegExp")) {
- createErrorResponse(QStringLiteral("breakpoint type \"%1\" is not implemented").arg(type));
- return;
+ m_error = QStringLiteral("breakpoint type \"%1\" is not implemented").arg(type);
+ return -1;
}
- QString fileName = args.value(QLatin1String("target")).toString();
+ const QString fileName = m_args.value(QLatin1String("target")).toString();
if (fileName.isEmpty()) {
- createErrorResponse(QStringLiteral("breakpoint has no file name"));
- return;
+ m_error = QStringLiteral("breakpoint has no file name");
+ return -1;
}
- int line = args.value(QLatin1String("line")).toInt(-1);
+
+ const int line = m_args.value(QLatin1String("line")).toInt(-1);
if (line < 0) {
- createErrorResponse(QStringLiteral("breakpoint has an invalid line number"));
- return;
+ m_error = QStringLiteral("breakpoint has an invalid line number");
+ return -1;
}
- bool enabled = args.value(QStringLiteral("enabled")).toBool(true);
- QString condition = args.value(QStringLiteral("condition")).toString();
+ const bool enabled = m_args.value(QStringLiteral("enabled")).toBool(true);
+ const QString condition = m_args.value(QStringLiteral("condition")).toString();
// set the break point:
- int id = debugService->debuggerAgent.addBreakPoint(fileName, line + 1, enabled, condition);
+ return debugService->debuggerAgent.addBreakPoint(fileName, line + 1, enabled, condition);
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- QJsonObject body;
- body.insert(QStringLiteral("type"), type);
- body.insert(QStringLiteral("breakpoint"), id);
// It's undocumented, but V8 sends back an actual_locations array too. However, our
// Debugger currently doesn't tell us when it resolved a breakpoint, so we'll leave them
// pending until the breakpoint is hit for the first time.
- addBody(body);
}
};
-class V8ClearBreakPointRequest: public V8CommandHandler
+class V4ClearBreakPointRequest: public V4BreakPointRequest
{
public:
- V8ClearBreakPointRequest(): V8CommandHandler(QStringLiteral("clearbreakpoint")) {}
+ V4ClearBreakPointRequest(): V4BreakPointRequest(QStringLiteral("clearbreakpoint")) {}
- void handleRequest() override
+ int handleBreakPointRequest() final
{
- // decypher the payload:
- QJsonObject args = req.value(QLatin1String("arguments")).toObject();
- if (args.isEmpty())
- return;
+ const int id = m_args.value(QLatin1String("breakpoint")).toInt(-1);
+ if (id < 0)
+ m_error = QStringLiteral("breakpoint has an invalid number");
+ else // remove the break point:
+ debugService->debuggerAgent.removeBreakPoint(id);
- int id = args.value(QLatin1String("breakpoint")).toInt(-1);
+ return id;
+ }
+};
+
+class V4ChangeBreakPointRequest: public V4BreakPointRequest
+{
+public:
+ V4ChangeBreakPointRequest(): V4BreakPointRequest(QStringLiteral("changebreakpoint")) {}
+
+ int handleBreakPointRequest() final
+ {
+ const int id = m_args.value(QLatin1String("breakpoint")).toInt(-1);
if (id < 0) {
- createErrorResponse(QStringLiteral("breakpoint has an invalid number"));
- return;
+ m_error = QStringLiteral("breakpoint has an invalid number");
+ return id;
}
- // remove the break point:
- debugService->debuggerAgent.removeBreakPoint(id);
+ const QJsonValue enabled = m_args.value(QLatin1String("enabled"));
+ if (!enabled.isBool()) {
+ m_error = QStringLiteral("missing bool \"enabled\" in breakpoint change request");
+ return -1;
+ }
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- QJsonObject body;
- body.insert(QStringLiteral("type"), QStringLiteral("scriptRegExp"));
- body.insert(QStringLiteral("breakpoint"), id);
- addBody(body);
+ // enable or disable the break point:
+ debugService->debuggerAgent.enableBreakPoint(id, enabled.toBool());
+ return id;
}
};
-class V8BacktraceRequest: public V8CommandHandler
+class V4BacktraceRequest: public V4CommandHandler
{
public:
- V8BacktraceRequest(): V8CommandHandler(QStringLiteral("backtrace")) {}
+ V4BacktraceRequest(): V4CommandHandler(QStringLiteral("backtrace")) {}
void handleRequest() override
{
@@ -296,7 +321,7 @@ public:
return;
}
- BacktraceJob job(saneCollector(debugger), fromFrame, toFrame);
+ BacktraceJob job(debugger->collector(), fromFrame, toFrame);
debugger->runInEngine(&job);
// response:
@@ -305,15 +330,13 @@ public:
addSuccess(true);
addRunning();
addBody(job.returnValue());
- if (debugService->clientRequiresRedundantRefs())
- addRefs(job.refs());
}
};
-class V8FrameRequest: public V8CommandHandler
+class V4FrameRequest: public V4CommandHandler
{
public:
- V8FrameRequest(): V8CommandHandler(QStringLiteral("frame")) {}
+ V4FrameRequest(): V4CommandHandler(QStringLiteral("frame")) {}
void handleRequest() override
{
@@ -333,7 +356,7 @@ public:
return;
}
- FrameJob job(saneCollector(debugger), frameNr);
+ FrameJob job(debugger->collector(), frameNr);
debugger->runInEngine(&job);
if (!job.wasSuccessful()) {
createErrorResponse(QStringLiteral("frame retrieval failed"));
@@ -348,15 +371,13 @@ public:
addSuccess(true);
addRunning();
addBody(job.returnValue());
- if (debugService->clientRequiresRedundantRefs())
- addRefs(job.refs());
}
};
-class V8ScopeRequest: public V8CommandHandler
+class V4ScopeRequest: public V4CommandHandler
{
public:
- V8ScopeRequest(): V8CommandHandler(QStringLiteral("scope")) {}
+ V4ScopeRequest(): V4CommandHandler(QStringLiteral("scope")) {}
void handleRequest() override
{
@@ -381,7 +402,7 @@ public:
return;
}
- ScopeJob job(saneCollector(debugger), frameNr, scopeNr);
+ ScopeJob job(debugger->collector(), frameNr, scopeNr);
debugger->runInEngine(&job);
if (!job.wasSuccessful()) {
createErrorResponse(QStringLiteral("scope retrieval failed"));
@@ -394,15 +415,13 @@ public:
addSuccess(true);
addRunning();
addBody(job.returnValue());
- if (debugService->clientRequiresRedundantRefs())
- addRefs(job.refs());
}
};
-class V8LookupRequest: public V8CommandHandler
+class V4LookupRequest: public V4CommandHandler
{
public:
- V8LookupRequest(): V8CommandHandler(QStringLiteral("lookup")) {}
+ V4LookupRequest(): V4CommandHandler(QStringLiteral("lookup")) {}
void handleRequest() override
{
@@ -423,7 +442,7 @@ public:
debugger = debuggers.first();
}
- ValueLookupJob job(handles, saneCollector(debugger));
+ ValueLookupJob job(handles, debugger->collector());
debugger->runInEngine(&job);
if (!job.exceptionMessage().isEmpty()) {
createErrorResponse(job.exceptionMessage());
@@ -434,16 +453,14 @@ public:
addSuccess(true);
addRunning();
addBody(job.returnValue());
- if (debugService->clientRequiresRedundantRefs())
- addRefs(job.refs());
}
}
};
-class V8ContinueRequest: public V8CommandHandler
+class V4ContinueRequest: public V4CommandHandler
{
public:
- V8ContinueRequest(): V8CommandHandler(QStringLiteral("continue")) {}
+ V4ContinueRequest(): V4CommandHandler(QStringLiteral("continue")) {}
void handleRequest() override
{
@@ -486,10 +503,10 @@ public:
}
};
-class V8DisconnectRequest: public V8CommandHandler
+class V4DisconnectRequest: public V4CommandHandler
{
public:
- V8DisconnectRequest(): V8CommandHandler(QStringLiteral("disconnect")) {}
+ V4DisconnectRequest(): V4CommandHandler(QStringLiteral("disconnect")) {}
void handleRequest() override
{
@@ -504,10 +521,10 @@ public:
}
};
-class V8SetExceptionBreakRequest: public V8CommandHandler
+class V4SetExceptionBreakRequest: public V4CommandHandler
{
public:
- V8SetExceptionBreakRequest(): V8CommandHandler(QStringLiteral("setexceptionbreak")) {}
+ V4SetExceptionBreakRequest(): V4CommandHandler(QStringLiteral("setexceptionbreak")) {}
void handleRequest() override
{
@@ -544,10 +561,10 @@ public:
}
};
-class V8ScriptsRequest: public V8CommandHandler
+class V4ScriptsRequest: public V4CommandHandler
{
public:
- V8ScriptsRequest(): V8CommandHandler(QStringLiteral("scripts")) {}
+ V4ScriptsRequest(): V4CommandHandler(QStringLiteral("scripts")) {}
void handleRequest() override
{
@@ -616,10 +633,10 @@ public:
// }
//
// The "value" key in "body" is the result of evaluating the expression in the request.
-class V8EvaluateRequest: public V8CommandHandler
+class V4EvaluateRequest: public V4CommandHandler
{
public:
- V8EvaluateRequest(): V8CommandHandler(QStringLiteral("evaluate")) {}
+ V4EvaluateRequest(): V4CommandHandler(QStringLiteral("evaluate")) {}
void handleRequest() override
{
@@ -644,7 +661,7 @@ public:
}
ExpressionEvalJob job(debugger->engine(), frame, context, expression,
- saneCollector(debugger));
+ debugger->collector());
debugger->runInEngine(&job);
if (job.hasExeption()) {
createErrorResponse(job.exceptionMessage());
@@ -654,44 +671,43 @@ public:
addSuccess(true);
addRunning();
addBody(job.returnValue());
- if (debugService->clientRequiresRedundantRefs())
- addRefs(job.refs());
}
}
};
} // anonymous namespace
-void QV4DebugServiceImpl::addHandler(V8CommandHandler* handler)
+void QV4DebugServiceImpl::addHandler(V4CommandHandler* handler)
{
handlers[handler->command()] = handler;
}
-V8CommandHandler *QV4DebugServiceImpl::v8CommandHandler(const QString &command) const
+V4CommandHandler *QV4DebugServiceImpl::v4CommandHandler(const QString &command) const
{
- V8CommandHandler *handler = handlers.value(command, 0);
+ V4CommandHandler *handler = handlers.value(command, 0);
if (handler)
return handler;
else
- return unknownV8CommandHandler.data();
+ return unknownV4CommandHandler.data();
}
QV4DebugServiceImpl::QV4DebugServiceImpl(QObject *parent) :
QQmlConfigurableDebugService<QV4DebugService>(1, parent),
- debuggerAgent(this), theSelectedFrame(0), redundantRefs(true), namesAsObjects(true),
- unknownV8CommandHandler(new UnknownV8CommandHandler)
+ debuggerAgent(this), theSelectedFrame(0),
+ unknownV4CommandHandler(new UnknownV4CommandHandler)
{
- addHandler(new V8VersionRequest);
- addHandler(new V8SetBreakPointRequest);
- addHandler(new V8ClearBreakPointRequest);
- addHandler(new V8BacktraceRequest);
- addHandler(new V8FrameRequest);
- addHandler(new V8ScopeRequest);
- addHandler(new V8LookupRequest);
- addHandler(new V8ContinueRequest);
- addHandler(new V8DisconnectRequest);
- addHandler(new V8SetExceptionBreakRequest);
- addHandler(new V8ScriptsRequest);
- addHandler(new V8EvaluateRequest);
+ addHandler(new V4VersionRequest);
+ addHandler(new V4SetBreakPointRequest);
+ addHandler(new V4ClearBreakPointRequest);
+ addHandler(new V4ChangeBreakPointRequest);
+ addHandler(new V4BacktraceRequest);
+ addHandler(new V4FrameRequest);
+ addHandler(new V4ScopeRequest);
+ addHandler(new V4LookupRequest);
+ addHandler(new V4ContinueRequest);
+ addHandler(new V4DisconnectRequest);
+ addHandler(new V4SetExceptionBreakRequest);
+ addHandler(new V4ScriptsRequest);
+ addHandler(new V4EvaluateRequest);
}
QV4DebugServiceImpl::~QV4DebugServiceImpl()
@@ -703,10 +719,9 @@ void QV4DebugServiceImpl::engineAdded(QJSEngine *engine)
{
QMutexLocker lock(&m_configMutex);
if (engine) {
- QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
+ QV4::ExecutionEngine *ee = engine->handle();
if (QQmlDebugConnector *server = QQmlDebugConnector::instance()) {
if (ee) {
- ee->iselFactory.reset(new QV4::Moth::ISelFactory);
QV4Debugger *debugger = new QV4Debugger(ee);
if (state() == Enabled)
ee->setDebugger(debugger);
@@ -722,7 +737,7 @@ void QV4DebugServiceImpl::engineAboutToBeRemoved(QJSEngine *engine)
{
QMutexLocker lock(&m_configMutex);
if (engine){
- const QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
+ const QV4::ExecutionEngine *ee = engine->handle();
if (ee) {
QV4Debugger *debugger = qobject_cast<QV4Debugger *>(ee->debugger());
if (debugger)
@@ -782,12 +797,7 @@ void QV4DebugServiceImpl::messageReceived(const QByteArray &message)
if (type == V4_CONNECT) {
QJsonObject parameters = QJsonDocument::fromJson(payload).object();
- namesAsObjects = true;
- redundantRefs = true;
- if (parameters.contains("namesAsObjects"))
- namesAsObjects = parameters.value("namesAsObjects").toBool();
- if (parameters.contains("redundantRefs"))
- redundantRefs = parameters.value("redundantRefs").toBool();
+ Q_UNUSED(parameters); // For future protocol changes
emit messageToClient(name(), packMessage(type));
stopWaiting();
@@ -805,10 +815,10 @@ void QV4DebugServiceImpl::messageReceived(const QByteArray &message)
else
breakOnSignals.removeOne(signalName);
} else if (type == "v8request") {
- handleV8Request(payload);
+ handleV4Request(payload);
} else if (type == V4_DISCONNECT) {
TRACE_PROTOCOL(qDebug() << "... payload:" << payload.constData());
- handleV8Request(payload);
+ handleV4Request(payload);
} else {
sendSomethingToSomebody(type, 0);
}
@@ -823,7 +833,7 @@ void QV4DebugServiceImpl::sendSomethingToSomebody(const char *type, int magicNum
emit messageToClient(name(), packMessage(type, rs.data()));
}
-void QV4DebugServiceImpl::handleV8Request(const QByteArray &payload)
+void QV4DebugServiceImpl::handleV4Request(const QByteArray &payload)
{
TRACE_PROTOCOL(qDebug() << "v8request, payload:" << payload.constData());
@@ -832,7 +842,7 @@ void QV4DebugServiceImpl::handleV8Request(const QByteArray &payload)
QJsonValue type = o.value(QLatin1String("type"));
if (type.toString() == QLatin1String("request")) {
QJsonValue command = o.value(QLatin1String("command"));
- V8CommandHandler *h = v8CommandHandler(command.toString());
+ V4CommandHandler *h = v4CommandHandler(command.toString());
if (h)
h->handle(o, this);
}
@@ -846,11 +856,11 @@ QByteArray QV4DebugServiceImpl::packMessage(const QByteArray &command, const QBy
return rs.data();
}
-void QV4DebugServiceImpl::send(QJsonObject v8Payload)
+void QV4DebugServiceImpl::send(QJsonObject v4Payload)
{
- v8Payload[QLatin1String("seq")] = sequence++;
+ v4Payload[QLatin1String("seq")] = sequence++;
QJsonDocument doc;
- doc.setObject(v8Payload);
+ doc.setObject(v4Payload);
#ifdef NO_PROTOCOL_TRACING
QByteArray responseData = doc.toJson(QJsonDocument::Compact);
#else