super.prop assignment can silently overwrite non-writable properties

Rick Waldron waldron.rick at gmail.com
Mon Apr 20 18:55:58 UTC 2015


On Mon, Apr 20, 2015 at 2:31 PM Allen Wirfs-Brock <allen at wirfs-brock.com>
wrote:

> On Apr 20, 2015, at 11:11 AM, Rick Waldron wrote:
>
>
>
> On Mon, Apr 20, 2015 at 1:45 PM Allen Wirfs-Brock <allen at wirfs-brock.com>
> wrote:
>
>>
>> On Apr 20, 2015, at 9:38 AM, Jason Orendorff wrote:
>>
>> > We're implementing `super` in Firefox, and ran across this surprising
>> behavior:
>> >
>> >    class X {
>> >        constructor() {
>> >            Object.defineProperty(this, "prop", {
>> >                configurable: true,
>> >                writable: false,
>> >                value: 1});
>> >        }
>> >        f() {
>> >            super.prop = 2;  // overwrites non-writable property!
>> >        }
>> >    }
>> >
>> >    var x = new X();
>> >    x.f();
>> >    assertEq(x.prop, 2);  // passes
>> >
>> > In the spec, 9.1.9 step 4.d.i. is where `super.prop = 2` ends up, with
>> > O=X.prototype.
>>
>> 4.d.1 doesn't set the property, it just comes up with the property
>> descriptor to use, if the `Receiver` does not already have a corresponding
>> own property.
>>
>> 5.c+5.e checks if the corresponding own property actually exists on the
>> `Receiver`.  If it already exits then it does a [[DefineOwnProperty]] that
>> only specifies the `value` attribute. This should respect the current
>> `writable` attribute of the property and hence reject the attempt to change
>> the value.
>>
>> So, sounds like a FF bug to me.  Of course, there might also be a problem
>> in the spec. that I'm blind to.
>>
>
> V8 has implemented the same behavior that Jason has reported.
>
> If it's determined that this behaviour is undesirable, implementations
> could agree to do something like:
>
>
> What!?  The behavior Jason described looks like it is  contrary to the
> specification.  Implementations that are not following the spec. have a
> bug.  Also, since apparently at least two implementations have this bug, it
> sounds like we really need to have test262 tests for the specified
> behavior.
>
> FWIW, I believe that once upon the time the spec. may have produced the
> results Jason is observing.  But that behavior was pretty clearly wrong, as
> a [[Set]] operations should not be ignoring the writability of the property
> whose value it is modifying.
>
>
>
>
> 14.5.1 Static Semantics: Early Errors
>
>   (extend with...)
>
>   ClassTail : ClassHeritage_opt { ClassBody }
>
>   ClassBody : ClassElementList
>
>   ClassElementList : ClassElement
>
>   ClassElement : MethodDefinition
>
>   ClassElement : static MethodDefinition
>
>     - It is a Syntax Error if ClassHeritage is not present and
> HasSuperProperty of MethodDefinition is true.
>
>
> This is nothing to do with class definition syntax.  This is about the
> semantics of the [[Set]] internal method.
>

I understand that, but it struck me as _very_ strange that class with no
class heritage could be allowed to have super.foo(), super.foo=2, but not
super(). Did I miss something obvious? What is wrote is certainly heavy
handed, but not more so than what the spec already does with HasDirectSuper
when ClassHeritage is not present. Having just written many tests* for the
early errors that will result when HasDirectSuper returns true, it seemed
subjectively strange to me that this syntax would even be allowed. I
suspect I'm missing something that explains why SuperProperty is allowed
where SuperCall is not.

Rick

*
https://github.com/tc39/test262/pull/224/files#diff-f4c5a205149ca3f002d9f865b1465f15
(and following files)




>
> allen
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20150420/a57abe6e/attachment-0001.html>


More information about the es-discuss mailing list