diff options
-rw-r--r-- | src/qml/jsruntime/qv4function.cpp | 19 | ||||
-rw-r--r-- | tests/auto/qml/qqmllanguage/data/badICAnnotation.qml | 25 | ||||
-rw-r--r-- | tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 34 |
3 files changed, 72 insertions, 6 deletions
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index 2e51366d64..a853eac41d 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -154,16 +154,23 @@ Function::Function(ExecutionEngine *engine, ExecutableCompilationUnit *unit, base->stringAt(type), typeLoader).type : QQmlType(); - if (!qmltype.isValid() || qmltype.typeId().isValid()) + if (!qmltype.isValid() || qmltype.isComposite()) return qmltype; - if (!qmltype.isComposite()) { - return qmltype.isInlineComponentType() - ? base->qmlTypeForComponent(qmltype.elementName()) - : QQmlType(); + if (qmltype.isInlineComponentType()) { + if (qmltype.typeId().isValid()) { + // If it seems to be an IC type, make sure there is an actual + // compilation unit for it. We create inline component types speculatively. + return QQmlMetaType::obtainCompilationUnit(qmltype.typeId()) + ? qmltype + : QQmlType(); + } else { + // TODO: Can this actually happen? + return base->qmlTypeForComponent(qmltype.elementName()); + } } - return qmltype; + return qmltype.typeId().isValid() ? qmltype : QQmlType(); }; for (quint16 i = 0; i < nFormals; ++i) diff --git a/tests/auto/qml/qqmllanguage/data/badICAnnotation.qml b/tests/auto/qml/qqmllanguage/data/badICAnnotation.qml new file mode 100644 index 0000000000..6f0db53f2a --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/badICAnnotation.qml @@ -0,0 +1,25 @@ +import QtQml + +QtObject { + id: self + + function doStuff(status: Binding.NotAnInlineComponent) : int { + return status + } + + function doStuff2(status: InlineComponentBase.IC) : QtObject { + return status + } + + function doStuff3(status: InlineComponentBase.NotIC) : QtObject { + return status + } + + property InlineComponentBase.IC ic: InlineComponentBase.IC {} + + property int a: doStuff(5) + property QtObject b: doStuff2(ic) + property QtObject c: doStuff3(ic) + property QtObject d: doStuff2(self) +} + diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 66246b7a49..ec906e61df 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -443,6 +443,7 @@ private slots: void ambiguousComponents(); void writeNumberToEnumAlias(); + void badInlineComponentAnnotation(); private: QQmlEngine engine; @@ -8512,6 +8513,39 @@ void tst_qqmllanguage::writeNumberToEnumAlias() QCOMPARE(o->property("strokeStyle").toInt(), 1); } +void tst_qqmllanguage::badInlineComponentAnnotation() +{ + QQmlEngine engine; + const QUrl url = testFileUrl("badICAnnotation.qml"); + QQmlComponent c(&engine, testFileUrl("badICAnnotation.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + + QTest::ignoreMessage( + QtCriticalMsg, + qPrintable(url.toString() + ":20: 5 should be coerced to void because the function " + "called is insufficiently annotated. The original " + "value is retained. This will change in a future " + "version of Qt.")); + QTest::ignoreMessage( + QtCriticalMsg, + QRegularExpression(":22: IC\\([^\\)]+\\) should be coerced to void because the " + "function called is insufficiently annotated. The original " + "value is retained. This will change in a future version of " + "Qt\\.")); + + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + + QCOMPARE(o->property("a").toInt(), 5); + + QObject *ic = o->property("ic").value<QObject *>(); + QVERIFY(ic); + + QCOMPARE(o->property("b").value<QObject *>(), ic); + QCOMPARE(o->property("c").value<QObject *>(), ic); + QCOMPARE(o->property("d").value<QObject *>(), nullptr); +} + QTEST_MAIN(tst_qqmllanguage) #include "tst_qqmllanguage.moc" |