Personally, I'd prefer it just be handled this way: - If either `desc.get` or `desc.set` is not `undefined`, treat it as a data descriptor. - Otherwise, treat it as a value descriptor and ignore `desc.get` and `desc.set`.
It'd be much easier to reason about, and I've personally had a few issues around this area - it's annoying to have to build objects polymorphically for the only area where [[HasProperty]] actually has any major semantic meaning and the object in question isn't a key/value dictionary (like for `Object.defineProperties`). Most everything else is just based on [[Get]], so it's just odd and annoying. ----- Isiah Meadows [email protected] www.isiahmeadows.com On Tue, Sep 4, 2018 at 3:32 AM Darien Valentine <[email protected]> wrote: > > The following instrinsic functions invoke the ToPropertyDescriptor internal > operation to convert JS-object property descriptors into "Property > Descriptors" (spec-internal object type): > > - `Reflect.defineProperty` > - `Object.create` > - `Object.defineProperty` > - `Object.defineProperties` > - a `Proxy` instance if its handler includes `getOwnPropertyDescriptor` > > The ToPropertyDescriptor operation uses HasProperty to check for and the > presence of the following properties of a JS object property descriptor in > the order enumerable, configurable, value, writable, get, set. > > If any two incompatible properties are found to be “had properties,” an error > is thrown. > > It seems unfortunate that this works: > > ```js > function breakEveryPropertyDescriptor() { > Object.prototype.value = undefined; > Object.prototype.get = undefined; > } > ``` > > But this has been mentioned before. I found this prior discussion: > > https://esdiscuss.org/topic/topropertydescriptor-hasproperty-hasownproperty > > As explained there, one can address this, if sufficiently paranoid, by only > ever passing in null-prototype objects (or objects with a prototype you > control) as JS-object property descriptors. > > It gets a bit more complex. FromPropertyDescriptor produces JS-object PDs > which also inherit from %ObjectPrototype%. Naturally you can perform the > own-property check yourself — but it has a consequence I find particularly > interesting: > > ``` > const obj1 = {}; > const obj2 = new Proxy({}, Reflect); > > breakEveryPropertyDescriptor(); > > const pd = Object.assign(Object.create(null), { value: 1 }); > > try { > Reflect.defineProperty(obj1, 'foo', pd); > console.log('successful on obj1'); > } catch { > console.log('unsuccessful on obj1'); > } > > try { > Reflect.defineProperty(obj2, 'foo', pd); > console.log('successful on obj2'); > } catch { > console.log('unsuccessful on obj2'); > } > ``` > > In the Proxy case, the input JS PD object is converted to an internal > Property Descriptor (`{ value: 1 }`) and then back to a fresh JS object (now > with %ObjectPrototype%) — and then back to an internal Property Descriptor > again. But it doesn’t successfully round trip! At this the result of > HasProperty(Obj, "get") changes from what it would have been if the PD had > not passed through Reflect.defineProperty, and the descriptor has become `{ > value: 1, get: undefined }`. > > My understanding was that, in theory, using `Reflect` as your handler object > should mean the behavior of all the trapped operations should be the same as > it would have been for an ordinary object. This may be an incorrect > assumption on my part (are there other examples like this?), but it does seem > desirable for that to be true. > > I’m curious about whether changes to these algorithms to alter this behavior > in some way would be web-safe. The obvious solution would be switching > HasProperty to HasOwnProperty in ToPropertyDescriptor and/or creating objects > that inherit from null in FromPropertyDescriptor. But I’m guessing those > changes would not be safe. In any case, I wanted to share the non-parity edge > case with Reflect.defineProperty in case this was not already a known quirk. > _______________________________________________ > es-discuss mailing list > [email protected] > https://mail.mozilla.org/listinfo/es-discuss _______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

