diff options
-rw-r--r-- | src/qml/jsapi/qjsvalue.cpp | 33 | ||||
-rw-r--r-- | src/qml/jsapi/qjsvalue.h | 1 | ||||
-rw-r--r-- | tests/auto/qml/qjsvalue/tst_qjsvalue.cpp | 46 | ||||
-rw-r--r-- | tests/auto/qml/qjsvalue/tst_qjsvalue.h | 2 |
4 files changed, 82 insertions, 0 deletions
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp index 5525aee595..6d70c72722 100644 --- a/src/qml/jsapi/qjsvalue.cpp +++ b/src/qml/jsapi/qjsvalue.cpp @@ -633,6 +633,39 @@ QVariant QJSValue::toVariant(QJSValue::ObjectConversionBehavior behavior) const } /*! + * Converts the value to a QJSPrimitiveValue. If the value holds a type + * supported by QJSPrimitiveValue, the value is copied. Otherwise the + * value is converted to a string, and the string is stored in + * QJSPrimitiveValue. + * + * \note Conversion of a managed value to a string can throw an exception. In + * particular, symbols cannot be coerced into strings, or a custom + * toString() method may throw. In this case the result is the undefined + * value and the engine carries an error after the conversion. + */ +QJSPrimitiveValue QJSValue::toPrimitive() const +{ + if (const QString *string = QJSValuePrivate::asQString(this)) + return *string; + + const QV4::Value val = QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(this)); + if (val.isUndefined()) + return QJSPrimitiveUndefined(); + if (val.isNull()) + return QJSPrimitiveNull(); + if (val.isBoolean()) + return val.toBoolean(); + if (val.isInteger()) + return val.integerValue(); + if (val.isDouble()) + return val.doubleValue(); + + bool ok; + const QString result = val.toQString(&ok); + return ok ? QJSPrimitiveValue(result) : QJSPrimitiveValue(QJSPrimitiveUndefined()); +} + +/*! Calls this QJSValue as a function, passing \a args as arguments to the function, and using the globalObject() as the "this"-object. Returns the value returned from the function. diff --git a/src/qml/jsapi/qjsvalue.h b/src/qml/jsapi/qjsvalue.h index 3f8a16a149..1844ed0989 100644 --- a/src/qml/jsapi/qjsvalue.h +++ b/src/qml/jsapi/qjsvalue.h @@ -136,6 +136,7 @@ public: QVariant toVariant() const; QVariant toVariant(ObjectConversionBehavior behavior) const; + QJSPrimitiveValue toPrimitive() const; QObject *toQObject() const; const QMetaObject *toQMetaObject() const; diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp index e2f83a78ba..fd2eb40717 100644 --- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp +++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp @@ -1149,6 +1149,52 @@ void tst_QJSValue::toVariant() } } +void tst_QJSValue::toPrimitive_data() +{ + newEngine(); + QTest::addColumn<QJSValue>("value"); + QTest::addColumn<QJSPrimitiveValue>("result"); + QTest::addColumn<bool>("causesError"); + + QTest::newRow("undefined") << QJSValue(QJSValue::UndefinedValue) + << QJSPrimitiveValue(QJSPrimitiveUndefined()) << false; + QTest::newRow("null") << QJSValue(QJSValue::NullValue) + << QJSPrimitiveValue(QJSPrimitiveNull()) << false; + QTest::newRow("bool(true)") << QJSValue(true) << QJSPrimitiveValue(true) << false; + QTest::newRow("bool(false)") << QJSValue(false) << QJSPrimitiveValue(false) << false; + QTest::newRow("int") << QJSValue(123) << QJSPrimitiveValue(123) << false; + QTest::newRow("double") << QJSValue(10.2) << QJSPrimitiveValue(10.2) << false; + QTest::newRow("string") << QJSValue(QStringLiteral("boo")) + << QJSPrimitiveValue(QStringLiteral("boo")) << false; + QTest::newRow("string(managed)") << engine->toScriptValue(QStringLiteral("mmmm")) + << QJSPrimitiveValue(QStringLiteral("mmmm")) << false; + QTest::newRow("symbol") << engine->evaluate(QStringLiteral("Symbol('bar')")) + << QJSPrimitiveValue(QJSPrimitiveUndefined()) << true; + QTest::newRow("throws") << engine->evaluate(QStringLiteral( + "var a = {};\n" + "a.__proto__.toString = function() {\n" + " throw new Error('naeh!');\n" + "};\n" + "a;")) + << QJSPrimitiveValue(QJSPrimitiveUndefined()) << true; +} + +void tst_QJSValue::toPrimitive() +{ + QFETCH(QJSValue, value); + QFETCH(QJSPrimitiveValue, result); + QFETCH(bool, causesError); + + QCOMPARE(value.toPrimitive(), result); + if (causesError) { + QVERIFY(engine->hasError()); + engine->catchError(); + } else { + QJSValue reconstructed(std::move(result)); + QVERIFY(reconstructed.strictlyEquals(value)); + } +} + void tst_QJSValue::toQObject_nonQObject_data() { newEngine(); diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.h b/tests/auto/qml/qjsvalue/tst_qjsvalue.h index a291e156e0..0b35b58c58 100644 --- a/tests/auto/qml/qjsvalue/tst_qjsvalue.h +++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.h @@ -69,6 +69,8 @@ private slots: void toInt(); void toUInt(); void toVariant(); + void toPrimitive_data(); + void toPrimitive(); void toQObject_nonQObject_data(); void toQObject_nonQObject(); void toQObject(); |