diff options
author | Erik Verbruggen <erik.verbruggen@qt.io> | 2018-01-26 11:28:06 +0100 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2018-02-05 09:15:25 +0000 |
commit | 8501993e5275076d9163a7e2f8bab9ba2f187f72 (patch) | |
tree | 3db7ebe28102dd1e952a6a511f5d70488adfbf4d | |
parent | c2bd33af9fb548ff20bf34323271baa89cbc8a55 (diff) |
QML: Collapse all NaNs into one single (encoded) NaN
The idea of NaN boxing is to use one single NaN as a "true" NaN, and all
others as a boxed value. So when encoding some NaN, be sure to use that
one "true" NaN. Otherwise, it will be interpreted as an encoded value.
Task-number: QTBUG-65998
Change-Id: Ia6e4641be180f3d626c40a57b473f181358e04db
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r-- | src/qml/jsruntime/qv4value_p.h | 4 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/data/nans.qml | 5 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 15 |
3 files changed, 24 insertions, 0 deletions
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 9adad881a1..94233d4ddb 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -56,6 +56,8 @@ #include "qv4global_p.h" #include <private/qv4heap_p.h> +#include <private/qnumeric_p.h> + #if QT_POINTER_SIZE == 8 #define QV4_USE_64_BIT_VALUE_ENCODING #endif @@ -362,6 +364,8 @@ public: return d; } QML_NEARLY_ALWAYS_INLINE void setDouble(double d) { + if (qt_is_nan(d)) + d = qt_qnan(); memcpy(&_val, &d, 8); #ifdef QV4_USE_64_BIT_VALUE_ENCODING _val ^= NaNEncodeMask; diff --git a/tests/auto/qml/qqmlecmascript/data/nans.qml b/tests/auto/qml/qqmlecmascript/data/nans.qml new file mode 100644 index 0000000000..ece69f2d79 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/nans.qml @@ -0,0 +1,5 @@ +import QtQuick 2.0 + +QtObject { + property var prop: undefined +} diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index db7ec87c02..14447383c1 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -338,6 +338,7 @@ private slots: void freeze_empty_object(); void singleBlockLoops(); void qtbug_60547(); + void anotherNaN(); private: // static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter); @@ -8266,6 +8267,20 @@ void tst_qqmlecmascript::qtbug_60547() QCOMPARE(object->property("counter"), QVariant(int(1))); } +void tst_qqmlecmascript::anotherNaN() +{ + QQmlComponent component(&engine, testFileUrl("nans.qml")); + QScopedPointer<QObject> object(component.create()); + QVERIFY2(!object.isNull(), qPrintable(component.errorString())); + object->setProperty("prop", std::numeric_limits<double>::quiet_NaN()); // don't crash + + std::uint64_t anotherNaN = 0xFFFFFF01000000F7ul; + double d; + std::memcpy(&d, &anotherNaN, sizeof(d)); + QVERIFY(std::isnan(d)); + object->setProperty("prop", d); // don't crash +} + QTEST_MAIN(tst_qqmlecmascript) #include "tst_qqmlecmascript.moc" |