aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsapi/qjsengine.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-02-16 10:47:04 +0100
committerUlf Hermann <ulf.hermann@qt.io>2022-02-18 12:13:47 +0100
commitd0f4e0c037cf61eb5bb559755ee7c9ce6cf6b7dc (patch)
treedf0ded3ef90e50a5c384d15b6120b0012cc4bbb2 /src/qml/jsapi/qjsengine.cpp
parentbd968fa6ff07cda5d96dd5c9851bb1c98ee4f318 (diff)
QmlCompiler: Perform QVariant conversion in JavaScript semantics
In JavaScript we have a number of extra conversions not covered by qvariant_cast. Therefore, add a method to perform a QVariant conversion in JavaScript semantics to QJSEngine, and use that in the compiler. Pick-to: 6.3 Fixes: QTBUG-100883 Change-Id: I8b0bfa0974bc6b339d2601fb373859bc710788c8 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Jarkko Koivikko <jarkko.koivikko@code-q.fi>
Diffstat (limited to 'src/qml/jsapi/qjsengine.cpp')
-rw-r--r--src/qml/jsapi/qjsengine.cpp140
1 files changed, 83 insertions, 57 deletions
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index 7b436645e9..f66488e04c 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -861,73 +861,87 @@ bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
return convertV2(value, QMetaType(type), ptr);
}
+static bool convertString(const QString &string, QMetaType metaType, void *ptr)
+{
+ // have a string based value without engine. Do conversion manually
+ if (metaType == QMetaType::fromType<bool>()) {
+ *reinterpret_cast<bool*>(ptr) = string.length() != 0;
+ return true;
+ }
+ if (metaType == QMetaType::fromType<QString>()) {
+ *reinterpret_cast<QString*>(ptr) = string;
+ return true;
+ }
+ if (metaType == QMetaType::fromType<QUrl>()) {
+ *reinterpret_cast<QUrl *>(ptr) = QUrl(string);
+ return true;
+ }
+
+ double d = QV4::RuntimeHelpers::stringToNumber(string);
+ switch (metaType.id()) {
+ case QMetaType::Int:
+ *reinterpret_cast<int*>(ptr) = QV4::Value::toInt32(d);
+ return true;
+ case QMetaType::UInt:
+ *reinterpret_cast<uint*>(ptr) = QV4::Value::toUInt32(d);
+ return true;
+ case QMetaType::LongLong:
+ *reinterpret_cast<qlonglong*>(ptr) = QV4::Value::toInteger(d);
+ return true;
+ case QMetaType::ULongLong:
+ *reinterpret_cast<qulonglong*>(ptr) = QV4::Value::toInteger(d);
+ return true;
+ case QMetaType::Double:
+ *reinterpret_cast<double*>(ptr) = d;
+ return true;
+ case QMetaType::Float:
+ *reinterpret_cast<float*>(ptr) = d;
+ return true;
+ case QMetaType::Short:
+ *reinterpret_cast<short*>(ptr) = QV4::Value::toInt32(d);
+ return true;
+ case QMetaType::UShort:
+ *reinterpret_cast<unsigned short*>(ptr) = QV4::Value::toUInt32(d);
+ return true;
+ case QMetaType::Char:
+ *reinterpret_cast<char*>(ptr) = QV4::Value::toInt32(d);
+ return true;
+ case QMetaType::UChar:
+ *reinterpret_cast<unsigned char*>(ptr) = QV4::Value::toUInt32(d);
+ return true;
+ case QMetaType::QChar:
+ *reinterpret_cast<QChar*>(ptr) = QChar(QV4::Value::toUInt32(d));
+ return true;
+ case QMetaType::Char16:
+ *reinterpret_cast<char16_t *>(ptr) = QV4::Value::toUInt32(d);
+ return true;
+ default:
+ return false;
+ }
+}
+
/*!
\internal
convert \a value to \a type, store the result in \a ptr
*/
bool QJSEngine::convertV2(const QJSValue &value, QMetaType metaType, void *ptr)
{
- if (const QString *string = QJSValuePrivate::asQString(&value)) {
- // have a string based value without engine. Do conversion manually
- if (metaType == QMetaType::fromType<bool>()) {
- *reinterpret_cast<bool*>(ptr) = string->length() != 0;
- return true;
- }
- if (metaType == QMetaType::fromType<QString>()) {
- *reinterpret_cast<QString*>(ptr) = *string;
- return true;
- }
- if (metaType == QMetaType::fromType<QUrl>()) {
- *reinterpret_cast<QUrl *>(ptr) = QUrl(*string);
- return true;
- }
-
- double d = QV4::RuntimeHelpers::stringToNumber(*string);
- switch (metaType.id()) {
- case QMetaType::Int:
- *reinterpret_cast<int*>(ptr) = QV4::Value::toInt32(d);
- return true;
- case QMetaType::UInt:
- *reinterpret_cast<uint*>(ptr) = QV4::Value::toUInt32(d);
- return true;
- case QMetaType::LongLong:
- *reinterpret_cast<qlonglong*>(ptr) = QV4::Value::toInteger(d);
- return true;
- case QMetaType::ULongLong:
- *reinterpret_cast<qulonglong*>(ptr) = QV4::Value::toInteger(d);
- return true;
- case QMetaType::Double:
- *reinterpret_cast<double*>(ptr) = d;
- return true;
- case QMetaType::Float:
- *reinterpret_cast<float*>(ptr) = d;
- return true;
- case QMetaType::Short:
- *reinterpret_cast<short*>(ptr) = QV4::Value::toInt32(d);
- return true;
- case QMetaType::UShort:
- *reinterpret_cast<unsigned short*>(ptr) = QV4::Value::toUInt32(d);
- return true;
- case QMetaType::Char:
- *reinterpret_cast<char*>(ptr) = QV4::Value::toInt32(d);
- return true;
- case QMetaType::UChar:
- *reinterpret_cast<unsigned char*>(ptr) = QV4::Value::toUInt32(d);
- return true;
- case QMetaType::QChar:
- *reinterpret_cast<QChar*>(ptr) = QChar(QV4::Value::toUInt32(d));
- return true;
- case QMetaType::Char16:
- *reinterpret_cast<char16_t *>(ptr) = QV4::Value::toUInt32(d);
- return true;
- default:
- return false;
- }
- }
+ if (const QString *string = QJSValuePrivate::asQString(&value))
+ return convertString(*string, metaType, ptr);
return QV4::ExecutionEngine::metaTypeFromJS(QJSValuePrivate::asReturnedValue(&value), metaType, ptr);
}
+bool QJSEngine::convertVariant(const QVariant &value, QMetaType metaType, void *ptr)
+{
+ if (value.metaType() == QMetaType::fromType<QString>())
+ return convertString(value.toString(), metaType, ptr);
+
+ // TODO: We could probably avoid creating a QV4::Value in many cases, but we'd have to
+ // duplicate much of metaTypeFromJS and some methods of QV4::Value itself here.
+ return QV4::ExecutionEngine::metaTypeFromJS(handle()->fromVariant(value), metaType, ptr);
+}
+
/*! \fn template <typename T> QJSValue QJSEngine::toScriptValue(const T &value)
Creates a QJSValue with the given \a value.
@@ -944,6 +958,18 @@ bool QJSEngine::convertV2(const QJSValue &value, QMetaType metaType, void *ptr)
\sa toScriptValue()
*/
+/*! \fn template <typename T> T QJSEngine::fromVariant(const QVariant &value)
+
+ Returns the given \a value converted to the template type \c{T}.
+ This works with any type \c{T} that has a \c{QMetaType}. The
+ conversion is done in JavaScript semantics. Those differ from
+ qvariant_cast's semantics. There are a number of implicit
+ conversions between JavaScript-equivalent types that are not
+ performed by qvariant_cast by default.
+
+ \sa fromScriptValue() qvariant_cast()
+*/
+
/*!
Throws a run-time error (exception) with the given \a message.