diff options
author | Mitch Curtis <mitch.curtis@qt.io> | 2019-11-27 11:00:59 +0100 |
---|---|---|
committer | Mitch Curtis <mitch.curtis@qt.io> | 2019-12-05 13:26:32 +0100 |
commit | aaec25a798352fc222f86ab3b299384575f51dc8 (patch) | |
tree | 577a15561689e65d8288c6c9596f9a103909f58e /src | |
parent | 75b6ef710cddbf9395df35650438f0feb57ec076 (diff) |
StackView: fix crash when recursively removing items
This can happen when e.g. calling clear() in Component.onDestruction
in response to a pop() call.
The patch fixes the crash by warning and returning early.
If users really need to do this, the clear() call can be delayed:
Component.onDestruction: {
Qt.callLater(function() { stackView.clear(StackView.Immediate) })
}
Change-Id: If3cf07495bb34b96089522f44c36976bd6c62492
Fixes: QTBUG-80353
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/quicktemplates2/qquickstackview.cpp | 20 | ||||
-rw-r--r-- | src/quicktemplates2/qquickstackview_p_p.h | 1 |
2 files changed, 21 insertions, 0 deletions
diff --git a/src/quicktemplates2/qquickstackview.cpp b/src/quicktemplates2/qquickstackview.cpp index f7a77374..4c314904 100644 --- a/src/quicktemplates2/qquickstackview.cpp +++ b/src/quicktemplates2/qquickstackview.cpp @@ -651,6 +651,13 @@ void QQuickStackView::push(QQmlV4Function *args) void QQuickStackView::pop(QQmlV4Function *args) { Q_D(QQuickStackView); + if (d->removingElements) { + d->warn(QStringLiteral("cannot pop while already in the process of removing elements")); + args->setReturnValue(QV4::Encode::null()); + return; + } + + QScopedValueRollback<bool> removingElements(d->removingElements, true); QScopedValueRollback<QString> rollback(d->operation, QStringLiteral("pop")); int argc = args->length(); if (d->elements.count() <= 1 || argc > 2) { @@ -806,6 +813,13 @@ void QQuickStackView::pop(QQmlV4Function *args) void QQuickStackView::replace(QQmlV4Function *args) { Q_D(QQuickStackView); + if (d->removingElements) { + d->warn(QStringLiteral("cannot replace while already in the process of removing elements")); + args->setReturnValue(QV4::Encode::null()); + return; + } + + QScopedValueRollback<bool> removingElements(d->removingElements, true); QScopedValueRollback<QString> rollback(d->operation, QStringLiteral("replace")); if (args->length() <= 0) { d->warn(QStringLiteral("missing arguments")); @@ -902,6 +916,12 @@ void QQuickStackView::clear(Operation operation) if (d->elements.isEmpty()) return; + if (d->removingElements) { + d->warn(QStringLiteral("cannot clear while already in the process of removing elements")); + return; + } + + QScopedValueRollback<bool> removingElements(d->removingElements, true); if (operation != Immediate) { QQuickStackElement *exit = d->elements.pop(); exit->removal = true; diff --git a/src/quicktemplates2/qquickstackview_p_p.h b/src/quicktemplates2/qquickstackview_p_p.h index c20ce776..b8c4b817 100644 --- a/src/quicktemplates2/qquickstackview_p_p.h +++ b/src/quicktemplates2/qquickstackview_p_p.h @@ -94,6 +94,7 @@ public: void depthChange(int newDepth, int oldDepth); bool busy = false; + bool removingElements = false; QString operation; QJSValue initialItem; QQuickItem *currentItem = nullptr; |