Perhaps @@unscopable shouldn't be a Set...
Conceptually it is a set but I don't think anyone cares enough to oppose this being an array given that it is a cleaner layering of the spec.
I sympathise with Allen's concern. Implementations might have layering issues as well, especially if Set is mostly self-hosted. We should make it a plain array.
On Wed, Sep 25, 2013 at 5:41 PM, Andreas Rossberg <rossberg at google.com>wrote:
I sympathise with Allen's concern. Implementations might have layering issues as well, especially if Set is mostly self-hosted. We should make it a plain array.
Agreed. I originally had thought there might be benefit in the implicit uniqueness, but it's not compelling.
So here is another concern, about the scheme we agreed to last week.
It needs to match a found own property against the possibility of an own @@unscopable property on the same object and that object may be somewhere up the inheritance chain of the actual with object. The means that [[HasProperty]]/[[Get]]/[[Set]] can not be used to do those resolve binding in an ObjectEnvironmentRecord because they don't tell us where the property was found. Instead, ObjectEnvironmentRecord needs to reimplement its own property lookup using [[GetOwnProperty]] and [[GetInheritanceOf]]. However, if the with object is a proxy that means we may be bypassing the actual inheritance mechanism implemented by the Proxy's 'has'/'get'/'set' traps and that could introduce observable semantics irregularities.
Specifying the duplicated lookup is doable but a pain. That and the semantic issues WRT proxies makes me a lot less comfortable with the added complexity of supporting @@unscopable.
This was never resolved and the spec is incomplete here
Specifying the duplicated lookup is doable but a pain. That and the semantic issues WRT proxies makes me a lot less comfortable with the added complexity of supporting @@unscopable.
I never liked it. It burdens the language in order to support legacy code. Are there other ways of fixing the problem?
A few, probably silly, ideas, for the sake of brainstorming:
- Hard-coding
with
to ignore only Array.prototype.values. - Patching the problematic libraries somehow.
- Use a property attribute to signal to
with
that a property should be ignored. [[Enumerable]] would be perfect, but unfortunately won’t work.
Somehow, we have to put the burden on with
and the legacy code instead of the future-facing parts of the language.
Axel
On Wed, Apr 30, 2014 at 1:14 PM, Axel Rauschmayer <axel at rauschma.de> wrote:
Specifying the duplicated lookup is doable but a pain. That and the semantic issues WRT proxies makes me a lot less comfortable with the added complexity of supporting @@unscopable.
I never liked it. It burdens the language in order to support legacy code. Are there other ways of fixing the problem?
A few, probably silly, ideas, for the sake of brainstorming:
Here's the conversation, everything in your list was discussed: rwaldron/tc39-notes/blob/master/es6/2013-07/july-23.md#43-arrayprototypevalues
- Hard-coding
with
to ignore only Array.prototype.values.
@@unscopables is this, but not limited to Array.prototype.values
- Patching the problematic libraries somehow.
This is not reasonably feasible when the libraries are being used in enterprise applications and are done so under contract/license (as in the case of Ext.js)
- Use a property attribute to signal to
with
that a property should be ignored. [[Enumerable]] would be perfect, but unfortunately won’t work.
Andreas suggested this originally, but the additional state bit on every object is undesirable.
Somehow, we have to put the burden on
with
and the legacy code instead of the future-facing parts of the language.
That's what @@unscopables does.
On Wed, Apr 30, 2014 at 1:22 PM, Rick Waldron <waldron.rick at gmail.com>wrote:
On Wed, Apr 30, 2014 at 1:14 PM, Axel Rauschmayer <axel at rauschma.de>wrote:
- Hard-coding
with
to ignore only Array.prototype.values.
My main use case for unscopable is for DOM. Today we cannot add nice named methods to Element or any of its superclasses since HTML attribute event handlers uses ObjectEnvironments.
From Web Animation spec
interface Animatable { AnimationPlayer animate (object? effect, optional (double or TimingInput) timing); ... }
Element implements Animatable;
This means that any HTML attribute event handler that tries to call a global function called animate are now broken.
@unscopable allows us to have nice things.
Including Tom because proxies and MOP.
My main use case for unscopable is for DOM. Today we cannot add nice named methods to Element or any of its superclasses since HTML attribute event handlers uses ObjectEnvironments.
So Element.prototype is in the variable scope chain of event handlers? Wow. Is this documented somewhere?
Thanks!
Axel
On 4/30/14, 2:49 PM, Axel Rauschmayer wrote:
So Element.prototype is in the variable scope chain of event handlers? Wow. Is this documented somewhere?
You mean other than in the spec? See www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#getting-the-current-value-of-the-event-handler step 10.
Note that it's not Element.prototype that's in the scope chain but the element itself. It's just that the property lookup on the element will walk its proto chain.
On 30 Apr 2014, at 21:17 , Boris Zbarsky <bzbarsky at mit.edu> wrote:
On 4/30/14, 2:49 PM, Axel Rauschmayer wrote:
So Element.prototype is in the variable scope chain of event handlers? Wow. Is this documented somewhere?
You mean other than in the spec? See www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#getting-the-current-value-of-the-event-handler step 10.
Thanks, wasn’t able to find it. Not pretty.
Where do you find the spec incomplete WRT @@unscopable. My recollection was that it was all resolved and fully specified and that I was relatively happy with the outcome.
Where do you find the spec incomplete WRT @@unscopable. My recollection was that it was all resolved and fully specified and that I was relatively happy with the outcome.
unscopables for the Object Environment Record is always the empty list. It's never populated.
On Wed, Apr 30, 2014 at 5:17 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:
Where do you find the spec incomplete WRT @@unscopable. My recollection was that it was all resolved and fully specified and that I was relatively happy with the outcome.
I thought so too but now that I look at it I cannot find where we Get the @unscopable list out of the with expression object. As far as I can tell unscopables is never populated.
people.mozilla.org/~jorendorff/es6-draft.html#sec-with-statement-runtime-semantics-evaluation, people.mozilla.org/~jorendorff/es6-draft.html#sec
The changes from ecmascript#1908 never made it into the spec.
The algorithms in the spec bug uses an object and HasOwnProperty check instead of an array and looping from 0 to length - 1. That has a lot of benefits since there are less things that can go wrong (no getters, no toString etc).
However, we might want to change to use HasProperty instead of HasOwnProperty, and have a null prototype Object for Array.prototype[Symbol.unscopables]. The reason is that would make it easier to make these more contained.
For example, in the DOM world we want to add append to Node [*] and animate to Element. If we used HasProperty we could do something like
Node.prototype[Symbol.unscopable] = {
__proto__: null,
append: true
};
Element.prototype[Symbol.unscopable] = {
__proto__: Node.prototype[Symbol.unscopable],
animate: true
};
If we used HasOwnProperty we would either need to change a subclass when a superclass changes or we would need to do the more complicated solution with manually walking the prototype chain in ObjectEnvironment HasBinding.
[*] not entirely true, it would go on the ParentNode interface
The correct code was in rev21, but somehow got lost in rev22 and later. What is currently in the spec. is essentially what was in rev20.
The algorithm given in Bug 1908, comment 2 is problematic, as a property name blacklisted by an @@unsopables
anywhere on the prototype chain will also be blacklisted when it appears as own property of the object itself, which is undesirable. According to the meeting notes of Sep 2013 meeting, this issue was discussed, but it appears that the algorithm presented in Bug 1908 does not incorpore the needed correction.
The algorithm for HasBinding(N)
on an object environment record should be (and it seems to have been suggested in the Consensus/Resolution section of the meeting notes, if I interpret it correctly):
- First, check if there is a property of name
N
in the prototype chain, usingHasProperty()
; - then, if the property of name
N
is found and if thewithEnvironment
flag is set totrue
, look for an own@@unscopables
property on the object of the prototype chain where the property of nameN
was found, and see if it is blacklisted there.
(I was first tempted to say that, if the property name is blacklisted, we could continue to walk deeper in the prototype chain to see if we find a non-blacklisted one; but we should not do that, as it would lead to complications on the algorithms that effectively get, set or delete such a property.)
(one more comment below)
Le 1 mai 2014 à 01:23, Erik Arvidsson <erik.arvidsson at gmail.com> a écrit :
The algorithms in the spec bug uses an object and HasOwnProperty check instead of an array and looping from 0 to length - 1. That has a lot of benefits since there are less things that can go wrong (no getters, no toString etc).
However, we might want to change to use HasProperty instead of HasOwnProperty, and have a null prototype Object for Array.prototype[Symbol.unscopables]. The reason is that would make it easier to make these more contained.
For example, in the DOM world we want to add append to Node [*] and animate to Element. If we used HasProperty we could do something like
Node.prototype[Symbol.unscopable] = { __proto__: null, append: true }; Element.prototype[Symbol.unscopable] = { __proto__: Node.prototype[Symbol.unscopable], animate: true };
If we used HasOwnProperty we would either need to change a subclass when a superclass changes or we would need to do the more complicated solution with manually walking the prototype chain in ObjectEnvironment HasBinding.
[*] not entirely true, it would go on the ParentNode interface
With my proposed algorithm, you just need to blacklist unscopable properties on the same object where they are defined:
Node.prototype.@@unsocopables = { append: true }
Element.prototype.@@unsocopables = { animate: true }
On 2 May 2014 14:45, Claude Pache <claude.pache at gmail.com> wrote:
The algorithm given in [Bug 1908, comment 2] (ecmascript#1908#c2) is problematic, as a property name blacklisted by an
@@unsopables
anywhere on the prototype chain will also be blacklisted when it appears as own property of the object itself, which is undesirable. According to the [meeting notes of Sep 2013 meeting] (rwaldron/tc39-notes/blob/master/es6/2013-09/sept-17.md#53-unscopeable), this issue was discussed, but it appears that the algorithm presented in Bug 1908 does not incorpore the needed correction.The algorithm for
HasBinding(N)
on an object environment record should be (and it seems to have been suggested in the Consensus/Resolution section of the meeting notes, if I interpret it correctly):
- First, check if there is a property of name
N
in the prototype chain, usingHasProperty()
;- then, if the property of name
N
is found and if thewithEnvironment
flag is set totrue
, look for an own@@unscopables
property on the object of the prototype chain where the property of nameN
was found, and see if it is blacklisted there.
Yes, we discussed all this at the September meeting, and the consensus was to refine the algorithm in the very way you suggest.
At last weeks TC39 meeting we had consensus that the value of the @@unscopable property should be a Set rwaldron/tc39-notes/blob/master/es6/2013-09/sept-17.md#53-unscopeable
As I begin to look at implementing this (and the other @@unscopable changes from the meeting) I'm not so sure that Set is such a good idea. My basic concern is that @@unscopable operates at a very low level of the ES name binding resolution mechanism. Set exists at a much higher conceptual level of the ES library and (until now) there was nothing in the fundamental language semantics of ES that depends upon the existence of a library Set object. Now that I have thought about this, it seems fundamentally wrong to unnecessarily create such an up-dependency.
I think we will have a cleaner semantics if we continue to treat an @@unscopable value as an array-like object for the purpose of accessing its property blacklist. Implementations, if they wish, can us2 caching scheme to obtain sub-linear time access to an @@unscopable blacklist.
In light of this consideration, does anybody still want to argue that we should require an @@unscopable value to be a Set instance?