diff options
author | Erik Verbruggen <erik.verbruggen@qt.io> | 2018-03-19 13:14:13 +0100 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2018-03-20 09:38:27 +0000 |
commit | 22b13921f8067f8a93164875a4ad59bed85b0400 (patch) | |
tree | 4422ba520a96c7c41466426b3ae26ac15816b52d /tests/auto/qml/qmlcachegen | |
parent | 971292128b292052ef935da67a5d04fb5a3753f4 (diff) |
Handle function expressions as signal handlers
There are two ways to use function expressions on the right-hand side
of bindings:
property var somethingPressed
somethingPressed: function() { /* ..press something else.. */ }
signal buttonPressed
onButtonPressed: function() { /* ..handle buttonPress.. */ }
In the former case, it declares a property that holds a function. So on
initialization, the right-hand side of the binding returns a closure
that gets assigned to the property 'somethingPressed'.
In the latter case, the signal handler is explicitly marked as a
function for clarity. So, the handler should not be returning the
closure, but the handler should *be* the closure.
In general, it is not possible to detect if the left-hand side is a
property or a signal handler when generating QML cache files ahead of
time. So for this case, we mark the function as only returning a
closure. Then when instantiating the object, we check if it is a signal
handler, and if the handler is marked as only returning a closure. If
so, we set that closure to be the signal handler.
Task-number: QTBUG-57043
Task-number: QTBUG-50328
Change-Id: I3008ddd847e30b7d0adef07344a326f84d85f1ba
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'tests/auto/qml/qmlcachegen')
-rw-r--r-- | tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp index 2f5ff0022e..e36edca699 100644 --- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp +++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp @@ -47,6 +47,7 @@ private slots: void signalHandlerParameters(); void errorOnArgumentsInSignalHandler(); void aheadOfTimeCompilation(); + void functionExpressions(); void workerScripts(); }; @@ -292,6 +293,69 @@ void tst_qmlcachegen::workerScripts() QTRY_VERIFY(obj->property("success").toBool()); } +void tst_qmlcachegen::functionExpressions() +{ + QTemporaryDir tempDir; + QVERIFY(tempDir.isValid()); + + const auto writeTempFile = [&tempDir](const QString &fileName, const char *contents) { + QFile f(tempDir.path() + '/' + fileName); + const bool ok = f.open(QIODevice::WriteOnly | QIODevice::Truncate); + Q_ASSERT(ok); + f.write(contents); + return f.fileName(); + }; + + const QString testFilePath = writeTempFile( + "test.qml", + "import QtQuick 2.0\n" + "Item {\n" + " id: di\n" + " \n" + " property var f\n" + " property bool f_called: false\n" + " f : function() { f_called = true }\n" + " \n" + " signal g\n" + " property bool g_handler_called: false\n" + " onG: function() { g_handler_called = true }\n" + " \n" + " signal h(int i)\n" + " property bool h_connections_handler_called: false\n" + " Connections {\n" + " target: di\n" + " onH: function(magic) { h_connections_handler_called = (magic == 42)\n }\n" + " }\n" + " \n" + " function runTest() { \n" + " f()\n" + " g()\n" + " h(42)\n" + " }\n" + "}"); + + QVERIFY(generateCache(testFilePath)); + + const QString cacheFilePath = testFilePath + QLatin1Char('c'); + QVERIFY(QFile::exists(cacheFilePath)); + QVERIFY(QFile::remove(testFilePath)); + + QQmlEngine engine; + CleanlyLoadingComponent component(&engine, QUrl::fromLocalFile(testFilePath)); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(!obj.isNull()); + + QCOMPARE(obj->property("f_called").toBool(), false); + QCOMPARE(obj->property("g_handler_called").toBool(), false); + QCOMPARE(obj->property("h_connections_handler_called").toBool(), false); + + QMetaObject::invokeMethod(obj.data(), "runTest"); + + QCOMPARE(obj->property("f_called").toBool(), true); + QCOMPARE(obj->property("g_handler_called").toBool(), true); + QCOMPARE(obj->property("h_connections_handler_called").toBool(), true); +} + QTEST_GUILESS_MAIN(tst_qmlcachegen) #include "tst_qmlcachegen.moc" |