Don't crash when using unshift on a states group

Amends 7e4b179430, which implements
Array.unshift by first appending nullptrs, then replacing those with
the existing previous items, and then replacing the old positions (now
nullptr) with the items to be prepended.

This assumes that the append implementation of a list property accepts
nullptr items, which QQuickStateGroup's implementation didn't.

Note: QQuickStateGroupPrivate::append_transition also doesn't append
a nullptr, and it is likely that other list property implementations
also make append(nullptr) a no-op.

Fixes: QTBUG-114858
Change-Id: Ib0459c2d12be5deb42563b5298f840d8ba641930
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
(cherry picked from commit f905876d6c)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Volker Hilsheimer 2023-06-28 13:56:22 +02:00 committed by Qt Cherry-pick Bot
parent bd08147028
commit 7eb239d43e
2 changed files with 23 additions and 12 deletions

View File

@ -96,8 +96,10 @@ QQuickStateGroup::QQuickStateGroup(QObject *parent)
QQuickStateGroup::~QQuickStateGroup()
{
Q_D(const QQuickStateGroup);
for (int i = 0; i < d->states.size(); ++i)
d->states.at(i)->setStateGroup(nullptr);
for (int i = 0; i < d->states.size(); ++i) {
if (d->states.at(i))
d->states.at(i)->setStateGroup(nullptr);
}
if (d->nullState)
d->nullState->setStateGroup(nullptr);
}
@ -143,11 +145,9 @@ QQmlListProperty<QQuickState> QQuickStateGroup::statesProperty()
void QQuickStateGroupPrivate::append_state(QQmlListProperty<QQuickState> *list, QQuickState *state)
{
QQuickStateGroup *_this = static_cast<QQuickStateGroup *>(list->object);
if (state) {
_this->d_func()->states.append(state);
_this->d_func()->states.append(state);
if (state)
state->setStateGroup(_this);
}
}
qsizetype QQuickStateGroupPrivate::count_state(QQmlListProperty<QQuickState> *list)
@ -167,7 +167,8 @@ void QQuickStateGroupPrivate::clear_states(QQmlListProperty<QQuickState> *list)
QQuickStateGroup *_this = static_cast<QQuickStateGroup *>(list->object);
_this->d_func()->setCurrentStateInternal(QString(), true);
for (qsizetype i = 0; i < _this->d_func()->states.size(); ++i) {
_this->d_func()->states.at(i)->setStateGroup(nullptr);
if (_this->d_func()->states.at(i))
_this->d_func()->states.at(i)->setStateGroup(nullptr);
}
_this->d_func()->states.clear();
}
@ -178,10 +179,11 @@ void QQuickStateGroupPrivate::replace_states(QQmlListProperty<QQuickState> *list
auto *d = self->d_func();
auto *oldState = d->states.at(index);
if (oldState != state) {
oldState->setStateGroup(nullptr);
if (oldState)
oldState->setStateGroup(nullptr);
state->setStateGroup(self);
d->states.replace(index, state);
if (d->currentState == oldState->name())
if (!oldState || d->currentState == oldState->name())
d->setCurrentStateInternal(state->name(), true);
}
}

View File

@ -1,12 +1,21 @@
import QtQml
import QtQuick 2.7
import Test
TestItem {
id: testItem
Item {
id: root
TestItem {
id: testItem
}
Component.onCompleted : {
testItem.data.push(null);
testItem.data.length = 5;
testItem.data.unshift(null);
var state = Qt.createQmlObject( "import QtQuick 2.7; State{ name: 'MyState' }", root, "dynamicState" );
root.states.length = 5;
root.states.push(null);
root.states.unshift(state);
}
}