From 1d88e9919ff837d535f9bbde53613b6a6b96fcd8 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 4 Dec 2018 14:06:59 +0100 Subject: QML: Fix registering and unregistering of context objects When we add a context object we need to include it into the list of contextObjects of its outer context, so that the outerContext member can be reset when the outer context disappears. On the flip side, we also need to remove it from this list when the object gets removed. We don't need to reset the inner context of an object when the outer context disappears, though. Fixes: QTBUG-72241 Change-Id: Ifd34650d852642a364df23b697d32e3961d0479b Reviewed-by: Mitch Curtis Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlcontext.cpp | 15 +++++++++------ src/qml/qml/qqmlcontext_p.h | 2 +- src/qml/qml/qqmlengine.cpp | 6 +++++- src/qml/qml/qqmlobjectcreator.cpp | 12 +++++++----- 4 files changed, 22 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index cbf5a6e259..eca00ffb51 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -640,7 +640,6 @@ void QQmlContextData::destroy() QQmlData *co = contextObjects; contextObjects = contextObjects->nextContextObject; - co->context = nullptr; co->outerContext = nullptr; co->nextContextObject = nullptr; co->prevContextObject = nullptr; @@ -783,13 +782,17 @@ void QQmlContextData::refreshExpressions() } } -void QQmlContextData::addObject(QObject *o) +void QQmlContextData::addObject(QQmlData *data) { - QQmlData *data = QQmlData::get(o, true); - - Q_ASSERT(data->context == nullptr); + if (data->outerContext) { + if (data->nextContextObject) + data->nextContextObject->prevContextObject = data->prevContextObject; + if (data->prevContextObject) + *data->prevContextObject = data->nextContextObject; + else if (data->outerContext->contextObjects == data) + data->outerContext->contextObjects = data->nextContextObject; + } - data->context = this; data->outerContext = this; data->nextContextObject = contextObjects; diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h index 290b7fc7ee..7e3cef8e1d 100644 --- a/src/qml/qml/qqmlcontext_p.h +++ b/src/qml/qml/qqmlcontext_p.h @@ -129,7 +129,7 @@ public: void setParent(QQmlContextData *, bool stronglyReferencedByParent = false); void refreshExpressions(); - void addObject(QObject *); + void addObject(QQmlData *data); QUrl resolvedUrl(const QUrl &); diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index c400e9239b..6db43a50eb 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1518,7 +1518,9 @@ void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context) } QQmlContextData *contextData = QQmlContextData::get(context); - contextData->addObject(object); + Q_ASSERT(data->context == nullptr); + data->context = contextData; + contextData->addObject(data); } /*! @@ -1882,6 +1884,8 @@ void QQmlData::destroyed(QObject *object) nextContextObject->prevContextObject = prevContextObject; if (prevContextObject) *prevContextObject = nextContextObject; + else if (outerContext && outerContext->contextObjects == this) + outerContext->contextObjects = nextContextObject; QQmlAbstractBinding *binding = bindings; while (binding) { diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index c181d791f5..68e2c2c928 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -1230,13 +1230,15 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo QQmlContextData *c = ddata->context; while (c->linkedContext) c = c->linkedContext; c->linkedContext = context; - } else - context->addObject(instance); + } else { + ddata->context = context; + } ddata->ownContext = ddata->context; - } else if (!ddata->context) - context->addObject(instance); + } else if (!ddata->context) { + ddata->context = context; + } - ddata->outerContext = context; + context->addObject(ddata); if (parserStatus) { parserStatus->classBegin(); -- cgit v1.2.3