Mark S. Miller wrote:
On Tue, Sep 30, 2014 at 4:58 PM, Domenic Denicola
<[email protected] <mailto:[email protected]>> wrote:
I see a few options:
1. Rename. The leading candidate would be `Array.prototype.has`. I
outlined in [1] why `contains` is better; note especially the DOM
classes. But you could stretch things, especially by removing the
`fromIndex` parameter, into an argument that `has` is OK.
(Basically, you'd be saying that an array is more like a set than
a map, and that its analogy with String is mostly accidental.)
If we do rename, it should be almost anything other than .has. Arrays
are clearly single-valued-mapping-like, not set-like, in that they map
from indexes to values. If Array.prototype.has were to exist, it would
need to test possible indexes.
Absolutely.
2. Specific hacks. I am thinking of e.g. making
`Array.prototype.contains` a getter, with a setter that does
[[DefineOwnProperty]].
This could work, and it requires no new kernel mechanisms. If we do
adopt this solution, the setter should be careful to play the same
games that SES plays to work around the override mistake: If the this
being set is not Array.prototype itself, the setter should use
[[DefineOwnProperty]] to emulate an assignment to that this's own
.contains.
Important safety tip with setters and Proxies -- Reflect helpers help.
3. General hacks. I joked about @@unMooToolsables, but seriously,
we could do something similar to @@unscopables of using MOP hooks
to fix this problem. One idea that seems reasonable is
@@enumerableWhenAssigned, so that `Array.prototype.contains`
starts non-enumerable, but when you do `Array.prototype.contains =
x`, it becomes enumerable. You could even generalize this into
something that also fixes the override mistake [2], e.g.
@@defineOwnPropertyOnAssign or @@assignIgnoresProto or similar. Or
you could attack the problem at the for-in level
I suggest we focus on the override mistake. If we come up with a way
of fixing it and .contains with one new kernel mechanism, that would
be great. If we only fix the override mistake, still likely worth it.
But if a new kernel mechanism only fixes .contains, it likely isn't
worth it and we should return to #1 or #2.
I wouldn't count on fixing the override mistake (inevitably by adding
something new under the sun) to help extant code like MooTools, though.
The most painful use case is the existence of perfectly reasonable ES5
code like:
function Point(x, y) { this.x = x; this.y = y; }
Point.prototype.toString() { return `<${x},${y}>`; };
You mean
Point.prototype.toString = function () { return ...; };
of course -- but you're using template string new syntax, so why not use
Object.defineProperty here? Just sayin' ;-).
Because of the override mistake, this reasonable code no longer works
after
Object.freeze(Object.prototype);
This sucks.
SES goes out of its way to not break code that follows ES5 best
practices. The above Point code does. That's why SES's
tamperProof(Object.prototype) replaces the data properties on
Object.prototype with accessor properties whose setter uses
[[DefineOwnProperty]] to emulate assignment on a this that is not
Object.prototype itself.
Yup, Domenic's #2.
With your #3, perhaps we'd have a less painful way to working around
the override mistake.
I think #3, if hacked via @@enumerableWhenAssigned or any such thing,
will just lead to more bugs. It's too implicit, modal.
Here's an alternative: add an assignment operator variant, spell it :=,
that overrides. Boom, new code can work around the override mistake.
Point.prototype.toString := function () { return ...; };
Yeah, I remember := being mooted as [[DefineOwnProperty]] sugar taking a
property descriptor, but I'm throwing this out here. It's simpler and
does not confusingly vary the RHS to be a propdesc where regular
assignment evaluates an arbitrary RHS assignment-expression.
Old code will need magic frozen-proto-setter hacks anyway. That ship
sailed with ES5.
/be
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss