aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2014-09-10 17:13:10 +0200
committerLars Knoll <lars.knoll@digia.com>2014-09-17 08:13:11 +0200
commit3dbe05f6bf3fd51ce8097c35f6c7f12b39acb0f6 (patch)
tree444ed433aa02085357b589b19b28f4bc1c243320 /tests/auto
parentcfe1a8152c948a4586ffa1fe79b47f9a0e88beb5 (diff)
Fix mapping of JS objects/arrays to C++
[ChangeLog][QtQml][Important Behavior Changes] When a JavaScript object/array is passed to C++ through a QVariant, the engine no longer immediately converts the object recursively into a QVariantMap or QVariantList but instead stores a QJSValue in the QVariant. This prevents a loss of data when the JS object contains non-primitive types such as function objects for example. Code that expects the variant type to be exactly QVariant::Map or QVariant::List may need to be adapted. Registered conversion functions however ensure that code that merely calls toMap() or toList() continues to work. Task-number: QTBUG-40431 Change-Id: I1dbc1d5f8e78ad28bb62db3681b9a0b34557e7f5 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'tests/auto')
-rw-r--r--tests/auto/qml/qjsvalue/tst_qjsvalue.cpp50
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp20
-rw-r--r--tests/auto/qml/qqmllocale/tst_qqmllocale.cpp4
-rw-r--r--tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp12
-rw-r--r--tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp5
5 files changed, 69 insertions, 22 deletions
diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
index 837403d391..9c615cfc15 100644
--- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
+++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
@@ -34,10 +34,6 @@
#include "tst_qjsvalue.h"
#include <QtWidgets/QPushButton>
-QT_BEGIN_NAMESPACE
-extern bool qt_script_isJITEnabled();
-QT_END_NAMESPACE
-
tst_QJSValue::tst_QJSValue()
: engine(0)
{
@@ -45,8 +41,7 @@ tst_QJSValue::tst_QJSValue()
tst_QJSValue::~tst_QJSValue()
{
- if (engine)
- delete engine;
+ delete engine;
}
void tst_QJSValue::ctor_invalid()
@@ -308,6 +303,19 @@ void tst_QJSValue::ctor_copyAndAssign()
QCOMPARE(v5.toNumber(), 1.0);
}
+static QJSValue createUnboundValue(const QJSValue &value)
+{
+ QVariant variant = QVariant::fromValue(value);
+ QBuffer buffer;
+ buffer.open(QIODevice::ReadWrite);
+ QDataStream stream(&buffer);
+ variant.save(stream);
+ buffer.seek(0);
+ QVariant resultVariant;
+ resultVariant.load(stream);
+ return resultVariant.value<QJSValue>();
+}
+
void tst_QJSValue::toString()
{
QJSEngine eng;
@@ -406,6 +414,28 @@ void tst_QJSValue::toString()
variant = eng.toScriptValue(QUrl());
QVERIFY(variant.isVariant());
QVERIFY(variant.toString().isEmpty());
+
+ {
+ QJSValue o = eng.newObject();
+ o.setProperty(QStringLiteral("test"), 42);
+ QCOMPARE(o.toString(), QStringLiteral("[object Object]"));
+
+ o = createUnboundValue(o);
+ QVERIFY(!o.engine());
+ QCOMPARE(o.toString(), QStringLiteral("[object Object]"));
+ }
+
+ {
+ QJSValue o = eng.newArray();
+ o.setProperty(0, 1);
+ o.setProperty(1, 2);
+ o.setProperty(2, 3);
+ QCOMPARE(o.toString(), QStringLiteral("1,2,3"));
+
+ o = createUnboundValue(o);
+ QVERIFY(!o.engine());
+ QCOMPARE(o.toString(), QStringLiteral("1,2,3"));
+ }
}
void tst_QJSValue::toNumber()
@@ -419,35 +449,43 @@ void tst_QJSValue::toNumber()
QJSValue null = eng.evaluate("null");
QCOMPARE(null.toNumber(), 0.0);
QCOMPARE(qjsvalue_cast<qreal>(null), 0.0);
+ QCOMPARE(createUnboundValue(null).toNumber(), 0.0);
{
QJSValue falskt = eng.toScriptValue(false);
QCOMPARE(falskt.toNumber(), 0.0);
+ QCOMPARE(createUnboundValue(falskt).toNumber(), 0.0);
QCOMPARE(qjsvalue_cast<qreal>(falskt), 0.0);
QJSValue sant = eng.toScriptValue(true);
QCOMPARE(sant.toNumber(), 1.0);
+ QCOMPARE(createUnboundValue(sant).toNumber(), 1.0);
QCOMPARE(qjsvalue_cast<qreal>(sant), 1.0);
QJSValue number = eng.toScriptValue(123.0);
QCOMPARE(number.toNumber(), 123.0);
QCOMPARE(qjsvalue_cast<qreal>(number), 123.0);
+ QCOMPARE(createUnboundValue(number).toNumber(), 123.0);
QJSValue str = eng.toScriptValue(QString("ciao"));
QCOMPARE(qIsNaN(str.toNumber()), true);
QCOMPARE(qIsNaN(qjsvalue_cast<qreal>(str)), true);
+ QCOMPARE(qIsNaN(createUnboundValue(str).toNumber()), true);
QJSValue str2 = eng.toScriptValue(QString("123"));
QCOMPARE(str2.toNumber(), 123.0);
QCOMPARE(qjsvalue_cast<qreal>(str2), 123.0);
+ QCOMPARE(createUnboundValue(str2).toNumber(), 123.0);
}
QJSValue object = eng.newObject();
QCOMPARE(qIsNaN(object.toNumber()), true);
+ QCOMPARE(qIsNaN(createUnboundValue(object).toNumber()), true);
QCOMPARE(qIsNaN(qjsvalue_cast<qreal>(object)), true);
QJSValue inv = QJSValue();
QVERIFY(qIsNaN(inv.toNumber()));
+ QCOMPARE(qIsNaN(createUnboundValue(inv).toNumber()), true);
QVERIFY(qIsNaN(qjsvalue_cast<qreal>(inv)));
// V2 constructors
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index c246647325..196f6b96f9 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -746,13 +746,13 @@ void tst_qqmlecmascript::arrayExpressions()
MyExpression expr(&context, "[a, b, c, 10]");
QVariant result = expr.evaluate();
- QCOMPARE(result.userType(), qMetaTypeId<QVariantList>());
- QVariantList list = qvariant_cast<QVariantList>(result);
- QCOMPARE(list.count(), 4);
- QCOMPARE(list.at(0).value<QObject*>(), &obj1);
- QCOMPARE(list.at(1).value<QObject*>(), &obj2);
- QCOMPARE(list.at(2).value<QObject*>(), &obj3);
- QCOMPARE(list.at(3).value<int>(), 10);
+ QCOMPARE(result.userType(), qMetaTypeId<QJSValue>());
+ QJSValue list = qvariant_cast<QJSValue>(result);
+ QCOMPARE(list.property("length").toInt(), 4);
+ QCOMPARE(list.property(0).toQObject(), &obj1);
+ QCOMPARE(list.property(1).toQObject(), &obj2);
+ QCOMPARE(list.property(2).toQObject(), &obj3);
+ QCOMPARE(list.property(3).toInt(), 10);
}
// Tests that modifying a context property will reevaluate expressions
@@ -4811,7 +4811,7 @@ void tst_qqmlecmascript::propertyVarCpp()
QCOMPARE(object->property("varProperty2"), QVariant(QLatin1String("randomString")));
QCOMPARE(object->property("varProperty2").userType(), (int)QVariant::String);
// now enforce behaviour when accessing JavaScript objects from cpp.
- QCOMPARE(object->property("jsobject").userType(), (int)QVariant::Map);
+ QCOMPARE(object->property("jsobject").userType(), qMetaTypeId<QJSValue>());
delete object;
}
@@ -5166,7 +5166,7 @@ void tst_qqmlecmascript::objectConversion()
QVERIFY(object != 0);
QVariant retn;
QMetaObject::invokeMethod(object, "circularObject", Q_RETURN_ARG(QVariant, retn));
- QCOMPARE(retn.value<QVariantMap>().value("test"), QVariant(100));
+ QCOMPARE(retn.value<QJSValue>().property("test").toInt(), int(100));
delete object;
}
@@ -5434,7 +5434,7 @@ void tst_qqmlecmascript::sequenceConversionWrite()
QVERIFY(seq != 0);
// we haven't registered QList<QPoint> as a sequence type, so writing shouldn't work.
- QString warningOne = qmlFile.toString() + QLatin1String(":16: Error: Cannot assign QVariantList to an unregistered type");
+ QString warningOne = qmlFile.toString() + QLatin1String(":16: Error: Cannot assign QJSValue to an unregistered type");
QTest::ignoreMessage(QtWarningMsg, warningOne.toLatin1().constData());
QMetaObject::invokeMethod(object, "performTest");
diff --git a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
index 320333f889..4ee75f8df5 100644
--- a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
+++ b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
@@ -486,7 +486,7 @@ void tst_qqmllocale::weekDays()
Q_ARG(QVariant, QVariant(locale)));
QVariant val = obj->property("weekDays");
- QVERIFY(val.type() == QVariant::List);
+ QVERIFY(val.userType() == qMetaTypeId<QJSValue>());
QList<QVariant> qmlDays = val.toList();
QList<Qt::DayOfWeek> days = QLocale(locale).weekdays();
@@ -528,7 +528,7 @@ void tst_qqmllocale::uiLanguages()
Q_ARG(QVariant, QVariant(locale)));
QVariant val = obj->property("uiLanguages");
- QVERIFY(val.type() == QVariant::List);
+ QVERIFY(val.userType() == qMetaTypeId<QJSValue>());
QList<QVariant> qmlLangs = val.toList();
QStringList langs = QLocale(locale).uiLanguages();
diff --git a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
index 510a76cc06..b6e7a43c46 100644
--- a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
+++ b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
@@ -249,16 +249,22 @@ void tst_QQmlMetaObject::property()
QSignalSpy changedSpy(object, SIGNAL(testChanged()));
QObject::connect(object, SIGNAL(testChanged()), object, SLOT(deleteLater()));
+ QVariant value = prop.read(object);
+ if (value.userType() == qMetaTypeId<QJSValue>())
+ value = value.value<QJSValue>().toVariant();
if (expectedValue.isValid())
- QCOMPARE(prop.read(object), expectedValue);
+ QCOMPARE(value, expectedValue);
else
- QVERIFY(prop.read(object).isValid());
+ QVERIFY(value.isValid());
QCOMPARE(changedSpy.count(), 0);
if (isWritable) {
QVERIFY(prop.write(object, newValue));
QCOMPARE(changedSpy.count(), 1);
- QCOMPARE(prop.read(object), newValue);
+ QVariant value = prop.read(object);
+ if (value.userType() == qMetaTypeId<QJSValue>())
+ value = value.value<QJSValue>().toVariant();
+ QCOMPARE(value, newValue);
} else {
QVERIFY(!prop.write(object, prop.read(object)));
QCOMPARE(changedSpy.count(), 0);
diff --git a/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp b/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp
index 66ddb392f9..801707f2ec 100644
--- a/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp
+++ b/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp
@@ -115,7 +115,10 @@ void tst_QQuickWorkerScript::messaging()
waitForEchoMessage(worker);
const QMetaObject *mo = worker->metaObject();
- QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker).value<QVariant>(), value);
+ QVariant response = mo->property(mo->indexOfProperty("response")).read(worker).value<QVariant>();
+ if (response.userType() == qMetaTypeId<QJSValue>())
+ response = response.value<QJSValue>().toVariant();
+ QCOMPARE(response, value);
qApp->processEvents();
delete worker;