diff options
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4debugging.cpp | 286 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4debugging_p.h | 159 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4globalobject.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qobjectwrapper.cpp | 3 |
4 files changed, 7 insertions, 443 deletions
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp index 7706a40da6..b04bcd33e7 100644 --- a/src/qml/jsruntime/qv4debugging.cpp +++ b/src/qml/jsruntime/qv4debugging.cpp @@ -51,290 +51,4 @@ QT_BEGIN_NAMESPACE -using namespace QV4; -using namespace QV4::Debugging; - -V4Debugger::JavaScriptJob::JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr, - const QString &script) - : engine(engine) - , frameNr(frameNr) - , script(script) - , resultIsException(false) -{} - -void V4Debugger::JavaScriptJob::run() -{ - Scope scope(engine); - - ExecutionContextSaver saver(scope); - - 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 V4Debugger::JavaScriptJob::hasExeption() const -{ - return resultIsException; -} - -class EvalJob: public V4Debugger::JavaScriptJob -{ - bool result; - -public: - EvalJob(QV4::ExecutionEngine *engine, const QString &script) - : V4Debugger::JavaScriptJob(engine, /*frameNr*/-1, script) - , result(false) - {} - - virtual void handleResult(QV4::ScopedValue &result) - { - this->result = result->toBoolean(); - } - - bool resultAsBoolean() const - { - return result; - } -}; - -V4Debugger::V4Debugger(QV4::ExecutionEngine *engine) - : m_engine(engine) - , m_state(Running) - , m_stepping(NotStepping) - , m_pauseRequested(false) - , m_haveBreakPoints(false) - , m_breakOnThrow(false) - , m_returnedValue(engine, Primitive::undefinedValue()) - , m_gatherSources(0) - , m_runningJob(0) -{ - qMetaTypeId<V4Debugger*>(); - qMetaTypeId<PauseReason>(); -} - -void V4Debugger::pause() -{ - QMutexLocker locker(&m_lock); - if (m_state == Paused) - return; - m_pauseRequested = true; -} - -void V4Debugger::resume(Speed speed) -{ - QMutexLocker locker(&m_lock); - if (m_state != Paused) - return; - - if (!m_returnedValue.isUndefined()) - m_returnedValue.set(m_engine, Encode::undefined()); - - m_currentContext.set(m_engine, *m_engine->currentContext); - m_stepping = speed; - m_runningCondition.wakeAll(); -} - -void V4Debugger::addBreakPoint(const QString &fileName, int lineNumber, const QString &condition) -{ - QMutexLocker locker(&m_lock); - m_breakPoints.insert(DebuggerBreakPoint(fileName.mid(fileName.lastIndexOf('/') + 1), lineNumber), condition); - m_haveBreakPoints = true; -} - -void V4Debugger::removeBreakPoint(const QString &fileName, int lineNumber) -{ - QMutexLocker locker(&m_lock); - m_breakPoints.remove(DebuggerBreakPoint(fileName.mid(fileName.lastIndexOf('/') + 1), lineNumber)); - m_haveBreakPoints = !m_breakPoints.isEmpty(); -} - -void V4Debugger::setBreakOnThrow(bool onoff) -{ - QMutexLocker locker(&m_lock); - - m_breakOnThrow = onoff; -} - -V4Debugger::ExecutionState V4Debugger::currentExecutionState() const -{ - ExecutionState state; - state.fileName = getFunction()->sourceFile(); - state.lineNumber = engine()->current->lineNumber; - - return state; -} - -QVector<StackFrame> V4Debugger::stackTrace(int frameLimit) const -{ - return m_engine->stackTrace(frameLimit); -} - -void V4Debugger::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 (Function *f = getFunction()) { - const int lineNumber = engine()->current->lineNumber; - if (reallyHitTheBreakPoint(f->sourceFile(), lineNumber)) - pauseAndWait(BreakPoint); - } - } -} - -void V4Debugger::enteringFunction() -{ - if (m_runningJob) - return; - QMutexLocker locker(&m_lock); - - if (m_stepping == StepIn) { - m_currentContext.set(m_engine, *m_engine->currentContext); - } -} - -void V4Debugger::leavingFunction(const 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 V4Debugger::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); -} - -Function *V4Debugger::getFunction() const -{ - Scope scope(m_engine); - ExecutionContext *context = m_engine->currentContext; - ScopedFunctionObject function(scope, context->getFunctionObject()); - if (function) - return function->function(); - else - return context->d()->engine->globalCode; -} - -void V4Debugger::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 V4Debugger::reallyHitTheBreakPoint(const QString &filename, int linenr) -{ - BreakPoints::iterator it = m_breakPoints.find(DebuggerBreakPoint(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 V4Debugger::runInEngine(V4Debugger::Job *job) -{ - QMutexLocker locker(&m_lock); - runInEngine_havingLock(job); -} - -void V4Debugger::runInEngine_havingLock(V4Debugger::Job *job) -{ - Q_ASSERT(job); - Q_ASSERT(m_runningJob == 0); - - m_runningJob = job; - m_runningCondition.wakeAll(); - m_jobIsRunning.wait(&m_lock); - m_runningJob = 0; -} - -V4Debugger::Job::~Job() -{ -} - QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4debugging_p.h b/src/qml/jsruntime/qv4debugging_p.h index fdc9cac24f..3a3ecef918 100644 --- a/src/qml/jsruntime/qv4debugging_p.h +++ b/src/qml/jsruntime/qv4debugging_p.h @@ -31,8 +31,8 @@ ** ****************************************************************************/ -#ifndef DEBUGGING_H -#define DEBUGGING_H +#ifndef QV4DEBUGGING_H +#define QV4DEBUGGING_H // // W A R N I N G @@ -46,50 +46,13 @@ // #include "qv4global_p.h" -#include "qv4engine_p.h" -#include "qv4context_p.h" -#include "qv4scopedvalue_p.h" - -#include <QHash> -#include <QThread> -#include <QMutex> -#include <QWaitCondition> - -#include <QtCore/QJsonObject> +#include <QtCore/qobject.h> QT_BEGIN_NAMESPACE namespace QV4 { - -struct Function; - namespace Debugging { -enum PauseReason { - PauseRequest, - BreakPoint, - Throwing, - Step -}; - -struct DebuggerBreakPoint { - DebuggerBreakPoint(const QString &fileName, int line) - : fileName(fileName), lineNumber(line) - {} - QString fileName; - int lineNumber; -}; -inline uint qHash(const DebuggerBreakPoint &b, uint seed = 0) Q_DECL_NOTHROW -{ - return qHash(b.fileName, seed) ^ b.lineNumber; -} -inline bool operator==(const DebuggerBreakPoint &a, const DebuggerBreakPoint &b) -{ - return a.lineNumber == b.lineNumber && a.fileName == b.fileName; -} - -typedef QHash<DebuggerBreakPoint, QString> BreakPoints; - class Q_QML_EXPORT Debugger : public QObject { Q_OBJECT @@ -103,123 +66,9 @@ public: virtual void aboutToThrow() = 0; }; -class Q_QML_EXPORT V4Debugger : public Debugger -{ - Q_OBJECT -public: - class Q_QML_EXPORT Job - { - public: - virtual ~Job() = 0; - virtual void run() = 0; - }; - - class Q_QML_EXPORT 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 - }; - - V4Debugger(ExecutionEngine *engine); - - ExecutionEngine *engine() const - { return m_engine; } - - void pause(); - void resume(Speed speed); - - State state() const { return m_state; } - - 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; - - bool pauseAtNextOpportunity() const { - return m_pauseRequested || m_haveBreakPoints || m_gatherSources || m_stepping >= StepOver; - } - - QVector<StackFrame> stackTrace(int frameLimit = -1) const; - QVector<Heap::ExecutionContext::ContextType> getScopeTypes(int frame = 0) const; - - Function *getFunction() const; - void runInEngine(Job *job); - -public: // compile-time interface - void maybeBreakAtInstruction(); - -public: // execution hooks - void enteringFunction(); - void leavingFunction(const ReturnedValue &retVal); - void aboutToThrow(); - -signals: - void sourcesCollected(QV4::Debugging::V4Debugger *self, const QStringList &sources, int seq); - void debuggerPaused(QV4::Debugging::V4Debugger *self, QV4::Debugging::PauseReason reason); - -private: - // requires lock to be held - void pauseAndWait(PauseReason reason); - bool reallyHitTheBreakPoint(const QString &filename, int linenr); - void runInEngine_havingLock(V4Debugger::Job *job); - -private: - 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; - - BreakPoints m_breakPoints; - QV4::PersistentValue m_returnedValue; - - Job *m_gatherSources; - Job *m_runningJob; - QWaitCondition m_jobIsRunning; -}; - } // namespace Debugging } // namespace QV4 QT_END_NAMESPACE -Q_DECLARE_METATYPE(QV4::Debugging::Debugger*) -Q_DECLARE_METATYPE(QV4::Debugging::PauseReason) - -#endif // DEBUGGING_H +#endif // QV4DEBUGGING_H diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp index 110a2c9089..b4733356ac 100644 --- a/src/qml/jsruntime/qv4globalobject.cpp +++ b/src/qml/jsruntime/qv4globalobject.cpp @@ -302,7 +302,7 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok) ++r; } if (*r) - output.append(input.mid(start, i - start + 1)); + output.append(input.midRef(start, i - start + 1)); else output.append(QChar(b)); } else { diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 8f471132b7..ee294b3678 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -1447,7 +1447,8 @@ static QV4::ReturnedValue CallOverloaded(const QQmlObjectOrGadget &object, const const QQmlPropertyData *candidate = &data; while (candidate) { error += QLatin1String("\n ") + - QString::fromUtf8(object.metaObject()->method(candidate->coreIndex).methodSignature().constData()); + QString::fromUtf8(object.metaObject()->method(candidate->coreIndex) + .methodSignature()); candidate = RelatedMethod(object, candidate, dummy, propertyCache); } |