aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-03-20 12:46:58 +0100
committerAapo Keskimolo <aapo.keskimolo@qt.io>2018-04-16 17:52:13 +0000
commit4909773f8162de49830d65e886747c11fff72934 (patch)
treeb5777ddbe5ada52afe3871e90085881e8b03d546 /tests
parent8e2cfa1d77dd4568a126f5ed5736dfef844a28ef (diff)
Fix calling Qt.binding() on bound functions
Calling Qt.binding() on a bound function object is a valid use case and used to work until Qt 5.8. The problem was that we optimized the code in QQmlBinding and QQmlJavascriptExpression to directly work on a QV4::Function, so this wouldn't work anymore. To fix this make sure recursive calls to Function.bind() are unrolled (so that the BoundFunction's target is never a bound function itself), then add the bound function as an optional member to the QQmlBinding and use it's bound arguments if present. Task-number: QTBUG-61927 Change-Id: I472214ddd82fc2a1212efd9b769861fc43d2ddaf Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp13
-rw-r--r--tests/auto/qml/qqmlecmascript/data/bindingBoundFunctions.qml34
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp12
3 files changed, 59 insertions, 0 deletions
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index e62e4a0980..f862cdb048 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -129,6 +129,7 @@ private slots:
void arraySort();
void lookupOnDisappearingProperty();
void arrayConcat();
+ void recursiveBoundFunctions();
void qRegExpInport_data();
void qRegExpInport();
@@ -3022,6 +3023,18 @@ void tst_QJSEngine::arrayConcat()
QCOMPARE(v.toString(), QString::fromLatin1("6,10,11,12"));
}
+void tst_QJSEngine::recursiveBoundFunctions()
+{
+
+ QJSEngine eng;
+ QJSValue v = eng.evaluate("function foo(x, y, z)"
+ "{ return this + x + y + z; }"
+ "var bar = foo.bind(-1, 10);"
+ "var baz = bar.bind(-2, 20);"
+ "baz(30)");
+ QCOMPARE(v.toInt(), 59);
+}
+
static QRegExp minimal(QRegExp r) { r.setMinimal(true); return r; }
void tst_QJSEngine::qRegExpInport_data()
diff --git a/tests/auto/qml/qqmlecmascript/data/bindingBoundFunctions.qml b/tests/auto/qml/qqmlecmascript/data/bindingBoundFunctions.qml
new file mode 100644
index 0000000000..8dbd2fd3d9
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/bindingBoundFunctions.qml
@@ -0,0 +1,34 @@
+import QtQuick 2.6
+
+QtObject {
+ property bool success: false
+ property var num: 100
+ property var simple: 0
+ property var complex: 0
+
+
+ Component.onCompleted: {
+ function s(x) {
+ return x
+ }
+ function c(x) {
+ return x + num
+ }
+
+ var bound = s.bind(undefined, 100)
+ simple = Qt.binding(bound)
+ if (simple != 100)
+ return;
+ var bound = c.bind(undefined, 100)
+ complex = Qt.binding(bound);
+
+ if (complex != 200)
+ return;
+ num = 0;
+ if (complex != 100)
+ return;
+
+ print("success!!!");
+ success = true;
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index c0cf123243..f40a9758f7 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -289,6 +289,7 @@ private slots:
void withStatement();
void tryStatement();
void replaceBinding();
+ void bindingBoundFunctions();
void deleteRootObjectInCreation();
void onDestruction();
void onDestructionViaGC();
@@ -7247,6 +7248,17 @@ void tst_qqmlecmascript::replaceBinding()
delete obj;
}
+void tst_qqmlecmascript::bindingBoundFunctions()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("bindingBoundFunctions.qml"));
+ QObject *obj = c.create();
+ QVERIFY(obj != nullptr);
+
+ QVERIFY(obj->property("success").toBool());
+ delete obj;
+}
+
void tst_qqmlecmascript::deleteRootObjectInCreation()
{
{