super.x = value should throw if super.x is not a setter
If it doesn't we get into the strange case where we end up changing a data property on the prototype chain which might be shadowed by an instance property.
class A {}
A.prototype.x = 5; // data property on a prototype
class B extends A {
m() {
print(super.x); // 5
super.x = 10; // data properties are not inherited,
// hence x is installed on a receiver
print(super.x); // 5
print(this.x); // 10
}
}
I'm not looking at the spec. right now but this doesn't sound correct. The [[Put]] receiver parameter should cause a data property to be set on the this object
I think you are right.
https://people.mozilla.org/~jorendorff/es6-draft.html#sec-putvalue
https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ordinary-object-internal-methods-and-internal-slots-set-p-v-receiver
super.x = 5 ends up calling [[HomeObject]].__proto__.[[Set]]('x', 5, this) which ends up setting 'x' on this (the receiver)
Wait I do not understand.
What this bug says is that precisely this semantics (super.x = 5 causing data property to be set on the receiver) is confusing and wrong. Yes according to the spec 'super.x = 5' ends up like 'this.x = 5', and this causes weird results here:
class A {}
A.prototype.x = 5; // data property on a prototype
class B extends A {
m() {
print(super.x); // 5
super.x = 10; // data properties are not inherited,
// hence x is installed on a receiver
print(super.x); // 5
print(this.x); // 10
}
}
you assign to super.x, but when you read from super.x, you get a different value - confusing.
It gets worse:
class B {
method() { super.x = 10; }
get x() { return 15; }
}
let b = new B();
b.x; // 15;
b.x = 5; // strict mode exception
b.method();
b.x; // 10;
b.x = 5; // ok
b.x; // 5
Suddenly you can override a getter unintentionally.
My suggestion would be to disallow 'super.x = ..' and 'super.x' if x is not an accessor property.
Or maybe I am missing something here?