aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2023-04-27 14:22:30 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-04-28 05:41:48 +0000
commited776128213aece4a06f8cb6782d0ce57350911f (patch)
treef912bc17d6ee854631e8f793362808833dab9c4e
parentc8e5e21eddd9ac1f1d71dda63c7d1fecc019287a (diff)
QQmlData: Implement markAsDeleted without recursion
While a normal QML scene should not feature extremely deep object trees, one can still encounter them in some test cases. Those test cases might then run out of (C++) stack space with the previous recursive version of markAsDeleted. Thus, we change the implementation to use an explicit workqueue instead of relying on recursion. This changes the visitation order, but code is not supposed to rely on the order of Component.onDestroyed calls anyway (and we keep at least the order in so far that the parent emits the "signal" before it's children. Change-Id: I93b30cc26b984d1a21cff92df1dd68cd45e67477 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> (cherry picked from commit 0a333bc7e5ae9db1d289a65aa7eef46ae7916936) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/qml/qml/qqmlengine.cpp14
1 files changed, 9 insertions, 5 deletions
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 285da1a4e4..c445651f06 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -386,11 +386,15 @@ int QQmlData::endpointCount(int index)
void QQmlData::markAsDeleted(QObject *o)
{
- QQmlData::setQueuedForDeletion(o);
-
- QObjectPrivate *p = QObjectPrivate::get(o);
- for (QList<QObject *>::const_iterator it = p->children.constBegin(), end = p->children.constEnd(); it != end; ++it) {
- QQmlData::markAsDeleted(*it);
+ QVarLengthArray<QObject *> workStack;
+ workStack.push_back(o);
+ while (!workStack.isEmpty()) {
+ auto currentObject = workStack.last();
+ workStack.pop_back();
+ QQmlData::setQueuedForDeletion(currentObject);
+ auto currentObjectPriv = QObjectPrivate::get(currentObject);
+ for (QObject *child: std::as_const(currentObjectPriv->children))
+ workStack.push_back(child);
}
}