aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@digia.com>2014-09-08 14:06:22 +0200
committerLars Knoll <lars.knoll@digia.com>2014-09-11 09:56:48 +0200
commit91d6a63ab317817990c3b2306860adbd8916cca4 (patch)
tree44962e20ce14c594d1f77c7ac4d54d53bd1b158e
parent8fab54a5495226b8c06d7708357a23e83444abc0 (diff)
Fix roundtrip conversion between JS var and QVariant
Always convert null to a QVariant(VoidStar) as documented in QJSValue. Make sure the reverse conversion will lead back to a null JS value. Adjusted two test cases that expected an invalid QVariant when setting the property to null, and added test cases for the correct conversion. Task-number: QTBUG-40880 Change-Id: I6eb01f0067f2c89779c53fd2cd0a1193047ed2cc Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
-rw-r--r--src/qml/qml/qqmlproperty.cpp7
-rw-r--r--src/qml/qml/v8/qv8engine.cpp8
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scarceResourceFunction.var.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scarceResourceFunction.variant.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/variants.qml55
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp24
6 files changed, 93 insertions, 5 deletions
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 42bf0dd657..09b735ae9e 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -1585,11 +1585,14 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
propertyType = propertyMetaObject.className();
}
} else if (value.userType() != QVariant::Invalid) {
- valueType = QMetaType::typeName(value.userType());
+ if (value.userType() == QMetaType::VoidStar)
+ valueType = "null";
+ else
+ valueType = QMetaType::typeName(value.userType());
}
if (!valueType)
- valueType = "null";
+ valueType = "undefined";
if (!propertyType)
propertyType = QMetaType::typeName(type);
if (!propertyType)
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index 35d31e4f1f..b56af2e7f6 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -240,6 +240,8 @@ QV4::ReturnedValue QV8Engine::fromVariant(const QVariant &variant)
case QMetaType::UnknownType:
case QMetaType::Void:
return QV4::Encode::undefined();
+ case QMetaType::VoidStar:
+ return QV4::Encode::null();
case QMetaType::Bool:
return QV4::Encode(*reinterpret_cast<const bool*>(ptr));
case QMetaType::Int:
@@ -379,8 +381,10 @@ QQmlContextData *QV8Engine::callingContext()
// [Any other object] -> QVariantMap(...)
QVariant QV8Engine::toBasicVariant(const QV4::ValueRef value)
{
- if (value->isNullOrUndefined())
+ if (value->isUndefined())
return QVariant();
+ if (value->isNull())
+ return QVariant(QMetaType::VoidStar, (void *)0);
if (value->isBoolean())
return value->booleanValue();
if (value->isInteger())
@@ -644,6 +648,8 @@ QV4::ReturnedValue QV8Engine::metaTypeToJS(int type, const void *data)
case QMetaType::UnknownType:
case QMetaType::Void:
return QV4::Encode::undefined();
+ case QMetaType::VoidStar:
+ return QV4::Encode::null();
case QMetaType::Bool:
return QV4::Encode(*reinterpret_cast<const bool*>(data));
case QMetaType::Int:
diff --git a/tests/auto/qml/qqmlecmascript/data/scarceResourceFunction.var.qml b/tests/auto/qml/qqmlecmascript/data/scarceResourceFunction.var.qml
index 23e4c8d15e..bb6ddc7876 100644
--- a/tests/auto/qml/qqmlecmascript/data/scarceResourceFunction.var.qml
+++ b/tests/auto/qml/qqmlecmascript/data/scarceResourceFunction.var.qml
@@ -17,7 +17,7 @@ QtObject {
}
function releaseScarceResource() {
- root.scarceResourceCopy = null;
+ root.scarceResourceCopy = undefined;
}
}
diff --git a/tests/auto/qml/qqmlecmascript/data/scarceResourceFunction.variant.qml b/tests/auto/qml/qqmlecmascript/data/scarceResourceFunction.variant.qml
index fe3707b5d3..e147188230 100644
--- a/tests/auto/qml/qqmlecmascript/data/scarceResourceFunction.variant.qml
+++ b/tests/auto/qml/qqmlecmascript/data/scarceResourceFunction.variant.qml
@@ -17,7 +17,7 @@ QtObject {
}
function releaseScarceResource() {
- root.scarceResourceCopy = null;
+ root.scarceResourceCopy = undefined;
}
}
diff --git a/tests/auto/qml/qqmlecmascript/data/variants.qml b/tests/auto/qml/qqmlecmascript/data/variants.qml
new file mode 100644
index 0000000000..d38c5a1b49
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/variants.qml
@@ -0,0 +1,55 @@
+import QtQuick 2.2
+
+ListView
+{
+ property variant undefinedVariant: undefined
+ property variant nullVariant: null
+ property variant intVariant: 1
+ property variant doubleVariant: 1.2
+
+ property var testVar
+ property variant testVariant
+
+ function checkNull() {
+ var result = [{'test': null}];
+ model = result;
+ if (model[0].test !== null)
+ return false;
+ testVar = null;
+ testVariant = testVar;
+ if (testVariant !== null)
+ return false;
+ testVar = testVariant;
+ if (testVar !== null)
+ return false;
+ return true;
+ }
+ function checkUndefined() {
+ var result = [{'test': undefined}];
+ model = result;
+ if (model[0].test !== undefined)
+ return false;
+ testVar = undefined;
+ testVariant = testVar;
+ if (testVariant !== undefined)
+ return false;
+ testVar = testVariant;
+ if (testVar !== undefined)
+ return false;
+ return true;
+ }
+ function checkNumber() {
+ var result = [{'test': 1}];
+ model = result;
+ if (model[0].test !== 1)
+ return false;
+ testVar = 1;
+ testVariant = testVar;
+ if (testVariant !== 1)
+ return false;
+ testVar = testVariant;
+ if (testVar !== 1)
+ return false;
+ return true;
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 06d061a9fa..01125f86f6 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -213,6 +213,7 @@ private slots:
void deletedEngine();
void libraryScriptAssert();
void variantsAssignedUndefined();
+ void variants();
void qtbug_9792();
void qtcreatorbug_1289();
void noSpuriousWarningsAtShutdown();
@@ -5737,6 +5738,29 @@ void tst_qqmlecmascript::variantsAssignedUndefined()
delete object;
}
+void tst_qqmlecmascript::variants()
+{
+ QQmlComponent component(&engine, testFileUrl("variants.qml"));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QVERIFY(object->property("undefinedVariant").type() == QVariant::Invalid);
+ QVERIFY(object->property("nullVariant").type() == (int)QMetaType::VoidStar);
+ QVERIFY(object->property("intVariant").type() == QVariant::Int);
+ QVERIFY(object->property("doubleVariant").type() == QVariant::Double);
+
+ QVariant result;
+ QMetaObject::invokeMethod(object, "checkNull", Q_RETURN_ARG(QVariant, result));
+ QCOMPARE(result.toBool(), true);
+
+ QMetaObject::invokeMethod(object, "checkUndefined", Q_RETURN_ARG(QVariant, result));
+ QCOMPARE(result.toBool(), true);
+
+ QMetaObject::invokeMethod(object, "checkNumber", Q_RETURN_ARG(QVariant, result));
+ QCOMPARE(result.toBool(), true);
+}
+
void tst_qqmlecmascript::qtbug_9792()
{
QQmlComponent component(&engine, testFileUrl("qtbug_9792.qml"));