QmlCompiler: Fix comparison of null and undefined
Those are not stored. If we compare null to null or undefined to undefined, we do not have to generate a comparison at all. the result is statically known. Pick-to: 6.4 Fixes: QTBUG-108634 Change-Id: I6a5323c2e0c023838609aec90d7ecc15b885dc08 Reviewed-by: Sami Shalayel <sami.shalayel@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
dca259f040
commit
bce216d5c0
|
@ -35,6 +35,15 @@ using namespace Qt::StringLiterals;
|
|||
m_body += u"// "_s + QStringLiteral(#function) + u'\n'; \
|
||||
}
|
||||
|
||||
|
||||
static bool isTypeStorable(const QQmlJSTypeResolver *resolver, const QQmlJSScope::ConstPtr &type)
|
||||
{
|
||||
return !type.isNull()
|
||||
&& !resolver->equals(type, resolver->nullType())
|
||||
&& !resolver->equals(type, resolver->emptyListType())
|
||||
&& !resolver->equals(type, resolver->voidType());
|
||||
}
|
||||
|
||||
QString QQmlJSCodeGenerator::castTargetName(const QQmlJSScope::ConstPtr &type) const
|
||||
{
|
||||
return type->augmentedInternalName();
|
||||
|
@ -75,14 +84,6 @@ QString QQmlJSCodeGenerator::metaObject(const QQmlJSScope::ConstPtr &objectType)
|
|||
return QString();
|
||||
}
|
||||
|
||||
static bool isTypeStorable(const QQmlJSTypeResolver *resolver, const QQmlJSScope::ConstPtr &type)
|
||||
{
|
||||
return !type.isNull()
|
||||
&& !resolver->equals(type, resolver->nullType())
|
||||
&& !resolver->equals(type, resolver->emptyListType())
|
||||
&& !resolver->equals(type, resolver->voidType());
|
||||
}
|
||||
|
||||
QQmlJSAotFunction QQmlJSCodeGenerator::run(
|
||||
const Function *function, const InstructionAnnotations *annotations,
|
||||
QQmlJS::DiagnosticMessage *error)
|
||||
|
@ -2459,9 +2460,18 @@ void QQmlJSCodeGenerator::generateEqualityOperation(int lhs, const QString &func
|
|||
|
||||
const auto primitive = m_typeResolver->jsPrimitiveType();
|
||||
if (m_typeResolver->equals(lhsType, rhsType) && !m_typeResolver->equals(lhsType, primitive)) {
|
||||
m_body += conversion(m_typeResolver->boolType(), m_state.accumulatorOut().storedType(),
|
||||
registerVariable(lhs) + (invert ? u" != "_s : u" == "_s)
|
||||
+ m_state.accumulatorVariableIn);
|
||||
if (isTypeStorable(m_typeResolver, lhsType)) {
|
||||
m_body += conversion(m_typeResolver->boolType(), m_state.accumulatorOut().storedType(),
|
||||
registerVariable(lhs) + (invert ? u" != "_s : u" == "_s)
|
||||
+ m_state.accumulatorVariableIn);
|
||||
} else if (m_typeResolver->equals(lhsType, m_typeResolver->emptyListType())) {
|
||||
// We cannot compare two empty lists, because we don't know whether it's
|
||||
// the same instance or not. "[] === []" is false, but "var a = []; a === a" is true;
|
||||
reject(u"comparison of two empty lists"_s);
|
||||
} else {
|
||||
// null === null and undefined === undefined
|
||||
m_body += invert ? u"false"_s : u"true"_s;
|
||||
}
|
||||
} else {
|
||||
m_body += conversion(
|
||||
m_typeResolver->boolType(), m_state.accumulatorOut().storedType(),
|
||||
|
|
|
@ -125,6 +125,7 @@ set(qml_files
|
|||
notEqualsInt.qml
|
||||
notNotString.qml
|
||||
nullAccess.qml
|
||||
nullComparison.qml
|
||||
objectInVar.qml
|
||||
outOfBounds.qml
|
||||
overriddenMember.qml
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
pragma Strict
|
||||
import QtQml
|
||||
|
||||
QtObject {
|
||||
property int v: 1
|
||||
property int w: 1
|
||||
property int x: 1
|
||||
property int y: 1
|
||||
Component.onCompleted: {
|
||||
var g = null;
|
||||
if (g !== null) {
|
||||
v = 2;
|
||||
}
|
||||
if (g === null) {
|
||||
w = 3;
|
||||
}
|
||||
|
||||
var h = undefined;
|
||||
if (h !== undefined) {
|
||||
x = 4;
|
||||
}
|
||||
if (h === undefined) {
|
||||
y = 5;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -145,6 +145,7 @@ private slots:
|
|||
void letAndConst();
|
||||
void signalIndexMismatch();
|
||||
void callWithSpread();
|
||||
void nullComparison();
|
||||
};
|
||||
|
||||
void tst_QmlCppCodegen::initTestCase()
|
||||
|
@ -2802,6 +2803,21 @@ void tst_QmlCppCodegen::callWithSpread()
|
|||
QTest::ignoreMessage(QtCriticalMsg, "That is great!");
|
||||
QScopedPointer<QObject> o(c.create());
|
||||
QVERIFY(!o.isNull());
|
||||
}
|
||||
|
||||
void tst_QmlCppCodegen::nullComparison()
|
||||
{
|
||||
QQmlEngine engine;
|
||||
|
||||
QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/nullComparison.qml"_s));
|
||||
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
|
||||
QScopedPointer<QObject> o(c.create());
|
||||
QVERIFY(!o.isNull());
|
||||
|
||||
QCOMPARE(o->property("v").toInt(), 1);
|
||||
QCOMPARE(o->property("w").toInt(), 3);
|
||||
QCOMPARE(o->property("x").toInt(), 1);
|
||||
QCOMPARE(o->property("y").toInt(), 5);
|
||||
};
|
||||
|
||||
QTEST_MAIN(tst_QmlCppCodegen)
|
||||
|
|
Loading…
Reference in New Issue