aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/jsapi/qjsvalue.cpp33
-rw-r--r--src/qml/jsapi/qjsvalue.h1
-rw-r--r--tests/auto/qml/qjsvalue/tst_qjsvalue.cpp46
-rw-r--r--tests/auto/qml/qjsvalue/tst_qjsvalue.h2
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();