QML JS Debugger: Better way to stream watch data

QVariant does not work as they can contain custom type that corrypt the stream
This commit is contained in:
Olivier Goffart
2010-07-22 13:00:26 +02:00
parent 0340d6ad8b
commit bfa609e336
3 changed files with 105 additions and 95 deletions

View File

@@ -47,9 +47,78 @@
#include <QtScript/QScriptContextInfo>
#include <QtCore/QDebug>
#include <QtCore/QUrl>
#include <QtCore/QDateTime>
#include <QtScript/qscriptvalueiterator.h>
QT_BEGIN_NAMESPACE
namespace {
struct JSAgentWatchData {
QByteArray exp;
QString name;
QString value;
QString type;
bool hasChildren;
static JSAgentWatchData fromScriptValue(const QString &expression, const QScriptValue &value)
{
JSAgentWatchData data;
data.exp = expression.toUtf8();
data.name = expression;
data.hasChildren = false;
data.value = value.toString();
if (value.isArray()) {
data.type = QLatin1String("Array");
data.value = QString::fromLatin1("[Array of length %1]").arg(value.property("length").toString());
data.hasChildren = true;
} else if (value.isBool()) {
data.type = QLatin1String("Bool");
// data.value = value.toBool() ? QLatin1String("true") : QLatin1String("false");
} else if (value.isDate()) {
data.type = QLatin1String("Date");
data.value = value.toDateTime().toString();
} else if (value.isError()) {
data.type = QLatin1String("Error");
} else if (value.isFunction()) {
data.type = QLatin1String("Function");
} else if (value.isUndefined()) {
data.type = QLatin1String("<undefined>");
} else if (value.isNumber()) {
data.type = QLatin1String("Number");
} else if (value.isRegExp()) {
data.type = QLatin1String("RegExp");
} else if (value.isString()) {
data.type = QLatin1String("String");
} else if (value.isVariant()) {
data.type = QLatin1String("Variant");
} else if (value.isObject()) {
data.type = QLatin1String("Object");
data.hasChildren = true;
data.value = QLatin1String("[Object]");
/* } else if (value.isQMetaObject()) {
data.setType(QLatin1String("QMetaObject"), false);
data.setValue(QString(QLatin1Char(' ')));
} else if (value.isQObject()) {
data.type = QLatin1String("QObject");
data.hasChildren = true;*/
} else if (value.isNull()) {
data.type = QLatin1String("<null>");
} else {
data.type = QLatin1String("<unknown>");
}
return data;
}
};
QDataStream& operator<<(QDataStream& s, const JSAgentWatchData& data)
{
return s << data.exp << data.name << data.value << data.type << data.hasChildren;
}
}
/*!
Constructs a new agent for the given \a engine. The agent will
report debugging-related events (e.g. step completion) to the given
@@ -219,13 +288,13 @@ void JSDebuggerAgent::messageReceived(const QByteArray& message)
QString expr;
ds >> id >> expr;
QVariant val = engine()->evaluate(expr).toVariant();
JSAgentWatchData data = JSAgentWatchData::fromScriptValue(expr, engine()->evaluate(expr));
// Clear any exceptions occurred during locals evaluation.
engine()->clearExceptions();
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("RESULT") << id << expr << val;
rs << QByteArray("RESULT") << id << data;
sendMessage(reply);
state = oldState;
@@ -265,18 +334,25 @@ void JSDebuggerAgent::stopped()
}
backtrace.append(qMakePair(functionName, qMakePair( QUrl(info.fileName()).toLocalFile(), info.lineNumber() ) ) );
}
QList<QPair<QString, QVariant> > watches;
QList<JSAgentWatchData> watches;
foreach (const QString &expr, watchExpressions) {
watches << qMakePair(expr, engine()->evaluate(expr).toVariant());
watches << JSAgentWatchData::fromScriptValue(expr, engine()->evaluate(expr));
}
QList<JSAgentWatchData> locals;
QScriptValue activationObject = engine()->currentContext()->activationObject();
QScriptValueIterator it(activationObject);
while (it.hasNext()) {
it.next();
locals << JSAgentWatchData::fromScriptValue(it.name(), it.value());
}
// Clear any exceptions occurred during locals evaluation.
engine()->clearExceptions();
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("STOPPED") << backtrace << watches << engine()->currentContext()->activationObject().toVariant();
rs << QByteArray("STOPPED") << backtrace << watches << locals;
sendMessage(reply);
loop.exec(QEventLoop::ExcludeUserInputEvents);