super.prop assignment can silently overwrite non-writable properties

Tom Van Cutsem tomvc.be at gmail.com
Wed Apr 22 06:52:34 UTC 2015


2015-04-21 21:52 GMT+02:00 Kevin Smith <zenparsing at gmail.com>:

> Another interpretation might be that since you've explicitly stated an
> intention to bypass the receiver's setter, falling back to that setter
> would be a bug.
>

No, that wouldn't be right. To clarify, Reflect.set takes the following
params: Reflect.set(lookupObject, propertyName, propertyValue,
receiverObject)

It states that we want to start the lookup of propertyName in lookupObject,
but eventually, the object to be updated is receiverObject. The reason for
the split between lookupObject and receiverObject is so that Reflect.set
(or the [[Set]] internal method, which mirrors it) can encode a prototype
chain walk. For a regular property assignment, we always start at the
receiverObject, that is, we initially call:

Reflect.set(receiverObject, propertyName, propertyValue, receiverObject)

As long as we don't find propertyName, we recurse:

Reflect.set(receiverObject.__proto__, propertyName, propertyValue,
receiverObject)
Reflect.set(receiverObject.__proto__.__proto__, propertyName,
propertyValue, receiverObject)
...
and so on until we hit the root.

The only reason why [[Set]] wants to climb the prototype chain in this way
is to see if there are non-writable inherited properties. However, if the
receiverObject has overridden that property (either with an accessor or a
writable property), then the inherited property takes precedence.

In normal ES5 code, since lookup is guaranteed to start at receiverObject,
this precedence is implicitly guaranteed. In ES6, with both `super.prop`
syntax and Reflect.set, the programmer can explicitly start the lookup
higher up the prototype chain. The implicit precedence of the
receiverObject's property is now no longer guaranteed, because we've
skipped looking for the property in receiverObject first.

That's why I think in step 5.c and onward, we must now explicitly ensure
that existingDescriptor takes precedence over the newly defined descriptor.

Cheers,
Tom
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20150422/931667e8/attachment.html>


More information about the es-discuss mailing list