Fix crash in QQuickLoader when source component is garbage collected
It may happen that the QQuickLoader is the last entity left in the system holding a reference to the QQmlComponent *sourceComponent. We have to let the garbage collector know about that by keeping a persistent value for it. Task-number: QTBUG-35334 Change-Id: I715864440378fd9dd4f2d5ef8ff2f171c81ed7ef Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
parent
433949df18
commit
adaedcb9ea
|
@ -106,6 +106,7 @@ void QQuickLoaderPrivate::clear()
|
|||
component->deleteLater();
|
||||
component = 0;
|
||||
}
|
||||
componentStrongReference.clear();
|
||||
source = QUrl();
|
||||
|
||||
if (item) {
|
||||
|
@ -472,6 +473,10 @@ void QQuickLoader::setSourceComponent(QQmlComponent *comp)
|
|||
d->clear();
|
||||
|
||||
d->component = comp;
|
||||
if (comp) {
|
||||
if (QQmlData *ddata = QQmlData::get(comp))
|
||||
d->componentStrongReference = ddata->jsWrapper.value();
|
||||
}
|
||||
d->loadingFromSource = false;
|
||||
|
||||
if (d->active)
|
||||
|
|
|
@ -106,6 +106,7 @@ public:
|
|||
QQuickItem *item;
|
||||
QObject *object;
|
||||
QQmlComponent *component;
|
||||
QV4::PersistentValue componentStrongReference; // To ensure GC doesn't delete components created by Qt.createComponent
|
||||
QQmlContext *itemContext;
|
||||
QQuickLoaderIncubator *incubator;
|
||||
QV4::PersistentValue initialPropertyValues;
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
import QtQml 2.0
|
||||
QtObject {}
|
|
@ -0,0 +1,8 @@
|
|||
import QtQuick 2.0
|
||||
|
||||
Loader {
|
||||
active: false
|
||||
function setSourceComponent() {
|
||||
sourceComponent = Qt.createComponent("SimpleTestComponent.qml");
|
||||
}
|
||||
}
|
|
@ -128,6 +128,8 @@ private slots:
|
|||
void sizeBound();
|
||||
void QTBUG_30183();
|
||||
|
||||
void sourceComponentGarbageCollection();
|
||||
|
||||
private:
|
||||
QQmlEngine engine;
|
||||
};
|
||||
|
@ -1144,6 +1146,26 @@ void tst_QQuickLoader::QTBUG_30183()
|
|||
delete loader;
|
||||
}
|
||||
|
||||
void tst_QQuickLoader::sourceComponentGarbageCollection()
|
||||
{
|
||||
QQmlComponent component(&engine, testFileUrl("sourceComponentGarbageCollection.qml"));
|
||||
QScopedPointer<QObject> obj(component.create());
|
||||
QVERIFY(!obj.isNull());
|
||||
|
||||
QMetaObject::invokeMethod(obj.data(), "setSourceComponent");
|
||||
engine.collectGarbage();
|
||||
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
|
||||
|
||||
QSignalSpy spy(obj.data(), SIGNAL(loaded()));
|
||||
|
||||
obj->setProperty("active", true);
|
||||
|
||||
if (spy.isEmpty())
|
||||
QVERIFY(spy.wait());
|
||||
|
||||
QCOMPARE(spy.count(), 1);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QQuickLoader)
|
||||
|
||||
#include "tst_qquickloader.moc"
|
||||
|
|
Loading…
Reference in New Issue