ToPropertyDescriptor, [[HasProperty]], & [[HasOwnProperty]]

# John-David Dalton (6 years ago)

ES6 additions like Object.assign use [[OwnPropertyKeys]] for getting the keys of source objects. This helps avoid the method gotchas faced by developers previously with things like Object.prototype.writable = true and Object.defineProperty(o, 'foo', { value: 'bar' }).

See developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty#Description (bottom of section)

"Bear in mind that these options are not necessarily own properties so, if inherited, will be considered too. In order to ensure these defaults are preserved you might freeze the Object.prototype upfront, specify all options explicitly, or point to null as proto property."

It's the reason I pre-populate my descriptor attributes with false even though false is the default. See lodash/lodash/blob/2.4.1/dist/lodash.js#L112-L117

With methods like Object.assign using [[OwnPropertyKeys]] does it make sense to make things like ToPropertyDescriptor use [[HasOwnProperty]] too. I think it would be a win for consistency and dev use.

Thoughts?

# Mameri, Fred (HBO) (6 years ago)

I agree with you that this would be a much better design, but it would break backwards compatibility with ES5, no? Minor nitpick: I guess you mean to say that ToPropertyDescriptor should use the abstract operation HasOwnProperty, not [[HasOwnProperty]]...

# John-David Dalton (6 years ago)

I agree with you that this would be a much better design, but it would break backwards compatibility with ES5, no?

There have been other changes to the spec that are technically back-compat breaking like Object.keys('x') no longer throwing an error. I think this change would benefit developers as the case seems to be devs getting bitten by the current behavior.

Minor nitpick: I guess you mean to say that ToPropertyDescriptor should use the abstract operation HasOwnProperty, not [[HasOwnProperty]]

Sure, I'll switch to ES6y terms. Yes, I mean the abstract operation HasOwnProperty.

# Andrea Giammarchi (6 years ago)

that does not save you from errors when Object.prototype.get = function(){} since writable and get/set cannot coexist in a descriptor ... a safe approach is to create var descriptor = Object.create(null); and then set its value later on before assignment.

I remember early discussion with Allen and Brendan about this, the solution was a hybrid [[HasNonObjectProperty]] check so that everything inherited except Object.prototype was considered ... although:

  1. we have two kind of descriptors, accessors and value descriptors. I don't know who would create classes in order to inherit just a couple of propeties ... like new WritableButNotConfigurable(value) ? Has anyone ever seen a piece of code like that?
  2. accordingly to point one, descriptors should rather change into null objects ASAP and stop this descriptor minefield I am pretty sure nobody expect or desire to work like that

Changing that part of the specs iw say easier than defining a new [[HasNonObjectProperty]] pattern, IMO

My 2 cents

# Andrea Giammarchi (6 years ago)

iw<=>say ... "is way"

# Andrea Giammarchi (6 years ago)

OK, hasOwnProperty per descriptor would work too ... probably even easier as spec change than having all null objects

+1 to that

# Allen Wirfs-Brock (6 years ago)

On May 8, 2014, at 1:25 PM, John-David Dalton wrote:

ES6 additions like Object.assign use [[OwnPropertyKeys]] for getting the keys of source objects. This helps avoid the method gotchas faced by developers previously with things like Object.prototype.writable = true and Object.defineProperty(o, 'foo', { value: 'bar' }).

See developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty#Description (bottom of section)

"Bear in mind that these options are not necessarily own properties so, if inherited, will be considered too. In order to ensure these defaults are preserved you might freeze the Object.prototype upfront, specify all options explicitly, or point to null as proto property."

It's the reason I pre-populate my descriptor attributes with false even though false is the default. See lodash/lodash/blob/2.4.1/dist/lodash.js#L112-L117

With methods like Object.assign using [[OwnPropertyKeys]] does it make sense to make things like ToPropertyDescriptor use [[HasOwnProperty]] too. I think it would be a win for consistency and dev use.

Thoughts?

some prior discussions on this topic (or related): esdiscuss.org/topic/nuking-misleading-properties-in-object-getownpropertydescriptor, www.esdiscuss.org/topic/object-prototype-get-bye-bye-object-defineproperty, esdiscuss.org/topic/property

# John-David Dalton (6 years ago)

Thanks for the discussion links, Allen. I'm I reading it right that there was no concrete resolution to the issue?

# Allen Wirfs-Brock (6 years ago)

On May 8, 2014, at 4:05 PM, John-David Dalton wrote:

Thanks for the discussion links, Allen. I'm I reading it right that there was no concrete resolution to the issue?

Right, nothing concrete came out of it so won't happen for ES6.

Post-ES6 is always possible.

# John-David Dalton (6 years ago)

Is Post-ES6 up for discussion? Should I create a spec bug for tracking this?

# Mathias Bynens (6 years ago)

On Fri, May 9, 2014 at 1:44 AM, John-David Dalton <john.david.dalton at gmail.com> wrote:

Should I create a spec bug for tracking this?

Please do.

# Allen Wirfs-Brock (6 years ago)

On May 8, 2014, at 9:08 PM, Mathias Bynens wrote:

On Fri, May 9, 2014 at 1:44 AM, John-David Dalton <john.david.dalton at gmail.com> wrote:

Should I create a spec bug for tracking this?

Please do.

Even better, submit a strawman proposal

# John-David Dalton (6 years ago)

Rock, will do.

# Andrea Giammarchi (6 years ago)

just wrote this down ... it takes an eye blink to agree with and adopt even in ES6, IMHO gist.github.com/WebReflection/48aecb771e61e8a3e168

# Andrea Giammarchi (6 years ago)

also, on top of this ... I'd like to add the fact that es5-sham, the drop in everyone thinks is cool to use to support old browsers not compatible with ES5, is entirely based on own properties since ever: es-shims/es5-shim/blob/master/es5-sham.js#L310

the owns definition in that scope: es-shims/es5-shim/blob/master/es5-sham.js#L28

I've never filed a bug against it, because as it is it has been just safer for "the old" Web

Best

P.S. we are 1 year later on fixing this :-(

# Andrea Giammarchi (6 years ago)

just for record sake, I've re-explained what's the issue here in a node.js related thread: joyent/node#7587

Best