diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2022-02-16 10:47:04 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2022-02-18 12:13:47 +0100 |
commit | d0f4e0c037cf61eb5bb559755ee7c9ce6cf6b7dc (patch) | |
tree | df0ded3ef90e50a5c384d15b6120b0012cc4bbb2 /src/qml/jsapi/qjsengine.cpp | |
parent | bd968fa6ff07cda5d96dd5c9851bb1c98ee4f318 (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.cpp | 140 |
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. |