Skip to content

Commit

Permalink
QtQml: Don't create metatypes for procedurally registered composites
Browse files Browse the repository at this point in the history
We never want to find or insert them in the compositeTypes. Anytime an
engine wants to use such a type it has to compile it all the way.

Amends commit b48bb41.

Pick-to: 6.7
Fixes: QTBUG-121014
Change-Id: I027f977643db01dac25d8fbc06a6d3e75a7183f5
Reviewed-by: Qt CI Bot <[email protected]>
Reviewed-by: Fabian Kosmale <[email protected]>
Reviewed-by: Nicolas Fella <[email protected]>
  • Loading branch information
Ulf Hermann committed Jan 17, 2024
1 parent 486cc33 commit d0e16e3
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 9 deletions.
23 changes: 14 additions & 9 deletions src/qml/qml/qqmlmetatype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,15 +168,15 @@ static void addQQmlMetaTypeInterfaces(QQmlTypePrivate *priv, const QByteArray &c
static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &elementName,
const QQmlPrivate::RegisterCompositeType &type)
{
// This is a procedurally registered composite type. It's evil. It doesn't get any metatypes
// because we never want to find it in the compositeTypes. Otherwise we might mix it up with an
// actually compiled version of the same type.

auto *d = new QQmlTypePrivate(QQmlType::CompositeType);
data->registerType(d);
d->setName(QString::fromUtf8(type.uri), elementName);
d->version = type.version;

const QUrl normalized = QQmlTypeLoader::normalize(type.url);
d->extraData.compositeTypeData = normalized;
addQQmlMetaTypeInterfaces(
d, QQmlPropertyCacheCreatorBase::createClassNameTypeByUrl(normalized));
d->extraData.compositeTypeData = QQmlTypeLoader::normalize(type.url);
return d;
}

Expand All @@ -185,15 +185,17 @@ static QQmlTypePrivate *createQQmlType(
const QQmlPrivate::RegisterCompositeSingletonType &type,
const QQmlType::SingletonInstanceInfo::ConstPtr &siinfo)
{
// This is a procedurally registered composite singleton. It's evil. It doesn't get any
// metatypes because we never want to find it in the compositeTypes. Otherwise we might mix it
// up with an actually compiled version of the same type.

auto *d = new QQmlTypePrivate(QQmlType::CompositeSingletonType);
data->registerType(d);
d->setName(QString::fromUtf8(type.uri), elementName);

d->version = type.version;

d->extraData.singletonTypeData->singletonInstanceInfo = siinfo;
addQQmlMetaTypeInterfaces(
d, QQmlPropertyCacheCreatorBase::createClassNameTypeByUrl(siinfo->url));
return d;
}

Expand Down Expand Up @@ -672,10 +674,13 @@ QQmlType QQmlMetaType::findCompositeType(
urlExists = false;
}

if (urlExists) {
if (const QtPrivate::QMetaTypeInterface *iface = urlExists
? found.value()->typeId.iface()
: nullptr) {
if (compilationUnit.isNull())
return QQmlType(*found);
const auto composite = data->compositeTypes.constFind(found.value()->typeId.iface());

const auto composite = data->compositeTypes.constFind(iface);
if (composite == data->compositeTypes.constEnd() || composite.value() == compilationUnit)
return QQmlType(*found);
}
Expand Down
6 changes: 6 additions & 0 deletions tests/auto/qml/qqmllanguage/data/ambiguousComponents.qml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@ import QtQuick
import Comps as Comps

Comps.OverlayDrawer {
id: self

property var dothing

Component.onCompleted: dothing = handleOpenIcon.dothing

function dodo() { dothing() }

function testInstanceOf() : bool {
return self instanceof Comps.OverlayDrawer
}
}
12 changes: 12 additions & 0 deletions tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8457,6 +8457,7 @@ void tst_qqmllanguage::ambiguousComponents()
{
auto e1 = std::make_unique<QQmlEngine>();
e1->addImportPath(dataDirectory());
bool isInstanceOf = false;

{
QQmlComponent c(e1.get());
Expand All @@ -8466,6 +8467,9 @@ void tst_qqmllanguage::ambiguousComponents()
QScopedPointer<QObject> o(c.create());
QTest::ignoreMessage(QtDebugMsg, "do");
QMetaObject::invokeMethod(o.data(), "dodo");

QMetaObject::invokeMethod(o.data(), "testInstanceOf", Q_RETURN_ARG(bool, isInstanceOf));
QVERIFY(isInstanceOf);
}

QQmlEngine e2;
Expand All @@ -8478,11 +8482,19 @@ void tst_qqmllanguage::ambiguousComponents()
QTest::ignoreMessage(QtDebugMsg, "do");
QMetaObject::invokeMethod(o2.data(), "dodo");

isInstanceOf = false;
QMetaObject::invokeMethod(o2.data(), "testInstanceOf", Q_RETURN_ARG(bool, isInstanceOf));
QVERIFY(isInstanceOf);

e1.reset();

// We can still invoke the function. This means its CU belongs to e2.
QTest::ignoreMessage(QtDebugMsg, "do");
QMetaObject::invokeMethod(o2.data(), "dodo");

isInstanceOf = false;
QMetaObject::invokeMethod(o2.data(), "testInstanceOf", Q_RETURN_ARG(bool, isInstanceOf));
QVERIFY(isInstanceOf);
}

QTEST_MAIN(tst_qqmllanguage)
Expand Down

0 comments on commit d0e16e3

Please sign in to comment.