diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2024-01-19 16:19:06 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2024-02-01 15:14:39 +0100 |
commit | 27ba69af2f64a8b194655c9fbb276ce981075f75 (patch) | |
tree | d36ebc5f777a6b7cb2d5c63a61aa841ca5ffae87 /src/qml/qml/qqmlengine.cpp | |
parent | c3474688f68607ffff301c01450f71c4920b501d (diff) |
QtQml: Clear context objects more thoroughly on destruction
The same object can be the context object of a hierarchy of contexts. So
far we would only clear one of them, leaving dangling pointers in the
others. Clear all the contexts.
Pick-to: 6.7 6.6 6.5 6.2 5.15
Fixes: QTBUG-119326
Change-Id: I509f257672813866e3736b51f430f1243a8577f0
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/qml/qqmlengine.cpp')
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 21 |
1 files changed, 6 insertions, 15 deletions
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 196312314c..c7812059a1 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -217,23 +217,16 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o) { QObjectPrivate *p = QObjectPrivate::get(o); if (QQmlData *d = QQmlData::get(p)) { + const auto invalidate = [](QQmlContextData *c) {c->invalidate();}; if (d->ownContext) { - for (QQmlRefPointer<QQmlContextData> lc = d->ownContext->linkedContext(); lc; - lc = lc->linkedContext()) { - lc->invalidate(); - if (lc->contextObject() == o) - lc->setContextObject(nullptr); - } - d->ownContext->invalidate(); - if (d->ownContext->contextObject() == o) - d->ownContext->setContextObject(nullptr); + d->ownContext->deepClearContextObject(o, invalidate, invalidate); d->ownContext.reset(); d->context = nullptr; + Q_ASSERT(!d->outerContext || d->outerContext->contextObject() != o); + } else if (d->outerContext && d->outerContext->contextObject() == o) { + d->outerContext->deepClearContextObject(o, invalidate, invalidate); } - if (d->outerContext && d->outerContext->contextObject() == o) - d->outerContext->setContextObject(nullptr); - if (d->hasVMEMetaObject || d->hasInterceptorMetaObject) { // This is somewhat dangerous because another thread might concurrently // try to resolve the dynamic metaobject. In practice this will then @@ -406,9 +399,7 @@ void QQmlData::setQueuedForDeletion(QObject *object) if (QQmlData *ddata = QQmlData::get(object)) { if (ddata->ownContext) { Q_ASSERT(ddata->ownContext.data() == ddata->context); - ddata->context->emitDestruction(); - if (ddata->ownContext->contextObject() == object) - ddata->ownContext->setContextObject(nullptr); + ddata->ownContext->deepClearContextObject(object); ddata->ownContext.reset(); ddata->context = nullptr; } |