Feedback on "Read-only Override Prohibition is [not a mistake]"

David Bruant bruant.d at gmail.com
Sun Jan 15 08:10:32 PST 2012


Hi,

I'm refering to Allen's writing at [1]:
>
> The basic idea is that the properties prototype object are shared
> parts of all of inheriting child object. Modifying such a shared part
> by a child, introduces a local change that is visible to that child
> (and its children) so this requires creation of a “own” property on
> the child. However, read-only properties can not modified (by normal
> means, eg assignment) so there is no need to create a “own” copy.
>
I agree with what you describe as an intention, but I don't know to what
extent it applies to JavaScript (I don't know Self unfortunately):
-----
var p = {};
var o = Object.create(p);
var o2 = Object.create(p);
o.a = 1; // creating an own property

Object.defineProperty(p, 'a', {value:2, configurable:false,
writable:false});
// now, o and o2 "share" an 'a' property. But do they really?
-----
The dynamicity of JavaScript makes the notion of "sharing" dynamic as
well, I think.


> Assigning to an inherited read-only property or a “own” read-only
> property should have the same affect (whether it is ignoring the
> assignment, throwing, etc.).
>
-----
// following above code
o.a = 3;
o2.a = 4;
-----
Due to o having an 'a' property before inheriting from a read-only one,
the notion of "same effect" cannot be applied (unless breaking other
invariants).


> Allowing assignment to an inherited read-only property would break the
> invariant that that a prototype’s readonly property is an immutable
> value that is shared among all children of the prototype.
>
> If there was a mistake in designing ES5, it was allowing
> Object.defineOwnProperty to create child properties that over-ride
> inherited read-only data properties.This broke an invariant that
> previously existed in the language but this invariant was already
> violated by some pre-ES5 clause 15 objects, (eg the writability of the
> prototype property of some children of Function.prototype). However, I
> think the ES5 decision was probably the right one given the legacy
> clause 15 usages and the overall reflective nature of defineOwnProperty).
>
If I sum up, the design of Object.defineProperty was necessary for
backward compatibility (pre-ES5) reasons. A consequence of this design
is breaking the invariant you mentionned ("a prototype’s readonly
property is an immutable value that is shared among all children of the
prototype").
Considering this invariant is broken (as i showed above, it was probably
doomed to be broken anyway), is there still a reason to not align
[[CanPut]] as Mark suggests?

For the record, at the last JSConf, someone showed me code he wrote
where he was declaring data attributes on the prototype with 'null' as
value. It was the only way for his analysis tool to understand that
"child instances" had such and such property. Such a practice prevents
freezing the prototype (because the constructor would fail to assign
values (unless using Object.defineProperty)).
I don't know whether any part of this experience is good or bad, but I
think it's worth noting that "declaring" things on the prototype is a
practice that exists.

David

[1] http://wiki.ecmascript.org/doku.php?id=strawman:fixing_override_mistake


More information about the es-discuss mailing list