Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using ownKeys trap for custom objects not working #2153

Open
adam-veego opened this issue Jul 23, 2019 · 3 comments
Open

Using ownKeys trap for custom objects not working #2153

adam-veego opened this issue Jul 23, 2019 · 3 comments
Labels

Comments

@adam-veego
Copy link

adam-veego commented Jul 23, 2019

Hey,

I have some kind of a custom object that uses proxy to virtualize properties and pass the properties access to an inner handler, so writing a.b.c.d will access each of the levels one by one with the getter function and push the next inner object (or final leaf value) to the stack along with its own proxy and other things. However, when I trap ownKeys for enumeration, to use in for-in clauses, my returned properties array seems to be ignored, and no cycle of the for loop ever runs.

I read this may have to do with the absence of getOwnPropertyDescriptor trap. Is it actually that as long as this trap is not handled by duktape, whatever returned in ownKeys is meaningless and for-in will never be executed for customized properties of user-implemented objects? Is there a different way to implement that while still using proxies? I cannot define each separate property of the objects explicitly, because they are dynamic - the usage of general getters and setters is essential for this specific purpose.

Both calling duk_def_prop for each property in each access to the custom object did not resolve the problem, even calling duk_get_prop_desc for each property of the object immediately afterwards does not even return what I just added. Also adding has trap to the proxy object and having it always return TRUE had no effect whatsoever.

I guess what I'm doing is pretty unusual and may seem a bit weird but it enables necessary semantics of access to internal data structures through javascript. Is there a solution currently supported? Am I doing something wrong and using the correct solution improperly? Or should I give up the usage of for-in clauses for this purpose with the current version of duktape.

Thanks.

@svaarala
Copy link
Owner

As you noted, the values returned by ownKeys must also exist in the target object (https://www.ecma-international.org/ecma-262/10.0/index.html#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys):

duk> O = {foo:1, bar:2, quux: 3}
= {foo:1,bar:2,quux:3}
duk> P = new Proxy(O, { ownKeys: function () { return ['foo', 'bar', 'quux', 'nosuch'] } })
= {foo:1,bar:2,quux:3}
duk> for (var i in P) { print(i); }
foo
bar
quux
= undefined

In the above, 'nosuch' does not exist in the target so it is not enumerated.

To virtualize enumeration one would need to define a "getOwnPropertyDescriptor" trap, but unfortunately Duktape doesn't support it at present.

Or should I give up the usage of for-in clauses for this purpose with the current version of duktape.

Unfortunately so :/

@adam-veego
Copy link
Author

Thank you for the quick and to the point reply. How difficult would it be to implement this trap, or even locally make a small custom code change to bypass the ECMA specification? This may be one pretty significant thing that enables duktape to serve as a fast scripting tool that utilizes internal interfaces of generic platforms, although I understand the way I'm using it is probably unusual.

@svaarala
Copy link
Owner

Adding specific support for the trap for enumeration would not be too difficult, but it also affects other places. Some of the existing Proxy limitations will need some reworking rather than incremental addition of functionality, so I'll probably address this and the remaining limitations in a larger rework.

As for the use case, virtualizing enumeration is IMO not a very unusual use case, so I can definitely understand why it would be useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants