aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2022-07-20 11:44:43 +0200
committerUlf Hermann <ulf.hermann@qt.io>2023-09-09 10:41:14 +0200
commit39d756b213683de294734e9628f11365053adf68 (patch)
treeec5d6ad58c220cc4ece2006dcb5c46abd4b8ffa4
parent335e2f005f1f604c670e1bb602280966b7739c3b (diff)
QQuickState::when: handle QJSValue properties correctly
If one assigns a binding whose evaluation results in a QJSValue, care must be take to correctly convert it into a bool. Instead of directly using QVariant::value<bool>, one needs to first extract the QJSValue, and only convert it to bool afterwards. This is necessary due to the custom binding evaluation we're doing to avoid state oscillation. Amends a8c729d83979fb0b9939044d246e73b1d578e65b. Fixes: QTBUG-105000 Change-Id: I4b093b48edecf9e0f09d2b54d10c2ff527f24ac3 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> (cherry picked from commit 2c31d25a44b1221c151681e1bb68ef78618e0166) Reviewed-by: Semih Yavuz <semih.yavuz@qt.io>
-rw-r--r--src/quick/util/qquickstategroup.cpp12
-rw-r--r--tests/auto/quick/qquickstates/data/jsValueWhen.qml18
-rw-r--r--tests/auto/quick/qquickstates/tst_qquickstates.cpp11
3 files changed, 39 insertions, 2 deletions
diff --git a/src/quick/util/qquickstategroup.cpp b/src/quick/util/qquickstategroup.cpp
index f2af12b81d..fedacbb8df 100644
--- a/src/quick/util/qquickstategroup.cpp
+++ b/src/quick/util/qquickstategroup.cpp
@@ -381,8 +381,16 @@ bool QQuickStateGroupPrivate::updateAutoState()
const auto potentialWhenBinding = QQmlPropertyPrivate::binding(whenProp);
// if there is a binding, the value in when might not be up-to-date at this point
// so we manually reevaluate the binding
- if (auto abstractBinding = dynamic_cast<QQmlBinding *>(potentialWhenBinding))
- whenValue = abstractBinding->evaluate().toBool();
+ if (auto binding = dynamic_cast<QQmlBinding *>(potentialWhenBinding)) {
+ if (binding->context() && binding->context()->isValid()) {
+ QVariant evalResult = binding->evaluate();
+ if (evalResult.userType() == qMetaTypeId<QJSValue>())
+ whenValue = evalResult.value<QJSValue>().toBool();
+ else
+ whenValue = evalResult.toBool();
+ }
+ }
+
if (whenValue) {
if (stateChangeDebug())
qWarning() << "Setting auto state due to expression";
diff --git a/tests/auto/quick/qquickstates/data/jsValueWhen.qml b/tests/auto/quick/qquickstates/data/jsValueWhen.qml
new file mode 100644
index 0000000000..6d5eb1600c
--- /dev/null
+++ b/tests/auto/quick/qquickstates/data/jsValueWhen.qml
@@ -0,0 +1,18 @@
+import QtQuick 2.15
+
+Item {
+ id: root
+ property var prop: null
+ property bool works: false
+ states: [
+ State {
+ name: "mystate"
+ when: root.prop
+ PropertyChanges {
+ target: root
+ works: "works"
+ }
+ }
+ ]
+ Component.onCompleted: root.prop = new Object
+}
diff --git a/tests/auto/quick/qquickstates/tst_qquickstates.cpp b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
index aa55b42935..26e86672b0 100644
--- a/tests/auto/quick/qquickstates/tst_qquickstates.cpp
+++ b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
@@ -188,6 +188,7 @@ private slots:
void revertListMemoryLeak();
void duplicateStateName();
void trivialWhen();
+ void jsValueWhen();
void noStateOsciallation();
void parentChangeCorrectReversal();
void revertNullObjectBinding();
@@ -1734,6 +1735,16 @@ void tst_qquickstates::trivialWhen()
QVERIFY(c.create());
}
+void tst_qquickstates::jsValueWhen()
+{
+ QQmlEngine engine;
+
+ QQmlComponent c(&engine, testFileUrl("jsValueWhen.qml"));
+ QScopedPointer<QObject> root(c.create());
+ QVERIFY(root);
+ QVERIFY(root->property("works").toBool());
+}
+
void tst_qquickstates::noStateOsciallation()
{
QQmlEngine engine;