aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/qmltooling/qmldbg_debugger
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/qmltooling/qmldbg_debugger')
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp105
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.h87
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro4
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservice.json2
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp8
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.h2
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp14
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp800
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.h98
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp16
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp44
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.h23
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp38
13 files changed, 79 insertions, 1162 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp
deleted file mode 100644
index b0f59717ac..0000000000
--- a/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qdebugmessageservice.h"
-#include "qqmldebugpacket.h"
-#include <private/qqmldebugconnector_p.h>
-
-QT_BEGIN_NAMESPACE
-
-void DebugMessageHandler(QtMsgType type, const QMessageLogContext &ctxt,
- const QString &buf)
-{
- QQmlDebugConnector::service<QDebugMessageServiceImpl>()->sendDebugMessage(type, ctxt, buf);
-}
-
-QDebugMessageServiceImpl::QDebugMessageServiceImpl(QObject *parent) :
- QDebugMessageService(2, parent), oldMsgHandler(0),
- prevState(QQmlDebugService::NotConnected)
-{
- // don't execute stateChanged() in parallel
- QMutexLocker lock(&initMutex);
- timer.start();
- if (state() == Enabled) {
- oldMsgHandler = qInstallMessageHandler(DebugMessageHandler);
- prevState = Enabled;
- }
-}
-
-void QDebugMessageServiceImpl::sendDebugMessage(QtMsgType type,
- const QMessageLogContext &ctxt,
- const QString &buf)
-{
- //We do not want to alter the message handling mechanism
- //We just eavesdrop and forward the messages to a port
- //only if a client is connected to it.
- QQmlDebugPacket ws;
- ws << QByteArray("MESSAGE") << int(type) << buf.toUtf8();
- ws << QByteArray(ctxt.file) << ctxt.line << QByteArray(ctxt.function);
- ws << QByteArray(ctxt.category) << timer.nsecsElapsed();
-
- emit messageToClient(name(), ws.data());
- if (oldMsgHandler)
- (*oldMsgHandler)(type, ctxt, buf);
-}
-
-void QDebugMessageServiceImpl::stateChanged(State state)
-{
- QMutexLocker lock(&initMutex);
-
- if (state != Enabled && prevState == Enabled) {
- QtMessageHandler handler = qInstallMessageHandler(oldMsgHandler);
- // has our handler been overwritten in between?
- if (handler != DebugMessageHandler)
- qInstallMessageHandler(handler);
-
- } else if (state == Enabled && prevState != Enabled) {
- oldMsgHandler = qInstallMessageHandler(DebugMessageHandler);
- }
-
- prevState = state;
-}
-
-void QDebugMessageServiceImpl::synchronizeTime(const QElapsedTimer &otherTimer)
-{
- QMutexLocker lock(&initMutex);
- timer = otherTimer;
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.h b/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.h
deleted file mode 100644
index c25e756c2d..0000000000
--- a/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QDEBUGMESSAGESERVICE_H
-#define QDEBUGMESSAGESERVICE_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <private/qqmldebugserviceinterfaces_p.h>
-
-#include <QtCore/qlogging.h>
-#include <QtCore/qmutex.h>
-#include <QtCore/qelapsedtimer.h>
-
-QT_BEGIN_NAMESPACE
-
-class QDebugMessageServicePrivate;
-
-class QDebugMessageServiceImpl : public QDebugMessageService
-{
- Q_OBJECT
-public:
- QDebugMessageServiceImpl(QObject *parent = 0);
-
- void sendDebugMessage(QtMsgType type, const QMessageLogContext &ctxt, const QString &buf);
- void synchronizeTime(const QElapsedTimer &otherTimer);
-
-protected:
- void stateChanged(State);
-
-private:
- friend class QQmlDebuggerServiceFactory;
-
- QtMessageHandler oldMsgHandler;
- QQmlDebugService::State prevState;
- QMutex initMutex;
- QElapsedTimer timer;
-};
-
-QT_END_NAMESPACE
-
-#endif // QDEBUGMESSAGESERVICE_H
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro b/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro
index 27b3a5b513..f3f8a21ff8 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro
+++ b/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro
@@ -2,10 +2,8 @@ TARGET = qmldbg_debugger
QT = qml-private core-private packetprotocol-private
SOURCES += \
- $$PWD/qdebugmessageservice.cpp \
$$PWD/qqmldebuggerservicefactory.cpp \
$$PWD/qqmlenginedebugservice.cpp \
- $$PWD/qqmlnativedebugservice.cpp \
$$PWD/qqmlwatcher.cpp \
$$PWD/qv4debugservice.cpp \
$$PWD/qv4debugger.cpp \
@@ -16,10 +14,8 @@ SOURCES += \
HEADERS += \
$$PWD/../shared/qqmlconfigurabledebugservice.h \
$$PWD/../shared/qqmldebugpacket.h \
- $$PWD/qdebugmessageservice.h \
$$PWD/qqmldebuggerservicefactory.h \
$$PWD/qqmlenginedebugservice.h \
- $$PWD/qqmlnativedebugservice.h \
$$PWD/qqmlwatcher.h \
$$PWD/qv4debugservice.h \
$$PWD/qv4debugger.h \
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservice.json b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservice.json
index 967a725903..442d7781a1 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservice.json
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservice.json
@@ -1,3 +1,3 @@
{
- "Keys": [ "DebugMessages", "QmlDebugger", "V8Debugger", "NativeQmlDebugger" ]
+ "Keys": [ "QmlDebugger", "V8Debugger" ]
}
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp
index ca3f07323d..9315adf4ce 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp
@@ -39,27 +39,19 @@
#include "qqmldebuggerservicefactory.h"
#include "qqmlenginedebugservice.h"
-#include "qdebugmessageservice.h"
#include "qv4debugservice.h"
-#include "qqmlnativedebugservice.h"
#include <private/qqmldebugserviceinterfaces_p.h>
QT_BEGIN_NAMESPACE
QQmlDebugService *QQmlDebuggerServiceFactory::create(const QString &key)
{
- if (key == QDebugMessageServiceImpl::s_key)
- return new QDebugMessageServiceImpl(this);
-
if (key == QQmlEngineDebugServiceImpl::s_key)
return new QQmlEngineDebugServiceImpl(this);
if (key == QV4DebugServiceImpl::s_key)
return new QV4DebugServiceImpl(this);
- if (key == QQmlNativeDebugServiceImpl::s_key)
- return new QQmlNativeDebugServiceImpl(this);
-
return 0;
}
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.h b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.h
index 99d6679833..50eed2369c 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.h
@@ -49,7 +49,7 @@ class QQmlDebuggerServiceFactory : public QQmlDebugServiceFactory
Q_OBJECT
Q_PLUGIN_METADATA(IID QQmlDebugServiceFactory_iid FILE "qqmldebuggerservice.json")
public:
- QQmlDebugService *create(const QString &key);
+ QQmlDebugService *create(const QString &key) override;
};
QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
index 2b8dcc19ee..151e44c4d4 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
@@ -289,10 +289,12 @@ void QQmlEngineDebugServiceImpl::buildObjectDump(QDataStream &message,
prop.value = expr->expression();
QObject *scope = expr->scopeObject();
if (scope) {
- QString methodName = QString::fromLatin1(QMetaObjectPrivate::signal(scope->metaObject(), signalHandler->signalIndex()).name());
- if (!methodName.isEmpty()) {
- prop.name = QLatin1String("on") + methodName[0].toUpper()
- + methodName.mid(1);
+ const QByteArray methodName = QMetaObjectPrivate::signal(scope->metaObject(),
+ signalHandler->signalIndex()).name();
+ const QLatin1String methodNameStr(methodName);
+ if (methodNameStr.size() != 0) {
+ prop.name = QLatin1String("on") + QChar(methodNameStr.at(0)).toUpper()
+ + methodNameStr.mid(1);
}
}
}
@@ -520,12 +522,12 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
ds >> file >> lineNumber >> columnNumber >> recurse >> dumpProperties;
- QList<QObject*> objects = objectForLocationInfo(file, lineNumber, columnNumber);
+ const QList<QObject*> objects = objectForLocationInfo(file, lineNumber, columnNumber);
rs << QByteArray("FETCH_OBJECTS_FOR_LOCATION_R") << queryId
<< objects.count();
- foreach (QObject *object, objects) {
+ for (QObject *object : objects) {
if (recurse)
prepareDeferredObjects(object);
buildObjectDump(rs, object, recurse, dumpProperties);
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp
deleted file mode 100644
index 14dfc5356e..0000000000
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp
+++ /dev/null
@@ -1,800 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlnativedebugservice.h"
-#include "qqmldebugpacket.h"
-
-#include <private/qqmldebugconnector_p.h>
-#include <private/qv4debugging_p.h>
-#include <private/qv8engine_p.h>
-#include <private/qv4engine_p.h>
-#include <private/qv4debugging_p.h>
-#include <private/qv4script_p.h>
-#include <private/qv4string_p.h>
-#include <private/qv4objectiterator_p.h>
-#include <private/qv4identifier_p.h>
-#include <private/qv4runtime_p.h>
-#include <private/qv4isel_moth_p.h>
-#include <private/qqmldebugserviceinterfaces_p.h>
-
-#include <QtQml/qjsengine.h>
-#include <QtCore/qjsonarray.h>
-#include <QtCore/qjsondocument.h>
-#include <QtCore/qjsonobject.h>
-#include <QtCore/qjsonvalue.h>
-#include <QtCore/qvector.h>
-#include <QtCore/qpointer.h>
-
-//#define TRACE_PROTOCOL(s) qDebug() << s
-#define TRACE_PROTOCOL(s)
-
-QT_BEGIN_NAMESPACE
-
-class BreakPoint
-{
-public:
- BreakPoint() : id(-1), lineNumber(-1), enabled(false), ignoreCount(0), hitCount(0) {}
- bool isValid() const { return lineNumber >= 0 && !fileName.isEmpty(); }
-
- int id;
- int lineNumber;
- QString fileName;
- bool enabled;
- QString condition;
- int ignoreCount;
-
- int hitCount;
-};
-
-inline uint qHash(const BreakPoint &b, uint seed = 0) Q_DECL_NOTHROW
-{
- return qHash(b.fileName, seed) ^ b.lineNumber;
-}
-
-inline bool operator==(const BreakPoint &a, const BreakPoint &b)
-{
- return a.lineNumber == b.lineNumber && a.fileName == b.fileName
- && a.enabled == b.enabled && a.condition == b.condition
- && a.ignoreCount == b.ignoreCount;
-}
-
-static void setError(QJsonObject *response, const QString &msg)
-{
- response->insert(QStringLiteral("type"), QStringLiteral("error"));
- response->insert(QStringLiteral("msg"), msg);
-}
-
-class NativeDebugger;
-
-class Collector
-{
-public:
- Collector(QV4::ExecutionEngine *engine)
- : m_engine(engine), m_anonCount(0)
- {}
-
- void collect(QJsonArray *output, const QString &parentIName, const QString &name,
- const QV4::Value &value);
-
- bool isExpanded(const QString &iname) const { return m_expanded.contains(iname); }
-
-public:
- QV4::ExecutionEngine *m_engine;
- int m_anonCount;
- QStringList m_expanded;
-};
-
-// Encapsulate Breakpoint handling
-// Could be made per-NativeDebugger (i.e. per execution engine, if needed)
-class BreakPointHandler
-{
-public:
- BreakPointHandler() : m_haveBreakPoints(false), m_breakOnThrow(true), m_lastBreakpoint(1) {}
-
- void handleSetBreakpoint(QJsonObject *response, const QJsonObject &arguments);
- void handleRemoveBreakpoint(QJsonObject *response, const QJsonObject &arguments);
-
- void removeBreakPoint(int id);
- void enableBreakPoint(int id, bool onoff);
-
- void setBreakOnThrow(bool onoff);
- bool m_haveBreakPoints;
- bool m_breakOnThrow;
- int m_lastBreakpoint;
- QVector<BreakPoint> m_breakPoints;
-};
-
-void BreakPointHandler::handleSetBreakpoint(QJsonObject *response, const QJsonObject &arguments)
-{
- TRACE_PROTOCOL("SET BREAKPOINT" << arguments);
- QString type = arguments.value(QLatin1String("type")).toString();
-
- QString fileName = arguments.value(QLatin1String("file")).toString();
- if (fileName.isEmpty()) {
- setError(response, QStringLiteral("breakpoint has no file name"));
- return;
- }
-
- int line = arguments.value(QLatin1String("line")).toInt(-1);
- if (line < 0) {
- setError(response, QStringLiteral("breakpoint has an invalid line number"));
- return;
- }
-
- BreakPoint bp;
- bp.id = m_lastBreakpoint++;
- bp.fileName = fileName.mid(fileName.lastIndexOf('/') + 1);
- bp.lineNumber = line;
- bp.enabled = arguments.value(QLatin1String("enabled")).toBool(true);
- bp.condition = arguments.value(QLatin1String("condition")).toString();
- bp.ignoreCount = arguments.value(QLatin1String("ignorecount")).toInt();
- m_breakPoints.append(bp);
-
- m_haveBreakPoints = true;
-
- response->insert(QStringLiteral("type"), type);
- response->insert(QStringLiteral("breakpoint"), bp.id);
-}
-
-void BreakPointHandler::handleRemoveBreakpoint(QJsonObject *response, const QJsonObject &arguments)
-{
- int id = arguments.value(QLatin1String("id")).toInt();
- removeBreakPoint(id);
- response->insert(QStringLiteral("id"), id);
-}
-
-class NativeDebugger : public QV4::Debugging::Debugger
-{
-public:
- NativeDebugger(QQmlNativeDebugServiceImpl *service, QV4::ExecutionEngine *engine);
-
- void signalEmitted(const QString &signal);
-
- QV4::ExecutionEngine *engine() const { return m_engine; }
-
- bool pauseAtNextOpportunity() const Q_DECL_OVERRIDE {
- return m_pauseRequested
- || m_service->m_breakHandler->m_haveBreakPoints
- || m_stepping >= StepOver;
- }
-
- void maybeBreakAtInstruction() Q_DECL_OVERRIDE;
- void enteringFunction() Q_DECL_OVERRIDE;
- void leavingFunction(const QV4::ReturnedValue &retVal) Q_DECL_OVERRIDE;
- void aboutToThrow() Q_DECL_OVERRIDE;
-
- void handleCommand(QJsonObject *response, const QString &cmd, const QJsonObject &arguments);
-
-private:
- void handleBacktrace(QJsonObject *response, const QJsonObject &arguments);
- void handleVariables(QJsonObject *response, const QJsonObject &arguments);
- void handleExpressions(QJsonObject *response, const QJsonObject &arguments);
-
- void handleDebuggerDeleted(QObject *debugger);
-
- void evaluateExpression(QV4::Scope &scope, const QString &expression);
- bool checkCondition(const QString &expression);
-
- QStringList breakOnSignals;
-
- enum Speed {
- NotStepping = 0,
- StepOut,
- StepOver,
- StepIn,
- };
-
- void pauseAndWait();
- void pause();
- void handleContinue(QJsonObject *reponse, Speed speed);
-
- QV4::Function *getFunction() const;
-
- bool reallyHitTheBreakPoint(const QV4::Function *function, int lineNumber);
-
- QV4::ExecutionEngine *m_engine;
- QQmlNativeDebugServiceImpl *m_service;
- QV4::PersistentValue m_currentContext;
- Speed m_stepping;
- bool m_pauseRequested;
- bool m_runningJob;
-
- QV4::PersistentValue m_returnedValue;
-};
-
-bool NativeDebugger::checkCondition(const QString &expression)
-{
- QV4::Scope scope(m_engine);
- evaluateExpression(scope, expression);
- return scope.result.booleanValue();
-}
-
-void NativeDebugger::evaluateExpression(QV4::Scope &scope, const QString &expression)
-{
- m_runningJob = true;
-
- QV4::ExecutionContextSaver saver(scope);
-
- QV4::ExecutionContext *ctx = m_engine->currentContext;
- m_engine->pushContext(ctx);
-
- QV4::Script script(ctx, expression);
- script.strictMode = ctx->d()->strictMode;
- // In order for property lookups in QML to work, we need to disable fast v4 lookups.
- // That is a side-effect of inheritContext.
- script.inheritContext = true;
- script.parse();
- if (!m_engine->hasException)
- scope.result = script.run();
-
- m_runningJob = false;
-}
-
-NativeDebugger::NativeDebugger(QQmlNativeDebugServiceImpl *service, QV4::ExecutionEngine *engine)
- : m_returnedValue(engine, QV4::Primitive::undefinedValue())
-{
- m_stepping = NotStepping;
- m_pauseRequested = false;
- m_runningJob = false;
- m_service = service;
- m_engine = engine;
- TRACE_PROTOCOL("Creating native debugger");
-}
-
-void NativeDebugger::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.
-
- //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, breakOnSignals) {
- if (signal == signalName) {
- // TODO: pause debugger
- break;
- }
- }
-}
-
-void NativeDebugger::handleCommand(QJsonObject *response, const QString &cmd,
- const QJsonObject &arguments)
-{
- if (cmd == QLatin1String("backtrace"))
- handleBacktrace(response, arguments);
- else if (cmd == QLatin1String("variables"))
- handleVariables(response, arguments);
- else if (cmd == QLatin1String("expressions"))
- handleExpressions(response, arguments);
- else if (cmd == QLatin1String("stepin"))
- handleContinue(response, StepIn);
- else if (cmd == QLatin1String("stepout"))
- handleContinue(response, StepOut);
- else if (cmd == QLatin1String("stepover"))
- handleContinue(response, StepOver);
- else if (cmd == QLatin1String("continue"))
- handleContinue(response, NotStepping);
-}
-
-static QString encodeContext(QV4::ExecutionContext *executionContext)
-{
- QQmlDebugPacket ds;
- ds << quintptr(executionContext);
- return QString::fromLatin1(ds.data().toHex());
-}
-
-static void decodeContext(const QString &context, QV4::ExecutionContext **executionContext)
-{
- quintptr rawContext;
- QQmlDebugPacket ds(QByteArray::fromHex(context.toLatin1()));
- ds >> rawContext;
- *executionContext = reinterpret_cast<QV4::ExecutionContext *>(rawContext);
-}
-
-void NativeDebugger::handleBacktrace(QJsonObject *response, const QJsonObject &arguments)
-{
- int limit = arguments.value(QLatin1String("limit")).toInt(0);
-
- QJsonArray frameArray;
- QV4::ExecutionContext *executionContext = m_engine->currentContext;
- for (int i = 0; i < limit && executionContext; ++i) {
- if (QV4::Function *function = executionContext->getFunction()) {
-
- QJsonObject frame;
- frame[QStringLiteral("language")] = QStringLiteral("js");
- frame[QStringLiteral("context")] = encodeContext(executionContext);
-
- if (QV4::Heap::String *functionName = function->name())
- frame[QStringLiteral("function")] = functionName->toQString();
- frame[QStringLiteral("file")] = function->sourceFile();
-
- int line = executionContext->d()->lineNumber;
- frame[QStringLiteral("line")] = (line < 0 ? -line : line);
-
- frameArray.push_back(frame);
- }
-
- executionContext = m_engine->parentContext(executionContext);
- }
-
- response->insert(QStringLiteral("frames"), frameArray);
-}
-
-void Collector::collect(QJsonArray *out, const QString &parentIName, const QString &name,
- const QV4::Value &value)
-{
- QJsonObject dict;
- QV4::Scope scope(m_engine);
-
- QString nonEmptyName = name.isEmpty() ? QString::fromLatin1("@%1").arg(m_anonCount++) : name;
- QString iname = parentIName + QLatin1Char('.') + nonEmptyName;
- dict.insert(QStringLiteral("iname"), iname);
- dict.insert(QStringLiteral("name"), nonEmptyName);
-
- QV4::ScopedValue typeString(scope, QV4::Runtime::method_typeofValue(m_engine, value));
- dict.insert(QStringLiteral("type"), typeString->toQStringNoThrow());
-
- switch (value.type()) {
- case QV4::Value::Empty_Type:
- dict.insert(QStringLiteral("valueencoded"), QStringLiteral("empty"));
- dict.insert(QStringLiteral("haschild"), false);
- break;
- case QV4::Value::Undefined_Type:
- dict.insert(QStringLiteral("valueencoded"), QStringLiteral("undefined"));
- dict.insert(QStringLiteral("haschild"), false);
- break;
- case QV4::Value::Null_Type:
- dict.insert(QStringLiteral("type"), QStringLiteral("object"));
- dict.insert(QStringLiteral("valueencoded"), QStringLiteral("null"));
- dict.insert(QStringLiteral("haschild"), false);
- break;
- case QV4::Value::Boolean_Type:
- dict.insert(QStringLiteral("value"), value.booleanValue());
- dict.insert(QStringLiteral("haschild"), false);
- break;
- case QV4::Value::Managed_Type:
- if (const QV4::String *string = value.as<QV4::String>()) {
- dict.insert(QStringLiteral("value"), string->toQStringNoThrow());
- dict.insert(QStringLiteral("haschild"), false);
- dict.insert(QStringLiteral("valueencoded"), QStringLiteral("utf16"));
- dict.insert(QStringLiteral("quoted"), true);
- } else if (const QV4::ArrayObject *array = value.as<QV4::ArrayObject>()) {
- // The size of an array is number of its numerical properties.
- // We don't consider free form object properties here.
- const uint n = array->getLength();
- dict.insert(QStringLiteral("value"), qint64(n));
- dict.insert(QStringLiteral("valueencoded"), QStringLiteral("itemcount"));
- dict.insert(QStringLiteral("haschild"), qint64(n));
- if (isExpanded(iname)) {
- QJsonArray children;
- for (uint i = 0; i < n; ++i) {
- QV4::ReturnedValue v = array->getIndexed(i);
- QV4::ScopedValue sval(scope, v);
- collect(&children, iname, QString::number(i), *sval);
- }
- dict.insert(QStringLiteral("children"), children);
- }
- } else if (const QV4::Object *object = value.as<QV4::Object>()) {
- QJsonArray children;
- bool expanded = isExpanded(iname);
- qint64 numProperties = 0;
- QV4::ObjectIterator it(scope, object, QV4::ObjectIterator::EnumerableOnly);
- QV4::ScopedProperty p(scope);
- QV4::ScopedString name(scope);
- while (true) {
- QV4::PropertyAttributes attrs;
- uint index;
- it.next(name.getRef(), &index, p, &attrs);
- if (attrs.isEmpty())
- break;
- if (name.getPointer()) {
- ++numProperties;
- if (expanded) {
- if (name.getPointer()) {
- QV4::Value v = p.property->value;
- collect(&children, iname, name->toQStringNoThrow(), v);
- }
- }
- }
- }
- dict.insert(QStringLiteral("value"), numProperties);
- dict.insert(QStringLiteral("valueencoded"), QStringLiteral("itemcount"));
- dict.insert(QStringLiteral("haschild"), numProperties > 0);
- if (expanded)
- dict.insert(QStringLiteral("children"), children);
- }
- break;
- case QV4::Value::Integer_Type:
- dict.insert(QStringLiteral("value"), value.integerValue());
- dict.insert(QStringLiteral("haschild"), false);
- break;
- default: // double
- dict.insert(QStringLiteral("value"), value.doubleValue());
- dict.insert(QStringLiteral("haschild"), false);
- }
-
- out->append(dict);
-}
-
-void NativeDebugger::handleVariables(QJsonObject *response, const QJsonObject &arguments)
-{
- TRACE_PROTOCOL("Build variables");
- QV4::ExecutionContext *executionContext = 0;
- decodeContext(arguments.value(QLatin1String("context")).toString(), &executionContext);
- if (!executionContext) {
- setError(response, QStringLiteral("No execution context passed"));
- return;
- }
- TRACE_PROTOCOL("Context: " << executionContext);
-
- QV4::ExecutionEngine *engine = executionContext->d()->engine;
- if (!engine) {
- setError(response, QStringLiteral("No execution engine passed"));
- return;
- }
- TRACE_PROTOCOL("Engine: " << engine);
-
- Collector collector(engine);
- QJsonArray expanded = arguments.value(QLatin1String("expanded")).toArray();
- foreach (const QJsonValue &ex, expanded)
- collector.m_expanded.append(ex.toString());
- TRACE_PROTOCOL("Expanded: " << collector.m_expanded);
-
- QJsonArray output;
- QV4::Scope scope(engine);
-
- if (QV4::CallContext *callContext = executionContext->asCallContext()) {
- QV4::Value thisObject = callContext->thisObject();
- collector.collect(&output, QString(), QStringLiteral("this"), thisObject);
- QV4::Identifier *const *variables = callContext->variables();
- QV4::Identifier *const *formals = callContext->formals();
- for (unsigned i = 0, ei = callContext->variableCount(); i != ei; ++i) {
- QString qName;
- if (QV4::Identifier *name = variables[i])
- qName = name->string;
- QV4::Value val = callContext->d()->locals[i];
- collector.collect(&output, QString(), qName, val);
- }
- for (unsigned i = 0, ei = callContext->formalCount(); i != ei; ++i) {
- QString qName;
- if (QV4::Identifier *name = formals[i])
- qName = name->string;
- QV4::ReturnedValue rval = callContext->argument(i);
- QV4::ScopedValue sval(scope, rval);
- collector.collect(&output, QString(), qName, *sval);
- }
- }
-
- response->insert(QStringLiteral("variables"), output);
-}
-
-void NativeDebugger::handleExpressions(QJsonObject *response, const QJsonObject &arguments)
-{
- TRACE_PROTOCOL("Evaluate expressions");
- QV4::ExecutionContext *executionContext = 0;
- decodeContext(arguments.value(QLatin1String("context")).toString(), &executionContext);
- if (!executionContext) {
- setError(response, QStringLiteral("No execution context passed"));
- return;
- }
- TRACE_PROTOCOL("Context: " << executionContext);
-
- QV4::ExecutionEngine *engine = executionContext->d()->engine;
- if (!engine) {
- setError(response, QStringLiteral("No execution engine passed"));
- return;
- }
- TRACE_PROTOCOL("Engines: " << engine << m_engine);
-
- Collector collector(engine);
- QJsonArray expanded = arguments.value(QLatin1String("expanded")).toArray();
- foreach (const QJsonValue &ex, expanded)
- collector.m_expanded.append(ex.toString());
- TRACE_PROTOCOL("Expanded: " << collector.m_expanded);
-
- QJsonArray output;
- QV4::Scope scope(engine);
-
- QJsonArray expressions = arguments.value(QLatin1String("expressions")).toArray();
- foreach (const QJsonValue &expr, expressions) {
- QString expression = expr.toObject().value(QLatin1String("expression")).toString();
- QString name = expr.toObject().value(QLatin1String("name")).toString();
- TRACE_PROTOCOL("Evaluate expression: " << expression);
- m_runningJob = true;
-
- evaluateExpression(scope, expression);
- QV4::ScopedValue result(scope, scope.result);
-
- m_runningJob = false;
- if (result->isUndefined()) {
- QJsonObject dict;
- dict[QStringLiteral("name")] = name;
- dict[QStringLiteral("valueencoded")] = QStringLiteral("undefined");
- output.append(dict);
- } else if (result.ptr && result.ptr->rawValue()) {
- collector.collect(&output, QString(), name, *result);
- } else {
- QJsonObject dict;
- dict[QStringLiteral("name")] = name;
- dict[QStringLiteral("valueencoded")] = QStringLiteral("notaccessible");
- output.append(dict);
- }
- TRACE_PROTOCOL("EXCEPTION: " << engine->hasException);
- engine->hasException = false;
- }
-
- response->insert(QStringLiteral("expressions"), output);
-}
-
-void BreakPointHandler::removeBreakPoint(int id)
-{
- for (int i = 0; i != m_breakPoints.size(); ++i) {
- if (m_breakPoints.at(i).id == id) {
- m_breakPoints.remove(i);
- m_haveBreakPoints = !m_breakPoints.isEmpty();
- return;
- }
- }
-}
-
-void BreakPointHandler::enableBreakPoint(int id, bool enabled)
-{
- m_breakPoints[id].enabled = enabled;
-}
-
-void NativeDebugger::pause()
-{
- m_pauseRequested = true;
-}
-
-void NativeDebugger::handleContinue(QJsonObject *response, Speed speed)
-{
- Q_UNUSED(response);
-
- if (!m_returnedValue.isUndefined())
- m_returnedValue.set(m_engine, QV4::Encode::undefined());
-
- m_currentContext.set(m_engine, *m_engine->currentContext);
- m_stepping = speed;
-}
-
-void NativeDebugger::maybeBreakAtInstruction()
-{
- if (m_runningJob) // do not re-enter when we're doing a job for the debugger.
- return;
-
- if (m_stepping == StepOver) {
- if (m_currentContext.asManaged()->d() == m_engine->current)
- pauseAndWait();
- return;
- }
-
- if (m_stepping == StepIn) {
- pauseAndWait();
- return;
- }
-
- if (m_pauseRequested) { // Serve debugging requests from the agent
- m_pauseRequested = false;
- pauseAndWait();
- return;
- }
-
- if (m_service->m_breakHandler->m_haveBreakPoints) {
- if (QV4::Function *function = getFunction()) {
- const int lineNumber = m_engine->current->lineNumber;
- if (reallyHitTheBreakPoint(function, lineNumber))
- pauseAndWait();
- }
- }
-}
-
-void NativeDebugger::enteringFunction()
-{
- if (m_runningJob)
- return;
-
- if (m_stepping == StepIn) {
- m_currentContext.set(m_engine, *m_engine->currentContext);
- }
-}
-
-void NativeDebugger::leavingFunction(const QV4::ReturnedValue &retVal)
-{
- if (m_runningJob)
- return;
-
- if (m_stepping != NotStepping && m_currentContext.asManaged()->d() == m_engine->current) {
- m_currentContext.set(m_engine, *m_engine->parentContext(m_engine->currentContext));
- m_stepping = StepOver;
- m_returnedValue.set(m_engine, retVal);
- }
-}
-
-void NativeDebugger::aboutToThrow()
-{
- if (!m_service->m_breakHandler->m_breakOnThrow)
- return;
-
- if (m_runningJob) // do not re-enter when we're doing a job for the debugger.
- return;
-
- QJsonObject event;
- // TODO: complete this!
- event.insert(QStringLiteral("event"), QStringLiteral("exception"));
- m_service->emitAsynchronousMessageToClient(event);
-}
-
-QV4::Function *NativeDebugger::getFunction() const
-{
- QV4::ExecutionContext *context = m_engine->currentContext;
- if (QV4::Function *function = context->getFunction())
- return function;
- else
- return context->d()->engine->globalCode;
-}
-
-void NativeDebugger::pauseAndWait()
-{
- QJsonObject event;
-
- event.insert(QStringLiteral("event"), QStringLiteral("break"));
- event.insert(QStringLiteral("language"), QStringLiteral("js"));
- if (QV4::ExecutionContext *executionContext = m_engine->currentContext) {
- if (QV4::Function *function = executionContext->getFunction()) {
- event.insert(QStringLiteral("file"), function->sourceFile());
- int line = executionContext->d()->lineNumber;
- event.insert(QStringLiteral("line"), (line < 0 ? -line : line));
- }
- }
-
- m_service->emitAsynchronousMessageToClient(event);
-}
-
-bool NativeDebugger::reallyHitTheBreakPoint(const QV4::Function *function, int lineNumber)
-{
- for (int i = 0, n = m_service->m_breakHandler->m_breakPoints.size(); i != n; ++i) {
- const BreakPoint &bp = m_service->m_breakHandler->m_breakPoints.at(i);
- if (bp.lineNumber == lineNumber) {
- const QString fileName = function->sourceFile();
- const QStringRef base = fileName.midRef(fileName.lastIndexOf('/') + 1);
- if (bp.fileName.endsWith(base)) {
- if (bp.condition.isEmpty() || checkCondition(bp.condition)) {
- BreakPoint &mbp = m_service->m_breakHandler->m_breakPoints[i];
- ++mbp.hitCount;
- if (mbp.hitCount > mbp.ignoreCount)
- return true;
- }
- }
- }
- }
- return false;
-}
-
-QQmlNativeDebugServiceImpl::QQmlNativeDebugServiceImpl(QObject *parent)
- : QQmlNativeDebugService(1.0, parent)
-{
- m_breakHandler = new BreakPointHandler;
-}
-
-QQmlNativeDebugServiceImpl::~QQmlNativeDebugServiceImpl()
-{
- delete m_breakHandler;
-}
-
-void QQmlNativeDebugServiceImpl::engineAboutToBeAdded(QJSEngine *engine)
-{
- TRACE_PROTOCOL("Adding engine" << engine);
- if (engine) {
- QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
- TRACE_PROTOCOL("Adding execution engine" << ee);
- if (ee) {
- NativeDebugger *debugger = new NativeDebugger(this, ee);
- ee->iselFactory.reset(new QV4::Moth::ISelFactory);
- if (state() == Enabled)
- ee->setDebugger(debugger);
- m_debuggers.append(QPointer<NativeDebugger>(debugger));
- }
- }
- QQmlDebugService::engineAboutToBeAdded(engine);
-}
-
-void QQmlNativeDebugServiceImpl::engineAboutToBeRemoved(QJSEngine *engine)
-{
- TRACE_PROTOCOL("Removing engine" << engine);
- if (engine) {
- QV4::ExecutionEngine *executionEngine = QV8Engine::getV4(engine->handle());
- foreach (NativeDebugger *debugger, m_debuggers) {
- if (debugger->engine() == executionEngine)
- m_debuggers.removeAll(debugger);
- }
- }
- QQmlDebugService::engineAboutToBeRemoved(engine);
-}
-
-void QQmlNativeDebugServiceImpl::stateAboutToBeChanged(QQmlDebugService::State state)
-{
- if (state == Enabled) {
- foreach (NativeDebugger *debugger, m_debuggers) {
- QV4::ExecutionEngine *engine = debugger->engine();
- if (!engine->debugger())
- engine->setDebugger(debugger);
- }
- }
- QQmlDebugService::stateAboutToBeChanged(state);
-}
-
-void QQmlNativeDebugServiceImpl::messageReceived(const QByteArray &message)
-{
- TRACE_PROTOCOL("Native message received: " << message);
- QJsonObject request = QJsonDocument::fromJson(message).object();
- QJsonObject response;
- QJsonObject arguments = request.value(QLatin1String("arguments")).toObject();
- QString cmd = request.value(QLatin1String("command")).toString();
-
- if (cmd == QLatin1String("setbreakpoint")) {
- m_breakHandler->handleSetBreakpoint(&response, arguments);
- } else if (cmd == QLatin1String("removebreakpoint")) {
- m_breakHandler->handleRemoveBreakpoint(&response, arguments);
- } else if (cmd == QLatin1String("echo")) {
- response.insert(QStringLiteral("result"), arguments);
- } else {
- foreach (NativeDebugger *debugger, m_debuggers)
- if (debugger)
- debugger->handleCommand(&response, cmd, arguments);
- }
- QJsonDocument doc;
- doc.setObject(response);
- QByteArray ba = doc.toJson(QJsonDocument::Compact);
- TRACE_PROTOCOL("Sending synchronous response:" << ba.constData() << endl);
- emit messageToClient(s_key, ba);
-}
-
-void QQmlNativeDebugServiceImpl::emitAsynchronousMessageToClient(const QJsonObject &message)
-{
- QJsonDocument doc;
- doc.setObject(message);
- QByteArray ba = doc.toJson(QJsonDocument::Compact);
- TRACE_PROTOCOL("Sending asynchronous message:" << ba.constData() << endl);
- emit messageToClient(s_key, ba);
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.h b/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.h
deleted file mode 100644
index 8015513f9e..0000000000
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQML_NATIVE_DEBUG_SERVICE_H
-#define QQML_NATIVE_DEBUG_SERVICE_H
-
-#include <private/qqmldebugconnector_p.h>
-#include <private/qv4debugging_p.h>
-#include <private/qv8engine_p.h>
-#include <private/qv4engine_p.h>
-#include <private/qv4debugging_p.h>
-#include <private/qv4script_p.h>
-#include <private/qv4string_p.h>
-#include <private/qv4objectiterator_p.h>
-#include <private/qv4identifier_p.h>
-#include <private/qv4runtime_p.h>
-#include <private/qqmldebugserviceinterfaces_p.h>
-
-#include <QtCore/qjsonarray.h>
-
-#include <qqmlengine.h>
-
-#include <QJsonArray>
-#include <QJsonDocument>
-#include <QJsonObject>
-#include <QJsonValue>
-#include <QVector>
-#include <QPointer>
-
-QT_BEGIN_NAMESPACE
-
-class NativeDebugger;
-class BreakPointHandler;
-class QQmlDebuggerServiceFactory;
-
-class QQmlNativeDebugServiceImpl : public QQmlNativeDebugService
-{
-public:
- QQmlNativeDebugServiceImpl(QObject *parent);
-
- ~QQmlNativeDebugServiceImpl() Q_DECL_OVERRIDE;
-
- void engineAboutToBeAdded(QJSEngine *engine) Q_DECL_OVERRIDE;
- void engineAboutToBeRemoved(QJSEngine *engine) Q_DECL_OVERRIDE;
-
- void stateAboutToBeChanged(State state) Q_DECL_OVERRIDE;
-
- void messageReceived(const QByteArray &message) Q_DECL_OVERRIDE;
-
- void emitAsynchronousMessageToClient(const QJsonObject &message);
-
-private:
- friend class QQmlDebuggerServiceFactory;
- friend class NativeDebugger;
-
- QList<QPointer<NativeDebugger> > m_debuggers;
- BreakPointHandler *m_breakHandler;
-};
-
-QT_END_NAMESPACE
-
-#endif // QQML_NATIVE_DEBUG_SERVICE_H
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp
index 756b6b28be..773bc937f5 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp
@@ -52,7 +52,7 @@ QV4DebuggerAgent::QV4DebuggerAgent(QV4DebugServiceImpl *debugService)
QV4Debugger *QV4DebuggerAgent::pausedDebugger() const
{
- foreach (QV4Debugger *debugger, m_debuggers) {
+ for (QV4Debugger *debugger : m_debuggers) {
if (debugger->state() == QV4Debugger::Paused)
return debugger;
}
@@ -147,13 +147,13 @@ void QV4DebuggerAgent::pause(QV4Debugger *debugger) const
void QV4DebuggerAgent::pauseAll() const
{
- foreach (QV4Debugger *debugger, m_debuggers)
+ for (QV4Debugger *debugger : m_debuggers)
pause(debugger);
}
void QV4DebuggerAgent::resumeAll() const
{
- foreach (QV4Debugger *debugger, m_debuggers)
+ for (QV4Debugger *debugger : m_debuggers)
if (debugger->state() == QV4Debugger::Paused)
debugger->resume(QV4Debugger::FullThrottle);
}
@@ -161,7 +161,7 @@ void QV4DebuggerAgent::resumeAll() const
int QV4DebuggerAgent::addBreakPoint(const QString &fileName, int lineNumber, bool enabled, const QString &condition)
{
if (enabled)
- foreach (QV4Debugger *debugger, m_debuggers)
+ for (QV4Debugger *debugger : qAsConst(m_debuggers))
debugger->addBreakPoint(fileName, lineNumber, condition);
int id = m_breakPoints.size();
@@ -178,7 +178,7 @@ void QV4DebuggerAgent::removeBreakPoint(int id)
m_breakPoints.remove(id);
if (breakPoint.enabled)
- foreach (QV4Debugger *debugger, m_debuggers)
+ for (QV4Debugger *debugger : qAsConst(m_debuggers))
debugger->removeBreakPoint(breakPoint.fileName, breakPoint.lineNr);
}
@@ -195,7 +195,7 @@ void QV4DebuggerAgent::enableBreakPoint(int id, bool onoff)
return;
breakPoint.enabled = onoff;
- foreach (QV4Debugger *debugger, m_debuggers) {
+ for (QV4Debugger *debugger : qAsConst(m_debuggers)) {
if (onoff)
debugger->addBreakPoint(breakPoint.fileName, breakPoint.lineNr, breakPoint.condition);
else
@@ -218,14 +218,14 @@ void QV4DebuggerAgent::setBreakOnThrow(bool onoff)
{
if (onoff != m_breakOnThrow) {
m_breakOnThrow = onoff;
- foreach (QV4Debugger *debugger, m_debuggers)
+ for (QV4Debugger *debugger : qAsConst(m_debuggers))
debugger->setBreakOnThrow(onoff);
}
}
void QV4DebuggerAgent::clearAllPauseRequests()
{
- foreach (QV4Debugger *debugger, m_debuggers)
+ for (QV4Debugger *debugger : qAsConst(m_debuggers))
debugger->clearPauseRequest();
}
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
index d5cc765ea8..df316c1ae6 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
@@ -43,6 +43,7 @@
#include <private/qqmlcontext_p.h>
#include <private/qv4qmlcontext_p.h>
#include <private/qv4qobjectwrapper_p.h>
+#include <private/qqmldebugservice_p.h>
#include <QtQml/qqmlengine.h>
@@ -52,9 +53,10 @@ QV4DebugJob::~QV4DebugJob()
{
}
-JavaScriptJob::JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr,
- const QString &script) :
- engine(engine), frameNr(frameNr), script(script), resultIsException(false)
+JavaScriptJob::JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr, int context,
+ const QString &script) :
+ engine(engine), frameNr(frameNr), context(context), script(script),
+ resultIsException(false)
{}
void JavaScriptJob::run()
@@ -65,7 +67,23 @@ void JavaScriptJob::run()
QV4::ExecutionContext *ctx = engine->currentContext;
QObject scopeObject;
- if (frameNr < 0) { // Use QML context if available
+
+ if (frameNr > 0) {
+ for (int i = 0; i < frameNr; ++i) {
+ ctx = engine->parentContext(ctx);
+ }
+ engine->pushContext(ctx);
+ ctx = engine->currentContext;
+ }
+
+ if (context >= 0) {
+ QQmlContext *extraContext = qmlContext(QQmlDebugService::objectForId(context));
+ if (extraContext) {
+ engine->pushContext(QV4::QmlContext::create(ctx, QQmlContextData::get(extraContext),
+ &scopeObject));
+ ctx = engine->currentContext;
+ }
+ } else if (frameNr < 0) { // Use QML context if available
QQmlEngine *qmlEngine = engine->qmlEngine();
if (qmlEngine) {
QQmlContext *qmlRootContext = qmlEngine->rootContext();
@@ -89,13 +107,6 @@ void JavaScriptJob::run()
engine->pushContext(ctx->newWithContext(withContext->toObject(engine)));
ctx = engine->currentContext;
}
- } else {
- if (frameNr > 0) {
- for (int i = 0; i < frameNr; ++i) {
- ctx = engine->parentContext(ctx);
- }
- engine->pushContext(ctx);
- }
}
QV4::Script script(ctx, this->script);
@@ -206,7 +217,7 @@ void ValueLookupJob::run()
QQmlContextData::get(engine->qmlEngine()->rootContext()),
scopeObject.data()));
}
- foreach (const QJsonValue &handle, handles) {
+ for (const QJsonValue &handle : handles) {
QV4DataCollector::Ref ref = handle.toInt();
if (!collector->isValidRef(ref)) {
exception = QString::fromLatin1("Invalid Ref: %1").arg(ref);
@@ -225,8 +236,9 @@ const QString &ValueLookupJob::exceptionMessage() const
}
ExpressionEvalJob::ExpressionEvalJob(QV4::ExecutionEngine *engine, int frameNr,
- const QString &expression, QV4DataCollector *collector) :
- JavaScriptJob(engine, frameNr, expression), collector(collector)
+ int context, const QString &expression,
+ QV4DataCollector *collector) :
+ JavaScriptJob(engine, frameNr, context, expression), collector(collector)
{
}
@@ -259,7 +271,7 @@ GatherSourcesJob::GatherSourcesJob(QV4::ExecutionEngine *engine)
void GatherSourcesJob::run()
{
- foreach (QV4::CompiledData::CompilationUnit *unit, engine->compilationUnits) {
+ for (QV4::CompiledData::CompilationUnit *unit : qAsConst(engine->compilationUnits)) {
QString fileName = unit->fileName();
if (!fileName.isEmpty())
sources.append(fileName);
@@ -272,7 +284,7 @@ const QStringList &GatherSourcesJob::result() const
}
EvalJob::EvalJob(QV4::ExecutionEngine *engine, const QString &script) :
- JavaScriptJob(engine, /*frameNr*/-1, script), result(false)
+ JavaScriptJob(engine, /*frameNr*/-1, /*context*/ -1, script), result(false)
{}
void EvalJob::handleResult(QV4::ScopedValue &result)
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.h
index 721f42b7c2..00d3e6206a 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.h
@@ -60,12 +60,13 @@ class JavaScriptJob : public QV4DebugJob
{
QV4::ExecutionEngine *engine;
int frameNr;
+ int context;
const QString &script;
bool resultIsException;
public:
- JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr, const QString &script);
- void run();
+ JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr, int context, const QString &script);
+ void run() override;
bool hasExeption() const;
protected:
@@ -90,7 +91,7 @@ class BacktraceJob: public CollectJob
int toFrame;
public:
BacktraceJob(QV4DataCollector *collector, int fromFrame, int toFrame);
- void run();
+ void run() override;
};
class FrameJob: public CollectJob
@@ -100,7 +101,7 @@ class FrameJob: public CollectJob
public:
FrameJob(QV4DataCollector *collector, int frameNr);
- void run();
+ void run() override;
bool wasSuccessful() const;
};
@@ -112,7 +113,7 @@ class ScopeJob: public CollectJob
public:
ScopeJob(QV4DataCollector *collector, int frameNr, int scopeNr);
- void run();
+ void run() override;
bool wasSuccessful() const;
};
@@ -123,7 +124,7 @@ class ValueLookupJob: public CollectJob
public:
ValueLookupJob(const QJsonArray &handles, QV4DataCollector *collector);
- void run();
+ void run() override;
const QString &exceptionMessage() const;
};
@@ -135,9 +136,9 @@ class ExpressionEvalJob: public JavaScriptJob
QJsonArray collectedRefs;
public:
- ExpressionEvalJob(QV4::ExecutionEngine *engine, int frameNr, const QString &expression,
- QV4DataCollector *collector);
- virtual void handleResult(QV4::ScopedValue &value);
+ ExpressionEvalJob(QV4::ExecutionEngine *engine, int frameNr, int context,
+ const QString &expression, QV4DataCollector *collector);
+ void handleResult(QV4::ScopedValue &value) override;
const QString &exceptionMessage() const;
const QJsonObject &returnValue() const;
const QJsonArray &refs() const;
@@ -150,7 +151,7 @@ class GatherSourcesJob: public QV4DebugJob
public:
GatherSourcesJob(QV4::ExecutionEngine *engine);
- void run();
+ void run() override;
const QStringList &result() const;
};
@@ -161,7 +162,7 @@ class EvalJob: public JavaScriptJob
public:
EvalJob(QV4::ExecutionEngine *engine, const QString &script);
- virtual void handleResult(QV4::ScopedValue &result);
+ void handleResult(QV4::ScopedValue &result) override;
bool resultAsBoolean() const;
};
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
index 00c5c1ad77..1d2cc092dc 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
@@ -152,7 +152,7 @@ class UnknownV8CommandHandler: public V8CommandHandler
public:
UnknownV8CommandHandler(): V8CommandHandler(QString()) {}
- virtual void handleRequest()
+ void handleRequest() override
{
QString msg = QLatin1String("unimplemented command \"")
+ req.value(QLatin1String("command")).toString()
@@ -167,7 +167,7 @@ class V8VersionRequest: public V8CommandHandler
public:
V8VersionRequest(): V8CommandHandler(QStringLiteral("version")) {}
- virtual void handleRequest()
+ void handleRequest() override
{
addCommand();
addRequestSequence();
@@ -177,6 +177,7 @@ public:
body.insert(QStringLiteral("V8Version"),
QLatin1String("this is not V8, this is V4 in Qt " QT_VERSION_STR));
body.insert(QStringLiteral("UnpausedEvaluate"), true);
+ body.insert(QStringLiteral("ContextEvaluate"), true);
addBody(body);
}
};
@@ -186,7 +187,7 @@ class V8SetBreakPointRequest: public V8CommandHandler
public:
V8SetBreakPointRequest(): V8CommandHandler(QStringLiteral("setbreakpoint")) {}
- virtual void handleRequest()
+ void handleRequest() override
{
// decypher the payload:
QJsonObject args = req.value(QLatin1String("arguments")).toObject();
@@ -237,7 +238,7 @@ class V8ClearBreakPointRequest: public V8CommandHandler
public:
V8ClearBreakPointRequest(): V8CommandHandler(QStringLiteral("clearbreakpoint")) {}
- virtual void handleRequest()
+ void handleRequest() override
{
// decypher the payload:
QJsonObject args = req.value(QLatin1String("arguments")).toObject();
@@ -270,7 +271,7 @@ class V8BacktraceRequest: public V8CommandHandler
public:
V8BacktraceRequest(): V8CommandHandler(QStringLiteral("backtrace")) {}
- virtual void handleRequest()
+ void handleRequest() override
{
// decypher the payload:
@@ -303,7 +304,7 @@ class V8FrameRequest: public V8CommandHandler
public:
V8FrameRequest(): V8CommandHandler(QStringLiteral("frame")) {}
- virtual void handleRequest()
+ void handleRequest() override
{
// decypher the payload:
QJsonObject arguments = req.value(QLatin1String("arguments")).toObject();
@@ -345,7 +346,7 @@ class V8ScopeRequest: public V8CommandHandler
public:
V8ScopeRequest(): V8CommandHandler(QStringLiteral("scope")) {}
- virtual void handleRequest()
+ void handleRequest() override
{
// decypher the payload:
QJsonObject arguments = req.value(QLatin1String("arguments")).toObject();
@@ -390,7 +391,7 @@ class V8LookupRequest: public V8CommandHandler
public:
V8LookupRequest(): V8CommandHandler(QStringLiteral("lookup")) {}
- virtual void handleRequest()
+ void handleRequest() override
{
// decypher the payload:
QJsonObject arguments = req.value(QLatin1String("arguments")).toObject();
@@ -430,7 +431,7 @@ class V8ContinueRequest: public V8CommandHandler
public:
V8ContinueRequest(): V8CommandHandler(QStringLiteral("continue")) {}
- virtual void handleRequest()
+ void handleRequest() override
{
// decypher the payload:
QJsonObject arguments = req.value(QLatin1String("arguments")).toObject();
@@ -476,7 +477,7 @@ class V8DisconnectRequest: public V8CommandHandler
public:
V8DisconnectRequest(): V8CommandHandler(QStringLiteral("disconnect")) {}
- virtual void handleRequest()
+ void handleRequest() override
{
debugService->debuggerAgent.removeAllBreakPoints();
debugService->debuggerAgent.resumeAll();
@@ -494,7 +495,7 @@ class V8SetExceptionBreakRequest: public V8CommandHandler
public:
V8SetExceptionBreakRequest(): V8CommandHandler(QStringLiteral("setexceptionbreak")) {}
- virtual void handleRequest()
+ void handleRequest() override
{
bool wasEnabled = debugService->debuggerAgent.breakOnThrow();
@@ -534,7 +535,7 @@ class V8ScriptsRequest: public V8CommandHandler
public:
V8ScriptsRequest(): V8CommandHandler(QStringLiteral("scripts")) {}
- virtual void handleRequest()
+ void handleRequest() override
{
//decypher the payload:
QJsonObject arguments = req.value(QLatin1String("arguments")).toObject();
@@ -558,7 +559,7 @@ public:
debugger->runInEngine(&job);
QJsonArray body;
- foreach (const QString &source, job.result()) {
+ for (const QString &source : job.result()) {
QJsonObject src;
src[QLatin1String("name")] = source;
src[QLatin1String("scriptType")] = 4;
@@ -606,10 +607,11 @@ class V8EvaluateRequest: public V8CommandHandler
public:
V8EvaluateRequest(): V8CommandHandler(QStringLiteral("evaluate")) {}
- virtual void handleRequest()
+ void handleRequest() override
{
QJsonObject arguments = req.value(QLatin1String("arguments")).toObject();
QString expression = arguments.value(QLatin1String("expression")).toString();
+ int context = arguments.value(QLatin1String("context")).toInt(-1);
int frame = -1;
QV4Debugger *debugger = debugService->debuggerAgent.pausedDebugger();
@@ -627,7 +629,8 @@ public:
frame = arguments.value(QLatin1String("frame")).toInt(0);
}
- ExpressionEvalJob job(debugger->engine(), frame, expression, debugger->collector());
+ ExpressionEvalJob job(debugger->engine(), frame, context, expression,
+ debugger->collector());
debugger->runInEngine(&job);
if (job.hasExeption()) {
createErrorResponse(job.exceptionMessage());
@@ -718,7 +721,8 @@ void QV4DebugServiceImpl::stateAboutToBeChanged(State state)
{
QMutexLocker lock(&m_configMutex);
if (state == Enabled) {
- foreach (QV4Debugger *debugger, debuggerAgent.debuggers()) {
+ const auto debuggers = debuggerAgent.debuggers();
+ for (QV4Debugger *debugger : debuggers) {
QV4::ExecutionEngine *ee = debugger->engine();
if (!ee->debugger())
ee->setDebugger(debugger);
@@ -737,7 +741,7 @@ void QV4DebugServiceImpl::signalEmitted(const QString &signal)
//Normalize to Lower case.
QString signalName = signal.left(signal.indexOf(QLatin1Char('('))).toLower();
- foreach (const QString &signal, breakOnSignals) {
+ for (const QString &signal : qAsConst(breakOnSignals)) {
if (signal == signalName) {
// TODO: pause debugger
break;