aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2019-12-09 15:26:14 +0100
committerUlf Hermann <ulf.hermann@qt.io>2019-12-20 10:51:21 +0100
commitea3bfc91e2a0fc8309f75e960f1891f15d7351c9 (patch)
treeff66f2071c8c14f3b298660c37be21f832f7a867 /tests
parent155a2e0d8d1d9c07fa22f523d84e3d583697aff4 (diff)
QV4Engine: support conversion of QJSValue to SequenceType
8704c640946ac852668638e2980d3e2b78aa27ae introduced new conversions via sequentialIterableToJS. Due to that, QVariant properties which formerly stored e.g. std::vector<QObject*> now would store a QJSValue. Those would still claim to support a conversion to QVariantList, but -contrary to what our documentation says-, we were not able to do a conversion to QSequentialIterable. The default constructed QSequentialIterable would then crash when calling begin(), as that function pointer was null. This patch fixes this by adding the necessary support to convert a QJSValue containing an array. Non-array QJSValues will still return an "empty" QSequentialIterable. Note that this changes what happens when a QJSValue is converted to a QVariantList, as QVariantValueHelperInterface<QVariantList> will check first if there is a converter to QSequentialIterableImpl before attempting to call any directly installed converter to QVariantList. In order to not change the existing behavior, the QSequentialIterable returns the QVariant corresponding to the QJSValue at a given array position, intead of a QVariant containing the QJSValue. Fixes: QTBUG-80609 Change-Id: I8101229c0d2043b3f2d618ed035b279844802dd8 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/qml/qjsvalue/tst_qjsvalue.cpp64
-rw-r--r--tests/auto/qml/qjsvalue/tst_qjsvalue.h2
2 files changed, 66 insertions, 0 deletions
diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
index 37d0ea4dea..95f554776f 100644
--- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
+++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
@@ -2708,6 +2708,70 @@ void tst_QJSValue::nestedObjectToVariant()
QCOMPARE(o.toVariant(), expected);
}
+static int instanceCount = 0;
+
+struct MyType
+{
+ MyType(int n = 0, const char *t=nullptr): number(n), text(t)
+ {
+ ++instanceCount;
+ }
+ MyType(const MyType &other)
+ : number(other.number), text(other.text)
+ {
+ ++instanceCount;
+ }
+ ~MyType()
+ {
+ --instanceCount;
+ }
+ int number;
+ const char *text;
+};
+
+Q_DECLARE_METATYPE(MyType)
+Q_DECLARE_METATYPE(MyType*)
+
+void tst_QJSValue::jsvalueArrayToSequenceType()
+{
+ QCOMPARE(instanceCount, 0);
+ {
+ QJSEngine eng {};
+ auto testObject = eng.newObject();
+ testObject.setProperty("test", 42);
+ testObject.setProperty("mytypeobject", eng.toScriptValue(QVariant::fromValue(MyType {42, "hello"})));
+ auto array = eng.newArray(4);
+ array.setProperty(0, QLatin1String("Hello World"));
+ array.setProperty(1, 42);
+ array.setProperty(2, QJSValue(QJSValue::UndefinedValue));
+ array.setProperty(3, testObject);
+ auto asVariant = QVariant::fromValue(array);
+ QVERIFY(asVariant.canConvert<QVariantList>());
+ auto asIterable = asVariant.value<QSequentialIterable>();
+ for (auto it = asIterable.begin(); it != asIterable.end(); ++it) {
+ Q_UNUSED(*it)
+ }
+ int i = 0;
+ for (QVariant myVariant: asIterable) {
+ QCOMPARE(myVariant.isValid(), i != 2);
+ ++i;
+ }
+ QVERIFY(asIterable.at(2).value<QVariant>().isNull());
+ QCOMPARE(asIterable.at(3).value<QVariantMap>().find("mytypeobject")->value<MyType>().number, 42);
+ QCOMPARE(asIterable.at(0).value<QVariant>().toString(), QLatin1String("Hello World"));
+ auto it1 = asIterable.begin();
+ auto it2 = asIterable.begin();
+ QCOMPARE((*it1).value<QVariant>().toString(), (*it2).value<QVariant>().toString());
+ QCOMPARE((*it1).value<QVariant>().toString(), QLatin1String("Hello World"));
+ ++it2;
+ QCOMPARE((*it1).value<QVariant>().toString(), QLatin1String("Hello World"));
+ QCOMPARE((*it2).value<QVariant>().toInt(), 42);
+ }
+ // tests need to be done after engine has been destroyed, else it will hold a reference until
+ // the gc decides to collect it
+ QCOMPARE(instanceCount, 0);
+}
+
void tst_QJSValue::deleteFromDifferentThread()
{
#if !QT_CONFIG(thread)
diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.h b/tests/auto/qml/qjsvalue/tst_qjsvalue.h
index f704169d43..d85b9a0552 100644
--- a/tests/auto/qml/qjsvalue/tst_qjsvalue.h
+++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.h
@@ -142,6 +142,8 @@ private slots:
void nestedObjectToVariant_data();
void nestedObjectToVariant();
+ void jsvalueArrayToSequenceType();
+
void deleteFromDifferentThread();
private: