JS Closures in Signal handlers
-
Using Qt Quick 2.1, after investing a good amount of time in debugging a refactor to some qml code I've noted a bug triggered by a nuanced behavior of how closures are constructed in signal handlers
I have some code that looks like the following:
// QML user defined component Foo.qml BaseUserType { //... signal somethingHappened(string description) //... }
// QML user defined component BarOne.qml Foo { onSomethingHappened: { console.log(description) } }
BarOne.qml appears to work fine. When the signal somethingHappened("blah") is emitted, the handler executes and prints "blah".
// QML user defined component BarTwo.qml Foo { function processSomethingHappened(callback) { //... do other stuff first if (callback) { callback() } } onSomethingHappened: { processSomethingHappened(function() { console.log(description) }) } }
BarTwo.qml does not properly function. When the signal somethingHappened("blah") is emitted, the handler executes and description is undefined. My take away was that the variable 'description' was not captured in the JS closure of my anonymous function, which had me questioning if closures work different in QML's JS subset. The last test really threw me off though...
// QML user defined component BarThree.qml Foo { function processSomethingHappened(callback, argument) { //... do other stuff first if (callback) { callback(argument) } } onSomethingHappened: { var tmp = description processSomethingHappened( function(argument) { console.log(description) console.log(argument) console.log(tmp) }, tmp ) } }
On emission of somethingHappened("blah") in this case I am seeing all 3 items (including 'description') print "blah" which means that where 'description' wasn't captured in the closure of the previous example, it is in this case, presumably because the QtQuick engine had to evaluate the argument in the original closure of the signal handler or something.
Is this a bug in QML? If so, is it corrected in newer versions? If not, is there documentation somewhere explaining the nuance of how closures are binded in QML's subset of JS?