diff options
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 9 | ||||
-rw-r--r-- | tests/auto/quick/qquickitem/data/objectCastInDestructor.qml | 23 | ||||
-rw-r--r-- | tests/auto/quick/qquickitem/tst_qquickitem.cpp | 25 |
3 files changed, 56 insertions, 1 deletions
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 54ec5e1dcd..d5a8371c7f 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -213,7 +213,8 @@ QQmlEnginePrivate::~QQmlEnginePrivate() void QQmlPrivate::qdeclarativeelement_destructor(QObject *o) { - if (QQmlData *d = QQmlData::get(o)) { + QObjectPrivate *p = QObjectPrivate::get(o); + if (QQmlData *d = QQmlData::get(p)) { if (d->ownContext) { for (QQmlRefPointer<QQmlContextData> lc = d->ownContext->linkedContext(); lc; lc = lc->linkedContext()) { @@ -231,6 +232,12 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o) if (d->outerContext && d->outerContext->contextObject() == o) d->outerContext->setContextObject(nullptr); + if (d->hasVMEMetaObject || d->hasInterceptorMetaObject) { + p->metaObject->objectDestroyed(o); + p->metaObject = nullptr; + d->hasVMEMetaObject = d->hasInterceptorMetaObject = false; + } + // Mark this object as in the process of deletion to // prevent it resolving in bindings QQmlData::markAsDeleted(o); diff --git a/tests/auto/quick/qquickitem/data/objectCastInDestructor.qml b/tests/auto/quick/qquickitem/data/objectCastInDestructor.qml new file mode 100644 index 0000000000..0cb3eea6e2 --- /dev/null +++ b/tests/auto/quick/qquickitem/data/objectCastInDestructor.qml @@ -0,0 +1,23 @@ +import QtQuick + +Rectangle { + width: 360 + height: 360 + + Component { + id: crashComponent + + Rectangle { + objectName: "testRectangle" + property bool customProperty: false + } + } + + Loader { + id: loader + objectName: "loader" + anchors.fill: parent + sourceComponent: crashComponent + } +} + diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp index 2736d6d9bb..e00c4cf42d 100644 --- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp @@ -8,6 +8,7 @@ #include <QtQuick/qquickwindow.h> #include <QtQuick/qquickview.h> #include "private/qquickfocusscope_p.h" +#include "private/qquickrectangle_p.h" #include "private/qquickitem_p.h" #include <QtGui/private/qevent_p.h> #include <qpa/qwindowsysteminterface.h> @@ -226,6 +227,8 @@ private slots: void polishLoopDetection_data(); void polishLoopDetection(); + void objectCastInDestructor(); + private: enum PaintOrderOp { @@ -2435,6 +2438,28 @@ void tst_qquickitem::receivesLocaleChangeEvent() QCOMPARE(child2->localeChangeEventCount, 1); } +void tst_qquickitem::objectCastInDestructor() +{ + QQuickView view; + view.setSource(testFileUrl("objectCastInDestructor.qml")); + view.show(); + + QQuickItem *item = view.findChild<QQuickItem *>("testRectangle"); + QVERIFY(item); + bool destroyed = false; + connect(item, &QObject::destroyed, [&]{ + destroyed = true; + QCOMPARE(qobject_cast<QQuickItem *>(item), nullptr); + QCOMPARE(qobject_cast<QQuickRectangle *>(item), nullptr); + }); + + QQuickItem *loader = view.findChild<QQuickItem *>("loader"); + QVERIFY(loader); + loader->setProperty("active", false); + + QVERIFY(QTest::qWaitFor([&destroyed]{ return destroyed; })); +} + QTEST_MAIN(tst_qquickitem) #include "tst_qquickitem.moc" |