1. I wasn't advocating to break the web but to **not** change the name
because of a library bug, the initial thread spoiler was not needed
2. the `@@enumerableWhenAssigned` might lead to shenanigans but it's
*polyfillable* which is IMO preferable if it can solve somehow the problem
```js
enumerableWhenAssigned(
Array.prototype,
'contains',
Array.prototype.contains
);
function enumerableWhenAssigned(obj, prop, value) {
Object.defineProperty(
obj,
prop,
{
configurable: true,
get: function () {
return value;
},
set: function (value) {
Object.defineProperty(
this,
prop,
{
value: value,
// writable: true, // maybe ?
configurable: true,
enumerable: true
}
);
}
}
);
}
```
my .02
Regards
On Wed, Oct 1, 2014 at 8:21 AM, Brendan Eich <[email protected]> wrote:
> 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
>
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss