Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-113721

JS Proxy Object cannot proxy function properties

    XMLWordPrintable

Details

    • Windows

    Description

      I am attempting to Proxy a simple JS object with a "name" property, however since Proxy objects are implemented as inheriting from function objects in QV4 (as a hack according to https://github.com/qt/qtdeclarative/blob/6d03f536bf10ccb0d6eedddd6426c250aa9657cf/src/qml/jsruntime/qv4proxy_p.h#L52) any property of a function cannot be proxied.

      Here's a simple example to show what I mean:

      // JS Proxy Qt issue
      // "name" property is always empty and "toString" returns function not "hello world3".
      
      // This is the simple object that we are attempting to proxy.
      const testTarget = {
        "name": "hello world",
        "test": "hello world2",
        "toString": "hello world3",
      }
      
      // This takes some target JS object and wraps it in a Proxy.
      // This Proxy is a simple passthrough proxy so should be invisible when used.
      function wrapInProxy(targetObject) {
        const result = new Proxy(targetObject, {
          get(target, prop, receiver) {
            const value = target[prop];
      
            // This is required to call a function property with the correct "this".
            if (value instanceof Function) {
              return function (...args) {
                return value.apply(this === receiver ? target : this, args);
              };
            }
            return value;
          },
        });
        return result;
      }
      
      // Create our wrapped target object
      let wrapped = wrapInProxy(testTarget, {})
      
      // Incorrect -> TypeError: Type error
      console.log("wrapped:", wrapped)
      
      // Incorrect should be "hello world" but is "".
      console.log("wrapped.name:", wrapped.name)
      console.log("wrapped['name']:", wrapped["name"])
      
      // Correct "hello world2".
      console.log("wrapped.test:", wrapped.test)
      console.log("wrapped['test']:", wrapped["test"])
      
      // Incorrect gives "function toString() { [native code] }" instead of "hello world3"
      console.log("wrapped.toString:", wrapped.toString)
      console.log("wrapped['toString']:", wrapped["toString"])
      

      Note the above logic works as I would expect in FireFox and Chrome.

      I will say this this causes an issue that is very hard to debug unless you know Qt implements Proxies as Functions under the hood as any property which is not exposed on function objects work just fine and at least some of the time I am also able to get "name" to work when calling from c++.

      Attachments

        1. QTBUG-113721_QML.tar.gz
          4 kB
          Amanda Hamblin-True
        2. QTBUG-113721.tar.gz
          4 kB
          Amanda Hamblin-True
        3. stacktrace TypeError.txt
          3 kB
          Amanda Hamblin-True

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              qtqmlteam Qt Qml Team User
              haiku Ollie Dawes
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:

                Gerrit Reviews

                  There are no open Gerrit changes