diff options
author | Ulf Hermann <ulf.hermann@theqtcompany.com> | 2016-01-04 13:05:51 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@theqtcompany.com> | 2016-01-05 11:36:57 +0000 |
commit | 881bb537c92684d25fae4fec9ac2dd61e1f9723c (patch) | |
tree | de753cacab905eae28a510f6a5a10c7082512cf2 | |
parent | d19acb0cbb81bc270291241fd2fde4bb0869ac89 (diff) |
Make RuntimeHelpers::numberToString() comply with EcmaScript
We could use DoubleToStringConverter::EcmaScriptConverter().ToShortest()
here, but we'd have to #ifdef it for the case that we're using the libc
double conversion. As the formatting does not produce a lot of code I
decided against that.
Task-number: QTBUG-50131
Change-Id: If7a2ef8063b57ab35cda4a60d8ddd65442d70103
Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 32 | ||||
-rw-r--r-- | tests/auto/qml/qqmlproperty/data/floatToStringPrecision.qml | 24 | ||||
-rw-r--r-- | tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp | 40 |
3 files changed, 83 insertions, 13 deletions
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 2d0eac079f..a1bcec4987 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -225,8 +225,36 @@ void RuntimeHelpers::numberToString(QString *result, double num, int radix) } if (radix == 10) { - const NumberLocale *locale = NumberLocale::instance(); - *result = locale->toString(num, 'g', locale->defaultDoublePrecision); + // We cannot use our usual locale->toString(...) here, because EcmaScript has special rules + // about the longest permissible number, depending on if it's <0 or >0. + const int ecma_shortest_low = -6; + const int ecma_shortest_high = 21; + + const QLatin1Char zero('0'); + const QLatin1Char dot('.'); + + int decpt = 0; + int sign = 0; + *result = qdtoa(num, &decpt, &sign); + + if (decpt <= ecma_shortest_low || decpt > ecma_shortest_high) { + if (result->length() > 1) + result->insert(1, dot); + result->append(QLatin1Char('e')); + if (decpt > 0) + result->append(QLatin1Char('+')); + result->append(QString::number(decpt - 1)); + } else if (decpt <= 0) { + result->prepend(QString::fromLatin1("0.%1").arg(QString().fill(zero, -decpt))); + } else if (decpt < result->length()) { + result->insert(decpt, dot); + } else { + result->append(QString().fill(zero, decpt - result->length())); + } + + if (sign) + result->prepend(QLatin1Char('-')); + return; } diff --git a/tests/auto/qml/qqmlproperty/data/floatToStringPrecision.qml b/tests/auto/qml/qqmlproperty/data/floatToStringPrecision.qml index a0429e0cc8..a1ff0c527a 100644 --- a/tests/auto/qml/qqmlproperty/data/floatToStringPrecision.qml +++ b/tests/auto/qml/qqmlproperty/data/floatToStringPrecision.qml @@ -2,9 +2,27 @@ import QtQuick 2.0 QtObject { property double a: 3.4 - property string b: a + property string a1: a + property string a2: a + "" - property double c: 0.035003945 - property string d: c + property double b: 0.035003945 + property string b1: b + property string b2: b + "" + + property double c: 0.0000012345 + property string c1: c + property string c2: c + "" + + property double d: 0.00000012345 + property string d1: d + property string d2: d + "" + + property double e: 100000000000000000000 + property string e1: e + property string e2: e + "" + + property double f: 1000000000000000000000 + property string f1: f + property string f2: f + "" } diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp index 3133d6c00a..fbbc10b0a1 100644 --- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp +++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp @@ -147,6 +147,8 @@ private slots: void registeredCompositeTypeProperty(); void deeplyNestedObject(); void readOnlyDynamicProperties(); + + void floatToStringPrecision_data(); void floatToStringPrecision(); void copy(); @@ -2055,21 +2057,43 @@ void tst_qqmlproperty::readOnlyDynamicProperties() delete obj; } +void tst_qqmlproperty::floatToStringPrecision_data() +{ + QTest::addColumn<QString>("propertyName"); + QTest::addColumn<double>("number"); + QTest::addColumn<QString>("qtString"); + QTest::addColumn<QString>("jsString"); + + QTest::newRow("3.4") << "a" << 3.4 << "3.4" << "3.4"; + QTest::newRow("0.035003945") << "b" << 0.035003945 << "0.035003945" << "0.035003945"; + QTest::newRow("0.0000012345") << "c" << 0.0000012345 << "1.2345e-6" << "0.0000012345"; + QTest::newRow("0.00000012345") << "d" << 0.00000012345 << "1.2345e-7" << "1.2345e-7"; + QTest::newRow("1e20") << "e" << 1e20 << "1e+20" << "100000000000000000000"; + QTest::newRow("1e21") << "f" << 1e21 << "1e+21" << "1e+21"; +} + void tst_qqmlproperty::floatToStringPrecision() { QQmlComponent comp(&engine, testFileUrl("floatToStringPrecision.qml")); QObject *obj = comp.create(); QVERIFY(obj != 0); - QCOMPARE(obj->property("a").toDouble(), 3.4); - QCOMPARE(obj->property("a").toString(), QLatin1String("3.4")); - QCOMPARE(obj->property("b").toDouble(), 3.4); - QCOMPARE(obj->property("b").toString(), QLatin1String("3.4")); + QFETCH(QString, propertyName); + QFETCH(double, number); + QFETCH(QString, qtString); + QFETCH(QString, jsString); + + const char *name = propertyName.toLatin1().constData(); + QCOMPARE(obj->property(name).toDouble(), number); + QCOMPARE(obj->property(name).toString(), qtString); + + const char *name1 = (propertyName + QLatin1Char('1')).toLatin1().constData(); + QCOMPARE(obj->property(name1).toDouble(), number); + QCOMPARE(obj->property(name1).toString(), qtString); - QCOMPARE(obj->property("c").toDouble(), 0.035003945); - QCOMPARE(obj->property("c").toString(), QLatin1String("0.035003945")); - QCOMPARE(obj->property("d").toDouble(), 0.035003945); - QCOMPARE(obj->property("d").toString(), QLatin1String("0.035003945")); + const char *name2 = (propertyName + QLatin1Char('2')).toLatin1().constData(); + QCOMPARE(obj->property(name2).toDouble(), number); + QCOMPARE(obj->property(name2).toString(), jsString); delete obj; } |