9da807d
From 0ab5784208ee7c531933ff36200998e8ff494465 Mon Sep 17 00:00:00 2001
faff1df
From: Fabian Kosmale <fabian.kosmale@qt.io>
faff1df
Date: Wed, 20 Jul 2022 11:44:43 +0200
9da807d
Subject: [PATCH 16/31] QQuickState::when: handle QJSValue properties correctly
faff1df
faff1df
If one assigns a binding whose evaluation results in a QJSValue, care
faff1df
must be take to correctly convert it into a bool. Instead of directly
faff1df
using QVariant::value<bool>, one needs to first extract the QJSValue,
faff1df
and only convert it to bool afterwards.
faff1df
This is necessary due to the custom binding evaluation we're doing to
faff1df
avoid state oscillation.
faff1df
Amends a8c729d83979fb0b9939044d246e73b1d578e65b.
faff1df
faff1df
Fixes: QTBUG-105000
faff1df
Pick-to: 6.4 6.3 6.2 5.15
faff1df
Change-Id: I4b093b48edecf9e0f09d2b54d10c2ff527f24ac3
faff1df
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
faff1df
(cherry picked from commit 2c31d25a44b1221c151681e1bb68ef78618e0166)
faff1df
---
faff1df
 src/quick/util/qquickstategroup.cpp            | 10 ++++++++--
faff1df
 .../quick/qquickstates/data/jsValueWhen.qml    | 18 ++++++++++++++++++
faff1df
 .../quick/qquickstates/tst_qquickstates.cpp    | 11 +++++++++++
faff1df
 3 files changed, 37 insertions(+), 2 deletions(-)
faff1df
 create mode 100644 tests/auto/quick/qquickstates/data/jsValueWhen.qml
faff1df
faff1df
diff --git a/src/quick/util/qquickstategroup.cpp b/src/quick/util/qquickstategroup.cpp
faff1df
index 7cb3138618..f732b1eb4a 100644
faff1df
--- a/src/quick/util/qquickstategroup.cpp
faff1df
+++ b/src/quick/util/qquickstategroup.cpp
faff1df
@@ -381,8 +381,14 @@ bool QQuickStateGroupPrivate::updateAutoState()
faff1df
                 const auto potentialWhenBinding = QQmlPropertyPrivate::binding(whenProp);
faff1df
                 // if there is a binding, the value in when might not be up-to-date at this point
faff1df
                 // so we manually reevaluate the binding
faff1df
-                if (auto abstractBinding = dynamic_cast<QQmlBinding *>(potentialWhenBinding))
faff1df
-                    whenValue = abstractBinding->evaluate().toBool();
faff1df
+                if (auto abstractBinding = dynamic_cast<QQmlBinding *>(potentialWhenBinding)) {
faff1df
+                    QVariant evalResult = abstractBinding->evaluate();
faff1df
+                    if (evalResult.userType() == qMetaTypeId<QJSValue>())
faff1df
+                        whenValue = evalResult.value<QJSValue>().toBool();
faff1df
+                    else
faff1df
+                        whenValue = evalResult.toBool();
faff1df
+                }
faff1df
+
faff1df
                 if (whenValue) {
faff1df
                     if (stateChangeDebug())
faff1df
                         qWarning() << "Setting auto state due to expression";
faff1df
diff --git a/tests/auto/quick/qquickstates/data/jsValueWhen.qml b/tests/auto/quick/qquickstates/data/jsValueWhen.qml
faff1df
new file mode 100644
faff1df
index 0000000000..6d5eb1600c
faff1df
--- /dev/null
faff1df
+++ b/tests/auto/quick/qquickstates/data/jsValueWhen.qml
faff1df
@@ -0,0 +1,18 @@
faff1df
+import QtQuick 2.15
faff1df
+
faff1df
+Item {
faff1df
+    id: root
faff1df
+    property var prop: null
faff1df
+    property bool works: false
faff1df
+    states: [
faff1df
+        State {
faff1df
+            name: "mystate"
faff1df
+            when: root.prop
faff1df
+            PropertyChanges {
faff1df
+                target: root
faff1df
+                works: "works"
faff1df
+            }
faff1df
+        }
faff1df
+    ]
faff1df
+    Component.onCompleted: root.prop = new Object
faff1df
+}
faff1df
diff --git a/tests/auto/quick/qquickstates/tst_qquickstates.cpp b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
faff1df
index aa55b42935..26e86672b0 100644
faff1df
--- a/tests/auto/quick/qquickstates/tst_qquickstates.cpp
faff1df
+++ b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
faff1df
@@ -188,6 +188,7 @@ private slots:
faff1df
     void revertListMemoryLeak();
faff1df
     void duplicateStateName();
faff1df
     void trivialWhen();
faff1df
+    void jsValueWhen();
faff1df
     void noStateOsciallation();
faff1df
     void parentChangeCorrectReversal();
faff1df
     void revertNullObjectBinding();
faff1df
@@ -1734,6 +1735,16 @@ void tst_qquickstates::trivialWhen()
faff1df
     QVERIFY(c.create());
faff1df
 }
faff1df
 
faff1df
+void tst_qquickstates::jsValueWhen()
faff1df
+{
faff1df
+    QQmlEngine engine;
faff1df
+
faff1df
+    QQmlComponent c(&engine, testFileUrl("jsValueWhen.qml"));
faff1df
+    QScopedPointer<QObject> root(c.create());
faff1df
+    QVERIFY(root);
faff1df
+    QVERIFY(root->property("works").toBool());
faff1df
+}
faff1df
+
faff1df
 void tst_qquickstates::noStateOsciallation()
faff1df
 {
faff1df
    QQmlEngine engine;
faff1df
-- 
9da807d
2.43.0
faff1df