aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMitch Curtis <mitch.curtis@qt.io>2019-11-27 11:00:59 +0100
committerMitch Curtis <mitch.curtis@qt.io>2019-12-05 13:26:32 +0100
commitaaec25a798352fc222f86ab3b299384575f51dc8 (patch)
tree577a15561689e65d8288c6c9596f9a103909f58e /src
parent75b6ef710cddbf9395df35650438f0feb57ec076 (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.cpp20
-rw-r--r--src/quicktemplates2/qquickstackview_p_p.h1
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;