aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@theqtcompany.com>2015-11-30 12:04:59 +0100
committerUlf Hermann <ulf.hermann@theqtcompany.com>2016-01-22 09:51:37 +0000
commit5537027094d26e517fc4ad3173ea84d254dd3013 (patch)
tree3457ba913c542447d2492ed32049ffb0f63bdf5b
parent872a05475721ad771bd347d1526035e6e7479d30 (diff)
V4 Debugger: Avoid looking up values in debugger thread
To avoid interaction with the engine from the debugger thread we move the value lookup functionality into the data collector, and drop the RefHolder. Also, we define some more debugger jobs to move the work the request handlers do into the GUI thread. Task-number: QTBUG-50481 Change-Id: Ia73ebd01e715f13110ef010a766e9b0a1e202df9 Reviewed-by: Nils Jeisecke <jeisecke@saltation.de> Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp378
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h114
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp208
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h10
-rw-r--r--tests/auto/qml/qv4debugger/tst_qv4debugger.cpp138
5 files changed, 434 insertions, 414 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
index 4cca1900de..a86373b627 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
@@ -89,9 +89,30 @@ QVector<QV4::Heap::ExecutionContext::ContextType> QV4DataCollector::getScopeType
return types;
}
+int QV4DataCollector::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;
+ }
+}
QV4DataCollector::QV4DataCollector(QV4::ExecutionEngine *engine)
- : m_engine(engine), m_collectedRefs(Q_NULLPTR)
+ : m_engine(engine)
{
values.set(engine, engine->newArrayObject());
}
@@ -100,10 +121,11 @@ QV4DataCollector::~QV4DataCollector()
{
}
-void QV4DataCollector::collect(const QV4::ScopedValue &value)
+QV4DataCollector::Ref QV4DataCollector::collect(const QV4::ScopedValue &value)
{
- if (m_collectedRefs)
- m_collectedRefs->append(addRef(value));
+ Ref ref = addRef(value);
+ collectedRefs.append(ref);
+ return ref;
}
const QV4::Object *collectProperty(const QV4::ScopedValue &value, QV4::ExecutionEngine *engine,
@@ -191,6 +213,7 @@ QV4DataCollector::Ref QV4DataCollector::addFunctionRef(const QString &functionNa
dict.insert(QStringLiteral("type"), QStringLiteral("function"));
dict.insert(QStringLiteral("name"), functionName);
specialRefs.insert(ref, dict);
+ collectedRefs.append(ref);
return ref;
}
@@ -204,36 +227,133 @@ QV4DataCollector::Ref QV4DataCollector::addScriptRef(const QString &scriptName)
dict.insert(QStringLiteral("type"), QStringLiteral("script"));
dict.insert(QStringLiteral("name"), scriptName);
specialRefs.insert(ref, dict);
+ collectedRefs.append(ref);
return ref;
}
-void QV4DataCollector::collectScope(QJsonObject *dict, QV4::Debugging::V4Debugger *debugger,
+bool QV4DataCollector::isValidRef(QV4DataCollector::Ref ref) const
+{
+ QV4::Scope scope(engine());
+ QV4::ScopedObject array(scope, values.value());
+ return ref < array->getLength();
+}
+
+bool QV4DataCollector::collectScope(QJsonObject *dict, QV4::Debugging::V4Debugger *debugger,
int frameNr, int scopeNr)
{
QStringList names;
- Refs refs;
+ QV4::Scope scope(engine());
if (debugger->state() == QV4::Debugging::V4Debugger::Paused) {
- RefHolder holder(this, &refs);
- ArgumentCollectJob argumentsJob(m_engine, this, &names, frameNr, scopeNr);
- debugger->runInEngine(&argumentsJob);
- LocalCollectJob localsJob(m_engine, this, &names, frameNr, scopeNr);
- debugger->runInEngine(&localsJob);
+ QV4::Scoped<QV4::CallContext> ctxt(scope, findScope(findContext(engine(), frameNr), scopeNr));
+ if (!ctxt)
+ return false;
+
+ QV4::ScopedValue v(scope);
+ int nFormals = ctxt->formalCount();
+ for (unsigned i = 0, ei = nFormals; i != ei; ++i) {
+ QString qName;
+ if (QV4::Identifier *name = ctxt->formals()[nFormals - i - 1])
+ qName = name->string;
+ names.append(qName);
+ v = ctxt->argument(i);
+ collect(v);
+ }
+
+ for (unsigned i = 0, ei = ctxt->variableCount(); i != ei; ++i) {
+ QString qName;
+ if (QV4::Identifier *name = ctxt->variables()[i])
+ qName = name->string;
+ names.append(qName);
+ v = ctxt->d()->locals[i];
+ collect(v);
+ }
}
- QV4::Scope scope(engine());
QV4::ScopedObject scopeObject(scope, engine()->newObject());
- Q_ASSERT(names.size() == refs.size());
- for (int i = 0, ei = refs.size(); i != ei; ++i)
+ Q_ASSERT(names.size() == collectedRefs.size());
+ for (int i = 0, ei = collectedRefs.size(); i != ei; ++i)
scopeObject->put(engine(), names.at(i),
- QV4::Value::fromReturnedValue(getValue(refs.at(i))));
+ QV4::Value::fromReturnedValue(getValue(collectedRefs.at(i))));
Ref scopeObjectRef = addRef(scopeObject);
dict->insert(QStringLiteral("ref"), qint64(scopeObjectRef));
- if (m_collectedRefs)
- m_collectedRefs->append(scopeObjectRef);
+ collectedRefs.append(scopeObjectRef);
+ return true;
+}
+
+QJsonObject toRef(QV4DataCollector::Ref ref) {
+ QJsonObject dict;
+ dict.insert(QStringLiteral("ref"), qint64(ref));
+ return dict;
+}
+
+QJsonObject QV4DataCollector::buildFrame(const QV4::StackFrame &stackFrame, int frameNr,
+ QV4::Debugging::V4Debugger *debugger)
+{
+ QV4DataCollector::Ref ref;
+
+ QJsonObject frame;
+ frame[QLatin1String("index")] = frameNr;
+ frame[QLatin1String("debuggerFrame")] = false;
+ ref = addFunctionRef(stackFrame.function);
+ frame[QLatin1String("func")] = toRef(ref);
+ ref = addScriptRef(stackFrame.source);
+ frame[QLatin1String("script")] = toRef(ref);
+ frame[QLatin1String("line")] = stackFrame.line - 1;
+ if (stackFrame.column >= 0)
+ frame[QLatin1String("column")] = stackFrame.column;
+
+ QJsonArray scopes;
+ if (debugger->state() == QV4::Debugging::V4Debugger::Paused) {
+ QV4::Scope scope(engine());
+ QV4::ScopedContext ctxt(scope, findContext(engine(), frameNr));
+ while (ctxt) {
+ if (QV4::CallContext *cCtxt = ctxt->asCallContext()) {
+ if (cCtxt->d()->activation)
+ break;
+ }
+ ctxt = ctxt->d()->outer;
+ }
+
+ if (ctxt) {
+ QV4::ScopedValue o(scope, ctxt->asCallContext()->d()->activation);
+ frame[QLatin1String("receiver")] = toRef(collect(o));
+ }
+
+ // Only type and index are used by Qt Creator, so we keep it easy:
+ QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes = getScopeTypes(engine(), 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;
+}
+
+QJsonArray QV4DataCollector::flushCollectedRefs()
+{
+ QJsonArray refs;
+ std::sort(collectedRefs.begin(), collectedRefs.end());
+ for (int i = 0, ei = collectedRefs.size(); i != ei; ++i) {
+ QV4DataCollector::Ref ref = collectedRefs.at(i);
+ if (i > 0 && ref == collectedRefs.at(i - 1))
+ continue;
+ refs.append(lookupRef(ref));
+ }
+
+ collectedRefs.clear();
+ return refs;
}
QV4DataCollector::Ref QV4DataCollector::addRef(QV4::Value value, bool deduplicate)
@@ -316,14 +436,117 @@ QJsonObject QV4DataCollector::collectAsJson(const QString &name, const QV4::Scop
if (value->isManaged() && !value->isString()) {
Ref ref = addRef(value);
dict.insert(QStringLiteral("ref"), qint64(ref));
- if (m_collectedRefs)
- m_collectedRefs->append(ref);
+ collectedRefs.append(ref);
}
collectProperty(value, engine(), dict);
return dict;
}
+BacktraceJob::BacktraceJob(QV4DataCollector *collector, int fromFrame, int toFrame) :
+ CollectJob(collector), fromFrame(fromFrame), toFrame(toFrame)
+{
+}
+
+void BacktraceJob::run()
+{
+ QJsonArray frameArray;
+ QVector<QV4::StackFrame> frames = collector->engine()->stackTrace(toFrame);
+ QV4::Debugging::V4Debugger *debugger =
+ qobject_cast<QV4::Debugging::V4Debugger *>(collector->engine()->debugger);
+ if (debugger) {
+ for (int i = fromFrame; i < toFrame && i < frames.size(); ++i)
+ frameArray.push_back(collector->buildFrame(frames[i], i, debugger));
+ }
+ if (frameArray.isEmpty()) {
+ result.insert(QStringLiteral("totalFrames"), 0);
+ } else {
+ result.insert(QStringLiteral("fromFrame"), fromFrame);
+ result.insert(QStringLiteral("toFrame"), fromFrame + frameArray.size());
+ result.insert(QStringLiteral("frames"), frameArray);
+ }
+ collectedRefs = collector->flushCollectedRefs();
+}
+
+FrameJob::FrameJob(QV4DataCollector *collector, int frameNr) :
+ CollectJob(collector), frameNr(frameNr), success(false)
+{
+}
+
+void FrameJob::run()
+{
+ QVector<QV4::StackFrame> frames = collector->engine()->stackTrace(frameNr + 1);
+ if (frameNr >= frames.length()) {
+ success = false;
+ } else {
+ QV4::Debugging::V4Debugger *debugger =
+ qobject_cast<QV4::Debugging::V4Debugger *>(collector->engine()->debugger);
+ if (debugger) {
+ result = collector->buildFrame(frames[frameNr], frameNr, debugger);
+ collectedRefs = collector->flushCollectedRefs();
+ success = true;
+ } else {
+ success = false;
+ }
+ }
+}
+
+bool FrameJob::wasSuccessful() const
+{
+ return success;
+}
+
+ScopeJob::ScopeJob(QV4DataCollector *collector, int frameNr, int scopeNr) :
+ CollectJob(collector), frameNr(frameNr), scopeNr(scopeNr), success(false)
+{
+}
+
+void ScopeJob::run()
+{
+ QJsonObject object;
+ QV4::Debugging::V4Debugger *debugger =
+ qobject_cast<QV4::Debugging::V4Debugger *>(collector->engine()->debugger);
+ success = (debugger && collector->collectScope(&object, debugger, frameNr, scopeNr));
+
+ if (success) {
+ QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes =
+ QV4DataCollector::getScopeTypes(collector->engine(), frameNr);
+ result[QLatin1String("type")] = QV4DataCollector::encodeScopeType(scopeTypes[scopeNr]);
+ } else {
+ result[QLatin1String("type")] = -1;
+ }
+ result[QLatin1String("index")] = scopeNr;
+ result[QLatin1String("frameIndex")] = frameNr;
+ result[QLatin1String("object")] = object;
+ collectedRefs = collector->flushCollectedRefs();
+}
+
+bool ScopeJob::wasSuccessful() const
+{
+ return success;
+}
+
+ValueLookupJob::ValueLookupJob(const QJsonArray &handles, QV4DataCollector *collector) :
+ CollectJob(collector), handles(handles) {}
+
+void ValueLookupJob::run()
+{
+ foreach (const QJsonValue &handle, handles) {
+ QV4DataCollector::Ref ref = handle.toInt();
+ if (!collector->isValidRef(ref)) {
+ exception = QString::fromLatin1("Invalid Ref: %1").arg(ref);
+ break;
+ }
+ result[QString::number(ref)] = collector->lookupRef(ref);
+ }
+ collectedRefs = collector->flushCollectedRefs();
+}
+
+const QString &ValueLookupJob::exceptionMessage() const
+{
+ return exception;
+}
+
ExpressionEvalJob::ExpressionEvalJob(QV4::ExecutionEngine *engine, int frameNr,
const QString &expression,
QV4DataCollector *collector)
@@ -336,7 +559,8 @@ void ExpressionEvalJob::handleResult(QV4::ScopedValue &result)
{
if (hasExeption())
exception = result->toQStringNoThrow();
- collector->collect(result);
+ value = collector->lookupRef(collector->collect(result));
+ collectedRefs = collector->flushCollectedRefs();
}
const QString &ExpressionEvalJob::exceptionMessage() const
@@ -344,6 +568,16 @@ const QString &ExpressionEvalJob::exceptionMessage() const
return exception;
}
+const QJsonObject &ExpressionEvalJob::returnValue() const
+{
+ return value;
+}
+
+const QJsonArray &ExpressionEvalJob::refs() const
+{
+ return collectedRefs;
+}
+
GatherSourcesJob::GatherSourcesJob(QV4::ExecutionEngine *engine, int seq)
: engine(engine)
, seq(seq)
@@ -364,111 +598,21 @@ void GatherSourcesJob::run()
emit debugger->sourcesCollected(debugger, sources, seq);
}
-ArgumentCollectJob::ArgumentCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector,
- QStringList *names, int frameNr, int scopeNr)
- : engine(engine)
- , collector(collector)
- , names(names)
- , frameNr(frameNr)
- , scopeNr(scopeNr)
-{}
-
-void ArgumentCollectJob::run()
-{
- if (frameNr < 0)
- return;
-
- QV4::Scope scope(engine);
- QV4::Scoped<QV4::CallContext> ctxt(
- scope, QV4DataCollector::findScope(QV4DataCollector::findContext(engine, frameNr), scopeNr));
- if (!ctxt)
- return;
-
- QV4::ScopedValue v(scope);
- int nFormals = ctxt->formalCount();
- for (unsigned i = 0, ei = nFormals; i != ei; ++i) {
- QString qName;
- if (QV4::Identifier *name = ctxt->formals()[nFormals - i - 1])
- qName = name->string;
- names->append(qName);
- v = ctxt->argument(i);
- collector->collect(v);
- }
-}
-
-LocalCollectJob::LocalCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector,
- QStringList *names, int frameNr, int scopeNr)
- : engine(engine)
- , collector(collector)
- , names(names)
- , frameNr(frameNr)
- , scopeNr(scopeNr)
-{}
-
-void LocalCollectJob::run()
-{
- if (frameNr < 0)
- return;
-
- QV4::Scope scope(engine);
- QV4::Scoped<QV4::CallContext> ctxt(
- scope, QV4DataCollector::findScope(QV4DataCollector::findContext(engine, frameNr), scopeNr));
- if (!ctxt)
- return;
-
- QV4::ScopedValue v(scope);
- for (unsigned i = 0, ei = ctxt->variableCount(); i != ei; ++i) {
- QString qName;
- if (QV4::Identifier *name = ctxt->variables()[i])
- qName = name->string;
- names->append(qName);
- v = ctxt->d()->locals[i];
- collector->collect(v);
- }
-}
-
-ThisCollectJob::ThisCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector,
- int frameNr, bool *foundThis)
+ExceptionCollectJob::ExceptionCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector)
: engine(engine)
, collector(collector)
- , frameNr(frameNr)
- , foundThis(foundThis)
+ , exception(-1)
{}
-void ThisCollectJob::run()
-{
- *foundThis = myRun();
-}
-
-bool ThisCollectJob::myRun()
-{
+void ExceptionCollectJob::run() {
QV4::Scope scope(engine);
- QV4::ScopedContext ctxt(scope, QV4DataCollector::findContext(engine, frameNr));
- while (ctxt) {
- if (QV4::CallContext *cCtxt = ctxt->asCallContext())
- if (cCtxt->d()->activation)
- break;
- ctxt = ctxt->d()->outer;
- }
-
- if (!ctxt)
- return false;
-
- QV4::ScopedValue o(scope, ctxt->asCallContext()->d()->activation);
- collector->collect(o);
- return true;
+ QV4::ScopedValue v(scope, *engine->exceptionValue);
+ exception = collector->collect(v);
}
-ExceptionCollectJob::ExceptionCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector)
- : engine(engine)
- , collector(collector)
-{}
-
-void ExceptionCollectJob::run()
+QV4DataCollector::Ref ExceptionCollectJob::exceptionValue() const
{
- QV4::Scope scope(engine);
- QV4::ScopedValue v(scope, *engine->exceptionValue);
- collector->collect(v);
+ return exception;
}
QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
index d0e4a4ad18..5a2c8ff33b 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
@@ -37,6 +37,9 @@
#include <private/qv4engine_p.h>
#include <private/qv4debugging_p.h>
+#include <QtCore/QJsonObject>
+#include <QtCore/QJsonArray>
+
QT_BEGIN_NAMESPACE
class QV4DataCollector
@@ -49,25 +52,27 @@ public:
static QV4::Heap::CallContext *findScope(QV4::ExecutionContext *ctxt, int scope);
static QVector<QV4::Heap::ExecutionContext::ContextType> getScopeTypes(
QV4::ExecutionEngine *engine, int frame);
+ static int encodeScopeType(QV4::Heap::ExecutionContext::ContextType scopeType);
QV4DataCollector(QV4::ExecutionEngine *engine);
~QV4DataCollector();
- void collect(const QV4::ScopedValue &value);
-
+ Ref collect(const QV4::ScopedValue &value);
+ bool isValidRef(Ref ref) const;
QJsonObject lookupRef(Ref ref);
Ref addFunctionRef(const QString &functionName);
Ref addScriptRef(const QString &scriptName);
- void collectScope(QJsonObject *dict, QV4::Debugging::V4Debugger *debugger, int frameNr,
+ bool collectScope(QJsonObject *dict, QV4::Debugging::V4Debugger *debugger, int frameNr,
int scopeNr);
+ QJsonObject buildFrame(const QV4::StackFrame &stackFrame, int frameNr,
+ QV4::Debugging::V4Debugger *debugger);
QV4::ExecutionEngine *engine() const { return m_engine; }
+ QJsonArray flushCollectedRefs();
private:
- friend class RefHolder;
-
Ref addRef(QV4::Value value, bool deduplicate = true);
QV4::ReturnedValue getValue(Ref ref);
bool lookupSpecialRef(Ref ref, QJsonObject *dict);
@@ -77,102 +82,103 @@ private:
void collectArgumentsInContext();
QV4::ExecutionEngine *m_engine;
- Refs *m_collectedRefs;
+ Refs collectedRefs;
QV4::PersistentValue values;
typedef QHash<Ref, QJsonObject> SpecialRefs;
SpecialRefs specialRefs;
};
-class RefHolder {
+class CollectJob : public QV4::Debugging::V4Debugger::Job
+{
+protected:
+ QV4DataCollector *collector;
+ QJsonObject result;
+ QJsonArray collectedRefs;
public:
- RefHolder(QV4DataCollector *collector, QV4DataCollector::Refs *target) :
- m_collector(collector), m_previousRefs(collector->m_collectedRefs)
- {
- m_collector->m_collectedRefs = target;
- }
-
- ~RefHolder()
- {
- std::swap(m_collector->m_collectedRefs, m_previousRefs);
- }
-
-private:
- QV4DataCollector *m_collector;
- QV4DataCollector::Refs *m_previousRefs;
+ CollectJob(QV4DataCollector *collector) : collector(collector) {}
+ const QJsonObject &returnValue() const { return result; }
+ const QJsonArray &refs() const { return collectedRefs; }
};
-class ExpressionEvalJob: public QV4::Debugging::V4Debugger::JavaScriptJob
+class BacktraceJob: public CollectJob
{
- QV4DataCollector *collector;
- QString exception;
-
+ int fromFrame;
+ int toFrame;
public:
- ExpressionEvalJob(QV4::ExecutionEngine *engine, int frameNr, const QString &expression,
- QV4DataCollector *collector);
- virtual void handleResult(QV4::ScopedValue &result);
- const QString &exceptionMessage() const;
+ BacktraceJob(QV4DataCollector *collector, int fromFrame, int toFrame);
+ void run();
};
-class GatherSourcesJob: public QV4::Debugging::V4Debugger::Job
+class FrameJob: public CollectJob
{
- QV4::ExecutionEngine *engine;
- const int seq;
+ int frameNr;
+ bool success;
public:
- GatherSourcesJob(QV4::ExecutionEngine *engine, int seq);
+ FrameJob(QV4DataCollector *collector, int frameNr);
void run();
+ bool wasSuccessful() const;
};
-class ArgumentCollectJob: public QV4::Debugging::V4Debugger::Job
+class ScopeJob: public CollectJob
{
- QV4::ExecutionEngine *engine;
- QV4DataCollector *collector;
- QStringList *names;
int frameNr;
int scopeNr;
+ bool success;
public:
- ArgumentCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector,
- QStringList *names, int frameNr, int scopeNr);
+ ScopeJob(QV4DataCollector *collector, int frameNr, int scopeNr);
void run();
+ bool wasSuccessful() const;
};
-class LocalCollectJob: public QV4::Debugging::V4Debugger::Job
+class ValueLookupJob: public CollectJob
{
- QV4::ExecutionEngine *engine;
- QV4DataCollector *collector;
- QStringList *names;
- int frameNr;
- int scopeNr;
+ const QJsonArray handles;
+ QString exception;
public:
- LocalCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector, QStringList *names,
- int frameNr, int scopeNr);
+ ValueLookupJob(const QJsonArray &handles, QV4DataCollector *collector);
void run();
+ const QString &exceptionMessage() const;
};
-class ThisCollectJob: public QV4::Debugging::V4Debugger::Job
+class ExpressionEvalJob: public QV4::Debugging::V4Debugger::JavaScriptJob
{
- QV4::ExecutionEngine *engine;
QV4DataCollector *collector;
- int frameNr;
- bool *foundThis;
+ QString exception;
+ QJsonObject value;
+ QJsonArray collectedRefs;
public:
- ThisCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector, int frameNr,
- bool *foundThis);
+ ExpressionEvalJob(QV4::ExecutionEngine *engine, int frameNr, const QString &expression,
+ QV4DataCollector *collector);
+ virtual void handleResult(QV4::ScopedValue &result);
+ const QString &exceptionMessage() const;
+ const QJsonObject &returnValue() const;
+ const QJsonArray &refs() const;
+};
+
+class GatherSourcesJob: public QV4::Debugging::V4Debugger::Job
+{
+ QV4::ExecutionEngine *engine;
+ const int seq;
+
+public:
+ GatherSourcesJob(QV4::ExecutionEngine *engine, int seq);
void run();
- bool myRun();
};
class ExceptionCollectJob: public QV4::Debugging::V4Debugger::Job
{
QV4::ExecutionEngine *engine;
QV4DataCollector *collector;
+ QV4DataCollector::Ref exception;
public:
ExceptionCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector);
void run();
+ QV4DataCollector::Ref exceptionValue() const;
};
QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
index 5233a09992..e9bcd772e5 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
@@ -114,9 +114,9 @@ protected:
response.insert(QStringLiteral("running"), debugService->debuggerAgent.isRunning());
}
- void addRefs()
+ void addRefs(const QJsonArray &refs)
{
- response.insert(QStringLiteral("refs"), debugService->buildRefs());
+ response.insert(QStringLiteral("refs"), refs);
}
void createErrorResponse(const QString &msg)
@@ -271,28 +271,16 @@ 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();
-
- QJsonArray frameArray;
- QVector<QV4::StackFrame> frames = debugger->stackTrace(toFrame);
- for (int i = fromFrame; i < toFrame && i < frames.size(); ++i)
- frameArray.push_back(debugService->buildFrame(frames[i], i, debugger));
+ BacktraceJob job(debugService->collector(), fromFrame, toFrame);
+ debugService->debuggerAgent.firstDebugger()->runInEngine(&job);
// response:
addCommand();
addRequestSequence();
addSuccess(true);
addRunning();
- QJsonObject body;
- if (frameArray.isEmpty()) {
- body.insert(QStringLiteral("totalFrames"), 0);
- } else {
- body.insert(QStringLiteral("fromFrame"), fromFrame);
- body.insert(QStringLiteral("toFrame"), fromFrame + frameArray.size());
- body.insert(QStringLiteral("frames"), frameArray);
- }
- addBody(body);
- addRefs();
+ addBody(job.returnValue());
+ addRefs(job.refs());
}
};
@@ -308,23 +296,27 @@ public:
const int frameNr = arguments.value(QStringLiteral("number")).toInt(
debugService->selectedFrame());
- QV4::Debugging::V4Debugger *debugger = debugService->debuggerAgent.firstDebugger();
- QVector<QV4::StackFrame> frames = debugger->stackTrace(frameNr + 1);
- if (frameNr < 0 || frameNr >= frames.size()) {
+ if (frameNr < 0) {
createErrorResponse(QStringLiteral("frame command has invalid frame number"));
return;
}
+ FrameJob job(debugService->collector(), frameNr);
+ debugService->debuggerAgent.firstDebugger()->runInEngine(&job);
+ if (!job.wasSuccessful()) {
+ createErrorResponse(QStringLiteral("frame retrieval failed"));
+ return;
+ }
+
debugService->selectFrame(frameNr);
- QJsonObject frame = debugService->buildFrame(frames[frameNr], frameNr, debugger);
// response:
addCommand();
addRequestSequence();
addSuccess(true);
addRunning();
- addBody(frame);
- addRefs();
+ addBody(job.returnValue());
+ addRefs(job.refs());
}
};
@@ -341,9 +333,7 @@ public:
debugService->selectedFrame());
const int scopeNr = arguments.value(QStringLiteral("number")).toInt(0);
- QV4::Debugging::V4Debugger *debugger = debugService->debuggerAgent.firstDebugger();
- QVector<QV4::StackFrame> frames = debugger->stackTrace(frameNr + 1);
- if (frameNr < 0 || frameNr >= frames.size()) {
+ if (frameNr < 0) {
createErrorResponse(QStringLiteral("scope command has invalid frame number"));
return;
}
@@ -352,15 +342,20 @@ public:
return;
}
- QJsonObject scope = debugService->buildScope(frameNr, scopeNr, debugger);
+ ScopeJob job(debugService->collector(), frameNr, scopeNr);
+ debugService->debuggerAgent.firstDebugger()->runInEngine(&job);
+ if (!job.wasSuccessful()) {
+ createErrorResponse(QStringLiteral("scope retrieval failed"));
+ return;
+ }
// response:
addCommand();
addRequestSequence();
addSuccess(true);
addRunning();
- addBody(scope);
- addRefs();
+ addBody(job.returnValue());
+ addRefs(job.refs());
}
};
@@ -375,17 +370,19 @@ public:
QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
QJsonArray handles = arguments.value(QStringLiteral("handles")).toArray();
- QJsonObject body;
- foreach (const QJsonValue &handle, handles)
- body[QString::number(handle.toInt())] = debugService->lookup(handle.toInt());
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- addBody(body);
- addRefs();
+ ValueLookupJob job(handles, debugService->collector());
+ debugService->debuggerAgent.firstDebugger()->runInEngine(&job);
+ if (!job.exceptionMessage().isEmpty()) {
+ createErrorResponse(job.exceptionMessage());
+ } else {
+ // response:
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ addBody(job.returnValue());
+ addRefs(job.refs());
+ }
}
};
@@ -557,7 +554,6 @@ public:
const int frame = arguments.value(QStringLiteral("frame")).toInt(0);
QV4DataCollector *collector = debugService->collector();
- RefHolder holder(collector, debugService->refs());
ExpressionEvalJob job(debugger->engine(), frame, expression, collector);
debugger->runInEngine(&job);
if (job.hasExeption()) {
@@ -567,8 +563,8 @@ public:
addRequestSequence();
addSuccess(true);
addRunning();
- addBody(collector->lookupRef(debugService->refs()->last()));
- addRefs();
+ addBody(job.returnValue());
+ addRefs(job.refs());
}
} else {
createErrorResponse(QStringLiteral("Debugger has to be paused for evaluate to work."));
@@ -789,135 +785,11 @@ void QV4DebugServiceImpl::clearHandles(QV4::ExecutionEngine *engine)
theCollector.reset(new QV4DataCollector(engine));
}
-QJsonObject QV4DebugServiceImpl::buildFrame(const QV4::StackFrame &stackFrame, int frameNr,
- QV4::Debugging::V4Debugger *debugger)
-{
- QV4DataCollector::Ref ref;
-
- QJsonObject frame;
- frame[QLatin1String("index")] = frameNr;
- frame[QLatin1String("debuggerFrame")] = false;
- ref = theCollector->addFunctionRef(stackFrame.function);
- collectedRefs.append(ref);
- frame[QLatin1String("func")] = toRef(ref);
- ref = theCollector->addScriptRef(stackFrame.source);
- collectedRefs.append(ref);
- frame[QLatin1String("script")] = toRef(ref);
- frame[QLatin1String("line")] = stackFrame.line - 1;
- if (stackFrame.column >= 0)
- frame[QLatin1String("column")] = stackFrame.column;
-
- QJsonArray scopes;
- if (debugger->state() == QV4::Debugging::V4Debugger::Paused) {
- RefHolder holder(theCollector.data(), &collectedRefs);
- bool foundThis = false;
- ThisCollectJob job(debugger->engine(), theCollector.data(), frameNr, &foundThis);
- debugger->runInEngine(&job);
- if (foundThis)
- frame[QLatin1String("receiver")] = toRef(collectedRefs.last());
-
- // Only type and index are used by Qt Creator, so we keep it easy:
- QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes =
- QV4DataCollector::getScopeTypes(debugger->engine(), 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 QV4DebugServiceImpl::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 QV4DebugServiceImpl::buildScope(int frameNr, int scopeNr,
- QV4::Debugging::V4Debugger *debugger)
-{
- QJsonObject scope;
-
- QJsonObject object;
- RefHolder holder(theCollector.data(), &collectedRefs);
- theCollector->collectScope(&object, debugger, frameNr, scopeNr);
-
- if (debugger->state() == QV4::Debugging::V4Debugger::Paused) {
- QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes =
- QV4DataCollector::getScopeTypes(debugger->engine(), frameNr);
- scope[QLatin1String("type")] = encodeScopeType(scopeTypes[scopeNr]);
- } else {
- scope[QLatin1String("type")] = -1;
- }
- scope[QLatin1String("index")] = scopeNr;
- scope[QLatin1String("frameIndex")] = frameNr;
- scope[QLatin1String("object")] = object;
-
- return scope;
-}
-
-QJsonValue QV4DebugServiceImpl::lookup(QV4DataCollector::Ref refId)
-{
- RefHolder holder(theCollector.data(), &collectedRefs);
- return theCollector->lookupRef(refId);
-}
-
-QJsonArray QV4DebugServiceImpl::buildRefs()
-{
- QJsonArray refs;
- std::sort(collectedRefs.begin(), collectedRefs.end());
- for (int i = 0, ei = collectedRefs.size(); i != ei; ++i) {
- QV4DataCollector::Ref ref = collectedRefs.at(i);
- if (i > 0 && ref == collectedRefs.at(i - 1))
- continue;
- refs.append(lookup(ref));
- }
-
- collectedRefs.clear();
- return refs;
-}
-
-QJsonValue QV4DebugServiceImpl::toRef(QV4DataCollector::Ref ref)
-{
- QJsonObject dict;
- dict.insert(QStringLiteral("ref"), qint64(ref));
- return dict;
-}
-
QV4DataCollector *QV4DebugServiceImpl::collector() const
{
return theCollector.data();
}
-QV4DataCollector::Refs *QV4DebugServiceImpl::refs()
-{
- return &collectedRefs;
-}
-
void QV4DebugServiceImpl::selectFrame(int frameNr)
{
theSelectedFrame = frameNr;
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h
index 273e5ffd62..658b1b3998 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h
@@ -78,13 +78,6 @@ public:
void signalEmitted(const QString &signal);
void send(QJsonObject v8Payload);
- QJsonObject buildScope(int frameNr, int scopeNr, QV4::Debugging::V4Debugger *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);
int selectedFrame() const;
void selectFrame(int frameNr);
@@ -92,7 +85,6 @@ public:
QV4DataCollector *collector() const;
QV4DebuggerAgent debuggerAgent;
- QV4DataCollector::Refs *refs();
protected:
void messageReceived(const QByteArray &);
@@ -106,14 +98,12 @@ private:
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);
QStringList breakOnSignals;
QMap<int, QV4::Debugging::V4Debugger *> debuggerMap;
static int debuggerIndex;
static int sequence;
const int version;
- QV4DataCollector::Refs collectedRefs;
QScopedPointer<QV4DataCollector> theCollector;
int theSelectedFrame;
diff --git a/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp
index 39a1fbc173..2532f73466 100644
--- a/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp
+++ b/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp
@@ -103,19 +103,24 @@ public:
typedef QV4DataCollector::Refs Refs;
typedef QV4DataCollector::Ref Ref;
struct NamedRefs {
- NamedRefs(QV4DataCollector *collector = 0): collector(collector) {}
-
- QStringList names;
- Refs refs;
- QV4DataCollector *collector;
+ QJsonArray refs;
+ QJsonObject scope;
int size() const {
- Q_ASSERT(names.size() == refs.size());
- return names.size();
+ return scope.size();
}
bool contains(const QString &name) const {
- return names.contains(name);
+ return scope.contains(name);
+ }
+
+ QJsonObject resolveRef(int ref) const {
+ foreach (const QJsonValue &val, refs) {
+ QJsonObject obj = val.toObject();
+ if (obj.value(QLatin1String("handle")).toInt() == ref)
+ return obj;
+ }
+ return QJsonObject();
}
#define DUMP_JSON(x) {\
@@ -125,7 +130,7 @@ public:
QJsonObject rawValue(const QString &name) const {
Q_ASSERT(contains(name));
- return collector->lookupRef(refs.at(names.indexOf(name)));
+ return scope[name].toObject();
}
QJsonValue value(const QString &name) const {
@@ -142,7 +147,7 @@ public:
return;
}
- QJsonObject o = collector->lookupRef(refs.at(names.indexOf(name)));
+ QJsonObject o = scope[name].toObject();
QJsonDocument d;
d.setObject(o);
qDebug() << name << "=" << d.toJson(QJsonDocument::Indented);
@@ -169,12 +174,9 @@ public slots:
if (debugger->state() == V4Debugger::Paused &&
debugger->engine()->hasException) {
- Refs refs;
- RefHolder holder(&collector, &refs);
ExceptionCollectJob job(debugger->engine(), &collector);
debugger->runInEngine(&job);
- Q_ASSERT(refs.size() > 0);
- m_thrownValue = refs.first();
+ m_thrownValue = job.exceptionValue();
}
foreach (const TestBreakPoint &bp, m_breakPointsToAddWhenPaused)
@@ -186,11 +188,11 @@ public slots:
while (!m_expressionRequests.isEmpty()) {
Q_ASSERT(debugger->state() == V4Debugger::Paused);
ExpressionRequest request = m_expressionRequests.takeFirst();
- m_expressionResults << Refs();
- RefHolder holder(&collector, &m_expressionResults.last());
ExpressionEvalJob job(debugger->engine(), request.frameNr, request.expression,
&collector);
debugger->runInEngine(&job);
+ m_expressionResults << job.returnValue();
+ m_expressionRefs << job.refs();
}
if (m_captureContextInfo)
@@ -212,17 +214,30 @@ public:
void captureContextInfo(V4Debugger *debugger)
{
for (int i = 0, ei = m_stackTrace.size(); i != ei; ++i) {
- m_capturedArguments.append(NamedRefs(&collector));
- RefHolder argHolder(&collector, &m_capturedArguments.last().refs);
- ArgumentCollectJob argumentsJob(debugger->engine(), &collector,
- &m_capturedArguments.last().names, i, 0);
- debugger->runInEngine(&argumentsJob);
-
- m_capturedLocals.append(NamedRefs(&collector));
- RefHolder localHolder(&collector, &m_capturedLocals.last().refs);
- LocalCollectJob localsJob(debugger->engine(), &collector,
- &m_capturedLocals.last().names, i, 0);
- debugger->runInEngine(&localsJob);
+ m_capturedScope.append(NamedRefs());
+ ScopeJob job(&collector, i, 0);
+ debugger->runInEngine(&job);
+ NamedRefs &refs = m_capturedScope.last();
+ refs.refs = job.refs();
+ QJsonObject object = job.returnValue();
+ object = object.value(QLatin1String("object")).toObject();
+ int ref = object.value(QLatin1String("ref")).toInt();
+ object = refs.resolveRef(ref);
+ foreach (const QJsonValue &value, object.value(QLatin1String("properties")).toArray()) {
+ QJsonObject property = value.toObject();
+ QString name = property.value(QLatin1String("name")).toString();
+ property.remove(QLatin1String("name"));
+ if (property.contains(QLatin1String("ref"))) {
+ int childRef = property.value(QLatin1String("ref")).toInt();
+ if (childRef >= 0 && refs.refs.size() > childRef) {
+ property.remove(QLatin1String("ref"));
+ property.insert(QLatin1String("properties"),
+ refs.resolveRef(childRef).value(
+ QLatin1String("properties")).toArray());
+ }
+ }
+ refs.scope.insert(name, property);
+ }
}
}
@@ -240,8 +255,7 @@ public:
QList<V4Debugger::ExecutionState> m_statesWhenPaused;
QList<TestBreakPoint> m_breakPointsToAddWhenPaused;
QVector<QV4::StackFrame> m_stackTrace;
- QVector<NamedRefs> m_capturedArguments;
- QVector<NamedRefs> m_capturedLocals;
+ QVector<NamedRefs> m_capturedScope;
qint64 m_thrownValue;
QV4DataCollector collector;
@@ -250,7 +264,8 @@ public:
int frameNr;
};
QVector<ExpressionRequest> m_expressionRequests;
- QVector<Refs> m_expressionResults;
+ QList<QJsonObject> m_expressionResults;
+ QList<QJsonArray> m_expressionRefs;
V4Debugger *m_debugger;
// Utility methods:
@@ -454,8 +469,8 @@ void tst_qv4debugger::conditionalBreakPoint()
QCOMPARE(state.fileName, QString("conditionalBreakPoint"));
QCOMPARE(state.lineNumber, 3);
- QVERIFY(m_debuggerAgent->m_capturedLocals.size() > 1);
- const TestAgent::NamedRefs &frame0 = m_debuggerAgent->m_capturedLocals.at(0);
+ QVERIFY(m_debuggerAgent->m_capturedScope.size() > 1);
+ const TestAgent::NamedRefs &frame0 = m_debuggerAgent->m_capturedScope.at(0);
QCOMPARE(frame0.size(), 2);
QVERIFY(frame0.contains("i"));
QCOMPARE(frame0.value("i").toInt(), 11);
@@ -511,13 +526,13 @@ void tst_qv4debugger::readArguments()
debugger()->addBreakPoint("readArguments", 2);
evaluateJavaScript(script, "readArguments");
QVERIFY(m_debuggerAgent->m_wasPaused);
- QVERIFY(m_debuggerAgent->m_capturedArguments.size() > 1);
- const TestAgent::NamedRefs &frame0 = m_debuggerAgent->m_capturedArguments.at(0);
+ QVERIFY(m_debuggerAgent->m_capturedScope.size() > 1);
+ const TestAgent::NamedRefs &frame0 = m_debuggerAgent->m_capturedScope.at(0);
QCOMPARE(frame0.size(), 4);
QVERIFY(frame0.contains(QStringLiteral("a")));
QCOMPARE(frame0.type(QStringLiteral("a")), QStringLiteral("number"));
QCOMPARE(frame0.value(QStringLiteral("a")).toDouble(), 1.0);
- QVERIFY(frame0.names.contains("b"));
+ QVERIFY(frame0.scope.contains("b"));
QCOMPARE(frame0.type(QStringLiteral("b")), QStringLiteral("string"));
QCOMPARE(frame0.value(QStringLiteral("b")).toString(), QStringLiteral("two"));
}
@@ -535,9 +550,9 @@ void tst_qv4debugger::readLocals()
debugger()->addBreakPoint("readLocals", 3);
evaluateJavaScript(script, "readLocals");
QVERIFY(m_debuggerAgent->m_wasPaused);
- QVERIFY(m_debuggerAgent->m_capturedLocals.size() > 1);
- const TestAgent::NamedRefs &frame0 = m_debuggerAgent->m_capturedLocals.at(0);
- QCOMPARE(frame0.size(), 2);
+ QVERIFY(m_debuggerAgent->m_capturedScope.size() > 1);
+ const TestAgent::NamedRefs &frame0 = m_debuggerAgent->m_capturedScope.at(0);
+ QCOMPARE(frame0.size(), 4); // locals and parameters
QVERIFY(frame0.contains("c"));
QCOMPARE(frame0.type("c"), QStringLiteral("number"));
QCOMPARE(frame0.value("c").toDouble(), 3.0);
@@ -557,9 +572,9 @@ void tst_qv4debugger::readObject()
debugger()->addBreakPoint("readObject", 3);
evaluateJavaScript(script, "readObject");
QVERIFY(m_debuggerAgent->m_wasPaused);
- QVERIFY(m_debuggerAgent->m_capturedLocals.size() > 1);
- const TestAgent::NamedRefs &frame0 = m_debuggerAgent->m_capturedLocals.at(0);
- QCOMPARE(frame0.size(), 1);
+ QVERIFY(m_debuggerAgent->m_capturedScope.size() > 1);
+ const TestAgent::NamedRefs &frame0 = m_debuggerAgent->m_capturedScope.at(0);
+ QCOMPARE(frame0.size(), 2);
QVERIFY(frame0.contains("b"));
QCOMPARE(frame0.type("b"), QStringLiteral("object"));
QJsonObject b = frame0.rawValue("b");
@@ -578,7 +593,7 @@ void tst_qv4debugger::readObject()
QCOMPARE(b_tail.value("name").toString(), QStringLiteral("tail"));
QVERIFY(b_tail.contains("ref"));
- QJsonObject b_tail_value = frame0.collector->lookupRef(b_tail.value("ref").toInt());
+ QJsonObject b_tail_value = m_debuggerAgent->collector.lookupRef(b_tail.value("ref").toInt());
QCOMPARE(b_tail_value.value("type").toString(), QStringLiteral("object"));
QVERIFY(b_tail_value.contains("properties"));
QJsonArray b_tail_props = b_tail_value.value("properties").toArray();
@@ -610,28 +625,23 @@ void tst_qv4debugger::readContextInAllFrames()
evaluateJavaScript(script, "readFormalsInAllFrames");
QVERIFY(m_debuggerAgent->m_wasPaused);
QCOMPARE(m_debuggerAgent->m_stackTrace.size(), 13);
- QCOMPARE(m_debuggerAgent->m_capturedArguments.size(), 13);
- QCOMPARE(m_debuggerAgent->m_capturedLocals.size(), 13);
+ QCOMPARE(m_debuggerAgent->m_capturedScope.size(), 13);
for (int i = 0; i < 12; ++i) {
- const TestAgent::NamedRefs &args = m_debuggerAgent->m_capturedArguments.at(i);
- QCOMPARE(args.size(), 1);
- QVERIFY(args.contains("n"));
- QCOMPARE(args.type("n"), QStringLiteral("number"));
- QCOMPARE(args.value("n").toDouble(), i + 1.0);
-
- const TestAgent::NamedRefs &locals = m_debuggerAgent->m_capturedLocals.at(i);
- QCOMPARE(locals.size(), 1);
- QVERIFY(locals.contains("n_1"));
+ const TestAgent::NamedRefs &scope = m_debuggerAgent->m_capturedScope.at(i);
+ QCOMPARE(scope.size(), 2);
+ QVERIFY(scope.contains("n"));
+ QCOMPARE(scope.type("n"), QStringLiteral("number"));
+ QCOMPARE(scope.value("n").toDouble(), i + 1.0);
+ QVERIFY(scope.contains("n_1"));
if (i == 0) {
- QCOMPARE(locals.type("n_1"), QStringLiteral("undefined"));
+ QCOMPARE(scope.type("n_1"), QStringLiteral("undefined"));
} else {
- QCOMPARE(locals.type("n_1"), QStringLiteral("number"));
- QCOMPARE(locals.value("n_1").toInt(), i);
+ QCOMPARE(scope.type("n_1"), QStringLiteral("number"));
+ QCOMPARE(scope.value("n_1").toInt(), i);
}
}
- QCOMPARE(m_debuggerAgent->m_capturedArguments[12].size(), 0);
- QCOMPARE(m_debuggerAgent->m_capturedLocals[12].size(), 0);
+ QCOMPARE(m_debuggerAgent->m_capturedScope[12].size(), 0);
}
void tst_qv4debugger::pauseOnThrow()
@@ -711,15 +721,13 @@ void tst_qv4debugger::evaluateExpression()
evaluateJavaScript(script, "evaluateExpression");
- QCOMPARE(m_debuggerAgent->m_expressionResults.count(), 2);
- QCOMPARE(m_debuggerAgent->m_expressionResults[0].size(), 1);
- QJsonObject result0 =
- m_debuggerAgent->collector.lookupRef(m_debuggerAgent->m_expressionResults[0].first());
+ QCOMPARE(m_debuggerAgent->m_expressionRefs.count(), 2);
+ QCOMPARE(m_debuggerAgent->m_expressionRefs[0].size(), 1);
+ QJsonObject result0 = m_debuggerAgent->m_expressionRefs[0].first().toObject();
QCOMPARE(result0.value("type").toString(), QStringLiteral("number"));
QCOMPARE(result0.value("value").toInt(), 10);
- QCOMPARE(m_debuggerAgent->m_expressionResults[1].size(), 1);
- QJsonObject result1 =
- m_debuggerAgent->collector.lookupRef(m_debuggerAgent->m_expressionResults[1].first());
+ QCOMPARE(m_debuggerAgent->m_expressionRefs[1].size(), 1);
+ QJsonObject result1 = m_debuggerAgent->m_expressionRefs[1].first().toObject();
QCOMPARE(result1.value("type").toString(), QStringLiteral("number"));
QCOMPARE(result1.value("value").toInt(), 20);
}