QtQml: Don't unnecessarily detour through the CU to look up types

Since we also store partial types as QQmlType now, we can just look them
up the regular way.

Pick-to: 6.6 6.5 6.2
Fixes: QTBUG-117788
Change-Id: Id3e81853f802419f1121ef5e856c3272a3c977a1
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Ulf Hermann 2023-10-16 09:17:42 +02:00
parent bbeca33068
commit bf2258e6f4
7 changed files with 43 additions and 26 deletions

View File

@ -136,7 +136,6 @@ Function::Function(ExecutionEngine *engine, ExecutableCompilationUnit *unit,
JSTypedFunction *synthesized = new JSTypedFunction;
QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine->qmlEngine());
auto findQmlType = [&](const CompiledData::ParameterType &param) {
const quint32 type = param.typeNameIndexOrCommonType();
if (param.indexIsCommonType()) {
@ -158,7 +157,7 @@ Function::Function(ExecutionEngine *engine, ExecutableCompilationUnit *unit,
: QQmlType();
}
return enginePrivate->typeLoader.getType(qmltype.sourceUrl())->compilationUnit()->qmlType;
return qmltype;
};
for (quint16 i = 0; i < nFormals; ++i)

View File

@ -1962,14 +1962,8 @@ bool AOTCompiledContext::loadTypeLookup(uint index, void *target) const
const QV4::Heap::QQmlTypeWrapper *typeWrapper = static_cast<const QV4::Heap::QQmlTypeWrapper *>(
l->qmlTypeLookup.qmlTypeWrapper);
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(qmlEngine());
QMetaType metaType = typeWrapper->type().typeId();
if (!metaType.isValid()) {
metaType = ep->typeLoader.getType(typeWrapper->type().sourceUrl())
->compilationUnit()->qmlType.typeId();
}
*static_cast<const QMetaObject **>(target)
= QQmlMetaType::metaObjectForType(metaType).metaObject();
return true;

View File

@ -673,6 +673,8 @@ QQmlType QQmlMetaType::findCompositeType(
}
if (urlExists) {
if (compilationUnit.isNull())
return QQmlType(*found);
const auto composite = data->compositeTypes.constFind(found.value()->typeId.iface());
if (composite == data->compositeTypes.constEnd() || composite.value() == compilationUnit)
return QQmlType(*found);
@ -1893,8 +1895,11 @@ void QQmlMetaType::registerInternalCompositeType(
auto doInsert = [&data, &compilationUnit](const QtPrivate::QMetaTypeInterface *iface) {
Q_ASSERT(iface);
const auto it = data->compositeTypes.constFind(iface);
Q_ASSERT(it == data->compositeTypes.constEnd() || *it == compilationUnit);
Q_ASSERT(compilationUnit);
// We can't assert on anything else here. We may get a completely new type as exposed
// by the qmldiskcache test that changes a QML file in place during the execution
// of the test.
data->compositeTypes.insert(iface, compilationUnit);
};

View File

@ -683,14 +683,9 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject(
compositeType = objectContainer->qmlTypeForComponent(icName);
Q_ASSERT(compositeType.isValid());
} else if (selfReference) {
compositeType = objectContainer->qmlTypeForComponent();
compositeType = objectContainer->qmlTypeForComponent();
} else {
QQmlRefPointer<QQmlTypeData> tdata = enginePrivate->typeLoader.getType(qmltype.sourceUrl());
Q_ASSERT(tdata);
Q_ASSERT(tdata->isComplete());
auto compilationUnit = tdata->compilationUnit();
compositeType = compilationUnit->qmlTypeForComponent();
compositeType = qmltype;
}
if (p->isList()) {
@ -766,15 +761,7 @@ inline QMetaType QQmlPropertyCacheCreator<ObjectContainer>::metaTypeForParameter
return param.isList() ? qmlType.qListTypeId() : qmlType.typeId();
}
QQmlRefPointer<QQmlTypeData> tdata = enginePrivate->typeLoader.getType(qmltype.sourceUrl());
Q_ASSERT(tdata);
Q_ASSERT(tdata->isComplete());
auto compilationUnit = tdata->compilationUnit();
return param.isList()
? compilationUnit->qmlType.qListTypeId()
: compilationUnit->qmlType.typeId();
return param.isList() ? qmltype.qListTypeId() : qmltype.typeId();
}
template <typename ObjectContainer, typename CompiledObject>

View File

@ -0,0 +1,15 @@
import QtQml
QtObject {
id: self
property QtObject b
property Component c
function a() : TypeAnnotationCycle2 { return c.createObject() as TypeAnnotationCycle2 }
Component.onCompleted: {
c = Qt.createComponent("TypeAnnotationCycle2.qml");
let v = a();
v.addTypeAnnotationCycle1(self as TypeAnnotationCycle1);
b = v.b;
}
}

View File

@ -0,0 +1,6 @@
import QtQml
QtObject {
property QtObject b
function addTypeAnnotationCycle1(c: TypeAnnotationCycle1) { b = c; }
}

View File

@ -432,6 +432,7 @@ private slots:
void callMethodOfAttachedDerived();
void multiVersionSingletons();
void typeAnnotationCycle();
private:
QQmlEngine engine;
@ -8285,6 +8286,16 @@ void tst_qqmllanguage::multiVersionSingletons()
}
}
void tst_qqmllanguage::typeAnnotationCycle()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("TypeAnnotationCycle1.qml"));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
QVERIFY(!o.isNull());
QCOMPARE(o->property("b").value<QObject*>(), o.data());
}
QTEST_MAIN(tst_qqmllanguage)
#include "tst_qqmllanguage.moc"