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>
This commit is contained in:
parent
074b66e007
commit
79e885537f
|
@ -1041,9 +1041,15 @@ void QQuickLoaderPrivate::createComponent()
|
||||||
const QQmlComponent::CompilationMode mode = asynchronous
|
const QQmlComponent::CompilationMode mode = asynchronous
|
||||||
? QQmlComponent::Asynchronous
|
? QQmlComponent::Asynchronous
|
||||||
: QQmlComponent::PreferSynchronous;
|
: QQmlComponent::PreferSynchronous;
|
||||||
QQmlContext *context = qmlContext(q);
|
if (QQmlContext *context = qmlContext(q)) {
|
||||||
component.setObject(new QQmlComponent(
|
if (QQmlEngine *engine = context->engine()) {
|
||||||
context->engine(), context->resolvedUrl(source), mode, q), q);
|
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>
|
#include <moc_qquickloader_p.cpp>
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -134,6 +134,7 @@ private slots:
|
||||||
|
|
||||||
void setSourceAndCheckStatus();
|
void setSourceAndCheckStatus();
|
||||||
void asyncLoaderRace();
|
void asyncLoaderRace();
|
||||||
|
void noEngine();
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(QList<QQmlError>)
|
Q_DECLARE_METATYPE(QList<QQmlError>)
|
||||||
|
@ -1533,6 +1534,20 @@ void tst_QQuickLoader::asyncLoaderRace()
|
||||||
QCOMPARE(loader->item(), nullptr);
|
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)
|
QTEST_MAIN(tst_QQuickLoader)
|
||||||
|
|
||||||
#include "tst_qquickloader.moc"
|
#include "tst_qquickloader.moc"
|
||||||
|
|
Loading…
Reference in New Issue