diff options
author | Ulf Hermann <ulf.hermann@theqtcompany.com> | 2015-07-16 14:12:04 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@theqtcompany.com> | 2015-07-31 11:31:09 +0000 |
commit | e061150cc54255726b8cda8cc928d3ed03ea8093 (patch) | |
tree | ea43c36b901831f3037b2fc5f9d141b868493ccd /src/qml/debugger | |
parent | 0768d0dff9b2dc647da480bd73f5f25c84fdb427 (diff) |
Remove pimpl from all classes derived from QQmlDebugService
There is no point in using pimpl for purely internal classes,
especially when we move them to their own plugins.
Change-Id: I2ee8bf2ded2242d91bab89f589a131dc3bcc9a55
Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
Diffstat (limited to 'src/qml/debugger')
-rw-r--r-- | src/qml/debugger/debugger.pri | 2 | ||||
-rw-r--r-- | src/qml/debugger/qdebugmessageservice.cpp | 45 | ||||
-rw-r--r-- | src/qml/debugger/qdebugmessageservice_p.h | 6 | ||||
-rw-r--r-- | src/qml/debugger/qqmlconfigurabledebugservice.cpp | 39 | ||||
-rw-r--r-- | src/qml/debugger/qqmlconfigurabledebugservice_p.h | 16 | ||||
-rw-r--r-- | src/qml/debugger/qqmlconfigurabledebugservice_p_p.h | 71 | ||||
-rw-r--r-- | src/qml/debugger/qqmldebugserver.cpp | 1 | ||||
-rw-r--r-- | src/qml/debugger/qqmldebugservice.cpp | 32 | ||||
-rw-r--r-- | src/qml/debugger/qqmldebugservice_p.h | 3 | ||||
-rw-r--r-- | src/qml/debugger/qqmldebugservice_p_p.h | 70 | ||||
-rw-r--r-- | src/qml/debugger/qqmlprofilerservice.cpp | 22 | ||||
-rw-r--r-- | src/qml/debugger/qv4debugservice.cpp | 501 | ||||
-rw-r--r-- | src/qml/debugger/qv4debugservice_p.h | 63 |
13 files changed, 343 insertions, 528 deletions
diff --git a/src/qml/debugger/debugger.pri b/src/qml/debugger/debugger.pri index cbb1646ff6..b3e3b3fc90 100644 --- a/src/qml/debugger/debugger.pri +++ b/src/qml/debugger/debugger.pri @@ -20,7 +20,6 @@ HEADERS += \ $$PWD/qqmldebugconnector_p.h \ $$PWD/qqmldebugpluginmanager_p.h \ $$PWD/qqmldebugservice_p.h \ - $$PWD/qqmldebugservice_p_p.h \ $$PWD/qqmlprofilerservice_p.h \ $$PWD/qqmldebugserver_p.h \ $$PWD/qqmldebugserverconnection_p.h \ @@ -32,7 +31,6 @@ HEADERS += \ $$PWD/qdebugmessageservice_p.h \ $$PWD/qv4debugservice_p.h \ $$PWD/qqmlconfigurabledebugservice_p.h \ - $$PWD/qqmlconfigurabledebugservice_p_p.h \ $$PWD/qqmlenginecontrolservice_p.h \ $$PWD/qqmlprofilerdefinitions_p.h \ $$PWD/qqmlabstractprofileradapter_p.h \ diff --git a/src/qml/debugger/qdebugmessageservice.cpp b/src/qml/debugger/qdebugmessageservice.cpp index 88ef9eb96c..3e5cec54b1 100644 --- a/src/qml/debugger/qdebugmessageservice.cpp +++ b/src/qml/debugger/qdebugmessageservice.cpp @@ -32,10 +32,8 @@ ****************************************************************************/ #include "qdebugmessageservice_p.h" -#include "qqmldebugservice_p_p.h" #include <QDataStream> -#include <QMutex> QT_BEGIN_NAMESPACE @@ -47,29 +45,15 @@ void DebugMessageHandler(QtMsgType type, const QMessageLogContext &ctxt, QDebugMessageService::instance()->sendDebugMessage(type, ctxt, buf); } -class QDebugMessageServicePrivate : public QQmlDebugServicePrivate -{ -public: - QDebugMessageServicePrivate() : QQmlDebugServicePrivate(QStringLiteral("DebugMessages"), 2), - oldMsgHandler(0), prevState(QQmlDebugService::NotConnected) - { - } - - QtMessageHandler oldMsgHandler; - QQmlDebugService::State prevState; - QMutex initMutex; -}; - QDebugMessageService::QDebugMessageService(QObject *parent) : - QQmlDebugService(*(new QDebugMessageServicePrivate), parent) + QQmlDebugService(QStringLiteral("DebugMessages"), 2, parent), oldMsgHandler(0), + prevState(QQmlDebugService::NotConnected) { - Q_D(QDebugMessageService); - // don't execute stateChanged() in parallel - QMutexLocker lock(&d->initMutex); + QMutexLocker lock(&initMutex); if (state() == Enabled) { - d->oldMsgHandler = qInstallMessageHandler(DebugMessageHandler); - d->prevState = Enabled; + oldMsgHandler = qInstallMessageHandler(DebugMessageHandler); + prevState = Enabled; } } @@ -82,8 +66,6 @@ void QDebugMessageService::sendDebugMessage(QtMsgType type, const QMessageLogContext &ctxt, const QString &buf) { - Q_D(QDebugMessageService); - //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. @@ -94,26 +76,25 @@ void QDebugMessageService::sendDebugMessage(QtMsgType type, ws << ctxt.line << QString::fromLatin1(ctxt.function).toUtf8(); emit messageToClient(name(), message); - if (d->oldMsgHandler) - (*d->oldMsgHandler)(type, ctxt, buf); + if (oldMsgHandler) + (*oldMsgHandler)(type, ctxt, buf); } void QDebugMessageService::stateChanged(State state) { - Q_D(QDebugMessageService); - QMutexLocker lock(&d->initMutex); + QMutexLocker lock(&initMutex); - if (state != Enabled && d->prevState == Enabled) { - QtMessageHandler handler = qInstallMessageHandler(d->oldMsgHandler); + 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 && d->prevState != Enabled) { - d->oldMsgHandler = qInstallMessageHandler(DebugMessageHandler); + } else if (state == Enabled && prevState != Enabled) { + oldMsgHandler = qInstallMessageHandler(DebugMessageHandler); } - d->prevState = state; + prevState = state; } QT_END_NAMESPACE diff --git a/src/qml/debugger/qdebugmessageservice_p.h b/src/qml/debugger/qdebugmessageservice_p.h index 694cd0e64c..55e92d437f 100644 --- a/src/qml/debugger/qdebugmessageservice_p.h +++ b/src/qml/debugger/qdebugmessageservice_p.h @@ -48,6 +48,7 @@ #include "qqmldebugservice_p.h" #include <QtCore/qlogging.h> +#include <QtCore/qmutex.h> QT_BEGIN_NAMESPACE @@ -68,8 +69,9 @@ protected: void stateChanged(State); private: - Q_DISABLE_COPY(QDebugMessageService) - Q_DECLARE_PRIVATE(QDebugMessageService) + QtMessageHandler oldMsgHandler; + QQmlDebugService::State prevState; + QMutex initMutex; }; QT_END_NAMESPACE diff --git a/src/qml/debugger/qqmlconfigurabledebugservice.cpp b/src/qml/debugger/qqmlconfigurabledebugservice.cpp index 9382cea42e..679fa04abe 100644 --- a/src/qml/debugger/qqmlconfigurabledebugservice.cpp +++ b/src/qml/debugger/qqmlconfigurabledebugservice.cpp @@ -32,48 +32,32 @@ ****************************************************************************/ #include "qqmlconfigurabledebugservice_p.h" -#include "qqmlconfigurabledebugservice_p_p.h" #include "qqmldebugconnector_p.h" QT_BEGIN_NAMESPACE QQmlConfigurableDebugService::QQmlConfigurableDebugService(const QString &name, float version, QObject *parent) : - QQmlDebugService((*new QQmlConfigurableDebugServicePrivate(name, version)), parent) + QQmlDebugService(name, version, parent), m_configMutex(QMutex::Recursive) { init(); } -QQmlConfigurableDebugService::QQmlConfigurableDebugService(QQmlDebugServicePrivate &dd, - QObject *parent) : - QQmlDebugService(dd, parent) -{ - init(); -} - -QMutex *QQmlConfigurableDebugService::configMutex() -{ - Q_D(QQmlConfigurableDebugService); - return &d->configMutex; -} - void QQmlConfigurableDebugService::init() { - Q_D(QQmlConfigurableDebugService); - QMutexLocker lock(&d->configMutex); + QMutexLocker lock(&m_configMutex); // If we're not enabled or not blocking, don't wait for configuration - d->waitingForConfiguration = (state() == Enabled && - QQmlDebugConnector::instance()->blockingMode()); + m_waitingForConfiguration = (state() == Enabled && + QQmlDebugConnector::instance()->blockingMode()); } void QQmlConfigurableDebugService::stopWaiting() { - Q_D(QQmlConfigurableDebugService); - QMutexLocker lock(&d->configMutex); - d->waitingForConfiguration = false; - foreach (QQmlEngine *engine, d->waitingEngines) + QMutexLocker lock(&m_configMutex); + m_waitingForConfiguration = false; + foreach (QQmlEngine *engine, m_waitingEngines) emit attachedToEngine(engine); - d->waitingEngines.clear(); + m_waitingEngines.clear(); } void QQmlConfigurableDebugService::stateChanged(QQmlDebugService::State newState) @@ -86,10 +70,9 @@ void QQmlConfigurableDebugService::stateChanged(QQmlDebugService::State newState void QQmlConfigurableDebugService::engineAboutToBeAdded(QQmlEngine *engine) { - Q_D(QQmlConfigurableDebugService); - QMutexLocker lock(&d->configMutex); - if (d->waitingForConfiguration) - d->waitingEngines.append(engine); + QMutexLocker lock(&m_configMutex); + if (m_waitingForConfiguration) + m_waitingEngines.append(engine); else emit attachedToEngine(engine); } diff --git a/src/qml/debugger/qqmlconfigurabledebugservice_p.h b/src/qml/debugger/qqmlconfigurabledebugservice_p.h index c7afcb94dd..28f0f4dfe2 100644 --- a/src/qml/debugger/qqmlconfigurabledebugservice_p.h +++ b/src/qml/debugger/qqmlconfigurabledebugservice_p.h @@ -47,31 +47,25 @@ // #include "qqmldebugservice_p.h" +#include <QtCore/qmutex.h> QT_BEGIN_NAMESPACE -class QMutex; -class QQmlConfigurableDebugServicePrivate; class QQmlConfigurableDebugService : public QQmlDebugService { Q_OBJECT -public: - QQmlConfigurableDebugService(const QString &name, float version, QObject *parent = 0); - protected: - QQmlConfigurableDebugService(QQmlDebugServicePrivate &dd, QObject *parent = 0); + QQmlConfigurableDebugService(const QString &name, float version, QObject *parent = 0); - QMutex *configMutex(); void stopWaiting(); void init(); void stateChanged(State); void engineAboutToBeAdded(QQmlEngine *); - virtual ~QQmlConfigurableDebugService() {} -private: - Q_DISABLE_COPY(QQmlConfigurableDebugService) - Q_DECLARE_PRIVATE(QQmlConfigurableDebugService) + QMutex m_configMutex; + QList<QQmlEngine *> m_waitingEngines; + bool m_waitingForConfiguration; }; QT_END_NAMESPACE diff --git a/src/qml/debugger/qqmlconfigurabledebugservice_p_p.h b/src/qml/debugger/qqmlconfigurabledebugservice_p_p.h deleted file mode 100644 index fcdefe3954..0000000000 --- a/src/qml/debugger/qqmlconfigurabledebugservice_p_p.h +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://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 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QQMLCONFIGURABLEDEBUGSERVICE_P_H -#define QQMLCONFIGURABLEDEBUGSERVICE_P_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 "qqmldebugservice_p.h" -#include "qqmldebugservice_p_p.h" - -#include <QMutex> - -QT_BEGIN_NAMESPACE - -class QQmlEngine; - -class QQmlConfigurableDebugServicePrivate : public QQmlDebugServicePrivate -{ - Q_DECLARE_PUBLIC(QQmlConfigurableDebugService) -public: - QQmlConfigurableDebugServicePrivate(const QString &name, float version) : - QQmlDebugServicePrivate(name, version), configMutex(QMutex::Recursive) {} - - QMutex configMutex; - QList<QQmlEngine *> waitingEngines; - bool waitingForConfiguration; -}; - -QT_END_NAMESPACE - -#endif // QQMLCONFIGURABLEDEBUGSERVICE_P_H diff --git a/src/qml/debugger/qqmldebugserver.cpp b/src/qml/debugger/qqmldebugserver.cpp index a2cb8fd5a1..711550efce 100644 --- a/src/qml/debugger/qqmldebugserver.cpp +++ b/src/qml/debugger/qqmldebugserver.cpp @@ -34,7 +34,6 @@ #include "qqmldebugserver_p.h" #include "qqmldebugserverconnection_p.h" #include "qqmldebugservice_p.h" -#include "qqmldebugservice_p_p.h" #include <private/qqmlengine_p.h> #include <private/qqmlglobal_p.h> diff --git a/src/qml/debugger/qqmldebugservice.cpp b/src/qml/debugger/qqmldebugservice.cpp index edebf7a8cb..3a69799da8 100644 --- a/src/qml/debugger/qqmldebugservice.cpp +++ b/src/qml/debugger/qqmldebugservice.cpp @@ -32,7 +32,6 @@ ****************************************************************************/ #include "qqmldebugservice_p.h" -#include "qqmldebugservice_p_p.h" #include "qqmldebugconnector_p.h" #include <private/qqmldata_p.h> #include <private/qqmlcontext_p.h> @@ -43,6 +42,19 @@ QT_BEGIN_NAMESPACE +class QQmlDebugServer; + +class QQmlDebugServicePrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QQmlDebugService) +public: + QQmlDebugServicePrivate(const QString &name, float version); + + const QString name; + const float version; + QQmlDebugService::State state; +}; + QQmlDebugServicePrivate::QQmlDebugServicePrivate(const QString &name, float version) : name(name), version(version), state(QQmlDebugService::NotConnected) { @@ -51,33 +63,17 @@ QQmlDebugServicePrivate::QQmlDebugServicePrivate(const QString &name, float vers QQmlDebugService::QQmlDebugService(const QString &name, float version, QObject *parent) : QObject(*(new QQmlDebugServicePrivate(name, version)), parent) { - registerService(); -} - -QQmlDebugService::QQmlDebugService(QQmlDebugServicePrivate &dd, QObject *parent) - : QObject(dd, parent) -{ - registerService(); -} - -/** - Registers the service. This should be called in the constructor of the inherited class. From - then on the service might get asynchronous calls to messageReceived(). - */ -QQmlDebugService::State QQmlDebugService::registerService() -{ Q_D(QQmlDebugService); QQmlDebugConnector *server = QQmlDebugConnector::instance(); if (!server) - return NotConnected; + return; if (server->service(d->name)) { qWarning() << "QQmlDebugService: Conflicting plugin name" << d->name; } else { server->addService(this); } - return state(); } QQmlDebugService::~QQmlDebugService() diff --git a/src/qml/debugger/qqmldebugservice_p.h b/src/qml/debugger/qqmldebugservice_p.h index 311ce3e355..3d692133cc 100644 --- a/src/qml/debugger/qqmldebugservice_p.h +++ b/src/qml/debugger/qqmldebugservice_p.h @@ -87,9 +87,6 @@ public: protected: explicit QQmlDebugService(const QString &, float version, QObject *parent = 0); - QQmlDebugService(QQmlDebugServicePrivate &dd, QObject *parent = 0); - - State registerService(); signals: void attachedToEngine(QQmlEngine *); diff --git a/src/qml/debugger/qqmldebugservice_p_p.h b/src/qml/debugger/qqmldebugservice_p_p.h deleted file mode 100644 index e1e93e5e0c..0000000000 --- a/src/qml/debugger/qqmldebugservice_p_p.h +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://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 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QQMLDEBUGSERVICE_P_H -#define QQMLDEBUGSERVICE_P_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 "qqmldebugservice_p.h" -#include <QtCore/qglobal.h> -#include <private/qobject_p.h> - -QT_BEGIN_NAMESPACE - - -class QQmlDebugServer; - -class QQmlDebugServicePrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QQmlDebugService) -public: - QQmlDebugServicePrivate(const QString &name, float version); - - const QString name; - const float version; - QQmlDebugService::State state; -}; - -QT_END_NAMESPACE - -#endif // QQMLDEBUGSERVICE_P_H diff --git a/src/qml/debugger/qqmlprofilerservice.cpp b/src/qml/debugger/qqmlprofilerservice.cpp index 62eae0ddd8..dfd9a0cd3b 100644 --- a/src/qml/debugger/qqmlprofilerservice.cpp +++ b/src/qml/debugger/qqmlprofilerservice.cpp @@ -63,7 +63,7 @@ QQmlProfilerService::~QQmlProfilerService() void QQmlProfilerService::dataReady(QQmlAbstractProfilerAdapter *profiler) { - QMutexLocker lock(configMutex()); + QMutexLocker lock(&m_configMutex); bool dataComplete = true; for (QMultiMap<qint64, QQmlAbstractProfilerAdapter *>::iterator i(m_startTimes.begin()); i != m_startTimes.end();) { if (i.value() == profiler) { @@ -104,7 +104,7 @@ void QQmlProfilerService::engineAboutToBeAdded(QQmlEngine *engine) Q_ASSERT_X(QThread::currentThread() == engine->thread(), Q_FUNC_INFO, "QML profilers have to be added from the engine thread"); - QMutexLocker lock(configMutex()); + QMutexLocker lock(&m_configMutex); QQmlProfilerAdapter *qmlAdapter = new QQmlProfilerAdapter(this, QQmlEnginePrivate::get(engine)); QV4ProfilerAdapter *v4Adapter = new QV4ProfilerAdapter(this, QV8Engine::getV4(engine->handle())); addEngineProfiler(qmlAdapter, engine); @@ -118,7 +118,7 @@ void QQmlProfilerService::engineAdded(QQmlEngine *engine) Q_ASSERT_X(QThread::currentThread() == engine->thread(), Q_FUNC_INFO, "QML profilers have to be added from the engine thread"); - QMutexLocker lock(configMutex()); + QMutexLocker lock(&m_configMutex); foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine)) profiler->stopWaiting(); } @@ -128,7 +128,7 @@ void QQmlProfilerService::engineAboutToBeRemoved(QQmlEngine *engine) Q_ASSERT_X(QThread::currentThread() == engine->thread(), Q_FUNC_INFO, "QML profilers have to be removed from the engine thread"); - QMutexLocker lock(configMutex()); + QMutexLocker lock(&m_configMutex); bool isRunning = false; foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine)) { if (profiler->isRunning()) @@ -148,7 +148,7 @@ void QQmlProfilerService::engineRemoved(QQmlEngine *engine) Q_ASSERT_X(QThread::currentThread() == engine->thread(), Q_FUNC_INFO, "QML profilers have to be removed from the engine thread"); - QMutexLocker lock(configMutex()); + QMutexLocker lock(&m_configMutex); foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine)) { removeProfilerFromStartTimes(profiler); delete profiler; @@ -165,7 +165,7 @@ void QQmlProfilerService::addEngineProfiler(QQmlAbstractProfilerAdapter *profile void QQmlProfilerService::addGlobalProfiler(QQmlAbstractProfilerAdapter *profiler) { - QMutexLocker lock(configMutex()); + QMutexLocker lock(&m_configMutex); profiler->synchronize(m_timer); m_globalProfilers.append(profiler); // Global profiler, not connected to a specific engine. @@ -181,7 +181,7 @@ void QQmlProfilerService::addGlobalProfiler(QQmlAbstractProfilerAdapter *profile void QQmlProfilerService::removeGlobalProfiler(QQmlAbstractProfilerAdapter *profiler) { - QMutexLocker lock(configMutex()); + QMutexLocker lock(&m_configMutex); removeProfilerFromStartTimes(profiler); m_globalProfilers.removeOne(profiler); delete profiler; @@ -208,7 +208,7 @@ void QQmlProfilerService::removeProfilerFromStartTimes(const QQmlAbstractProfile */ void QQmlProfilerService::startProfiling(QQmlEngine *engine, quint64 features) { - QMutexLocker lock(configMutex()); + QMutexLocker lock(&m_configMutex); QByteArray message; QQmlDebugStream d(&message, QIODevice::WriteOnly); @@ -257,7 +257,7 @@ void QQmlProfilerService::startProfiling(QQmlEngine *engine, quint64 features) */ void QQmlProfilerService::stopProfiling(QQmlEngine *engine) { - QMutexLocker lock(configMutex()); + QMutexLocker lock(&m_configMutex); QList<QQmlAbstractProfilerAdapter *> stopping; QList<QQmlAbstractProfilerAdapter *> reporting; @@ -339,7 +339,7 @@ void QQmlProfilerService::sendMessages() void QQmlProfilerService::stateAboutToBeChanged(QQmlDebugService::State newState) { - QMutexLocker lock(configMutex()); + QMutexLocker lock(&m_configMutex); if (state() == newState) return; @@ -353,7 +353,7 @@ void QQmlProfilerService::stateAboutToBeChanged(QQmlDebugService::State newState void QQmlProfilerService::messageReceived(const QByteArray &message) { - QMutexLocker lock(configMutex()); + QMutexLocker lock(&m_configMutex); QByteArray rwData = message; QQmlDebugStream stream(&rwData, QIODevice::ReadOnly); 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 diff --git a/src/qml/debugger/qv4debugservice_p.h b/src/qml/debugger/qv4debugservice_p.h index f7b38b11b6..b824b47b23 100644 --- a/src/qml/debugger/qv4debugservice_p.h +++ b/src/qml/debugger/qv4debugservice_p.h @@ -46,12 +46,38 @@ // #include "qqmlconfigurabledebugservice_p.h" +#include <private/qv4debugging_p.h> + +#include <QtCore/QJsonValue> QT_BEGIN_NAMESPACE namespace QV4 { struct ExecutionEngine; } + class QQmlEngine; -class QV4DebugServicePrivate; +class VariableCollector; +class V8CommandHandler; +class UnknownV8CommandHandler; +class QV4DebugService; + +class QV4DebuggerAgent : public QV4::Debugging::DebuggerAgent +{ + Q_OBJECT +public: + QV4DebuggerAgent(QV4DebugService *debugService); + QV4::Debugging::Debugger *firstDebugger() const; + bool isRunning() const; + +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: + QV4DebugService *debugService; +}; + class QV4DebugService : public QQmlConfigurableDebugService { @@ -65,6 +91,21 @@ public: void engineAboutToBeRemoved(QQmlEngine *engine); void signalEmitted(const QString &signal); + void send(QJsonObject v8Payload); + + QJsonObject buildScope(int frameNr, int scopeNr, QV4::Debugging::Debugger *debugger); + QJsonArray buildRefs(); + QJsonValue lookup(int refId) const; + + QJsonObject buildFrame(const QV4::StackFrame &stackFrame, int frameNr, + QV4::Debugging::Debugger *debugger); + int selectedFrame() const; + void selectFrame(int frameNr); + + void clearHandles(QV4::ExecutionEngine *engine); + + VariableCollector *collector() const; + QV4DebuggerAgent debuggerAgent; protected: void messageReceived(const QByteArray &); @@ -72,10 +113,24 @@ protected: private: void handleV8Request(const QByteArray &payload); + static QByteArray packMessage(const QByteArray &command, + const QByteArray &message = QByteArray()); + void processCommand(const QByteArray &command, const QByteArray &data); + V8CommandHandler *v8CommandHandler(const QString &command) const; + int encodeScopeType(QV4::Heap::ExecutionContext::ContextType scopeType); -private: - Q_DISABLE_COPY(QV4DebugService) - Q_DECLARE_PRIVATE(QV4DebugService) + QStringList breakOnSignals; + QMap<int, QV4::Debugging::Debugger *> debuggerMap; + static int debuggerIndex; + static int sequence; + const int version; + + QScopedPointer<VariableCollector> theCollector; + int theSelectedFrame; + + void addHandler(V8CommandHandler* handler); + QHash<QString, V8CommandHandler*> handlers; + QScopedPointer<UnknownV8CommandHandler> unknownV8CommandHandler; }; QT_END_NAMESPACE |