Re: Proxy .__proto__ is not getPrototypeOf?

2014-05-05 Thread Andrea Giammarchi
not sure I understand but ...

 that makes no sense as hasProxyAsProto is not a Proxy

it's inheriting from a Proxy so where is the surprise? it does what I'd
expect it to do, pass through the inherited Proxy same as you pass through
inherited get/set methods when creating from an object that has get/set
behaviors

Moreover, since you inheriting a proxy that reacts on accessors you have
the right behavior when you access `__proto__`, the `target.__proto__`
should be returned instead.

Last, but not least, `__proto__` is an `Object.prototype` property that has
nothing to do with `Object.getPrototypeOf`  you can redefine
`__proto__` behavior either in the `Object.prototype` itself, through a
proxy, or within an object, but that won't affect returned value of
`Object.getPrototypeOf`

```javascript
var o = {};
Object.defineProperty(o, '__proto__', {
  get: function () {
return String.prototype;
  }
});

o.__proto__ === String.prototype;
Object.getPrototypeOf(o); // Object.prototype
```

Best Regards



On Mon, May 5, 2014 at 10:40 AM, John Barton johnjbar...@google.com wrote:

 I'm hoping someone can explain this result which surprises me.

 If I create an object with a Proxy-ed prototype, the resulting object does
 not obey .__proto__ equal Object.getPrototypeOf().

 For example:
   var aPrototype = {foo: 'foo'};
   var handler = {
   get: function(target, name, receiver) {
   console.log('   (Proxy handler \'get\' called for name = ' + name +
 ')');
   return target[name];
   }
   };
   var aProxy = Proxy(aPrototype, handler);
   var hasProxyAsProto = Object.create(aProxy);

 At this point, I expected
   hasProxyAsProto.__proto__ === aProxy
 but it it not true.  Moreover, the operation
   hasProxyAsProto.__proto__
 calls the Proxy handler get function with name === '__proto__': that makes
 no sense as hasProxyAsProto is not a Proxy.

 I tried this on Firefox 29 and Chrome 36.  Complete example is here:
 https://gist.github.com/johnjbarton/f8a837104f0292fa088c

 Any ideas?
 jjb

 ___
 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: Proxy .__proto__ is not getPrototypeOf?

2014-05-05 Thread Allen Wirfs-Brock

On May 5, 2014, at 10:40 AM, John Barton wrote:

 I'm hoping someone can explain this result which surprises me.
 
 If I create an object with a Proxy-ed prototype, the resulting object does 
 not obey .__proto__ equal Object.getPrototypeOf().
 
 For example:
   var aPrototype = {foo: 'foo'};
   var handler = {
 get: function(target, name, receiver) {
   console.log('   (Proxy handler \'get\' called for name = ' + name + 
 ')');
   return target[name];

the above line needs to be:
 return Reflect.get(target, name, receiver);

Object.prototype.__proto__ is an accessor property and to work correctly it 
needs to have the originally accessed object passed at the this value.  That's 
why 'get' handlers (and others) have a 'receiver' argument.




 }
   };
   var aProxy = Proxy(aPrototype, handler);
   var hasProxyAsProto = Object.create(aProxy);
 
 At this point, I expected 
   hasProxyAsProto.__proto__ === aProxy
 but it it not true.  Moreover, the operation 
   hasProxyAsProto.__proto__
 calls the Proxy handler get function with name === '__proto__': that makes no 
 sense as hasProxyAsProto is not a Proxy.
 
 I tried this on Firefox 29 and Chrome 36.  Complete example is here: 
 https://gist.github.com/johnjbarton/f8a837104f0292fa088c

I can't speak to the correctness of those implementations but you need to have 
change for it to even have a chance of working.

Allen

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proxy .__proto__ is not getPrototypeOf?

2014-05-05 Thread Tom Van Cutsem
2014-05-05 19:40 GMT+02:00 John Barton johnjbar...@google.com:

 I'm hoping someone can explain this result which surprises me.

 If I create an object with a Proxy-ed prototype, the resulting object does
 not obey .__proto__ equal Object.getPrototypeOf().


There's no such equivalence, even for regular objects. `__proto__` is just
a property name, so `proxy.__proto__` just triggers the get trap, as any
normal property access. If the proxy should treat it specially, you need to
special-case the name `__proto__` in the get trap. However, as Allen
points out, forwarding should work correctly as long as you also forward
the receiver binding using the Reflect.get method.


 At this point, I expected
   hasProxyAsProto.__proto__ === aProxy
 but it it not true.  Moreover, the operation
   hasProxyAsProto.__proto__
 calls the Proxy handler get function with name === '__proto__': that makes
 no sense as hasProxyAsProto is not a Proxy.


If an object inherits from a proxy, then any property access for a non-own
property will traverse the prototype chain. If it hits a proxy, that
proxy's get trap is called.

Cheers,
Tom
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proxy .__proto__ is not getPrototypeOf?

2014-05-05 Thread John Barton
On Mon, May 5, 2014 at 11:44 AM, Allen Wirfs-Brock al...@wirfs-brock.comwrote:


 On May 5, 2014, at 10:40 AM, John Barton wrote:

 I'm hoping someone can explain this result which surprises me.

 If I create an object with a Proxy-ed prototype, the resulting object does
 not obey .__proto__ equal Object.getPrototypeOf().

 For example:
   var aPrototype = {foo: 'foo'};
   var handler = {
   get: function(target, name, receiver) {
   console.log('   (Proxy handler \'get\' called for name = ' + name +
 ')');
   return target[name];


 the above line needs to be:
  return Reflect.get(target, name, receiver);

 Object.prototype.__proto__ is an accessor property and to work correctly
 it needs to have the originally accessed object passed at the this value.
  That's why 'get' handlers (and others) have a 'receiver' argument.


Thanks! With your change the example works. Unfortunately I'm still
confused.

Before I reduced the code to a short example I was using
Object.getPrototypeOf(obj), like:
  https://gist.github.com/johnjbarton/30c3e72d51d9d64e36d1
rather than targt[name] my first examples shows. It also fails the same
way.

Let me rephrase my question: why is the Proxy get even called in this case?

jjb
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proxy .__proto__ is not getPrototypeOf?

2014-05-05 Thread Boris Zbarsky

On 5/5/14, 4:21 PM, John Barton wrote:

Let me rephrase my question: why is the Proxy get even called in this case?


Because the way __proto__ works is as if the JS implementation had done:

(function() {
  protoGetter = Object.getPrototypeOf;
  Object.defineProperty(Object.prototype, __proto__,
{
   set: function() { /* magic here */ },
   get: function() { return protoGetter(this); }
});
})();

before any page script got to run.

Which means that __proto__ is a simple accessor property on 
Object.prototype.  On the one hand, that means that by default it 
appears on all objects.  On the other hand it means it can be shadowed, 
for example by someone doing an explicit defineProperty for that 
property name on some object.


But it can also be shadowed by proxies, because those get to intercept 
_all_ property access.  So when a obj.__proto__ get happens the 
implementation walks up the proto chain of obj looking for a proxy or 
an object with an own property named __proto__.  If a proxy is found, 
its get() is invoked and that's all there is to do as far as the 
implementation is concerned.  If an own property named __proto__ is 
found, then the implementation checks whether it's an accessor or value 
property, and either returns the value or calls the getter, depending on 
which sort it is.


-Boris
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proxy .__proto__ is not getPrototypeOf?

2014-05-05 Thread Andrea Giammarchi
but that's exactly what I've replied to you already?

Once again, `__proto__` is spec'd in the `Object.prototype` like this:

```javascript

Object.defineProperty(
  Object.prototype,
  '__proto__',
  {
configurable: true,
get: function () {
  return Object.getPrototypeOf(this);
},
set: function (proto) {
  Object.setPrototypeOf(this, proto);
}
  }
);

```

the only exception to that specification is as literal syntax so that
`{__proto__:[]}` is instanceof Array but `{__proto__:[]}` is not ... that
is the only magic about the property, everything else passes through the
`Object.prototype`

Best Regards




On Mon, May 5, 2014 at 1:36 PM, John Barton johnjbar...@google.com wrote:

 Thanks, Boris, this explanation solves the puzzle for me.


 On Mon, May 5, 2014 at 1:32 PM, Boris Zbarsky bzbar...@mit.edu wrote:

 On 5/5/14, 4:21 PM, John Barton wrote:

 Let me rephrase my question: why is the Proxy get even called in this
 case?


 Because the way __proto__ works is as if the JS implementation had done:

 (function() {
   protoGetter = Object.getPrototypeOf;
   Object.defineProperty(Object.prototype, __proto__,
 {
set: function() { /* magic here */ },
get: function() { return protoGetter(this); }
 });
 })();

 before any page script got to run.

 Which means that __proto__ is a simple accessor property on
 Object.prototype.  On the one hand, that means that by default it appears
 on all objects.  On the other hand it means it can be shadowed, for example
 by someone doing an explicit defineProperty for that property name on some
 object.

 But it can also be shadowed by proxies, because those get to intercept
 _all_ property access.  So when a obj.__proto__ get happens the
 implementation walks up the proto chain of obj looking for a proxy or an
 object with an own property named __proto__.  If a proxy is found, its
 get() is invoked and that's all there is to do as far as the implementation
 is concerned.  If an own property named __proto__ is found, then the
 implementation checks whether it's an accessor or value property, and
 either returns the value or calls the getter, depending on which sort it is.

 -Boris

 ___
 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


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proxy .__proto__ is not getPrototypeOf?

2014-05-05 Thread Andrea Giammarchi
 everything else passes through the `Object.prototype`

of course, unless not intercepted or shadowed as shown already in my
previous reply ... `Object.defineProperty(anyObject, '__proto__', {value:
false})`


On Mon, May 5, 2014 at 4:57 PM, Andrea Giammarchi 
andrea.giammar...@gmail.com wrote:

 but that's exactly what I've replied to you already?

 Once again, `__proto__` is spec'd in the `Object.prototype` like this:

 ```javascript

 Object.defineProperty(
   Object.prototype,
   '__proto__',
   {
 configurable: true,
 get: function () {
   return Object.getPrototypeOf(this);
 },
 set: function (proto) {
   Object.setPrototypeOf(this, proto);
 }
   }
 );

 ```

 the only exception to that specification is as literal syntax so that
 `{__proto__:[]}` is instanceof Array but `{__proto__:[]}` is not ... that
 is the only magic about the property, everything else passes through the
 `Object.prototype`

 Best Regards




 On Mon, May 5, 2014 at 1:36 PM, John Barton johnjbar...@google.comwrote:

 Thanks, Boris, this explanation solves the puzzle for me.


 On Mon, May 5, 2014 at 1:32 PM, Boris Zbarsky bzbar...@mit.edu wrote:

 On 5/5/14, 4:21 PM, John Barton wrote:

 Let me rephrase my question: why is the Proxy get even called in this
 case?


 Because the way __proto__ works is as if the JS implementation had done:

 (function() {
   protoGetter = Object.getPrototypeOf;
   Object.defineProperty(Object.prototype, __proto__,
 {
set: function() { /* magic here */ },
get: function() { return protoGetter(this); }
 });
 })();

 before any page script got to run.

 Which means that __proto__ is a simple accessor property on
 Object.prototype.  On the one hand, that means that by default it appears
 on all objects.  On the other hand it means it can be shadowed, for example
 by someone doing an explicit defineProperty for that property name on some
 object.

 But it can also be shadowed by proxies, because those get to intercept
 _all_ property access.  So when a obj.__proto__ get happens the
 implementation walks up the proto chain of obj looking for a proxy or an
 object with an own property named __proto__.  If a proxy is found, its
 get() is invoked and that's all there is to do as far as the implementation
 is concerned.  If an own property named __proto__ is found, then the
 implementation checks whether it's an accessor or value property, and
 either returns the value or calls the getter, depending on which sort it is.

 -Boris

 ___
 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



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proxy .__proto__ is not getPrototypeOf?

2014-05-05 Thread John Barton
Since you ask for a response:


On Mon, May 5, 2014 at 11:30 AM, Andrea Giammarchi 
andrea.giammar...@gmail.com wrote:

 not sure I understand but ...

  that makes no sense as hasProxyAsProto is not a Proxy

 it's inheriting from a Proxy so where is the surprise? it does what I'd
 expect it to do, pass through the inherited Proxy same as you pass through
 inherited get/set methods when creating from an object that has get/set
 behaviors


I was incorrectly assuming that the proto chain would not be consulted for
__proto__: it would be found on every object. Boris' post described the
mechanism of __proto__, then I could see why the get operation traversed
the proto chain and thus why my proxy's getter was called. (IMO, having a
getter high on the proto chain that uses 'this' (receiver) to return values
only known to the 'this' object is pretty evil business, even among
notoriously dubious functions like getters.)

May I suggest that trying to guess why someone is surprised is a better
strategy than telling them that you are not surprised.



 Moreover, since you inheriting a proxy that reacts on accessors you have
 the right behavior when you access `__proto__`, the `target.__proto__`
 should be returned instead.


This makes no sense to me, sorry. Since `target`  is already obj.__proto__,
target.__proto__ should not be returned.



 Last, but not least, `__proto__` is an `Object.prototype` property that
 has nothing to do with `Object.getPrototypeOf`  you can redefine
 `__proto__` behavior either in the `Object.prototype` itself, through a
 proxy, or within an object, but that won't affect returned value of
 `Object.getPrototypeOf`


Fine but not relevant: the code I am analyzing would, absent my proxy,
always give the same result for Object.getPrototypeOf and __proto__.  Sure
these could be different, but in reality it doe not happen because too much
code relies on these being the same.


 ```javascript
 var o = {};
 Object.defineProperty(o, '__proto__', {
   get: function () {
 return String.prototype;
   }
 });

 o.__proto__ === String.prototype;
 Object.getPrototypeOf(o); // Object.prototype
 ```

 Best Regards



 On Mon, May 5, 2014 at 10:40 AM, John Barton johnjbar...@google.comwrote:

 I'm hoping someone can explain this result which surprises me.

 If I create an object with a Proxy-ed prototype, the resulting object
 does not obey .__proto__ equal Object.getPrototypeOf().

 For example:
   var aPrototype = {foo: 'foo'};
   var handler = {
   get: function(target, name, receiver) {
   console.log('   (Proxy handler \'get\' called for name = ' + name +
 ')');
   return target[name];
   }
   };
   var aProxy = Proxy(aPrototype, handler);
   var hasProxyAsProto = Object.create(aProxy);

 At this point, I expected
   hasProxyAsProto.__proto__ === aProxy
 but it it not true.  Moreover, the operation
   hasProxyAsProto.__proto__
 calls the Proxy handler get function with name === '__proto__': that
 makes no sense as hasProxyAsProto is not a Proxy.

 I tried this on Firefox 29 and Chrome 36.  Complete example is here:
 https://gist.github.com/johnjbarton/f8a837104f0292fa088c

 Any ideas?
 jjb

 ___
 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: Proxy .__proto__ is not getPrototypeOf?

2014-05-05 Thread Andrea Giammarchi
that code is wrong and I don't know why or who would assume that
accordingly with specs

I'd rather file a bug in there, pointing at specs ... there are two places
about __proto__, everything else/other interpretations are evil indeed

take care


On Mon, May 5, 2014 at 6:48 PM, John Barton johnjbar...@google.com wrote:

 Since you ask for a response:


 On Mon, May 5, 2014 at 11:30 AM, Andrea Giammarchi 
 andrea.giammar...@gmail.com wrote:

 not sure I understand but ...

  that makes no sense as hasProxyAsProto is not a Proxy

 it's inheriting from a Proxy so where is the surprise? it does what I'd
 expect it to do, pass through the inherited Proxy same as you pass through
 inherited get/set methods when creating from an object that has get/set
 behaviors


 I was incorrectly assuming that the proto chain would not be consulted for
 __proto__: it would be found on every object. Boris' post described the
 mechanism of __proto__, then I could see why the get operation traversed
 the proto chain and thus why my proxy's getter was called. (IMO, having a
 getter high on the proto chain that uses 'this' (receiver) to return values
 only known to the 'this' object is pretty evil business, even among
 notoriously dubious functions like getters.)

 May I suggest that trying to guess why someone is surprised is a better
 strategy than telling them that you are not surprised.



 Moreover, since you inheriting a proxy that reacts on accessors you have
 the right behavior when you access `__proto__`, the `target.__proto__`
 should be returned instead.


 This makes no sense to me, sorry. Since `target`  is already
 obj.__proto__, target.__proto__ should not be returned.



 Last, but not least, `__proto__` is an `Object.prototype` property that
 has nothing to do with `Object.getPrototypeOf`  you can redefine
 `__proto__` behavior either in the `Object.prototype` itself, through a
 proxy, or within an object, but that won't affect returned value of
 `Object.getPrototypeOf`


 Fine but not relevant: the code I am analyzing would, absent my proxy,
 always give the same result for Object.getPrototypeOf and __proto__.  Sure
 these could be different, but in reality it doe not happen because too much
 code relies on these being the same.


 ```javascript
 var o = {};
 Object.defineProperty(o, '__proto__', {
   get: function () {
 return String.prototype;
   }
 });

 o.__proto__ === String.prototype;
 Object.getPrototypeOf(o); // Object.prototype
 ```

 Best Regards



 On Mon, May 5, 2014 at 10:40 AM, John Barton johnjbar...@google.comwrote:

 I'm hoping someone can explain this result which surprises me.

 If I create an object with a Proxy-ed prototype, the resulting object
 does not obey .__proto__ equal Object.getPrototypeOf().

 For example:
   var aPrototype = {foo: 'foo'};
   var handler = {
   get: function(target, name, receiver) {
   console.log('   (Proxy handler \'get\' called for name = ' + name +
 ')');
   return target[name];
   }
   };
   var aProxy = Proxy(aPrototype, handler);
   var hasProxyAsProto = Object.create(aProxy);

 At this point, I expected
   hasProxyAsProto.__proto__ === aProxy
 but it it not true.  Moreover, the operation
   hasProxyAsProto.__proto__
 calls the Proxy handler get function with name === '__proto__': that
 makes no sense as hasProxyAsProto is not a Proxy.

 I tried this on Firefox 29 and Chrome 36.  Complete example is here:
 https://gist.github.com/johnjbarton/f8a837104f0292fa088c

 Any ideas?
 jjb

 ___
 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