QmlCompiler: Allow primitive conversion if output is stored in var

We can always convertStored() if the contained type has been fixed.

Pick-to: 6.7
Fixes: QTBUG-120322
Change-Id: I7d834fa32a12503341c863c095d578ca6e838531
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Ulf Hermann 2023-12-21 15:06:28 +01:00
parent 953f0d4487
commit be481412cc
4 changed files with 56 additions and 14 deletions

View File

@ -3723,22 +3723,31 @@ QString QQmlJSCodeGenerator::conversion(
{
const QQmlJSScope::ConstPtr contained = m_typeResolver->containedType(to);
// If both types are stored in QJSPrimitiveValue we coerce using QJSPrimitiveValue
// If from is QJSPrimitiveValue and to contains a primitive we coerce using QJSPrimitiveValue
if (m_typeResolver->registerIsStoredIn(from, m_typeResolver->jsPrimitiveType())
&& m_typeResolver->registerIsStoredIn(to, m_typeResolver->jsPrimitiveType())) {
if (m_typeResolver->equals(contained, m_typeResolver->jsPrimitiveType()))
return variable;
&& m_typeResolver->isPrimitive(to)) {
const QString conversion = variable + u".to<QJSPrimitiveValue::%1>()"_s;
if (m_typeResolver->equals(contained, m_typeResolver->boolType()))
return conversion.arg(u"Boolean"_s);
if (m_typeResolver->isIntegral(to))
return conversion.arg(u"Integer"_s);
if (m_typeResolver->equals(contained, m_typeResolver->realType()))
return conversion.arg(u"Double"_s);
if (m_typeResolver->equals(contained, m_typeResolver->stringType()))
return conversion.arg(u"String"_s);
reject(u"Conversion of QJSPrimitiveValue to "_s + contained->internalName());
QString primitive = [&]() {
if (m_typeResolver->equals(contained, m_typeResolver->jsPrimitiveType()))
return variable;
const QString conversion = variable + u".to<QJSPrimitiveValue::%1>()"_s;
if (m_typeResolver->equals(contained, m_typeResolver->boolType()))
return conversion.arg(u"Boolean"_s);
if (m_typeResolver->isIntegral(to))
return conversion.arg(u"Integer"_s);
if (m_typeResolver->isNumeric(to))
return conversion.arg(u"Double"_s);
if (m_typeResolver->equals(contained, m_typeResolver->stringType()))
return conversion.arg(u"String"_s);
reject(u"Conversion of QJSPrimitiveValue to "_s + contained->internalName());
return QString();
}();
if (primitive.isEmpty())
return primitive;
return convertStored(m_typeResolver->jsPrimitiveType(), to.storedType(), primitive);
}
if (m_typeResolver->registerIsStoredIn(to, contained)

View File

@ -103,6 +103,7 @@ set(qml_files
conversionInDeadCode.qml
conversions.qml
conversions2.qml
convertPrimitiveToVar.qml
convertQJSPrimitiveValueToIntegral.qml
convertToOriginalReadAcumulatorForUnaryOperators.qml
curlygrouped.qml

View File

@ -0,0 +1,18 @@
pragma Strict
import QtQml
QtObject {
id: foo
property int offsetValue
function send(data : variant) {
}
Component.onCompleted: () => {
let deltaOffset = 42
deltaOffset -= 1
foo.offsetValue = deltaOffset
foo.send({offset: deltaOffset})
}
}

View File

@ -71,6 +71,7 @@ private slots:
void conversionDecrement();
void conversionInDeadCode();
void conversions();
void convertPrimitiveToVar();
void convertQJSPrimitiveValueToIntegral();
void convertToOriginalReadAcumulatorForUnaryOperators();
void cppValueTypeList();
@ -1307,6 +1308,19 @@ void tst_QmlCppCodegen::conversions()
QVERIFY(!undef.isValid());
}
void tst_QmlCppCodegen::convertPrimitiveToVar()
{
QQmlEngine engine;
QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/convertPrimitiveToVar.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
QVERIFY(!o.isNull());
QCOMPARE(o->property("offsetValue").toInt(), 41);
}
void tst_QmlCppCodegen::convertQJSPrimitiveValueToIntegral()
{
QQmlEngine engine;