Duplicate property names (was Re: @@new)

# Erik Arvidsson (10 years ago)

On Wed, Jun 18, 2014 at 12:07 AM, Brendan Eich <brendan at mozilla.org> wrote:

Domenic Denicola wrote:

Another way of guiding the decision: I don't quite recall where the spec landed { x: 1, ["x"]: 2 }, but we should probably be consistent with that.

Mark Miller: I am ok with removing the constraint that duplicate dynamic object properties throw (in strict mode) with the caveat that we also remove the same constraint for duplicate static properties.

from esdiscuss.org/notes/2014-06-06#rest-properties-and-spread-properties-sebastian-markb-ge-.

rwaldron/tc39-notes/blob/master/es6/2014-06/jun-6.md#conclusionresolution-3

  • For both strict and sloppy object literals, both computed and static properties no longer have any duplicate name checking.

I would like this the above to be clarified.

At the f2f we were talking about spread in object literals.

var a = {x: 1, y: 2};
var b = {x: 3, ...a};

However, reading the notes the context is lost and it seems like we are suggestion removing the duplicate property check added in ES5 for strict mode.

# Mark S. Miller (10 years ago)

Yes. For both strict and sloppy, for both static/literal and dynamic/computed, duplicate property names/symbols in object literals are no longer an error. Instead, in left-to-right order, each cause the equivalent of a [[DefineOwnProperty]] on the new object, so that rightward definitions silently overwrite conflicting leftward definitions. This should not result in any change to sloppy literals. It just makes strict literals, regarding this issue alone, act like sloppy literals. (Once we have a way to express that a property is to be initialized to a non-configurable state, we'll need to revisit this. But that's after ES6.)

Since the object is a new normal object, i.e., not exotic and especially not a proxy, no one should ever be able to observe the object until its initialization is complete.

If linters want to warn about statically determined duplicate properties, that is of course their business, and is fine.

# Mark Miller (10 years ago)

Domenic Denicola wrote:

Another way of guiding the decision: I don't quite recall where the spec landed { x: 1, ["x"]: 2 }, but we should probably be consistent with that.

The initial value of the x property would be 2. It should not be observable that it was 1 at an intermediate stage of the initialization.

# Andy Wingo (10 years ago)

On Thu 19 Jun 2014 18:02, "Mark S. Miller" <erights at google.com> writes:

Yes. For both strict and sloppy, for both static/literal and dynamic/computed, duplicate property names/symbols in object literals are no longer an error. Instead, in left-to-right order, each cause the equivalent of a [[DefineOwnProperty]] on the new object, so that rightward definitions silently overwrite conflicting leftward definitions. This should not result in any change to sloppy literals. It just makes strict literals, regarding this issue alone, act like sloppy literals. (Once we have a way to express that a property is to be initialized to a non-configurable state, we'll need to revisit this. But that's after ES6.)

There is one change:

({ foo: 3, get foo() { return 4 } })

This is not allowed with current sloppy mode. Are you proposing that it be allowed, given that this situation may arise with computed property names:

({ ['foo']: 3, get foo() { return 4 } })

or

({ foo: 3, get ['foo']() { return 4 } })

Andy

# Mark S. Miller (10 years ago)

Yes, good catch. This is a change, and it is now allowed.

# Andy Wingo (10 years ago)

What about:

({ get __proto__() {}, __proto__: foo })  // (1)

Does this end up setting the prototype of the result? Would it if there were a setter?

Likewise:

({ __proto__: foo, get __proto__() {} })  // (2)

This one is kinda similar:

({ ['__proto__']: 34, __proto__: foo })   // (3)

I would propose that the answers to the question "does the prototype get set" be "yes" for all of these, since the model is that each one is like an invocation of Object.defineProperty, with the exception that __proto__ is clownshoes-special and that a getter or setter inherits the setter or getter (respectively) of the currently installed property, if any.

# Andy Wingo (10 years ago)

And another one:

({ get __proto__() {}, __proto__: foo, set __proto__(x) {} })

Does the resulting accessor have a setter and a getter, or just a setter? I would think just a setter, in the same way that this one would only have a setter:

({ get qux() {}, qux: foo, set qux(x) {} })
# Erik Arvidsson (10 years ago)

If I recall correctly the intent was that proto was special syntax for setting the [[Prototype]]. So only three following cases are setting the [[Prototype]]

{__proto__: object}
{'__proto__': object}
{"__proto__": object}

Other combinations set an own property:

{['__proto__']: object}
{'__\u0070roto__]: object}
{__proto__() {}}
var __proto__;
{__proto__}
{get __proto__() {}}
{set __proto__(x) {}}

Combining these leads to confusing code (so don't do that) but the semantics is clear.

# Andy Wingo (10 years ago)

On Wed 25 Jun 2014 17:09, Erik Arvidsson <erik.arvidsson at gmail.com> writes:

Other combinations set an own property [...] Combining these leads to confusing code (so don't do that) but the semantics is clear.

I'm glad that the semantics are clear to you ;-)) The tricky case is not __proto__ in isolation; it's how it interacts with other defined properties. Particularly, from my mail:

({ get __proto__() {}, __proto__: foo, set __proto__(x) {} })

Does the resulting accessor have a setter and a getter, or just a setter?

What do you think should happen in this case?

# Allen Wirfs-Brock (10 years ago)

yes, this is covered by people.mozilla.org/~jorendorff/es6-draft.html#sec-proto-property-names-in-object-initializers

__proto__ only has special meaning within a production:

PropertyDefiniton : PropertyName ":" AssignmentExpression

and when PropertyName is not a ComputedPropertyName.

All other PropertyDefinition forms that have __proto__ as the property name (whether literally or as a ComputedPropertyName) just define ordinary properties with the name "__proto__".

The current non-duplicated name restriction made it illegal to have more than one __proto__ : something property definitions in an object literal. Because __proto__: something is a special form with its own semantics I think we should continue to make it illegal to have more than one of them, even when we relax the duplicate rule for regular property definitions.

# Erik Arvidsson (10 years ago)

If propKey is the string value "__proto__"

Do we want to allow "__\u0070roto__" or not? For "use strict" we made it clear that no escape sequences are allowed. I think we should follow that route unless it makes implementation and/or speccing too hard.

# Allen Wirfs-Brock (10 years ago)

I think the usual rules should apply. LiteralPropertyName is either an IdentifierName or a StringLiteral. people.mozilla.org/~jorendorff/es6-draft.html#sec-names-and-keywords says the escaped and non-escaped code points are equivalent within an IdentifierName. people.mozilla.org/~jorendorff/es6-draft.html#sec-static-semantics-sv-s-and-cv-s says the the SV of is the same for a string containing non-escaped code points and a string containing escapes for the same code points.

That means that {__proto__: something}, {__\u0070roto__: something}, {"__proto__": something}, and {"__\u0070__": something} should all mean the same thing and if Annex B is being implemented that means they all do a [[SetPrototypeOf]].

I think "use strict" is a special care where we were trying to simulate what we would allow in a statement composed of reserved words and escapes are now allowed in keywords. people.mozilla.org/~jorendorff/es6-draft.html#sec

# Erik Arvidsson (10 years ago)

On Wed, Jun 25, 2014 at 3:20 PM, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:

people.mozilla.org/~jorendorff/es6-draft.html#sec-reserved-words

That says: "A code point in a ReservedWord cannot be expressed by a UnicodeEscapeSequence." which fits with what I remember too.

# Allen Wirfs-Brock (10 years ago)

right, typo now-> not