On Aug 8, 2012, at 9:35 AM, Brendan Eich wrote:

> Erik Corry wrote:
>> Hi
>> 
>> This proposal offers a way to get around some of the strange semantics
>> of '=', specifically the way read-only properties and setters on
>> objects in the prototype chain can restrict what you can do on the
>> receiver of an assignment.
> 
> This is "strange" only insofar as you can't say what you mean if you want to 
> override. There's no law of nature requiring = to override, though.
> 
> Assigning != defining in ES5, even in reality in fixed implementations of 
> ES3, and in truth going back to the first JS implementation: proto-setters 
> (internal, hidden) are invoked by assignment, readonly proto-props prevent = 
> being used to override on a delegating object (silent failure, of course, due 
> to lack of try/catch).
> 
> What I'm getting at: is assignment != defining strange, or is the lack of 
> expressiveness that left JS with = but not := strange, or is = not defining 
> strange? I didn't want to assume the last was what you meant, since it is not 
> obvious and not the only possible strangeness or asymmetry.
> 
>>   However it has some strangeness itself:
>> 
>> * There is little point in having read-only properties if the common
>> way to do assignment is :=.  := will just walk all over a read-only
>> property.
> 
> No, readonly properties must be {writable: false, configurable: false} to 
> have integrity, and := cannot redefine a non-configurable property.

And, := should not be thought of or become the common way to do assignment.   
That should remain the job of =
> 
>> * Copying private members from one object to another violates the
>> encapsulation pretty badly.  You would hope that using private names
>> allowed you to easily reason about which objects have which
>> properties, just by looking at the limited number of places a private
>> name is used.  But with this any code in the system that has two
>> instances of a class can splat object a's private properties with
>> those from object b.  It's rather like a replay attack in crypto.
> 
> Yes, this is an open issue in my view. If one uses a private name to brand an 
> object, attackers who have access to such an object can use := to forge 
> trojan objects.

"Encapsulation"? ES doesn't have any encapsulation...

I originally thought that I would spec. := to ignore properties with private 
names (but not those with just unique names). As I thought about this more, I 
realized that in many cases this was likely to violate the user's intent when 
using :=.

Here is a trivial example, that is only intended to be illustrative of more 
likely scenarios:

//this would all be modularized in some manner
const px = Name.private(), py = Name.private();   //I'm not sure what this API 
is ultimately going to look like
let PointLike = {
     get x() {return this[px]},
     set x(v) {this[px] = v},
     get y() {return this[py]},
     set y(v) {this[py] = v}
};
Object.defineProperty(PointLike,px,{value: writable: true});  //@px: 0 in the 
above obj lit would be so much nicer..
Object.defineProperty(PointLike,py,{value: 0, writable: true});

//somewhere else in program:

myObj := PointLike;  // mixin the PointLike properties 

Presumably, the above mixinobject would advertise that it provides public 'x' 
and 'y' properties, but it doesn't advertise or otherwise reveal the private 
names of the  px and py properties.

If := does not replicate the private named properties that the public 
properties are dependent upon then the mixin won't work. Essentially, the 
public and private named properties form a cohesive unit that needs to be 
replicated as a unit.  But this don't violate the secretness of those private 
names.  As long as the original definer of the names has protected them as a 
secret then only the public methods they provide that know the secret names can 
actually reference those properties. 

This does mean that the simple existence of some specific private named 
property is insufficient to serve as a reliable brand (for some meaning of 
brand).   Such brand properties need to be own properties, otherwise __proto__ 
tweaking could be used to circumvent such branding.  So,  there is a simple 
workaround.  When defining a own brand property set the value of the property 
to the object.  Then a brand check would look like:

   function isGenuine(obj) {return this[mySecretBrand] === this}

Cloning the mySecretBrand property of an object breaks the branding.  This, or 
similar identify based techniques could also be a solution to the "like a 
replay attach" issue.

Finally, I do have a way that we could put the cloning of private named 
properties by := under programmer control.  Note that private named properties 
are never enumerated or exposed via reflection.  Hence, the [[Enumerable]] 
attribute really doesn't mean anything for such properties.  We could enhance 
the semantics of := so that used the value of the [[Enumerable]] attribute to 
control the whether or not private named (and only private named) properties 
are cloned.  I'm not thrilled with this idea, but it probably could work. 

Allen



_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to