diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2013-11-05 13:20:24 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-11-05 21:13:00 +0100 |
commit | 4ffa7d3f651757b7bc10ae9801b7802a8f2e260f (patch) | |
tree | 973b50f41d00719c179b9a332feca11dc0c0f32c | |
parent | b63e2e270f79d76d5624e73eb6d05b1bbb55968f (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.0 | 4 | ||||
-rw-r--r-- | src/qml/compiler/qv4ssa.cpp | 14 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qobjectwrapper.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlproperty.cpp | 2 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 8 | ||||
-rw-r--r-- | tests/auto/quick/qquickstates/tst_qquickstates.cpp | 2 |
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() |