aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/quick/qquickloader
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/quick/qquickloader')
-rw-r--r--tests/auto/quick/qquickloader/data/invalidateContext.qml28
-rw-r--r--tests/auto/quick/qquickloader/tst_qquickloader.cpp56
2 files changed, 84 insertions, 0 deletions
diff --git a/tests/auto/quick/qquickloader/data/invalidateContext.qml b/tests/auto/quick/qquickloader/data/invalidateContext.qml
new file mode 100644
index 0000000000..b5a28f5d0f
--- /dev/null
+++ b/tests/auto/quick/qquickloader/data/invalidateContext.qml
@@ -0,0 +1,28 @@
+import QtQuick
+
+Item {
+ Loader {
+ active: loaderActive
+ sourceComponent: comp
+ }
+
+ Component {
+ id: comp
+ Column {
+ Repeater {
+ id: repeater
+ model: cppModel
+
+ Component.onCompleted: console.log("Repeater constructed");
+ Component.onDestruction: console.log("Repeater destroyed");
+
+ delegate: Text {
+ text: {
+ console.log("updating text");
+ return display + rootData.getValue();
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
index 389f037166..afc49fe74d 100644
--- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp
+++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
@@ -117,6 +117,8 @@ private slots:
void stackOverflow();
void stackOverflow2();
void boundComponent();
+
+ void invalidateContext();
};
Q_DECLARE_METATYPE(QList<QQmlError>)
@@ -1585,6 +1587,60 @@ void tst_QQuickLoader::boundComponent()
QCOMPARE(o->objectName(), QStringLiteral("loaded"));
}
+class CppModel : public QAbstractListModel
+{
+public:
+ virtual int rowCount(const QModelIndex &) const override {return 1;}
+ virtual QVariant data(const QModelIndex &, int) const override { return "test"; }
+
+ void reset () {beginResetModel(); endResetModel();}
+};
+
+class RootData : public QObject
+{
+ Q_OBJECT
+public:
+ RootData() : object(std::make_unique<QObject>())
+ {
+ object->setObjectName("objectName");
+ }
+
+ Q_INVOKABLE QString getValue() const { return object->objectName(); }
+
+ void deleteObject() { object.reset(); }
+
+private:
+ std::unique_ptr<QObject> object;
+};
+
+void tst_QQuickLoader::invalidateContext()
+{
+ CppModel model;
+ RootData rootData;
+
+ QQmlEngine engine;
+ QQmlContext *rootContext = engine.rootContext();
+ rootContext->setContextProperty("cppModel", &model);
+ rootContext->setContextProperty("loaderActive", true);
+ rootContext->setContextProperty("rootData", &rootData);
+
+ QQmlComponent component(&engine, testFileUrl("invalidateContext.qml"));\
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+
+ QTest::ignoreMessage(QtDebugMsg, "Repeater constructed");
+ QTest::ignoreMessage(QtDebugMsg, "updating text");
+ QScopedPointer<QObject> o(component.create());
+
+ QTest::ignoreMessage(QtDebugMsg, "Repeater destroyed");
+ rootContext->setContextProperty("loaderActive", false);
+
+ // The object should never be used anymore, as loader is inactive
+ rootData.deleteObject();
+
+ // Should not trigger any re-evaluation (which would crash in getValue())
+ model.reset();
+}
+
QTEST_MAIN(tst_QQuickLoader)
#include "tst_qquickloader.moc"