forked from qt-creator/qt-creator
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:
@@ -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);
|
||||
|
Reference in New Issue
Block a user