aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/qml/qqmlengine.cpp9
-rw-r--r--tests/auto/quick/qquickitem/data/objectCastInDestructor.qml23
-rw-r--r--tests/auto/quick/qquickitem/tst_qquickitem.cpp25
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"