Re: Type of property names, as seen by proxy traps
Follow-up: I updated http://wiki.ecmascript.org/doku.php?id=harmony:proxies_semantics with a more precise specification of the default behavior of all derived traps. This should also resolve the double-coercion issue with Object.keys. In summary: - for has, hasOwn and get it's easy to fall back on specifications of existing built-ins (Object.[[HasProperty]] for has, Object.prototype.hasOwnProperty for hasOwn and Object.[[Get]] for get) - for set, falling back on Object.[[Put]] is not ideal, as this built-in performs redundant invocations of [[Get{Own}Property]] through [[CanPut]]. Starting from Object.[[Put]] and the default set trap as specified in JS itself, I formulated a new DefaultPut algorithm that avoids this redundancy. - for keys and enumerate, there is no proper built-in to fall back on. I added two algorithms (FilterEnumerableOwn and FilterEnumerable) that take the uncoerced result of the get{Own}PropertyNames trap, and filter out the enumerable properties, specced after Array.prototype.filter. I also updated http://wiki.ecmascript.org/doku.php?id=harmony:proxies#trap_defaults so that it is clear that that section is only a non-normative description of how derived traps could be implemented in pure Javascript. Cheers, Tom 2011/7/8 Tom Van Cutsem tomvc...@gmail.com I believe the alternative that David is talking about is the following (pending the acceptance of http://wiki.ecmascript.org/doku.php?id=strawman:handler_access_to_proxy) keys: function(proxy) { return Object.getOwnPropertyNames(proxy).filter( function (name) { return Object.getOwnPropertyDescriptor(proxy, name).enumerable }); } (assuming that Object here refers to the built-in Object) With this definition, I don't see the need for double coercion: the handler's getOwnPropertyNames trap is called, and its result is coerced. Then, the proxy implementation knows that each of the above |name|s passed to getOwnPropertyDescriptor will be a String already, so it doesn't need to coerce again. Finally, `keys' does not need to coerce its own result array, since it is simply a filtered version of an already fresh, coerced array. Perhaps all self-sends to fundamental traps should be expressed in terms of the operation that causes the trap, rather than a direct trap invocation. Similar issues could arise in the default 'set' trap behavior when it calls 'this.defineProperty' rather than 'Object.defineProperty(proxy,...)'. 2011/7/7 Andreas Rossberg rossb...@google.com On 7 July 2011 19:35, David Bruant david.bru...@labri.fr wrote: No, with the current keys default trap (calling this.getOwnPropertyNames()) there is no double conversion. Only one at the exit of the keys trap. There would be 2 conversions if the keys trap had the proxy argument (based on http://wiki.ecmascript.org/doku.php?id=strawman:handler_access_to_proxy) and if internally, the default keys trap was calling Object.getOwnPropertyNames(proxy) (which would call the trap and do type coercion). But the current implementation and a type coercion only when going out of traps would do double-conversion. not. would not do double-conversion, sorry. I thought the fix we were discussing was changing the `keys' default trap from keys: function() { return this.getOwnPropertyNames().filter( function (name) { return this.getOwnPropertyDescriptor(name).enumerable }.bind(this)); } to something along the lines of keys: function() { return this.getOwnPropertyNames().filter( function (name) { return this.getOwnPropertyDescriptor('' + name).enumerable }.bind(this)); } That would fix passing non-strings to the getOwnPropertyDescriptor trap, but introduce double conversions when you invoke Object.keys. I'm not sure what alternative you are proposing now. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Type of property names, as seen by proxy traps
Very much appreciated. Given all the nasty mutability in JS, I think for the non-normative JS implementations you also might want to note that it assumes that nobody has hampered with the primordial Object object. /Andreas On 14 July 2011 12:34, Tom Van Cutsem tomvc...@gmail.com wrote: Follow-up: I updated http://wiki.ecmascript.org/doku.php?id=harmony:proxies_semantics with a more precise specification of the default behavior of all derived traps. This should also resolve the double-coercion issue with Object.keys. In summary: - for has, hasOwn and get it's easy to fall back on specifications of existing built-ins (Object.[[HasProperty]] for has, Object.prototype.hasOwnProperty for hasOwn and Object.[[Get]] for get) - for set, falling back on Object.[[Put]] is not ideal, as this built-in performs redundant invocations of [[Get{Own}Property]] through [[CanPut]]. Starting from Object.[[Put]] and the default set trap as specified in JS itself, I formulated a new DefaultPut algorithm that avoids this redundancy. - for keys and enumerate, there is no proper built-in to fall back on. I added two algorithms (FilterEnumerableOwn and FilterEnumerable) that take the uncoerced result of the get{Own}PropertyNames trap, and filter out the enumerable properties, specced after Array.prototype.filter. I also updated http://wiki.ecmascript.org/doku.php?id=harmony:proxies#trap_defaults so that it is clear that that section is only a non-normative description of how derived traps could be implemented in pure Javascript. Cheers, Tom 2011/7/8 Tom Van Cutsem tomvc...@gmail.com I believe the alternative that David is talking about is the following (pending the acceptance of http://wiki.ecmascript.org/doku.php?id=strawman:handler_access_to_proxy) keys: function(proxy) { return Object.getOwnPropertyNames(proxy).filter( function (name) { return Object.getOwnPropertyDescriptor(proxy, name).enumerable }); } (assuming that Object here refers to the built-in Object) With this definition, I don't see the need for double coercion: the handler's getOwnPropertyNames trap is called, and its result is coerced. Then, the proxy implementation knows that each of the above |name|s passed to getOwnPropertyDescriptor will be a String already, so it doesn't need to coerce again. Finally, `keys' does not need to coerce its own result array, since it is simply a filtered version of an already fresh, coerced array. Perhaps all self-sends to fundamental traps should be expressed in terms of the operation that causes the trap, rather than a direct trap invocation. Similar issues could arise in the default 'set' trap behavior when it calls 'this.defineProperty' rather than 'Object.defineProperty(proxy,...)'. 2011/7/7 Andreas Rossberg rossb...@google.com On 7 July 2011 19:35, David Bruant david.bru...@labri.fr wrote: No, with the current keys default trap (calling this.getOwnPropertyNames()) there is no double conversion. Only one at the exit of the keys trap. There would be 2 conversions if the keys trap had the proxy argument (based on http://wiki.ecmascript.org/doku.php?id=strawman:handler_access_to_proxy) and if internally, the default keys trap was calling Object.getOwnPropertyNames(proxy) (which would call the trap and do type coercion). But the current implementation and a type coercion only when going out of traps would do double-conversion. not. would not do double-conversion, sorry. I thought the fix we were discussing was changing the `keys' default trap from keys: function() { return this.getOwnPropertyNames().filter( function (name) { return this.getOwnPropertyDescriptor(name).enumerable }.bind(this)); } to something along the lines of keys: function() { return this.getOwnPropertyNames().filter( function (name) { return this.getOwnPropertyDescriptor('' + name).enumerable }.bind(this)); } That would fix passing non-strings to the getOwnPropertyDescriptor trap, but introduce double conversions when you invoke Object.keys. I'm not sure what alternative you are proposing now. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Type of property names, as seen by proxy traps
tampered, not hampered, of course... On 14 July 2011 12:52, Andreas Rossberg rossb...@google.com wrote: Very much appreciated. Given all the nasty mutability in JS, I think for the non-normative JS implementations you also might want to note that it assumes that nobody has hampered with the primordial Object object. /Andreas On 14 July 2011 12:34, Tom Van Cutsem tomvc...@gmail.com wrote: Follow-up: I updated http://wiki.ecmascript.org/doku.php?id=harmony:proxies_semantics with a more precise specification of the default behavior of all derived traps. This should also resolve the double-coercion issue with Object.keys. In summary: - for has, hasOwn and get it's easy to fall back on specifications of existing built-ins (Object.[[HasProperty]] for has, Object.prototype.hasOwnProperty for hasOwn and Object.[[Get]] for get) - for set, falling back on Object.[[Put]] is not ideal, as this built-in performs redundant invocations of [[Get{Own}Property]] through [[CanPut]]. Starting from Object.[[Put]] and the default set trap as specified in JS itself, I formulated a new DefaultPut algorithm that avoids this redundancy. - for keys and enumerate, there is no proper built-in to fall back on. I added two algorithms (FilterEnumerableOwn and FilterEnumerable) that take the uncoerced result of the get{Own}PropertyNames trap, and filter out the enumerable properties, specced after Array.prototype.filter. I also updated http://wiki.ecmascript.org/doku.php?id=harmony:proxies#trap_defaults so that it is clear that that section is only a non-normative description of how derived traps could be implemented in pure Javascript. Cheers, Tom 2011/7/8 Tom Van Cutsem tomvc...@gmail.com I believe the alternative that David is talking about is the following (pending the acceptance of http://wiki.ecmascript.org/doku.php?id=strawman:handler_access_to_proxy) keys: function(proxy) { return Object.getOwnPropertyNames(proxy).filter( function (name) { return Object.getOwnPropertyDescriptor(proxy, name).enumerable }); } (assuming that Object here refers to the built-in Object) With this definition, I don't see the need for double coercion: the handler's getOwnPropertyNames trap is called, and its result is coerced. Then, the proxy implementation knows that each of the above |name|s passed to getOwnPropertyDescriptor will be a String already, so it doesn't need to coerce again. Finally, `keys' does not need to coerce its own result array, since it is simply a filtered version of an already fresh, coerced array. Perhaps all self-sends to fundamental traps should be expressed in terms of the operation that causes the trap, rather than a direct trap invocation. Similar issues could arise in the default 'set' trap behavior when it calls 'this.defineProperty' rather than 'Object.defineProperty(proxy,...)'. 2011/7/7 Andreas Rossberg rossb...@google.com On 7 July 2011 19:35, David Bruant david.bru...@labri.fr wrote: No, with the current keys default trap (calling this.getOwnPropertyNames()) there is no double conversion. Only one at the exit of the keys trap. There would be 2 conversions if the keys trap had the proxy argument (based on http://wiki.ecmascript.org/doku.php?id=strawman:handler_access_to_proxy) and if internally, the default keys trap was calling Object.getOwnPropertyNames(proxy) (which would call the trap and do type coercion). But the current implementation and a type coercion only when going out of traps would do double-conversion. not. would not do double-conversion, sorry. I thought the fix we were discussing was changing the `keys' default trap from keys: function() { return this.getOwnPropertyNames().filter( function (name) { return this.getOwnPropertyDescriptor(name).enumerable }.bind(this)); } to something along the lines of keys: function() { return this.getOwnPropertyNames().filter( function (name) { return this.getOwnPropertyDescriptor('' + name).enumerable }.bind(this)); } That would fix passing non-strings to the getOwnPropertyDescriptor trap, but introduce double conversions when you invoke Object.keys. I'm not sure what alternative you are proposing now. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Type of property names, as seen by proxy traps
2011/7/7 David Herman dher...@mozilla.com 2011/7/6 Andreas Rossberg rossb...@google.com While putting together some test cases for Object.keys, I wondered: is it intended that property names are always passed to traps as strings? That is indeed the intent. Unless they are private name objects, right? I'm not sure. I briefly checked the private names proposal http://wiki.ecmascript.org/doku.php?id=harmony:private_name_objects and I think the detailed interaction with proxies still has to be fleshed out. The proposal does mention: All reflective operations that produce a property name, when reflecting on a private name, produce the name’s .public property instead of the name itself. Would the same hold for reflective operations that consume property names, such as handler traps? Cheers, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Type of property names, as seen by proxy traps
I'm not sure. I briefly checked the private names proposal http://wiki.ecmascript.org/doku.php?id=harmony:private_name_objects and I think the detailed interaction with proxies still has to be fleshed out. Sure, I'll be happy to work with you on this. The proposal does mention: All reflective operations that produce a property name, when reflecting on a private name, produce the name’s .public property instead of the name itself. Would the same hold for reflective operations that consume property names, such as handler traps? No, they would require the private name object. The idea here is that you need a reference to the private name to get access to its property. So you can't do any proxy operations on a private property if you don't have the private name object. But the proxy traps do not automatically hand out that reference to a handler trap, in case the trap didn't already have a reference to it (which would constitute a leak). Instead, it hands them the corresponding public key. This way, *if* the trap has a reference to the private key, it can identify which private name is being accessed. Otherwise, the trap can't conclude anything more than operation X was requested on *some* private name. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Type of property names, as seen by proxy traps
On Jul 8, 2011, at 7:17 AM, David Herman wrote: The proposal does mention: All reflective operations that produce a property name, when reflecting on a private name, produce the name’s .public property instead of the name itself. Would the same hold for reflective operations that consume property names, such as handler traps? No, they would require the private name object. I don't think that's what Tom was asking about, though. The proposal may simply be unclear in using produce instead of consume since the proxy mechanism does not produce private names in any generative sense when one writes p[q] for proxy p and private name q. Rather, the VM substitutes q.public for q when calling p's handler's relevant trap (getOwnPropertyDescriptor, get, ...). So there's no leak, as you note, and the owner of q is free to share it with trap implementations that should have access to it, so they can compare name == q.public, memoize in q.public in a weak map, etc. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Type of property names, as seen by proxy traps
Sorry, yes. Too early in the morning for me. :) Indeed, handler traps are exactly the place where the system *produces* names and hands them to handler traps which consume them, and that's where it must produce a public key rather than a private name object. Dave On Jul 8, 2011, at 8:20 AM, Brendan Eich wrote: On Jul 8, 2011, at 7:17 AM, David Herman wrote: The proposal does mention: All reflective operations that produce a property name, when reflecting on a private name, produce the name’s .public property instead of the name itself. Would the same hold for reflective operations that consume property names, such as handler traps? No, they would require the private name object. I don't think that's what Tom was asking about, though. The proposal may simply be unclear in using produce instead of consume since the proxy mechanism does not produce private names in any generative sense when one writes p[q] for proxy p and private name q. Rather, the VM substitutes q.public for q when calling p's handler's relevant trap (getOwnPropertyDescriptor, get, ...). So there's no leak, as you note, and the owner of q is free to share it with trap implementations that should have access to it, so they can compare name == q.public, memoize in q.public in a weak map, etc. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Type of property names, as seen by proxy traps
And just to be clear, I meant produce in the sense of producer/consumer relationship on the trap functions, not in the generative sense. Dave On Jul 8, 2011, at 8:40 AM, David Herman wrote: Sorry, yes. Too early in the morning for me. :) Indeed, handler traps are exactly the place where the system *produces* names and hands them to handler traps which consume them, and that's where it must produce a public key rather than a private name object. Dave On Jul 8, 2011, at 8:20 AM, Brendan Eich wrote: On Jul 8, 2011, at 7:17 AM, David Herman wrote: The proposal does mention: All reflective operations that produce a property name, when reflecting on a private name, produce the name’s .public property instead of the name itself. Would the same hold for reflective operations that consume property names, such as handler traps? No, they would require the private name object. I don't think that's what Tom was asking about, though. The proposal may simply be unclear in using produce instead of consume since the proxy mechanism does not produce private names in any generative sense when one writes p[q] for proxy p and private name q. Rather, the VM substitutes q.public for q when calling p's handler's relevant trap (getOwnPropertyDescriptor, get, ...). So there's no leak, as you note, and the owner of q is free to share it with trap implementations that should have access to it, so they can compare name == q.public, memoize in q.public in a weak map, etc. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Type of property names, as seen by proxy traps
Le 07/07/2011 13:11, Tom Van Cutsem a écrit : 2011/7/6 Andreas Rossberg rossb...@google.com mailto:rossb...@google.com While putting together some test cases for Object.keys, I wondered: is it intended that property names are always passed to traps as strings? That is indeed the intent. It seems like a reasonable assumption, but is not currently the case everywhere (e.g. the default implementation for `keys' can violate this assumption when passing names to this.getOwnPropertyDescriptor). How so? The default implementation for the keys trap relies on the return value of the getOwnPropertyNames() trap, whose return value is coerced to an array of Strings. The return value of the trap is. The return value of this.getOwnPropertyNames isn't. With a pure mapping from internal methods to trap, the trap call and handler.trap (this.trap) are the same. However, with invariant enforcement, they are different. Type coercion is a such an invariant enforcement (that actually could be added to FixedHandler). David Cheers, Tom /Andreas ___ es-discuss mailing list es-discuss@mozilla.org mailto:es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Type of property names, as seen by proxy traps
On 7 July 2011 13:11, Tom Van Cutsem tomvc...@gmail.com wrote: 2011/7/6 Andreas Rossberg rossb...@google.com While putting together some test cases for Object.keys, I wondered: is it intended that property names are always passed to traps as strings? That is indeed the intent. It seems like a reasonable assumption, but is not currently the case everywhere (e.g. the default implementation for `keys' can violate this assumption when passing names to this.getOwnPropertyDescriptor). How so? The default implementation for the keys trap relies on the return value of the getOwnPropertyNames() trap, whose return value is coerced to an array of Strings. Not quite. The coercion is taking place in Object.getOwnPropertyNames, but the default `keys' trap doesn't go through that, but instead calls the trap directly. Moreover, it has to do it like that, because it doesn't even have a reference to the proxy itself. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Type of property names, as seen by proxy traps
Le 07/07/2011 14:29, Andreas Rossberg a écrit : On 7 July 2011 13:11, Tom Van Cutsemtomvc...@gmail.com wrote: 2011/7/6 Andreas Rossbergrossb...@google.com It seems like a reasonable assumption, but is not currently the case everywhere (e.g. the default implementation for `keys' can violate this assumption when passing names to this.getOwnPropertyDescriptor). How so? The default implementation for the keys trap relies on the return value of the getOwnPropertyNames() trap, whose return value is coerced to an array of Strings. Not quite. The coercion is taking place in Object.getOwnPropertyNames, but the default `keys' trap doesn't go through that, but instead calls the trap directly. Moreover, it has to do it like that, because it doesn't even have a reference to the proxy itself. However, if we assume that the getOwnPropertyNames trap is able to do type coercion on its output, there is no reason for the keys trap to not do that too, regardless of how it was implemented. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Type of property names, as seen by proxy traps
On 7 July 2011 14:32, David Bruant david.bru...@labri.fr wrote: However, if we assume that the getOwnPropertyNames trap is able to do type coercion on its output, there is no reason for the keys trap to not do that too, regardless of how it was implemented. Yes, that's what I would propose, too. It's just a bit ugly that we have to do that in two places now. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Type of property names, as seen by proxy traps
Le 07/07/2011 14:40, Andreas Rossberg a écrit : On 7 July 2011 14:32, David Bruantdavid.bru...@labri.fr wrote: However, if we assume that the getOwnPropertyNames trap is able to do type coercion on its output, there is no reason for the keys trap to not do that too, regardless of how it was implemented. Yes, that's what I would propose, too. It's just a bit ugly that we have to do that in two places now. Three if counting the enumerate trap for for-in loops. Regardless of ugliness, it's necessary. keys and enumerate are derived traps. They have a default implementation for developer convenience, however, developers could decide to reimplement the trap and the proxy engine implementation have to enforce types anyway. Each trap has to be guarded independently. Derived traps as showed are written in JS for expository purposes. Engines will be free to optimize as they wish internally as long as the observed behavior is the same. Specifically, I think that type inference engines can be of a great help in ensuring that types are correct without having to pay the price of looking at every single element independently. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Type of property names, as seen by proxy traps
On 7 July 2011 15:09, David Bruant david.bru...@labri.fr wrote: Yes, that's what I would propose, too. It's just a bit ugly that we have to do that in two places now. Three if counting the enumerate trap for for-in loops. Regardless of ugliness, it's necessary. keys and enumerate are derived traps. They have a default implementation for developer convenience, however, developers could decide to reimplement the trap and the proxy engine implementation have to enforce types anyway. Each trap has to be guarded independently. Derived traps as showed are written in JS for expository purposes. Engines will be free to optimize as they wish internally as long as the observed behavior is the same. True, but optimizing that actually is more tricky than you might think, since in general it would change the semantics if an engine decided to call toString only once. It has to make sure that none of the names are objects, or at least none of their toString methods was modified and they are all free of side effects. Specifically, I think that type inference engines can be of a great help in ensuring that types are correct without having to pay the price of looking at every single element independently. I don't think that the type checks are the biggest cost. Doing the actual conversion several times for those cases where the type is _not_ string is potentially much more expensive. I guess it's fine if programmers suffer for returning objects as property names. But something like integers might be a valid use case. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Type of property names, as seen by proxy traps
2011/7/6 Andreas Rossberg rossb...@google.com While putting together some test cases for Object.keys, I wondered: is it intended that property names are always passed to traps as strings? That is indeed the intent. Unless they are private name objects, right? Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Type of property names, as seen by proxy traps
On 7 July 2011 16:12, David Bruant david.bru...@labri.fr wrote: Derived traps as showed are written in JS for expository purposes. Engines will be free to optimize as they wish internally as long as the observed behavior is the same. True, but optimizing that actually is more tricky than you might think, since in general it would change the semantics if an engine decided to call toString only once. It has to make sure that none of the names are objects, or at least none of their toString methods was modified and they are all free of side effects. Interesting. However, I'm not sure side-effects are a problem. - var o = {a:1, toString:function(){o.b = 12; return 'a'; }}; console.log(o[o], o.b); // 1, 12 on Firefox 5 - Here, o[o] triggers a side effect and that sound like the normal behavior. I'm not sure I understand what your example is intended to show. But consider this: var i = 0 var o = {toString: function() { ++i; return a } var p = Proxy.create({getOwnPropertyNames: function() { return [o] }, ...}) var k = Object.keys(p) // What's the value of i now? /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Type of property names, as seen by proxy traps
On Jul 7, 2011, at 8:32 AM, Andreas Rossberg wrote: On 7 July 2011 16:12, David Bruant david.bru...@labri.fr wrote: Derived traps as showed are written in JS for expository purposes. Engines will be free to optimize as they wish internally as long as the observed behavior is the same. True, but optimizing that actually is more tricky than you might think, since in general it would change the semantics if an engine decided to call toString only once. It has to make sure that none of the names are objects, or at least none of their toString methods was modified and they are all free of side effects. Interesting. However, I'm not sure side-effects are a problem. - var o = {a:1, toString:function(){o.b = 12; return 'a'; }}; console.log(o[o], o.b); // 1, 12 on Firefox 5 - Here, o[o] triggers a side effect and that sound like the normal behavior. I'm not sure I understand what your example is intended to show. But consider this: var i = 0 var o = {toString: function() { ++i; return a } var p = Proxy.create({getOwnPropertyNames: function() { return [o] }, ...}) var k = Object.keys(p) // What's the value of i now? Fresh tracemonkey tip js shell: js var i = 0 js var o = {toString: function() { ++i; return a }} js var p = Proxy.create({getOwnPropertyNames: function() { return [o] }, getOwnPropertyDescriptor: function() { return {value:42} }}) js var k = Object.keys(p) js i 1 Where would there be a double-conversion? /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Type of property names, as seen by proxy traps
On 7 July 2011 17:58, Brendan Eich bren...@mozilla.com wrote: On Jul 7, 2011, at 8:32 AM, Andreas Rossberg wrote: On 7 July 2011 16:12, David Bruant david.bru...@labri.fr wrote: Derived traps as showed are written in JS for expository purposes. Engines will be free to optimize as they wish internally as long as the observed behavior is the same. True, but optimizing that actually is more tricky than you might think, since in general it would change the semantics if an engine decided to call toString only once. It has to make sure that none of the names are objects, or at least none of their toString methods was modified and they are all free of side effects. Interesting. However, I'm not sure side-effects are a problem. - var o = {a:1, toString:function(){o.b = 12; return 'a'; }}; console.log(o[o], o.b); // 1, 12 on Firefox 5 - Here, o[o] triggers a side effect and that sound like the normal behavior. I'm not sure I understand what your example is intended to show. But consider this: var i = 0 var o = {toString: function() { ++i; return a } var p = Proxy.create({getOwnPropertyNames: function() { return [o] }, ...}) var k = Object.keys(p) // What's the value of i now? Fresh tracemonkey tip js shell: js var i = 0 js var o = {toString: function() { ++i; return a }} js var p = Proxy.create({getOwnPropertyNames: function() { return [o] }, getOwnPropertyDescriptor: function() { return {value:42} }}) js var k = Object.keys(p) js i 1 Where would there be a double-conversion? Well, with the canonical fix to the spec we discussed further up the thread (adding a conversion to string in the default trap for `keys') there would (have to) be. So my concern was that that is perhaps not the best fix, despite its simplicity. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Type of property names, as seen by proxy traps
Le 07/07/2011 18:05, Andreas Rossberg a écrit : On 7 July 2011 17:58, Brendan Eich bren...@mozilla.com wrote: On Jul 7, 2011, at 8:32 AM, Andreas Rossberg wrote: On 7 July 2011 16:12, David Bruant david.bru...@labri.fr wrote: Derived traps as showed are written in JS for expository purposes. Engines will be free to optimize as they wish internally as long as the observed behavior is the same. True, but optimizing that actually is more tricky than you might think, since in general it would change the semantics if an engine decided to call toString only once. It has to make sure that none of the names are objects, or at least none of their toString methods was modified and they are all free of side effects. Interesting. However, I'm not sure side-effects are a problem. - var o = {a:1, toString:function(){o.b = 12; return 'a'; }}; console.log(o[o], o.b); // 1, 12 on Firefox 5 - Here, o[o] triggers a side effect and that sound like the normal behavior. I'm not sure I understand what your example is intended to show. But consider this: var i = 0 var o = {toString: function() { ++i; return a } var p = Proxy.create({getOwnPropertyNames: function() { return [o] }, ...}) var k = Object.keys(p) // What's the value of i now? Fresh tracemonkey tip js shell: js var i = 0 js var o = {toString: function() { ++i; return a }} js var p = Proxy.create({getOwnPropertyNames: function() { return [o] }, getOwnPropertyDescriptor: function() { return {value:42} }}) js var k = Object.keys(p) js i 1 Where would there be a double-conversion? Well, with the canonical fix to the spec we discussed further up the thread (adding a conversion to string in the default trap for `keys') there would (have to) be. So my concern was that that is perhaps not the best fix, despite its simplicity. No, with the current keys default trap (calling this.getOwnPropertyNames()) there is no double conversion. Only one at the exit of the keys trap. There would be 2 conversions if the keys trap had the proxy argument (based on http://wiki.ecmascript.org/doku.php?id=strawman:handler_access_to_proxy) and if internally, the default keys trap was calling Object.getOwnPropertyNames(proxy) (which would call the trap and do type coercion). But the current implementation and a type coercion only when going out of traps would do double-conversion. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Type of property names, as seen by proxy traps
Le 07/07/2011 18:24, David Bruant a écrit : Le 07/07/2011 18:05, Andreas Rossberg a écrit : On 7 July 2011 17:58, Brendan Eich bren...@mozilla.com wrote: On Jul 7, 2011, at 8:32 AM, Andreas Rossberg wrote: On 7 July 2011 16:12, David Bruant david.bru...@labri.fr wrote: Derived traps as showed are written in JS for expository purposes. Engines will be free to optimize as they wish internally as long as the observed behavior is the same. True, but optimizing that actually is more tricky than you might think, since in general it would change the semantics if an engine decided to call toString only once. It has to make sure that none of the names are objects, or at least none of their toString methods was modified and they are all free of side effects. Interesting. However, I'm not sure side-effects are a problem. - var o = {a:1, toString:function(){o.b = 12; return 'a'; }}; console.log(o[o], o.b); // 1, 12 on Firefox 5 - Here, o[o] triggers a side effect and that sound like the normal behavior. I'm not sure I understand what your example is intended to show. But consider this: var i = 0 var o = {toString: function() { ++i; return a } var p = Proxy.create({getOwnPropertyNames: function() { return [o] }, ...}) var k = Object.keys(p) // What's the value of i now? Fresh tracemonkey tip js shell: js var i = 0 js var o = {toString: function() { ++i; return a }} js var p = Proxy.create({getOwnPropertyNames: function() { return [o] }, getOwnPropertyDescriptor: function() { return {value:42} }}) js var k = Object.keys(p) js i 1 Where would there be a double-conversion? Well, with the canonical fix to the spec we discussed further up the thread (adding a conversion to string in the default trap for `keys') there would (have to) be. So my concern was that that is perhaps not the best fix, despite its simplicity. No, with the current keys default trap (calling this.getOwnPropertyNames()) there is no double conversion. Only one at the exit of the keys trap. There would be 2 conversions if the keys trap had the proxy argument (based on http://wiki.ecmascript.org/doku.php?id=strawman:handler_access_to_proxy) and if internally, the default keys trap was calling Object.getOwnPropertyNames(proxy) (which would call the trap and do type coercion). But the current implementation and a type coercion only when going out of traps would do double-conversion. not. would not do double-conversion, sorry. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Type of property names, as seen by proxy traps
On 7 July 2011 19:35, David Bruant david.bru...@labri.fr wrote: No, with the current keys default trap (calling this.getOwnPropertyNames()) there is no double conversion. Only one at the exit of the keys trap. There would be 2 conversions if the keys trap had the proxy argument (based on http://wiki.ecmascript.org/doku.php?id=strawman:handler_access_to_proxy) and if internally, the default keys trap was calling Object.getOwnPropertyNames(proxy) (which would call the trap and do type coercion). But the current implementation and a type coercion only when going out of traps would do double-conversion. not. would not do double-conversion, sorry. I thought the fix we were discussing was changing the `keys' default trap from keys: function() { return this.getOwnPropertyNames().filter( function (name) { return this.getOwnPropertyDescriptor(name).enumerable }.bind(this)); } to something along the lines of keys: function() { return this.getOwnPropertyNames().filter( function (name) { return this.getOwnPropertyDescriptor('' + name).enumerable }.bind(this)); } That would fix passing non-strings to the getOwnPropertyDescriptor trap, but introduce double conversions when you invoke Object.keys. I'm not sure what alternative you are proposing now. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Type of property names, as seen by proxy traps
Le 07/07/2011 20:52, Andreas Rossberg a écrit : On 7 July 2011 19:35, David Bruant david.bru...@labri.fr wrote: No, with the current keys default trap (calling this.getOwnPropertyNames()) there is no double conversion. Only one at the exit of the keys trap. There would be 2 conversions if the keys trap had the proxy argument (based on http://wiki.ecmascript.org/doku.php?id=strawman:handler_access_to_proxy) and if internally, the default keys trap was calling Object.getOwnPropertyNames(proxy) (which would call the trap and do type coercion). But the current implementation and a type coercion only when going out of traps would do double-conversion. not. would not do double-conversion, sorry. I thought the fix we were discussing was changing the `keys' default trap from keys: function() { return this.getOwnPropertyNames().filter( function (name) { return this.getOwnPropertyDescriptor(name).enumerable }.bind(this)); } to something along the lines of keys: function() { return this.getOwnPropertyNames().filter( function (name) { return this.getOwnPropertyDescriptor('' + name).enumerable }.bind(this)); } That would fix passing non-strings to the getOwnPropertyDescriptor trap, but introduce double conversions when you invoke Object.keys. I'm not sure what alternative you are proposing now. I was completely not thinking about this one. Sorry for the misunderstanding. I would be in favor to not do the conversion at all for this.getOwnPropertyDescriptor. I think that derived trap default implementation should be lightweight (no conversion if a trap calls another handler method). Type coercion can be implemented manually (like anything else). I think it's good to give as default behavior (implemented by engines, so hopefully more efficient) the one that is the most consistent with internal methods expetations (for instance [[GetOwnProperty]] expects a string as a name, for instance) The way I view it, it's up to the handler author to write his/her traps consistently. If he/she decides to return objects on a this.getOwnPropertyNames call, then if the spec says that this function will be called without type coercion, he/she has to implement this.getOwnPropertyDescriptor accordingly. But that's just my opinion. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss