diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2019-09-11 16:38:29 +0200 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2019-09-12 08:07:10 +0200 |
commit | 5ca1d2e0b2912e578a32c5e11b4fd1d7a0ef28f3 (patch) | |
tree | 1b5b3949a606ce7691c13d98167adf82a6c73d19 | |
parent | d38bac596946c3dd9cce3c0b4127509421dc917d (diff) |
QQmlTypeLoader: Prevent trivial cycles
The type loader already contained a cycle check, however it did not work
for the attached example. We now do an additional test for A->B->A
cycles, which fixes the bug. This is a valid strategy, as in that case
the currently resolved type would immediately fullfill the depentency of
the type waiting on it, which in turn resolves the only dependency of
the current type.
Fixes: QTBUG-78098
Change-Id: I8b550a1c240d3d0fbf158beb99a5daf992904cb0
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
8 files changed, 44 insertions, 2 deletions
diff --git a/src/qml/qml/qqmldatablob_p.h b/src/qml/qml/qqmldatablob_p.h index da3bbe2c1f..0450e94c02 100644 --- a/src/qml/qml/qqmldatablob_p.h +++ b/src/qml/qml/qqmldatablob_p.h @@ -242,7 +242,9 @@ private: mutable QString m_finalUrlString; // List of QQmlDataBlob's that are waiting for me to complete. +protected: QList<QQmlDataBlob *> m_waitingOnMe; +private: // List of QQmlDataBlob's that I am waiting for to complete. QVector<QQmlRefPointer<QQmlDataBlob>> m_waitingFor; diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp index 8d75b57fc1..b9fbf40e96 100644 --- a/src/qml/qml/qqmltypedata.cpp +++ b/src/qml/qml/qqmltypedata.cpp @@ -678,7 +678,7 @@ void QQmlTypeData::resolveTypes() if (ref.type.isCompositeSingleton()) { ref.typeData = typeLoader()->getType(ref.type.sourceUrl()); - if (ref.typeData->status() == QQmlDataBlob::ResolvingDependencies) { + if (ref.typeData->status() == QQmlDataBlob::ResolvingDependencies || m_waitingOnMe.contains(ref.typeData.data())) { // TODO: give an error message? If so, we should record and show the path of the cycle. continue; } diff --git a/tests/auto/qml/qqmltypeloader/data/Com/Orga/BaseStyle.qml b/tests/auto/qml/qqmltypeloader/data/Com/Orga/BaseStyle.qml new file mode 100644 index 0000000000..28521e3af2 --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/Com/Orga/BaseStyle.qml @@ -0,0 +1,5 @@ +import QtQuick 2.6 + +Item { + +} diff --git a/tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/Handler.qml b/tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/Handler.qml new file mode 100644 index 0000000000..b20a2def11 --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/Handler.qml @@ -0,0 +1,7 @@ +import QtQuick 2.6 +import Com.Orga 1.0 + +Rectangle { + color: Style.name + Text {text: "Hello world!"} +} diff --git a/tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/qmldir b/tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/qmldir new file mode 100644 index 0000000000..368cb65b35 --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/qmldir @@ -0,0 +1,2 @@ +module Com.Orga.Handlers +Handler 1.0 Handler.qml diff --git a/tests/auto/qml/qqmltypeloader/data/Com/Orga/Style.qml b/tests/auto/qml/qqmltypeloader/data/Com/Orga/Style.qml new file mode 100644 index 0000000000..7951f5e768 --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/Com/Orga/Style.qml @@ -0,0 +1,6 @@ +pragma Singleton +import QtQuick 2.6 + +BaseStyle { + property color name: "black" +} diff --git a/tests/auto/qml/qqmltypeloader/data/Com/Orga/qmldir b/tests/auto/qml/qqmltypeloader/data/Com/Orga/qmldir new file mode 100644 index 0000000000..9c5560b323 --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/Com/Orga/qmldir @@ -0,0 +1,2 @@ +singleton Style 1.0 Style.qml +BaseStyle 1.0 BaseStyle.qml diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp index 2993b4b3c8..9ad53aaa8b 100644 --- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp +++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp @@ -60,6 +60,7 @@ private slots: void implicitComponentModule(); void qrcRootPathUrl(); void implicitImport(); + void compositeSingletonCycle(); }; void tst_QQMLTypeLoader::testLoadComplete() @@ -434,7 +435,7 @@ void tst_QQMLTypeLoader::redirect() component.loadUrl(server.urlString("/Load.qml"), QQmlComponent::Asynchronous); QTRY_VERIFY2(component.isReady(), qPrintable(component.errorString())); - QObject *object = component.create(); + QScopedPointer<QObject> object {component.create()}; QTRY_COMPARE(object->property("xy").toInt(), 323232); } @@ -524,6 +525,23 @@ void tst_QQMLTypeLoader::implicitImport() QVERIFY(!obj.isNull()); } +void tst_QQMLTypeLoader::compositeSingletonCycle() +{ + TestHTTPServer server; + QVERIFY2(server.listen(), qPrintable(server.errorString())); + QVERIFY(server.serveDirectory(dataDirectory())); + + QQmlEngine engine; + QQmlComponent component(&engine); + engine.addImportPath(server.baseUrl().toString()); + component.loadUrl(server.urlString("Com/Orga/Handlers/Handler.qml"), QQmlComponent::Asynchronous); + QTRY_VERIFY2(component.isReady(), qPrintable(component.errorString())); + + QScopedPointer<QObject> object {component.create()}; + QVERIFY(object); + QCOMPARE(qvariant_cast<QColor>(object->property("color")), QColorConstants::Black); +} + QTEST_MAIN(tst_QQMLTypeLoader) #include "tst_qqmltypeloader.moc" |