On Jan 20, 2013, at 11:12 AM, David Bruant wrote:

> Le 20/01/2013 18:54, Allen Wirfs-Brock a écrit :
>> On Jan 20, 2013, at 3:04 AM, David Bruant wrote:
>> 
>>> Le 20/01/2013 05:27, Allen Wirfs-Brock a écrit :
>>>> Weakmaps and symbol keyed properties (private or not) are very different 
>>>> mechanism.  They each have a variety of uses and differing implementation 
>>>> and performance characteristics.  It really is a distraction to focus 
>>>> exclusively on a single use case that might be supported by two different 
>>>> mechanism and use it to argue that only one of the mechanism is needed.
>>> What are the different uses of private symbols?
>> Branding is the important one.
>> 
>> Secure private communications between "friend" objects is another possible 
>> one.
> Secure private communication between friend objects can be achieved simply 
> and efficiently with functions or weakmaps already. Why is there a need for 
> an additional construct for that use case?

You didn't address branding.

Also, here is another use case.  Self hosting the ES built-in library, which 
makes extensive use of private internal state.

I don't think you can make valid statements about simplicity and efficiencies 
without working through more specific use cases.  I have a fundamental 
disagreement with arguments that start with the premise that WeakMaps and 
private Symbol keyed properties have comparable performance profiles.  

> 
>>> More specifically: what are the remaining explicit uses of private symbols 
>>> in a language with private syntax in classes?
>> But we don't have such a language.  There are no harmonious proposals for 
>> such a syntax.  Getting classes into ES6 via the max-min class proposal was 
>> possible because we agreed not to debate that issue.
> Will we ever? If the answer is yes, my point stands. TypeScript has private 
> syntax in class. People want it. The ES6 cut-off was too short for TC39 to 
> settle on private in class, but the pressure is here so it's going to happen 
> sooner or later (Mark was saying ES7).

The problem wasn't that the ES6 cut-off was too short to get private into 
class.  The problem was that we couldn't agree upon a meaning (or syntax) for 
private in classes and it was preventing the inclusion of any class syntax.  I 
don't know how long it will take to resolve this.  Never is always a 
possibility.

TypeScript private is not what you want.  The are a purely compile-time 
construct and don't provide any strong runtime encapsulation.

> 
>> We we were going to talk about adding support for addition semantics to  
>> classes we should start at the level of the object model.  Not with syntax. 
>> ES6 class syntax is good because it is defined in terms of the object model 
>> and more basic operations that are defined in the language.  You don't have 
>> to use class syntax to define a class equivalent. So, if we are going to 
>> introduce private object state the first step is to define how it works at 
>> the object model level.
> Does defining how it works at the object model level commits the language to 
> expose a runtime construct allowing to use the lowest-level feature directly?

Hopefully.  I think an important characteristic of the current class definition 
syntax is that it conceptually desugars to more primitive features of the 
object model that are exposed to the language.  If you don't like the class 
syntax or want to extend it you can use functional definitional forms or write 
a transpiler that produce identical runtime structures to what is produced by 
class declarations.

If class definitions exploit capabilities that are only available to them, then 
we would loose this characteristic.

> I think it does not. You think it does, hence private symbols:
> * For which benefits?
> * One downside is that it brings along more complexity to the language... 
> well... to proxies at least. I understand and somewhat agree with your 
> argument that complexifying proxies isn't a problem, but at least, there 
> should be a benefit.
> Also, given that private-in-classes aren't in ES6, why would it be necessary 
> to add private symbols in ES6? Until there is a feature that demands to be 
> desugared as private symbols (I don't think there is, but you probably know 
> better, so tell me if so), it might be wise to put them on hold.

Branding of a large population of highly volatile object instances.  The need 
to do this is completely orthogonal with classes. Arguably private symbols adds 
no complexity to the actual syntactic ES language, but only to the standard 
library (including the Proxy handler API).

> 
>> IMO and for reasons I've already presented, saying that private state is 
>> just relationships defined via WeakMaps is a non-starter.
> I disagree with your arguments on WeakMaps, because choosing to desugar the 
> syntax to WeakMaps doesn't commit neither the implementation nor the spec to 
> actually use weakmaps to spec or to implement the feature.

How something is specified is certainly an indication of design intent.  All 
object properties could be specified in terms of WeakMap induced relationships 
among otherwise stateless object identities.  Why don't we do that?  Presumably 
because there is a design intent is that an object is most often a 
manifestation of  a strongly coupled set of data that should be managed as 
unit. To specify it as a loosely couple set of externally imposed relationships 
would be sending a completely different message to both language implementors 
and users.

A table/relationship based language may be a find thing (I think there already 
is a widely used one) but it isn't a particularly good way to describe an 
object based language.

Probably more significantly, your "this is just the spec" argument depends upon 
class level syntax that is specified using the same specification mechanisms.  
In other the syntax only works in the context of  class declarations.  For it 
to work equivalently for non-class syntax based uses (and still be 
interoperable with actual syntactic class declarations) actual WeakMap objects 
would have to be exposed.

> 
> 
>>> I think symbols were introduced given experience in ES5 and assuming being 
>>> an improvement on top of ES5 as we know it. On top of pure ES5, private 
>>> symbols make a lot of sense. In ES5+class-with-private-syntax, I'm much 
>>> more skeptical.
>> Actually experience with a number of languages.  But like I said, there is 
>> no ES5+class-with-private-syntax so I don't see how that is a useful 
>> argument.
> There will be.

Arguable, and certainly the timeframe isn't short. I don't really want to wait 
5-10 years before addressing the branding use case.


> 
>>> Also, private syntax as private symbol makes the proxy story complicated 
>>> [1], because the class or its instances need to publicize private symbols 
>>> so that proxies can add them to their whitelist when wrapping class 
>>> instances. I don't think leaking abstraction is a valid option, so it means 
>>> that only 2 out of the 3 following can be kept in the language:
>> I don't have a problem at all with making the proxy story more complicated.
> "complicated" was an expression. Either proxies don't work with class 
> instances, making them vastly pointless or classes need to publicize their 
> private symbols (or maybe expose something like "myClass.acceptProxy" which 
> is marginally better), thus ruining their own encapsulation.

Actually this whole discussion makes me question the validity of the current 
Proxy design rather than that of private Symbol.  I may be on the road towards 
getting on the NotificationProxy train.

Class instances are just objects so classes shouldn't be part of this 
discussion.  In particularly, the built-ins are examples of objects that have 
private per instance state which also presumably needs to work with Proxies if 
we expect to be using Proxies to wrap arbitrary objects.  I'm particularly 
sensitive to build-in related issues because I've been spending lots of time in 
the built-in spec. making sure they are subclassable. We also have a lot more 
built-ins in ES6 so special case handling of each one is starting to be 
problematic. 

It seems to me that the real problem isn't just with private symbols, its about 
what a method can assume about its this value.

Consider:

var d = new Date();
var p = Proxy(d, {});

p.getSeconds();

This is going to result in a call to getSeconds with p as its this value.

Now, getSeconds is currently specified to only work with objects that it can 
identify as real date instances. The first thing that getSeconds does is a 
brand check on its this value.  That brand check is specified as checking that 
the this object has a [[DateValue]] internal data property.  Later it will use 
the value of that internal data property as the timeValue that the seconds is 
extracted from. Now p, as a proxy instance, doesn't have such an internal data 
property but instead has other internal data properties such as [[Target]] so, 
without special case magic, the internal access to p's [[DateValue]] will fail 
and the method will throw a TypeError.

The magic, that presumably has to be applied to all such internal data property 
accesses, is that when an internal data property is accessed off of a proxy 
that access must be applied to the target object rather than the proxy object.  
In that case the [[DateValue]] on p would become a [[DateValue]] access on d 
which would work.  If Date is self hosted and a private Symbol was used to 
represent [[DateValue]] then we would want things to work the same way.

This suggests a possible generalized solution to the Proxy/private symbol 
exposure problem:

The [[Get]] and [[Set]]  (and probably some others) internal methods of a proxy 
never call the corresponding trap when the property key is a private Symbol.  
Instead, they trace the [[Target]] chain of the proxy until a non-proxy object 
is reached (call this the "ultimate target").  It then invokes the ultimate 
target's [[Gett]]/[[Set]] using that same private Symbol key.  The result of 
that operation is then returned as the value of the original [[Get]]/[[Set]].

The "private" state access is applied to the correct object and there is no 
exposure of the private symbol!

> 
>> Proxys are an expert feature designed for some specific use cases.  they are 
>> probably an attractive nuisance.  I would advise most JS programmer that if 
>> they are going down the road of using a Proxy, they are probably making a 
>> mistake.  In that light,  placing the extra complexity within the Proxy 
>> story seems just fine.
> To the point of making proxies useless when interacting with class instances 
> or ruining class encapsulation?
> 
>>> 1) proxy-wrapping class instances (without leaking abstractions)
>>> 2) private syntax in class
>>> 3) private symbols
>>> We can probably predict in advance that JavaScript authors will largely not 
>>> want to give up on 2) (even if it comes only in ES7). Should 1) or 3) be 
>>> given up? Unless relevant use cases different than class-like usages are 
>>> provided, 3) can disappear in my opinion.
>> If the above was the only choice (and I don't think it is)
> Which other choices do you think are available?

for example, the above.


> 
> Davud
> 

_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to