Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Unsolved JS Closures in Signal handlers

    QML and Qt Quick
    1
    1
    245
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • C
      corruptedsyntax last edited by

      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?

      1 Reply Last reply Reply Quote 0
      • First post
        Last post