aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-02-28 15:28:34 +0100
committerUlf Hermann <ulf.hermann@qt.io>2022-03-01 08:55:32 +0100
commit79e885537f8546a18d7d9d902d6efe40b1915c96 (patch)
treeed4d080063e3fbc32632fd7a0d2d0ac8bab370e9
parent074b66e0073b55d32060ffd542a02c811ad763a8 (diff)
QQuickLoader: Check for QQmlEngine before using it
The loader's context may have been removed from the context hierarchy or it may not have a context in the first place. We should not crash then. Pick-to: 5.15 6.2 6.3 Fixes: QTBUG-67950 Change-Id: I1058d5b1f978aa040f8b2f018c4357dd7a3ef333 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r--src/quick/items/qquickloader.cpp12
-rw-r--r--tests/auto/quick/qquickloader/data/noEngine.qml32
-rw-r--r--tests/auto/quick/qquickloader/tst_qquickloader.cpp15
3 files changed, 56 insertions, 3 deletions
diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp
index bde39d99bd..ea1aa7b0c9 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -1041,9 +1041,15 @@ void QQuickLoaderPrivate::createComponent()
const QQmlComponent::CompilationMode mode = asynchronous
? QQmlComponent::Asynchronous
: QQmlComponent::PreferSynchronous;
- QQmlContext *context = qmlContext(q);
- component.setObject(new QQmlComponent(
- context->engine(), context->resolvedUrl(source), mode, q), q);
+ if (QQmlContext *context = qmlContext(q)) {
+ if (QQmlEngine *engine = context->engine()) {
+ component.setObject(new QQmlComponent(
+ engine, context->resolvedUrl(source), mode, q), q);
+ return;
+ }
+ }
+
+ qmlWarning(q) << "createComponent: Cannot find a QML engine.";
}
#include <moc_qquickloader_p.cpp>
diff --git a/tests/auto/quick/qquickloader/data/noEngine.qml b/tests/auto/quick/qquickloader/data/noEngine.qml
new file mode 100644
index 0000000000..19e619f32e
--- /dev/null
+++ b/tests/auto/quick/qquickloader/data/noEngine.qml
@@ -0,0 +1,32 @@
+import QtQuick 2
+
+Item {
+ id: root
+ property bool a: false
+ property int changes: 0
+ onAChanged: {
+ m.model = 0
+ m.model = 1
+ ++changes;
+ }
+
+ Repeater {
+ id: m
+ model: 1
+
+ Item {
+ Timer {
+ onTriggered: {
+ root.a = true
+ l.source = "loaded.qml"
+ }
+ interval: 0
+ running: true
+ }
+
+ Loader {
+ id: l
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
index cf1c4fcce0..e990e94bc3 100644
--- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp
+++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
@@ -134,6 +134,7 @@ private slots:
void setSourceAndCheckStatus();
void asyncLoaderRace();
+ void noEngine();
};
Q_DECLARE_METATYPE(QList<QQmlError>)
@@ -1533,6 +1534,20 @@ void tst_QQuickLoader::asyncLoaderRace()
QCOMPARE(loader->item(), nullptr);
}
+void tst_QQuickLoader::noEngine()
+{
+ QQmlEngine engine;
+ const QUrl url = testFileUrl("noEngine.qml");
+ QQmlComponent component(&engine, url);
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+
+ const QString message = url.toString()
+ + QStringLiteral(":27:13: QML Loader: createComponent: Cannot find a QML engine.");
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
+ QTRY_COMPARE(o->property("changes").toInt(), 1);
+}
+
QTEST_MAIN(tst_QQuickLoader)
#include "tst_qquickloader.moc"