Property Descriptors as script compatible representation (was: Property descriptors as ES6 Maps)

Allen Wirfs-Brock allen at
Fri Nov 2 08:39:27 PDT 2012

On Nov 2, 2012, at 4:20 AM, Tom Van Cutsem wrote:

> Hi Allen,
> 2012/11/1 Allen Wirfs-Brock <allen at>
> The above isn't how this will be expressed in the final spec.  Instead we will have
> 3) Let desc be the result of calling the [[GetOwnProperty]] internal
> method of O with argument name.
> 4) Return the result of calling FromPropertyDescriptor(desc) (8.10.4).
> And all Proxy objects will have a [[GetOwnProperty]] internal methods that looks something like:
> 1) Let O be the object upon which this internal method was invoked.
> 2) Let desc be the result of calling TrapGetOwnProperty(O,name)
> 3) Return ToPropertyDescriptor(desc)
> (I left out details of exception handling)
> Actually, while reviewing the spec, I realized that there is a good reason why the spec isn't currently specified this way (i.e. why the Proxy spec redefines Object.defineProperty and Object.getOwnPropertyDescriptor and does not just override [[DefineOwnProperty]] and [[GetOwnProperty]]) 
> It is to avoid the lossy conversion that otherwise occurs between the return value of [[GetOwnProperty]] and Object.getOwnPropertyDescriptor.
> With your alternative spec above, consider a call to |Object.getOwnPropertyDescriptor(proxy, name)|
> 1. The Object.gOPD built-in calls proxy.[[GetOwnProperty]]
> 2. [[GetOwnProperty]] invokes the trap, gets back an object
> 3. [[GetOwnProperty]] converts the object into an internal descriptor and returns
> 4. Object.gOPD takes this internal descriptor and turns it into an object again
> Not only are steps 3. and 4. logical inverses, they lose information: recall that we had previously decided that custom attributes on property descriptors would be passed through. So if a proxy trap returns the descriptor {value:42, custom: true}, we want clients to still see the "custom" attribute. That's why we need to avoid coercing the trap result to an internal descriptor.

Ah, yes.  I wondered about that and wasn't sure when I wrote the above whether we were allowing custom attributes. I figured you would speak up if that was an issue...

So, yes, in that case Object.getOwnPropertyDescriptor and Object.defineProperty need to pass through object level descriptors from/to the corresponding proxy traps which means they can't normalize via a property descriptor record.  So, it is perfectly appropriate for them to explicitly test if O is a proxy and act accordingly.   I think, this should be the only place where an explicit Proxy test is required outside of the actual proxy object specification algorithms.

> The case for Object.defineProperty is entirely analogous.
> That's why there exist TrapDefineOwnProperty and TrapGetOwnProperty auxiliary functions: they abstract the common parts between the Object.* built-ins and the internal methods without doing conversions. This is so that the Object.* built-ins can call these auxiliaries directly, and avoid the conversions.
> I realize you want to avoid explicit tests for proxies as much as possible. One way to do that would be to introduce two new built-ins, so that we end up with:
> [[GetOwnProperty]]( P ) -> PropDesc (same as ES5)
> [[GetOwnPropertyObject]] ( P) -> Object (called by Object.gOPD)
> [[DefineOwnProperty]] (P, PropDesc) -> Boolean (same as ES5)
> [[DefineOwnPropertyObject]] (P, Object) -> Boolean (called by Object.defineProperty)

No, we don't need the object variants.  We should only use "internal methods" were we need an algorithm to be polymorphically overloaded across multiple implementation level object representations.  In this case, it is only the proxy representation that needs the object variation so no polymorphic dispatch is required. Direct calls to your TrapGetOwn.../TrapDefine... routines is fine for the two places this actually occurs.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list