aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2019-09-11 16:38:29 +0200
committerFabian Kosmale <fabian.kosmale@qt.io>2019-09-12 08:07:10 +0200
commit5ca1d2e0b2912e578a32c5e11b4fd1d7a0ef28f3 (patch)
tree1b5b3949a606ce7691c13d98167adf82a6c73d19
parentd38bac596946c3dd9cce3c0b4127509421dc917d (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>
-rw-r--r--src/qml/qml/qqmldatablob_p.h2
-rw-r--r--src/qml/qml/qqmltypedata.cpp2
-rw-r--r--tests/auto/qml/qqmltypeloader/data/Com/Orga/BaseStyle.qml5
-rw-r--r--tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/Handler.qml7
-rw-r--r--tests/auto/qml/qqmltypeloader/data/Com/Orga/Handlers/qmldir2
-rw-r--r--tests/auto/qml/qqmltypeloader/data/Com/Orga/Style.qml6
-rw-r--r--tests/auto/qml/qqmltypeloader/data/Com/Orga/qmldir2
-rw-r--r--tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp20
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"