aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-11-05 13:20:24 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-11-05 21:13:00 +0100
commit4ffa7d3f651757b7bc10ae9801b7802a8f2e260f (patch)
tree973b50f41d00719c179b9a332feca11dc0c0f32c
parentb63e2e270f79d76d5624e73eb6d05b1bbb55968f (diff)
Fix rounding behavior of Qml when assigning doubles to integer properties
The engine used to round, but that is inconsistent with ECMAScript's way of converting doubles to integers by truncation. With this patch we can also enable the propagation of integer type information into the IR, but we have to be careful not to utilize it when writing properties. Change-Id: I04af4879ba5131349eca2eeff2b27f4598f5267b Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r--dist/changes-5.2.04
-rw-r--r--src/qml/compiler/qv4ssa.cpp14
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp2
-rw-r--r--src/qml/qml/qqmlproperty.cpp2
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp8
-rw-r--r--tests/auto/quick/qquickstates/tst_qquickstates.cpp2
6 files changed, 17 insertions, 15 deletions
diff --git a/dist/changes-5.2.0 b/dist/changes-5.2.0
index 969d4e30e6..9db8458319 100644
--- a/dist/changes-5.2.0
+++ b/dist/changes-5.2.0
@@ -42,6 +42,10 @@ Third party components
flag QSGNode::DirtySubtreeBlocked whenever the state of
QSGNode::isSubtreeBlocked() is changed.
+ - When assigning double precision floating point values to integer properties,
+ the engine now truncates instead of rounding. This is consistent with the
+ ECMAScript specification's way of converting doubles to ints.
+
****************************************************************************
* Library *
****************************************************************************
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index 6b8c8af8e4..8f17fb1aff 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -1572,10 +1572,7 @@ protected:
{
switch (propType) {
case QMetaType::Bool: return BoolType;
-
- // Can't propagate integers right now, because QML rounds doubles to integers on assignment, as opposed to EcmaScript
-// case QMetaType::Int: return SInt32Type;
-
+ case QMetaType::Int: return SInt32Type;
case QMetaType::Double: return DoubleType;
case QMetaType::QString: return StringType;
default: break;
@@ -1813,11 +1810,12 @@ protected:
}
}
- // Resettable properties need to be able to receive the un-converted
- // value, because assigning "undefined" to them calls the reset function
- // of the property.
+ // Don't convert when writing to QObject properties. All sorts of extra behavior
+ // is defined when writing to them, for example resettable properties are reset
+ // when writing undefined to them, and an exception is thrown when they're missing
+ // a reset function.
const Member *targetMember = s->target->asMember();
- const bool inhibitConversion = targetMember && targetMember->type == Member::MemberOfQObject && targetMember->property->isResettable();
+ const bool inhibitConversion = targetMember && targetMember->type == Member::MemberOfQObject && targetMember->property;
run(s->source, s->target->type, !inhibitConversion);
}
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 07a4ff7cd7..d5aa9f4ead 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -524,7 +524,7 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
} else if (value->asFunctionObject()) {
// this is handled by the binding creation above
} else if (property->propType == QMetaType::Int && value->isNumber()) {
- PROPERTY_STORE(int, qRound(value->asDouble()));
+ PROPERTY_STORE(int, value->asDouble());
} else if (property->propType == QMetaType::QReal && value->isNumber()) {
PROPERTY_STORE(qreal, qreal(value->asDouble()));
} else if (property->propType == QMetaType::Float && value->isNumber()) {
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 7723404831..3975b88bb0 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -1485,7 +1485,7 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
if (result->isInteger())
QUICK_STORE(int, result->integerValue())
else if (result->isNumber())
- QUICK_STORE(int, qRound(result->doubleValue()))
+ QUICK_STORE(int, result->doubleValue())
break;
case QMetaType::Double:
if (result->isNumber())
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 5b06c3cce9..b1cf8c905f 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -3489,9 +3489,9 @@ void tst_qqmlecmascript::compiled()
QCOMPARE(object->property("test15").toBool(), false);
QCOMPARE(object->property("test16").toBool(), true);
- QCOMPARE(object->property("test17").toInt(), 5);
+ QCOMPARE(object->property("test17").toInt(), 4);
QCOMPARE(object->property("test18").toReal(), qreal(176));
- QCOMPARE(object->property("test19").toInt(), 7);
+ QCOMPARE(object->property("test19").toInt(), 6);
QCOMPARE(object->property("test20").toReal(), qreal(6.7));
QCOMPARE(object->property("test21").toString(), QLatin1String("6.7"));
QCOMPARE(object->property("test22").toString(), QLatin1String("!"));
@@ -3516,7 +3516,7 @@ void tst_qqmlecmascript::numberAssignment()
QCOMPARE(object->property("test3"), QVariant((qreal)6));
QCOMPARE(object->property("test4"), QVariant((qreal)6));
- QCOMPARE(object->property("test5"), QVariant((int)7));
+ QCOMPARE(object->property("test5"), QVariant((int)6));
QCOMPARE(object->property("test6"), QVariant((int)7));
QCOMPARE(object->property("test7"), QVariant((int)6));
QCOMPARE(object->property("test8"), QVariant((int)6));
@@ -6445,7 +6445,7 @@ void tst_qqmlecmascript::realToInt()
QMetaObject::invokeMethod(object, "test1");
QCOMPARE(object->value(), int(4));
QMetaObject::invokeMethod(object, "test2");
- QCOMPARE(object->value(), int(8));
+ QCOMPARE(object->value(), int(7));
}
void tst_qqmlecmascript::urlProperty()
diff --git a/tests/auto/quick/qquickstates/tst_qquickstates.cpp b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
index e165b559f7..0c9b75636f 100644
--- a/tests/auto/quick/qquickstates/tst_qquickstates.cpp
+++ b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
@@ -1567,7 +1567,7 @@ void tst_qquickstates::QTBUG_14830()
QVERIFY(rect != 0);
QQuickItem *item = rect->findChild<QQuickItem*>("area");
- QCOMPARE(item->width(), qreal(171));
+ QCOMPARE(item->width(), qreal(170));
}
void tst_qquickstates::avoidFastForward()