diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2023-04-27 14:22:30 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-04-28 05:41:48 +0000 |
commit | ed776128213aece4a06f8cb6782d0ce57350911f (patch) | |
tree | f912bc17d6ee854631e8f793362808833dab9c4e | |
parent | c8e5e21eddd9ac1f1d71dda63c7d1fecc019287a (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.cpp | 14 |
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); } } |