QmlDebugging: Fix Watched Expressions

The data response was incorrectly parsed for watched expressions.
This patch fixes the parsing. It also fixes removal and readdition
of a watched expression.

Change-Id: I1a9e2db3d4963d7fe12ed468ae5466a106011487
Reviewed-by: hjk <qthjk@ovi.com>
Reviewed-by: Kai Koehne <kai.koehne@nokia.com>
This commit is contained in:
Aurindam Jana
2012-03-21 09:46:33 +01:00
parent d75c404078
commit 44de30e769
2 changed files with 53 additions and 37 deletions

View File

@@ -150,6 +150,7 @@ public:
QHash<int, QString> evaluatingExpression; QHash<int, QString> evaluatingExpression;
QHash<int, QByteArray> localsAndWatchers; QHash<int, QByteArray> localsAndWatchers;
QList<int> updateLocalsAndWatchers;
//Cache //Cache
QStringList watchedExpressions; QStringList watchedExpressions;
@@ -831,6 +832,7 @@ QmlV8ObjectData QmlV8DebuggerClientPrivate::extractData(const QVariant &data,
objectData.properties = data.properties; objectData.properties = data.properties;
} }
} else { } else {
objectData.handle = dataMap.value(_(HANDLE)).toInt();
QString type = dataMap.value(_(TYPE)).toString(); QString type = dataMap.value(_(TYPE)).toString();
if (type == _("undefined")) { if (type == _("undefined")) {
@@ -1161,6 +1163,7 @@ void QmlV8DebuggerClient::assignValueInDebugger(const WatchData * /*data*/,
QString expression = QString(_("%1 = %2;")).arg(expr).arg(valueV.toString()); QString expression = QString(_("%1 = %2;")).arg(expr).arg(valueV.toString());
if (stackHandler->isContentsValid() && stackHandler->currentFrame().isUsable()) { if (stackHandler->isContentsValid() && stackHandler->currentFrame().isUsable()) {
d->evaluate(expression, false, false, stackHandler->currentIndex()); d->evaluate(expression, false, false, stackHandler->currentIndex());
d->updateLocalsAndWatchers.append(d->sequence);
} else { } else {
d->engine->showMessage(QString(_("Cannot evaluate" d->engine->showMessage(QString(_("Cannot evaluate"
"%1 in current stack frame")). "%1 in current stack frame")).
@@ -1178,7 +1181,6 @@ void QmlV8DebuggerClient::executeDebuggerCommand(const QString &command)
StackHandler *stackHandler = d->engine->stackHandler(); StackHandler *stackHandler = d->engine->stackHandler();
if (stackHandler->isContentsValid() && stackHandler->currentFrame().isUsable()) { if (stackHandler->isContentsValid() && stackHandler->currentFrame().isUsable()) {
d->evaluate(command, false, false, stackHandler->currentIndex()); d->evaluate(command, false, false, stackHandler->currentIndex());
d->evaluatingExpression.insert(d->sequence, command);
} else { } else {
//Currently cannot evaluate if not in a javascript break //Currently cannot evaluate if not in a javascript break
d->engine->showMessage(QString(_("Cannot evaluate %1" d->engine->showMessage(QString(_("Cannot evaluate %1"
@@ -1192,7 +1194,6 @@ void QmlV8DebuggerClient::synchronizeWatchers(const QStringList &watchers)
SDEBUG(watchers); SDEBUG(watchers);
foreach (const QString &exp, watchers) { foreach (const QString &exp, watchers) {
if (!d->watchedExpressions.contains(exp)) { if (!d->watchedExpressions.contains(exp)) {
d->watchedExpressions << exp;
StackHandler *stackHandler = d->engine->stackHandler(); StackHandler *stackHandler = d->engine->stackHandler();
if (stackHandler->isContentsValid() && stackHandler->currentFrame().isUsable()) { if (stackHandler->isContentsValid() && stackHandler->currentFrame().isUsable()) {
d->evaluate(exp, false, false, stackHandler->currentIndex()); d->evaluate(exp, false, false, stackHandler->currentIndex());
@@ -1200,11 +1201,12 @@ void QmlV8DebuggerClient::synchronizeWatchers(const QStringList &watchers)
} }
} }
} }
d->watchedExpressions = watchers;
} }
void QmlV8DebuggerClient::expandObject(const QByteArray &iname, quint64 objectId) void QmlV8DebuggerClient::expandObject(const QByteArray &iname, quint64 objectId)
{ {
d->localsAndWatchers.insert(objectId, iname); d->localsAndWatchers.insertMulti(objectId, iname);
d->lookup(QList<int>() << objectId); d->lookup(QList<int>() << objectId);
} }
@@ -1799,15 +1801,16 @@ void QmlV8DebuggerClient::updateEvaluationResult(int sequence, bool success, con
// "running" : <is the VM running after sending this response> // "running" : <is the VM running after sending this response>
// "success" : true // "success" : true
// } // }
if (!d->evaluatingExpression.contains(sequence)) { if (d->updateLocalsAndWatchers.contains(sequence)) {
d->updateLocalsAndWatchers.removeOne(sequence);
//Update the locals //Update the locals
foreach (int index, d->currentFrameScopes) foreach (int index, d->currentFrameScopes)
d->scope(index); d->scope(index);
} else { } else {
QmlV8ObjectData body = d->extractData(bodyVal, refsVal); QmlV8ObjectData body = d->extractData(bodyVal, refsVal);
if (d->evaluatingExpression.contains(sequence)) {
QString exp = d->evaluatingExpression.take(sequence); QString exp = d->evaluatingExpression.take(sequence);
if (d->watchedExpressions.contains(exp)) {
QByteArray iname = d->engine->watchHandler()->watcherName(exp.toLatin1()); QByteArray iname = d->engine->watchHandler()->watcherName(exp.toLatin1());
SDEBUG(QString(iname)); SDEBUG(QString(iname));
WatchData data; WatchData data;
@@ -1823,10 +1826,11 @@ void QmlV8DebuggerClient::updateEvaluationResult(int sequence, bool success, con
//Do not set type since it is unknown //Do not set type since it is unknown
data.setError(body.value.toString()); data.setError(body.value.toString());
} }
QList<WatchData> watchDataList;
watchDataList << data << createWatchDataList(&data, body.properties, refsVal);
//Insert the newly evaluated expression to the Watchers Window //Insert the newly evaluated expression to the Watchers Window
d->engine->watchHandler()->beginCycle(false); d->engine->watchHandler()->beginCycle(false);
d->engine->watchHandler()->insertData(data); d->engine->watchHandler()->insertBulkData(watchDataList);
d->engine->watchHandler()->endCycle(); d->engine->watchHandler()->endCycle();
} else { } else {
@@ -1911,35 +1915,9 @@ void QmlV8DebuggerClient::expandLocalsAndWatchers(const QVariant &bodyVal, const
if (prepend.startsWith("local.") || prepend.startsWith("watch.")) { if (prepend.startsWith("local.") || prepend.startsWith("watch.")) {
//Data for expanded local/watch //Data for expanded local/watch
if (bodyObjectData.properties.count()) {
//Could be an object or function //Could be an object or function
const WatchData *parent = d->engine->watchHandler()->findItem(prepend); const WatchData *parent = d->engine->watchHandler()->findItem(prepend);
foreach (const QVariant &property, bodyObjectData.properties) { watchDataList << createWatchDataList(parent, bodyObjectData.properties, refsVal);
QmlV8ObjectData propertyData = d->extractData(property, refsVal);
WatchData data;
data.name = propertyData.name;
//Check for v8 specific local data
if (data.name.startsWith(QLatin1Char('.')) || data.name.isEmpty())
continue;
if (parent && parent->type == "object") {
if (parent->value == _("Array"))
data.exp = parent->exp + QByteArray("[") +
data.name.toLatin1() + QByteArray("]");
else if (parent->value == _("Object"))
data.exp = parent->exp + QByteArray(".") + data.name.toLatin1();
} else {
data.exp = data.name.toLatin1();
}
data.iname = prepend + '.' + data.name.toLatin1();
data.id = propertyData.handle;
data.type = propertyData.type;
data.value = propertyData.value.toString();
data.setHasChildren(propertyData.properties.count());
watchDataList << data;
}
}
} else { } else {
//rest //rest
WatchData data; WatchData data;
@@ -1962,6 +1940,41 @@ void QmlV8DebuggerClient::expandLocalsAndWatchers(const QVariant &bodyVal, const
d->engine->watchHandler()->endCycle(); d->engine->watchHandler()->endCycle();
} }
QList<WatchData> QmlV8DebuggerClient::createWatchDataList(const WatchData *parent,
const QVariantList &properties,
const QVariant &refsVal)
{
QList<WatchData> watchDataList;
if (properties.count()) {
QTC_ASSERT(parent, return watchDataList);
foreach (const QVariant &property, properties) {
QmlV8ObjectData propertyData = d->extractData(property, refsVal);
WatchData data;
data.name = propertyData.name;
//Check for v8 specific local data
if (data.name.startsWith(QLatin1Char('.')) || data.name.isEmpty())
continue;
if (parent->type == "object") {
if (parent->value == _("Array"))
data.exp = parent->exp + '[' + data.name.toLatin1() + ']';
else if (parent->value == _("Object"))
data.exp = parent->exp + '.' + data.name.toLatin1();
} else {
data.exp = data.name.toLatin1();
}
data.iname = parent->iname + '.' + data.name.toLatin1();
data.id = propertyData.handle;
data.type = propertyData.type;
data.value = propertyData.value.toString();
data.setHasChildren(propertyData.properties.count());
watchDataList << data;
}
}
return watchDataList;
}
void QmlV8DebuggerClient::highlightExceptionCode(int lineNumber, void QmlV8DebuggerClient::highlightExceptionCode(int lineNumber,
const QString &filePath, const QString &filePath,
const QString &errorMessage) const QString &errorMessage)

View File

@@ -116,6 +116,9 @@ private:
void updateBreakpoints(const QVariant &bodyVal); void updateBreakpoints(const QVariant &bodyVal);
void expandLocalsAndWatchers(const QVariant &bodyVal, const QVariant &refsVal); void expandLocalsAndWatchers(const QVariant &bodyVal, const QVariant &refsVal);
QList<WatchData> createWatchDataList(const WatchData *parent,
const QVariantList &properties,
const QVariant &refsVal);
void highlightExceptionCode(int lineNumber, const QString &filePath, void highlightExceptionCode(int lineNumber, const QString &filePath,
const QString &errorMessage); const QString &errorMessage);