diff options
Diffstat (limited to 'src/plugins/qmltooling/qmldbg_debugger')
9 files changed, 610 insertions, 76 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro b/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro index 8d1a54e9e4..b0678ef2d9 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro +++ b/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro @@ -12,9 +12,11 @@ SOURCES += \ $$PWD/qqmlnativedebugservice.cpp \ $$PWD/qqmlwatcher.cpp \ $$PWD/qv4debugservice.cpp \ + $$PWD/qv4debugger.cpp \ $$PWD/qv4debuggeragent.cpp \ $$PWD/qv4datacollector.cpp + HEADERS += \ $$PWD/../shared/qqmlconfigurabledebugservice.h \ $$PWD/qdebugmessageservice.h \ @@ -23,6 +25,7 @@ HEADERS += \ $$PWD/qqmlnativedebugservice.h \ $$PWD/qqmlwatcher.h \ $$PWD/qv4debugservice.h \ + $$PWD/qv4debugger.h \ $$PWD/qv4debuggeragent.h \ $$PWD/qv4datacollector.h diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp index 377f0845d0..e3347be14c 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp @@ -40,6 +40,7 @@ #include <private/qv4runtime_p.h> #include <QtCore/qjsonarray.h> +#include <QtCore/qjsonobject.h> QT_BEGIN_NAMESPACE @@ -208,13 +209,13 @@ QV4DataCollector::Ref QV4DataCollector::addScriptRef(const QString &scriptName) return ref; } -void QV4DataCollector::collectScope(QJsonObject *dict, QV4::Debugging::V4Debugger *debugger, - int frameNr, int scopeNr) +void QV4DataCollector::collectScope(QJsonObject *dict, QV4Debugger *debugger, int frameNr, + int scopeNr) { QStringList names; Refs refs; - if (debugger->state() == QV4::Debugging::V4Debugger::Paused) { + if (debugger->state() == QV4Debugger::Paused) { RefHolder holder(this, &refs); ArgumentCollectJob argumentsJob(m_engine, this, &names, frameNr, scopeNr); debugger->runInEngine(&argumentsJob); diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h index 0ea40f896c..bfa3bd2fe1 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h @@ -34,8 +34,9 @@ #ifndef QV4DATACOLLECTOR_H #define QV4DATACOLLECTOR_H +#include "qv4debugger.h" #include <private/qv4engine_p.h> -#include <private/qv4debugging_p.h> +#include <private/qv4persistent_p.h> QT_BEGIN_NAMESPACE @@ -60,8 +61,7 @@ public: Ref addFunctionRef(const QString &functionName); Ref addScriptRef(const QString &scriptName); - void collectScope(QJsonObject *dict, QV4::Debugging::V4Debugger *debugger, int frameNr, - int scopeNr); + void collectScope(QJsonObject *dict, QV4Debugger *debugger, int frameNr, int scopeNr); QV4::ExecutionEngine *engine() const { return m_engine; } @@ -101,7 +101,7 @@ private: QV4DataCollector::Refs *m_previousRefs; }; -class ExpressionEvalJob: public QV4::Debugging::V4Debugger::JavaScriptJob +class ExpressionEvalJob: public QV4Debugger::JavaScriptJob { QV4DataCollector *collector; QString exception; @@ -113,7 +113,7 @@ public: const QString &exceptionMessage() const; }; -class GatherSourcesJob: public QV4::Debugging::V4Debugger::Job +class GatherSourcesJob: public QV4Debugger::Job { QV4::ExecutionEngine *engine; QStringList sources; @@ -124,7 +124,7 @@ public: const QStringList &result() const; }; -class ArgumentCollectJob: public QV4::Debugging::V4Debugger::Job +class ArgumentCollectJob: public QV4Debugger::Job { QV4::ExecutionEngine *engine; QV4DataCollector *collector; @@ -138,7 +138,7 @@ public: void run(); }; -class LocalCollectJob: public QV4::Debugging::V4Debugger::Job +class LocalCollectJob: public QV4Debugger::Job { QV4::ExecutionEngine *engine; QV4DataCollector *collector; @@ -152,7 +152,7 @@ public: void run(); }; -class ThisCollectJob: public QV4::Debugging::V4Debugger::Job +class ThisCollectJob: public QV4Debugger::Job { QV4::ExecutionEngine *engine; QV4DataCollector *collector; @@ -166,7 +166,7 @@ public: bool myRun(); }; -class ExceptionCollectJob: public QV4::Debugging::V4Debugger::Job +class ExceptionCollectJob: public QV4Debugger::Job { QV4::ExecutionEngine *engine; QV4DataCollector *collector; diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp new file mode 100644 index 0000000000..6198e2c039 --- /dev/null +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp @@ -0,0 +1,358 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qv4debugger.h" + +#include <private/qv4scopedvalue_p.h> +#include <private/qv4script_p.h> + +QT_BEGIN_NAMESPACE + +QV4Debugger::BreakPoint::BreakPoint(const QString &fileName, int line) + : fileName(fileName), lineNumber(line) +{} + +inline uint qHash(const QV4Debugger::BreakPoint &b, uint seed = 0) Q_DECL_NOTHROW +{ + return qHash(b.fileName, seed) ^ b.lineNumber; +} + +inline bool operator==(const QV4Debugger::BreakPoint &a, + const QV4Debugger::BreakPoint &b) +{ + return a.lineNumber == b.lineNumber && a.fileName == b.fileName; +} + +QV4Debugger::JavaScriptJob::JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr, + const QString &script) + : engine(engine) + , frameNr(frameNr) + , script(script) + , resultIsException(false) +{} + +void QV4Debugger::JavaScriptJob::run() +{ + QV4::Scope scope(engine); + + QV4::ExecutionContextSaver saver(scope); + + QV4::ExecutionContext *ctx = engine->currentContext; + if (frameNr > 0) { + for (int i = 0; i < frameNr; ++i) { + ctx = engine->parentContext(ctx); + } + engine->pushContext(ctx); + } + + QV4::Script script(ctx, this->script); + 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(); + QV4::ScopedValue result(scope); + if (!scope.engine->hasException) + result = script.run(); + if (scope.engine->hasException) { + result = scope.engine->catchException(); + resultIsException = true; + } + handleResult(result); +} + +bool QV4Debugger::JavaScriptJob::hasExeption() const +{ + return resultIsException; +} + +class EvalJob: public QV4Debugger::JavaScriptJob +{ + bool result; + +public: + EvalJob(QV4::ExecutionEngine *engine, const QString &script) + : QV4Debugger::JavaScriptJob(engine, /*frameNr*/-1, script) + , result(false) + {} + + virtual void handleResult(QV4::ScopedValue &result) + { + this->result = result->toBoolean(); + } + + bool resultAsBoolean() const + { + return result; + } +}; + +QV4Debugger::QV4Debugger(QV4::ExecutionEngine *engine) + : m_engine(engine) + , m_state(Running) + , m_stepping(NotStepping) + , m_pauseRequested(false) + , m_haveBreakPoints(false) + , m_breakOnThrow(false) + , m_returnedValue(engine, QV4::Primitive::undefinedValue()) + , m_gatherSources(0) + , m_runningJob(0) +{ + static int debuggerId = qRegisterMetaType<QV4Debugger*>(); + static int pauseReasonId = qRegisterMetaType<QV4Debugger::PauseReason>(); + Q_UNUSED(debuggerId); + Q_UNUSED(pauseReasonId); +} + +QV4::ExecutionEngine *QV4Debugger::engine() const +{ + return m_engine; +} + +void QV4Debugger::pause() +{ + QMutexLocker locker(&m_lock); + if (m_state == Paused) + return; + m_pauseRequested = true; +} + +void QV4Debugger::resume(Speed speed) +{ + QMutexLocker locker(&m_lock); + if (m_state != Paused) + return; + + if (!m_returnedValue.isUndefined()) + m_returnedValue.set(m_engine, QV4::Encode::undefined()); + + m_currentContext.set(m_engine, *m_engine->currentContext); + m_stepping = speed; + m_runningCondition.wakeAll(); +} + +QV4Debugger::State QV4Debugger::state() const +{ + return m_state; +} + +void QV4Debugger::addBreakPoint(const QString &fileName, int lineNumber, const QString &condition) +{ + QMutexLocker locker(&m_lock); + m_breakPoints.insert(BreakPoint(fileName.mid(fileName.lastIndexOf('/') + 1), + lineNumber), condition); + m_haveBreakPoints = true; +} + +void QV4Debugger::removeBreakPoint(const QString &fileName, int lineNumber) +{ + QMutexLocker locker(&m_lock); + m_breakPoints.remove(BreakPoint(fileName.mid(fileName.lastIndexOf('/') + 1), + lineNumber)); + m_haveBreakPoints = !m_breakPoints.isEmpty(); +} + +void QV4Debugger::setBreakOnThrow(bool onoff) +{ + QMutexLocker locker(&m_lock); + + m_breakOnThrow = onoff; +} + +QV4Debugger::ExecutionState QV4Debugger::currentExecutionState() const +{ + ExecutionState state; + state.fileName = getFunction()->sourceFile(); + state.lineNumber = engine()->current->lineNumber; + + return state; +} + +bool QV4Debugger::pauseAtNextOpportunity() const { + return m_pauseRequested || m_haveBreakPoints || m_gatherSources || m_stepping >= StepOver; +} + +QVector<QV4::StackFrame> QV4Debugger::stackTrace(int frameLimit) const +{ + return m_engine->stackTrace(frameLimit); +} + +void QV4Debugger::maybeBreakAtInstruction() +{ + if (m_runningJob) // do not re-enter when we're doing a job for the debugger. + return; + + QMutexLocker locker(&m_lock); + + if (m_gatherSources) { + m_gatherSources->run(); + delete m_gatherSources; + m_gatherSources = 0; + } + + switch (m_stepping) { + case StepOver: + if (m_currentContext.asManaged()->d() != m_engine->current) + break; + // fall through + case StepIn: + pauseAndWait(Step); + return; + case StepOut: + case NotStepping: + break; + } + + if (m_pauseRequested) { // Serve debugging requests from the agent + m_pauseRequested = false; + pauseAndWait(PauseRequest); + } else if (m_haveBreakPoints) { + if (QV4::Function *f = getFunction()) { + const int lineNumber = engine()->current->lineNumber; + if (reallyHitTheBreakPoint(f->sourceFile(), lineNumber)) + pauseAndWait(BreakPointHit); + } + } +} + +void QV4Debugger::enteringFunction() +{ + if (m_runningJob) + return; + QMutexLocker locker(&m_lock); + + if (m_stepping == StepIn) { + m_currentContext.set(m_engine, *m_engine->currentContext); + } +} + +void QV4Debugger::leavingFunction(const QV4::ReturnedValue &retVal) +{ + if (m_runningJob) + return; + Q_UNUSED(retVal); // TODO + + QMutexLocker locker(&m_lock); + + 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 QV4Debugger::aboutToThrow() +{ + if (!m_breakOnThrow) + return; + + if (m_runningJob) // do not re-enter when we're doing a job for the debugger. + return; + + QMutexLocker locker(&m_lock); + pauseAndWait(Throwing); +} + +QV4::Function *QV4Debugger::getFunction() const +{ + QV4::Scope scope(m_engine); + QV4::ExecutionContext *context = m_engine->currentContext; + QV4::ScopedFunctionObject function(scope, context->getFunctionObject()); + if (function) + return function->function(); + else + return context->d()->engine->globalCode; +} + +void QV4Debugger::pauseAndWait(PauseReason reason) +{ + if (m_runningJob) + return; + + m_state = Paused; + emit debuggerPaused(this, reason); + + while (true) { + m_runningCondition.wait(&m_lock); + if (m_runningJob) { + m_runningJob->run(); + m_jobIsRunning.wakeAll(); + } else { + break; + } + } + + m_state = Running; +} + +bool QV4Debugger::reallyHitTheBreakPoint(const QString &filename, int linenr) +{ + QHash<BreakPoint, QString>::iterator it = m_breakPoints.find( + BreakPoint(filename.mid(filename.lastIndexOf('/') + 1), linenr)); + if (it == m_breakPoints.end()) + return false; + QString condition = it.value(); + if (condition.isEmpty()) + return true; + + Q_ASSERT(m_runningJob == 0); + EvalJob evilJob(m_engine, condition); + m_runningJob = &evilJob; + m_runningJob->run(); + m_runningJob = 0; + + return evilJob.resultAsBoolean(); +} + +void QV4Debugger::runInEngine(QV4Debugger::Job *job) +{ + QMutexLocker locker(&m_lock); + runInEngine_havingLock(job); +} + +void QV4Debugger::runInEngine_havingLock(QV4Debugger::Job *job) +{ + Q_ASSERT(job); + Q_ASSERT(m_runningJob == 0); + + m_runningJob = job; + m_runningCondition.wakeAll(); + m_jobIsRunning.wait(&m_lock); + m_runningJob = 0; +} + +QV4Debugger::Job::~Job() +{ +} + +QT_END_NAMESPACE diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h new file mode 100644 index 0000000000..adc58141d0 --- /dev/null +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h @@ -0,0 +1,183 @@ +/**************************************************************************** +** +** 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 QV4DEBUGGER_H +#define QV4DEBUGGER_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/qv4debugging_p.h> +#include <private/qv4function_p.h> +#include <private/qv4context_p.h> +#include <private/qv4persistent_p.h> + +#include <QtCore/qmutex.h> +#include <QtCore/qwaitcondition.h> + +QT_BEGIN_NAMESPACE + +class QV4Debugger : public QV4::Debugging::Debugger +{ + Q_OBJECT +public: + struct BreakPoint { + BreakPoint(const QString &fileName, int line); + QString fileName; + int lineNumber; + }; + + class Job + { + public: + virtual ~Job(); + virtual void run() = 0; + }; + + class JavaScriptJob: public Job + { + QV4::ExecutionEngine *engine; + int frameNr; + const QString &script; + bool resultIsException; + + public: + JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr, const QString &script); + void run(); + bool hasExeption() const; + + protected: + virtual void handleResult(QV4::ScopedValue &result) = 0; + }; + + enum State { + Running, + Paused + }; + + enum Speed { + FullThrottle = 0, + StepOut, + StepOver, + StepIn, + + NotStepping = FullThrottle + }; + + enum PauseReason { + PauseRequest, + BreakPointHit, + Throwing, + Step + }; + + QV4Debugger(QV4::ExecutionEngine *engine); + + QV4::ExecutionEngine *engine() const; + + void pause(); + void resume(Speed speed); + + State state() const; + + void addBreakPoint(const QString &fileName, int lineNumber, + const QString &condition = QString()); + void removeBreakPoint(const QString &fileName, int lineNumber); + + void setBreakOnThrow(bool onoff); + + // used for testing + struct ExecutionState + { + QString fileName; + int lineNumber; + }; + ExecutionState currentExecutionState() const; + + QVector<QV4::StackFrame> stackTrace(int frameLimit = -1) const; + QVector<QV4::Heap::ExecutionContext::ContextType> getScopeTypes(int frame = 0) const; + + QV4::Function *getFunction() const; + void runInEngine(Job *job); + + // compile-time interface + void maybeBreakAtInstruction() Q_DECL_OVERRIDE; + + // execution hooks + void enteringFunction() Q_DECL_OVERRIDE; + void leavingFunction(const QV4::ReturnedValue &retVal) Q_DECL_OVERRIDE; + void aboutToThrow() Q_DECL_OVERRIDE; + + bool pauseAtNextOpportunity() const Q_DECL_OVERRIDE; + +signals: + void debuggerPaused(QV4Debugger *self, QV4Debugger::PauseReason reason); + +private: + // requires lock to be held + void pauseAndWait(PauseReason reason); + bool reallyHitTheBreakPoint(const QString &filename, int linenr); + void runInEngine_havingLock(QV4Debugger::Job *job); + + QV4::ExecutionEngine *m_engine; + QV4::PersistentValue m_currentContext; + QMutex m_lock; + QWaitCondition m_runningCondition; + State m_state; + Speed m_stepping; + bool m_pauseRequested; + bool m_haveBreakPoints; + bool m_breakOnThrow; + + QHash<BreakPoint, QString> m_breakPoints; + QV4::PersistentValue m_returnedValue; + + Job *m_gatherSources; + Job *m_runningJob; + QWaitCondition m_jobIsRunning; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QV4Debugger::PauseReason) +Q_DECLARE_METATYPE(QV4Debugger*) + +#endif // QV4DEBUGGER_H diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp index dcb40dd548..da43257b24 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp @@ -44,7 +44,7 @@ QV4DebuggerAgent::QV4DebuggerAgent(QV4DebugServiceImpl *debugService) : m_breakOnThrow(false), m_debugService(debugService) {} -QV4::Debugging::V4Debugger *QV4DebuggerAgent::firstDebugger() const +QV4Debugger *QV4DebuggerAgent::firstDebugger() const { // Currently only 1 single engine is supported, so: if (m_debuggers.isEmpty()) @@ -56,14 +56,13 @@ QV4::Debugging::V4Debugger *QV4DebuggerAgent::firstDebugger() const bool QV4DebuggerAgent::isRunning() const { // Currently only 1 single engine is supported, so: - if (QV4::Debugging::V4Debugger *debugger = firstDebugger()) - return debugger->state() == QV4::Debugging::V4Debugger::Running; + if (QV4Debugger *debugger = firstDebugger()) + return debugger->state() == QV4Debugger::Running; else return false; } -void QV4DebuggerAgent::debuggerPaused(QV4::Debugging::V4Debugger *debugger, - QV4::Debugging::PauseReason reason) +void QV4DebuggerAgent::debuggerPaused(QV4Debugger *debugger, QV4Debugger::PauseReason reason) { Q_UNUSED(reason); @@ -73,9 +72,9 @@ void QV4DebuggerAgent::debuggerPaused(QV4::Debugging::V4Debugger *debugger, event.insert(QStringLiteral("type"), QStringLiteral("event")); switch (reason) { - case QV4::Debugging::Step: - case QV4::Debugging::PauseRequest: - case QV4::Debugging::BreakPoint: { + case QV4Debugger::Step: + case QV4Debugger::PauseRequest: + case QV4Debugger::BreakPointHit: { event.insert(QStringLiteral("event"), QStringLiteral("break")); QVector<QV4::StackFrame> frames = debugger->stackTrace(1); if (frames.isEmpty()) @@ -92,7 +91,7 @@ void QV4DebuggerAgent::debuggerPaused(QV4::Debugging::V4Debugger *debugger, body.insert(QStringLiteral("breakpoints"), breakPoints); script.insert(QStringLiteral("name"), topFrame.source); } break; - case QV4::Debugging::Throwing: + case QV4Debugger::Throwing: // TODO: complete this! event.insert(QStringLiteral("event"), QStringLiteral("exception")); break; @@ -105,7 +104,7 @@ void QV4DebuggerAgent::debuggerPaused(QV4::Debugging::V4Debugger *debugger, m_debugService->send(event); } -void QV4DebuggerAgent::addDebugger(QV4::Debugging::V4Debugger *debugger) +void QV4DebuggerAgent::addDebugger(QV4Debugger *debugger) { Q_ASSERT(!m_debuggers.contains(debugger)); m_debuggers << debugger; @@ -116,57 +115,50 @@ void QV4DebuggerAgent::addDebugger(QV4::Debugging::V4Debugger *debugger) if (breakPoint.enabled) debugger->addBreakPoint(breakPoint.fileName, breakPoint.lineNr, breakPoint.condition); - connect(debugger, SIGNAL(destroyed(QObject*)), - this, SLOT(handleDebuggerDeleted(QObject*))); - connect(debugger, - SIGNAL(debuggerPaused(QV4::Debugging::V4Debugger*,QV4::Debugging::PauseReason)), - this, SLOT(debuggerPaused(QV4::Debugging::V4Debugger*,QV4::Debugging::PauseReason)), + connect(debugger, &QObject::destroyed, this, &QV4DebuggerAgent::handleDebuggerDeleted); + connect(debugger, &QV4Debugger::debuggerPaused, this, &QV4DebuggerAgent::debuggerPaused, Qt::QueuedConnection); } -void QV4DebuggerAgent::removeDebugger(QV4::Debugging::V4Debugger *debugger) +void QV4DebuggerAgent::removeDebugger(QV4Debugger *debugger) { m_debuggers.removeAll(debugger); - disconnect(debugger, SIGNAL(destroyed(QObject*)), - this, SLOT(handleDebuggerDeleted(QObject*))); - disconnect(debugger, - SIGNAL(debuggerPaused(QV4::Debugging::V4Debugger*,QV4::Debugging::PauseReason)), - this, - SLOT(debuggerPaused(QV4::Debugging::V4Debugger*,QV4::Debugging::PauseReason))); + disconnect(debugger, &QObject::destroyed, this, &QV4DebuggerAgent::handleDebuggerDeleted); + disconnect(debugger, &QV4Debugger::debuggerPaused, this, &QV4DebuggerAgent::debuggerPaused); } -const QList<QV4::Debugging::V4Debugger *> &QV4DebuggerAgent::debuggers() +const QList<QV4Debugger *> &QV4DebuggerAgent::debuggers() { return m_debuggers; } void QV4DebuggerAgent::handleDebuggerDeleted(QObject *debugger) { - m_debuggers.removeAll(static_cast<QV4::Debugging::V4Debugger *>(debugger)); + m_debuggers.removeAll(static_cast<QV4Debugger *>(debugger)); } -void QV4DebuggerAgent::pause(QV4::Debugging::V4Debugger *debugger) const +void QV4DebuggerAgent::pause(QV4Debugger *debugger) const { debugger->pause(); } void QV4DebuggerAgent::pauseAll() const { - foreach (QV4::Debugging::V4Debugger *debugger, m_debuggers) + foreach (QV4Debugger *debugger, m_debuggers) pause(debugger); } void QV4DebuggerAgent::resumeAll() const { - foreach (QV4::Debugging::V4Debugger *debugger, m_debuggers) - if (debugger->state() == QV4::Debugging::V4Debugger::Paused) - debugger->resume(QV4::Debugging::V4Debugger::FullThrottle); + foreach (QV4Debugger *debugger, m_debuggers) + if (debugger->state() == QV4Debugger::Paused) + debugger->resume(QV4Debugger::FullThrottle); } int QV4DebuggerAgent::addBreakPoint(const QString &fileName, int lineNumber, bool enabled, const QString &condition) { if (enabled) - foreach (QV4::Debugging::V4Debugger *debugger, m_debuggers) + foreach (QV4Debugger *debugger, m_debuggers) debugger->addBreakPoint(fileName, lineNumber, condition); int id = m_breakPoints.size(); @@ -183,7 +175,7 @@ void QV4DebuggerAgent::removeBreakPoint(int id) m_breakPoints.remove(id); if (breakPoint.enabled) - foreach (QV4::Debugging::V4Debugger *debugger, m_debuggers) + foreach (QV4Debugger *debugger, m_debuggers) debugger->removeBreakPoint(breakPoint.fileName, breakPoint.lineNr); } @@ -201,7 +193,7 @@ void QV4DebuggerAgent::enableBreakPoint(int id, bool onoff) return; breakPoint.enabled = onoff; - foreach (QV4::Debugging::V4Debugger *debugger, m_debuggers) { + foreach (QV4Debugger *debugger, m_debuggers) { if (onoff) debugger->addBreakPoint(breakPoint.fileName, breakPoint.lineNr, breakPoint.condition); else @@ -224,7 +216,7 @@ void QV4DebuggerAgent::setBreakOnThrow(bool onoff) { if (onoff != m_breakOnThrow) { m_breakOnThrow = onoff; - foreach (QV4::Debugging::V4Debugger *debugger, m_debuggers) + foreach (QV4Debugger *debugger, m_debuggers) debugger->setBreakOnThrow(onoff); } } diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h index 9f77a17b45..d133c6954b 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h @@ -34,7 +34,7 @@ #ifndef QV4DEBUGGERAGENT_H #define QV4DEBUGGERAGENT_H -#include <private/qv4debugging_p.h> +#include "qv4debugger.h" QT_BEGIN_NAMESPACE @@ -46,14 +46,14 @@ class QV4DebuggerAgent : public QObject public: QV4DebuggerAgent(QV4DebugServiceImpl *m_debugService); - QV4::Debugging::V4Debugger *firstDebugger() const; + QV4Debugger *firstDebugger() const; bool isRunning() const; - void addDebugger(QV4::Debugging::V4Debugger *debugger); - void removeDebugger(QV4::Debugging::V4Debugger *debugger); - const QList<QV4::Debugging::V4Debugger *> &debuggers(); + void addDebugger(QV4Debugger *debugger); + void removeDebugger(QV4Debugger *debugger); + const QList<QV4Debugger *> &debuggers(); - void pause(QV4::Debugging::V4Debugger *debugger) const; + void pause(QV4Debugger *debugger) const; void pauseAll() const; void resumeAll() const; int addBreakPoint(const QString &fileName, int lineNumber, bool enabled = true, const QString &condition = QString()); @@ -66,11 +66,11 @@ public: void setBreakOnThrow(bool onoff); public slots: - void debuggerPaused(QV4::Debugging::V4Debugger *debugger, QV4::Debugging::PauseReason reason); + void debuggerPaused(QV4Debugger *debugger, QV4Debugger::PauseReason reason); void handleDebuggerDeleted(QObject *debugger); private: - QList<QV4::Debugging::V4Debugger *> m_debuggers; + QList<QV4Debugger *> m_debuggers; struct BreakPoint { QString fileName; diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp index f742502e2a..3a080be125 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp @@ -270,7 +270,7 @@ 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::V4Debugger *debugger = debugService->debuggerAgent.firstDebugger(); + QV4Debugger *debugger = debugService->debuggerAgent.firstDebugger(); QJsonArray frameArray; QVector<QV4::StackFrame> frames = debugger->stackTrace(toFrame); @@ -307,7 +307,7 @@ public: const int frameNr = arguments.value(QStringLiteral("number")).toInt( debugService->selectedFrame()); - QV4::Debugging::V4Debugger *debugger = debugService->debuggerAgent.firstDebugger(); + QV4Debugger *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")); @@ -340,7 +340,7 @@ public: debugService->selectedFrame()); const int scopeNr = arguments.value(QStringLiteral("number")).toInt(0); - QV4::Debugging::V4Debugger *debugger = debugService->debuggerAgent.firstDebugger(); + QV4Debugger *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")); @@ -398,10 +398,10 @@ public: // decypher the payload: QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject(); - QV4::Debugging::V4Debugger *debugger = debugService->debuggerAgent.firstDebugger(); + QV4Debugger *debugger = debugService->debuggerAgent.firstDebugger(); if (arguments.empty()) { - debugger->resume(QV4::Debugging::V4Debugger::FullThrottle); + debugger->resume(QV4Debugger::FullThrottle); } else { QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject(); QString stepAction = arguments.value(QStringLiteral("stepaction")).toString(); @@ -410,11 +410,11 @@ public: qWarning() << "Step count other than 1 is not supported."; if (stepAction == QStringLiteral("in")) { - debugger->resume(QV4::Debugging::V4Debugger::StepIn); + debugger->resume(QV4Debugger::StepIn); } else if (stepAction == QStringLiteral("out")) { - debugger->resume(QV4::Debugging::V4Debugger::StepOut); + debugger->resume(QV4Debugger::StepOut); } else if (stepAction == QStringLiteral("next")) { - debugger->resume(QV4::Debugging::V4Debugger::StepOver); + debugger->resume(QV4Debugger::StepOver); } else { createErrorResponse(QStringLiteral("continue command has invalid stepaction")); return; @@ -506,7 +506,7 @@ public: } // do it: - QV4::Debugging::V4Debugger *debugger = debugService->debuggerAgent.firstDebugger(); + QV4Debugger *debugger = debugService->debuggerAgent.firstDebugger(); GatherSourcesJob job(debugger->engine()); debugger->runInEngine(&job); @@ -561,8 +561,8 @@ public: virtual void handleRequest() { - QV4::Debugging::V4Debugger *debugger = debugService->debuggerAgent.firstDebugger(); - if (debugger->state() == QV4::Debugging::V4Debugger::Paused) { + QV4Debugger *debugger = debugService->debuggerAgent.firstDebugger(); + if (debugger->state() == QV4Debugger::Paused) { QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject(); QString expression = arguments.value(QStringLiteral("expression")).toString(); const int frame = arguments.value(QStringLiteral("frame")).toInt(0); @@ -634,7 +634,7 @@ void QV4DebugServiceImpl::engineAboutToBeAdded(QQmlEngine *engine) if (QQmlDebugConnector *server = QQmlDebugConnector::instance()) { if (ee) { ee->iselFactory.reset(new QV4::Moth::ISelFactory); - QV4::Debugging::V4Debugger *debugger = new QV4::Debugging::V4Debugger(ee); + QV4Debugger *debugger = new QV4Debugger(ee); if (state() == Enabled) ee->setDebugger(debugger); debuggerAgent.addDebugger(debugger); @@ -651,8 +651,7 @@ void QV4DebugServiceImpl::engineAboutToBeRemoved(QQmlEngine *engine) if (engine){ const QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle()); if (ee) { - QV4::Debugging::V4Debugger *debugger - = qobject_cast<QV4::Debugging::V4Debugger *>(ee->debugger); + QV4Debugger *debugger = qobject_cast<QV4Debugger *>(ee->debugger); if (debugger) debuggerAgent.removeDebugger(debugger); } @@ -664,7 +663,7 @@ void QV4DebugServiceImpl::stateAboutToBeChanged(State state) { QMutexLocker lock(&m_configMutex); if (state == Enabled) { - foreach (QV4::Debugging::V4Debugger *debugger, debuggerAgent.debuggers()) { + foreach (QV4Debugger *debugger, debuggerAgent.debuggers()) { QV4::ExecutionEngine *ee = debugger->engine(); if (!ee->debugger) ee->setDebugger(debugger); @@ -787,7 +786,7 @@ void QV4DebugServiceImpl::clearHandles(QV4::ExecutionEngine *engine) } QJsonObject QV4DebugServiceImpl::buildFrame(const QV4::StackFrame &stackFrame, int frameNr, - QV4::Debugging::V4Debugger *debugger) + QV4Debugger *debugger) { QV4DataCollector::Ref ref; @@ -805,7 +804,7 @@ QJsonObject QV4DebugServiceImpl::buildFrame(const QV4::StackFrame &stackFrame, i frame[QLatin1String("column")] = stackFrame.column; QJsonArray scopes; - if (debugger->state() == QV4::Debugging::V4Debugger::Paused) { + if (debugger->state() == QV4Debugger::Paused) { RefHolder holder(theCollector.data(), &collectedRefs); bool foundThis = false; ThisCollectJob job(debugger->engine(), theCollector.data(), frameNr, &foundThis); @@ -854,8 +853,7 @@ int QV4DebugServiceImpl::encodeScopeType(QV4::Heap::ExecutionContext::ContextTyp } } -QJsonObject QV4DebugServiceImpl::buildScope(int frameNr, int scopeNr, - QV4::Debugging::V4Debugger *debugger) +QJsonObject QV4DebugServiceImpl::buildScope(int frameNr, int scopeNr, QV4Debugger *debugger) { QJsonObject scope; @@ -863,7 +861,7 @@ QJsonObject QV4DebugServiceImpl::buildScope(int frameNr, int scopeNr, RefHolder holder(theCollector.data(), &collectedRefs); theCollector->collectScope(&object, debugger, frameNr, scopeNr); - if (debugger->state() == QV4::Debugging::V4Debugger::Paused) { + if (debugger->state() == QV4Debugger::Paused) { QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes = QV4DataCollector::getScopeTypes(debugger->engine(), frameNr); scope[QLatin1String("type")] = encodeScopeType(scopeTypes[scopeNr]); diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h index ea4a695fed..37b9f6f976 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h @@ -78,13 +78,12 @@ public: void signalEmitted(const QString &signal); void send(QJsonObject v8Payload); - QJsonObject buildScope(int frameNr, int scopeNr, QV4::Debugging::V4Debugger *debugger); + QJsonObject buildScope(int frameNr, int scopeNr, QV4Debugger *debugger); QJsonArray buildRefs(); QJsonValue lookup(QV4DataCollector::Ref refId); QJsonValue toRef(QV4DataCollector::Ref ref); - QJsonObject buildFrame(const QV4::StackFrame &stackFrame, int frameNr, - QV4::Debugging::V4Debugger *debugger); + QJsonObject buildFrame(const QV4::StackFrame &stackFrame, int frameNr, QV4Debugger *debugger); int selectedFrame() const; void selectFrame(int frameNr); |