summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2018-05-25 16:59:42 +0200
committerUlf Hermann <ulf.hermann@qt.io>2018-05-25 15:21:32 +0000
commit9a44e3b6ca81f0e84d774a95e45b449b5d4cb583 (patch)
treee57fe07bfbfc8e64fd2f9214e9ddd5d47b3d9136
parent71688bab1b7abf64ae840dff887aa501e83d5acc (diff)
QML Debugger: Don't crash when encoding JSON data
Apparently QVariant::save cannot deal with QJsonObject and friends. Transform them into QVariants before sending them over the wire. Task-number: QTBUG-68474 Change-Id: I8fc9fade4915c2b40f8d16aea51ea6ff65247dc1 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp63
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp63
2 files changed, 99 insertions, 27 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
index d008b86a78..17bae6d695 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
@@ -55,6 +55,11 @@
#include <QtCore/qdebug.h>
#include <QtCore/qmetaobject.h>
#include <QtCore/qfileinfo.h>
+#include <QtCore/qjsonvalue.h>
+#include <QtCore/qjsonobject.h>
+#include <QtCore/qjsonarray.h>
+#include <QtCore/qjsondocument.h>
+
#include <private/qmetaobject_p.h>
#include <private/qqmldebugconnector_p.h>
#include <private/qversionedpacket_p.h>
@@ -211,34 +216,40 @@ QVariant QQmlEngineDebugServiceImpl::valueContents(QVariant value) const
return contents;
}
- if (QQmlValueTypeFactory::isValueType(userType)) {
- switch (userType) {
- case QMetaType::QRect:
- case QMetaType::QRectF:
- case QMetaType::QPoint:
- case QMetaType::QPointF:
- case QMetaType::QSize:
- case QMetaType::QSizeF:
- case QMetaType::QFont:
- // Don't call the toString() method on those. The stream operators are better.
- return value;
- default:
- break;
- }
-
- const QMetaObject *mo = QQmlValueTypeFactory::metaObjectForMetaType(userType);
- if (mo) {
- int toStringIndex = mo->indexOfMethod("toString()");
- if (toStringIndex != -1) {
- QMetaMethod mm = mo->method(toStringIndex);
- QString s;
- if (mm.invokeOnGadget(value.data(), Q_RETURN_ARG(QString, s)))
- return s;
+ switch (userType) {
+ case QMetaType::QRect:
+ case QMetaType::QRectF:
+ case QMetaType::QPoint:
+ case QMetaType::QPointF:
+ case QMetaType::QSize:
+ case QMetaType::QSizeF:
+ case QMetaType::QFont:
+ // Don't call the toString() method on those. The stream operators are better.
+ return value;
+ case QMetaType::QJsonValue:
+ return value.toJsonValue().toVariant();
+ case QMetaType::QJsonObject:
+ return value.toJsonObject().toVariantMap();
+ case QMetaType::QJsonArray:
+ return value.toJsonArray().toVariantList();
+ case QMetaType::QJsonDocument:
+ return value.toJsonDocument().toVariant();
+ default:
+ if (QQmlValueTypeFactory::isValueType(userType)) {
+ const QMetaObject *mo = QQmlValueTypeFactory::metaObjectForMetaType(userType);
+ if (mo) {
+ int toStringIndex = mo->indexOfMethod("toString()");
+ if (toStringIndex != -1) {
+ QMetaMethod mm = mo->method(toStringIndex);
+ QString s;
+ if (mm.invokeOnGadget(value.data(), Q_RETURN_ARG(QString, s)))
+ return s;
+ }
}
- }
- // We expect all QML value types to either have a toString() method or stream operators
- return value;
+ // We expect all QML value types to either have a toString() method or stream operators
+ return value;
+ }
}
if (QQmlMetaType::isQObject(userType)) {
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
index 89217e7556..417b75e760 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
@@ -53,6 +53,9 @@
#include <QtCore/qdebug.h>
#include <QtCore/qthread.h>
#include <QtCore/qabstractitemmodel.h>
+#include <QtCore/qjsonobject.h>
+#include <QtCore/qjsonarray.h>
+#include <QtCore/qjsondocument.h>
#define QVERIFYOBJECT(statement) \
do {\
@@ -82,6 +85,40 @@ public:
QModelIndex modelIndex() { return QModelIndex(); }
};
+class JsonTest : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QJsonObject data READ data WRITE setData NOTIFY dataChanged)
+
+public:
+ JsonTest(QObject *parent = 0) : QObject(parent)
+ {
+ m_data["foo"] = QJsonValue(12);
+ m_data["ttt"] = QJsonArray({4, 5, 4, 3, 2});
+ m_data["a"] = QJsonValue(QJsonValue::Null);
+ m_data["b"] = QJsonValue(QJsonValue::Undefined);
+ m_data["c"] = QJsonValue("fffff");
+ }
+
+ QJsonObject data() const { return m_data; }
+
+signals:
+ void dataChanged(const QJsonObject &data);
+
+public slots:
+ void setData(const QJsonObject &data)
+ {
+ if (data != m_data) {
+ m_data = data;
+ emit dataChanged(data);
+ }
+ }
+
+private:
+ QJsonObject m_data;
+};
+
+
class tst_QQmlEngineDebugService : public QObject
{
Q_OBJECT
@@ -139,6 +176,7 @@ private slots:
void regression_QTCREATORBUG_7451();
void queryObjectWithNonStreamableTypes();
+ void jsonData();
void asynchronousCreate();
void invalidContexts();
void createObjectOnDestruction();
@@ -363,6 +401,11 @@ void tst_QQmlEngineDebugService::initTestCase()
"CustomTypes {}"
;
+ qmlRegisterType<JsonTest>("JsonTest", 1, 0, "JsonTest");
+ qml << "import JsonTest 1.0\n"
+ "JsonTest {}"
+ ;
+
for (int i=0; i<qml.count(); i++) {
QQmlComponent component(m_engine);
component.setData(qml[i], QUrl::fromLocalFile(""));
@@ -676,7 +719,7 @@ void tst_QQmlEngineDebugService::queryRootContexts()
// root context query sends only root object data - it doesn't fill in
// the children or property info
QCOMPARE(context.objects.count(), 0);
- QCOMPARE(context.contexts.count(), 6);
+ QCOMPARE(context.contexts.count(), 7);
QVERIFY(context.contexts[0].debugId >= 0);
QCOMPARE(context.contexts[0].name, QString("tst_QQmlDebug_childContext"));
}
@@ -915,6 +958,24 @@ void tst_QQmlEngineDebugService::queryObjectWithNonStreamableTypes()
QVariant(QLatin1String("QModelIndex()")));
}
+void tst_QQmlEngineDebugService::jsonData()
+{
+ bool success;
+
+ QmlDebugObjectReference rootObject = findRootObject(5, true);
+ QVERIFY(!rootObject.className.isEmpty());
+
+ m_dbg->queryObject(rootObject, &success);
+ QVERIFY(success);
+ QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
+
+ QmlDebugObjectReference obj = m_dbg->object();
+ QVERIFY(!obj.className.isEmpty());
+
+ QCOMPARE(findProperty(obj.properties, "data").value,
+ QJsonDocument::fromJson("{\"a\":null,\"c\":\"fffff\",\"foo\":12,\"ttt\":[4,5,4,3,2]}")
+ .toVariant());
+}
void tst_QQmlEngineDebugService::queryExpressionResult()
{