Re: Some questions about Private Name Objects
I just spoke to Allen and need to make a correction the post above: computed properties were, in fact, later dropped. Rick On Fri, Sep 14, 2012 at 5:34 PM, Irakli Gozalishvili rfo...@gmail.comwrote: Hey Dean, I also really love clojure protocols and in fact tried to propose few extensions for private names to make them little more usable as such: https://mail.mozilla.org/pipermail/es-discuss/2012-June/023657.html https://gist.github.com/2967124 Unfortunately thread did not got any replies from anyone. That being said I did couple of experiments in these area: Implemented clojure like protocols as library: http://jeditoolkit.com/2012/03/21/protocol-based-polymorphism.html#post But after using it for some time I realised it was not very javascripty, so I have prototyped a more minimalistic version, which I'm using happily since then: https://github.com/Gozala/method I still really wish we could make private names callable such that: var method = Name() method(object, arg1, arg2) = object[method](arg1, arg2) Regards -- Irakli Gozalishvili Web: http://www.jeditoolkit.com/ On Thursday, 2012-09-13 at 14:46 , Dean Landolt wrote: The real point I'm trying to make is that Name objects give us something akin to clojure's protocols. Imagine an orm protocol -- this is just a set of names that must exist on an object (or its proto chain). An object can implement any number of protocols (or interfaces, or whatever) without fear of conflict. You can easily override any implementation so long as you have a handle on the appropriate name object. This is easier, better looking and more correct than anything we can do today. It's not too disimilar from using using instanceof as a brand, but without the pitfalls (it doesn't fall flat crossing sandbox boundaries). This is a safe and flexible inheritance model that works just as a js programmer would expect, all without begging for mutable or multiple prototypes. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
The real point I'm trying to make is that Name objects give us something akin to clojure's protocols. Imagine an orm protocol -- this is just a set of names that must exist on an object (or its proto chain). An object can implement any number of protocols (or interfaces, or whatever) without fear of conflict. You can easily override any implementation so long as you have a handle on the appropriate name object. This is easier, better looking and more correct than anything we can do today. It's not too disimilar from using using instanceof as a brand, but without the pitfalls (it doesn't fall flat crossing sandbox boundaries). This is a safe and flexible inheritance model that works just as a js programmer would expect, all without begging for mutable or multiple prototypes. I think this is a winning argument. So the problem becomes: how can we implement this in a non-fugly way? As it stands (and as Allen has pointed out), we don't currently have the syntax to make this work, even for iterator: import iterator from sys:iterator; // Sorry, hate @'s : ) class Derived extends Base { // Hmmm... No way to put iterator here. } // Try here? Fugly... X.prototype[iterator] = function() { super.doSomething(); // Oops - super outside of class definition : ( }; The absolute minimum we need is a way to specify computed property names in classes (and what the heck, object literals too): import iterator from sys:iterator; class Derived extends Base { [iterator]() { super.doSomething(); // Works like a charm! } } This is IMO the best way forward. It's generally useful beyond the use case presented here and does not use up a valuable free ASCII character. It also doesn't require any new symbolism since we already understand that brackets indicate computed property names. Why were computed property names killed again? Kevin ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
On Fri, Sep 14, 2012 at 12:58 PM, Kevin Smith khs4...@gmail.com wrote: The real point I'm trying to make is that Name objects give us something akin to clojure's protocols. Imagine an orm protocol -- this is just a set of names that must exist on an object (or its proto chain). An object can implement any number of protocols (or interfaces, or whatever) without fear of conflict. You can easily override any implementation so long as you have a handle on the appropriate name object. This is easier, better looking and more correct than anything we can do today. It's not too disimilar from using using instanceof as a brand, but without the pitfalls (it doesn't fall flat crossing sandbox boundaries). This is a safe and flexible inheritance model that works just as a js programmer would expect, all without begging for mutable or multiple prototypes. I think this is a winning argument. So the problem becomes: how can we implement this in a non-fugly way? As it stands (and as Allen has pointed out), we don't currently have the syntax to make this work, even for iterator: import iterator from sys:iterator; // Sorry, hate @'s : ) class Derived extends Base { // Hmmm... No way to put iterator here. } // Try here? Fugly... X.prototype[iterator] = function() { super.doSomething(); // Oops - super outside of class definition : ( }; The absolute minimum we need is a way to specify computed property names in classes (and what the heck, object literals too): import iterator from sys:iterator; class Derived extends Base { [iterator]() { super.doSomething(); // Works like a charm! } } This is IMO the best way forward. It's generally useful beyond the use case presented here and does not use up a valuable free ASCII character. It also doesn't require any new symbolism since we already understand that brackets indicate computed property names. Why were computed property names killed again? I can't find any evidence that they were, however I did dig up evidence that they were in fact accepted by everyone at the July 2011 meeting: https://mail.mozilla.org/pipermail/es-discuss/2011-August/016188.html search that page for private-name-alternatives.pdf Rick Kevin ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
On Thu, Sep 13, 2012 at 5:46 PM, Dean Landolt d...@deanlandolt.com wrote: On Thu, Sep 13, 2012 at 2:59 PM, Rick Waldron waldron.r...@gmail.comwrote: On Thu, Sep 13, 2012 at 1:46 PM, Dean Landolt d...@deanlandolt.comwrote: On Thu, Sep 13, 2012 at 12:09 PM, Erik Arvidsson erik.arvids...@gmail.com wrote: On Thu, Sep 13, 2012 at 8:37 AM, Kevin Smith khs4...@gmail.com wrote: 1) Is method name-collision a practical problem, or just a theoretical problem? If it's just a theoretical problem, then we don't need unique names, and in teaching the language we can simply guide users away from trying to create private methods. In fact, without supporting syntax it's unlikely that users would even bother trying to create them in the first place. Yes. This is a real problem. It is a common problem that we see a lot with private members using naming conventions. class Base { constructor() { this._element = ...; } } class Derived extends Base { constructor() { this._element = ...; // OOPS! } } Another good example where this is a problem is on prototype chains, a good example of which you parenthetically noted (iterators). With unique names it becomes feasible to hang any properties and methods you want off of prototypes without worrying about collision. For instance, imagine an persistance lib with a Record.prototype.save method: var rec = new Record({ save: 'whoops' }); rec.save() // TypeError: Property 'save' is not a function And thus we all fall back to the lovely Record.prototype.save.call(rec) pattern. Unique names neatly sidestep this, giving us back our prototype chains. This could also be designed to use a WeakMap as the store for the data :) https://gist.github.com/3716743 Sure, but now we're back to the whole object.get/set pattern -- to be otherwise rendered irrelevant by the Object.observe proposal (fingers crossed). There's clearly demand for treating objects as records instead of playing interface gymnastics. And when writing generic code we don't always have that luxury. Names (or Symbols, or whatever we're calling them these days) finally allow us to use the prototype chain safely w/ high integrity lookups. Of course and I've been a constantly vocal champion of Object.observe. Instead of further abusing the plain object, I think a better way forward is designing smart record object constructors that construct instances that are pre-initialized as observable, eg. https://github.com/rwldrn/fact(even that's at the mercy of property name collision (eg. on, off, emit... etc) and desires some form of purified prototype chain.) The real point I'm trying to make is that Name objects give us something akin to clojure's protocols. Imagine an orm protocol -- this is just a set of names that must exist on an object (or its proto chain). An object can implement any number of protocols (or interfaces, or whatever) without fear of conflict. You can easily override any implementation so long as you have a handle on the appropriate name object. This is easier, better looking and more correct than anything we can do today. It's not too disimilar from using using instanceof as a brand, but without the pitfalls (it doesn't fall flat crossing sandbox boundaries). This is a safe and flexible inheritance model that works just as a js programmer would expect, all without begging for mutable or multiple prototypes. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
Hey Dean, I also really love clojure protocols and in fact tried to propose few extensions for private names to make them little more usable as such: https://mail.mozilla.org/pipermail/es-discuss/2012-June/023657.html https://gist.github.com/2967124 Unfortunately thread did not got any replies from anyone. That being said I did couple of experiments in these area: Implemented clojure like protocols as library: http://jeditoolkit.com/2012/03/21/protocol-based-polymorphism.html#post But after using it for some time I realised it was not very javascripty, so I have prototyped a more minimalistic version, which I'm using happily since then: https://github.com/Gozala/method I still really wish we could make private names callable such that: var method = Name() method(object, arg1, arg2) = object[method](arg1, arg2) Regards -- Irakli Gozalishvili Web: http://www.jeditoolkit.com/ On Thursday, 2012-09-13 at 14:46 , Dean Landolt wrote: The real point I'm trying to make is that Name objects give us something akin to clojure's protocols. Imagine an orm protocol -- this is just a set of names that must exist on an object (or its proto chain). An object can implement any number of protocols (or interfaces, or whatever) without fear of conflict. You can easily override any implementation so long as you have a handle on the appropriate name object. This is easier, better looking and more correct than anything we can do today. It's not too disimilar from using using instanceof as a brand, but without the pitfalls (it doesn't fall flat crossing sandbox boundaries). This is a safe and flexible inheritance model that works just as a js programmer would expect, all without begging for mutable or multiple prototypes. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
It all start because of a fundamental missing piece in the language that is the ability to add a private property to an object. Not socially private as per the _field convention. I mean actually private, enforced by the runtime. I've been pondering this for a while now, and I think I've figured out what's bothering me... I think privately named fields are a great addition to the language: let privateThing = new Symbol(); // Or whatever the API is... class X { constructor() { this[privateThing] = something; } } This is good. However (imagining that we have Allen's private name syntax): let privateThing = new Symbol(); // Or whatever the API is... class X { @privateThing() { console.log(I'm private!); } } This is not, because now class X is (probably unintentionally) un-mixable, for the reasons stated previously. As we said before, we could use a unique name here, but the distinction between private and unique names is very subtle and probably easy to miss. We are conflating the privacy solution with the name-conflict solution. Since each solution has different and subtle runtime implications, there should be a clear and distinct way for the user to select between them. I argue that the current proposal does not make a sufficient distinction between private and unique names to lead the user to the correct choice. If that is a problem, then what are the options? 1) Is method name-collision a practical problem, or just a theoretical problem? If it's just a theoretical problem, then we don't need unique names, and in teaching the language we can simply guide users away from trying to create private methods. In fact, without supporting syntax it's unlikely that users would even bother trying to create them in the first place. (This would mean that the iterator hook would need to be called simply iterator.) 2) Provide two distinct constructors for private and unique names, and provide supporting method syntax ONLY to unique names. This will ensure that private names are not incorrectly used as prototype method names. (If unique names are provided, then there will have to be some supporting method syntax, as Allen has suggested.) I currently lean toward option 1. Kevin ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
On Thu, Sep 13, 2012 at 8:37 AM, Kevin Smith khs4...@gmail.com wrote: 1) Is method name-collision a practical problem, or just a theoretical problem? If it's just a theoretical problem, then we don't need unique names, and in teaching the language we can simply guide users away from trying to create private methods. In fact, without supporting syntax it's unlikely that users would even bother trying to create them in the first place. Yes. This is a real problem. It is a common problem that we see a lot with private members using naming conventions. class Base { constructor() { this._element = ...; } } class Derived extends Base { constructor() { this._element = ...; // OOPS! } } -- erik ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
On Thu, Sep 13, 2012 at 12:09 PM, Erik Arvidsson erik.arvids...@gmail.comwrote: On Thu, Sep 13, 2012 at 8:37 AM, Kevin Smith khs4...@gmail.com wrote: 1) Is method name-collision a practical problem, or just a theoretical problem? If it's just a theoretical problem, then we don't need unique names, and in teaching the language we can simply guide users away from trying to create private methods. In fact, without supporting syntax it's unlikely that users would even bother trying to create them in the first place. Yes. This is a real problem. It is a common problem that we see a lot with private members using naming conventions. class Base { constructor() { this._element = ...; } } class Derived extends Base { constructor() { this._element = ...; // OOPS! } } Another good example where this is a problem is on prototype chains, a good example of which you parenthetically noted (iterators). With unique names it becomes feasible to hang any properties and methods you want off of prototypes without worrying about collision. For instance, imagine an persistance lib with a Record.prototype.save method: var rec = new Record({ save: 'whoops' }); rec.save() // TypeError: Property 'save' is not a function And thus we all fall back to the lovely Record.prototype.save.call(rec) pattern. Unique names neatly sidestep this, giving us back our prototype chains. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
Another good example where this is a problem is on prototype chains, a good example of which you parenthetically noted (iterators). With unique names it becomes feasible to hang any properties and methods you want off of prototypes without worrying about collision. For instance, imagine an persistance lib with a Record.prototype.save method: var rec = new Record({ save: 'whoops' }); rec.save() // TypeError: Property 'save' is not a function And thus we all fall back to the lovely Record.prototype.save.call(rec) pattern. Unique names neatly sidestep this, giving us back our prototype chains. Interesting - thanks! Kevin ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
On Thu, Sep 13, 2012 at 1:46 PM, Dean Landolt d...@deanlandolt.com wrote: On Thu, Sep 13, 2012 at 12:09 PM, Erik Arvidsson erik.arvids...@gmail.com wrote: On Thu, Sep 13, 2012 at 8:37 AM, Kevin Smith khs4...@gmail.com wrote: 1) Is method name-collision a practical problem, or just a theoretical problem? If it's just a theoretical problem, then we don't need unique names, and in teaching the language we can simply guide users away from trying to create private methods. In fact, without supporting syntax it's unlikely that users would even bother trying to create them in the first place. Yes. This is a real problem. It is a common problem that we see a lot with private members using naming conventions. class Base { constructor() { this._element = ...; } } class Derived extends Base { constructor() { this._element = ...; // OOPS! } } Another good example where this is a problem is on prototype chains, a good example of which you parenthetically noted (iterators). With unique names it becomes feasible to hang any properties and methods you want off of prototypes without worrying about collision. For instance, imagine an persistance lib with a Record.prototype.save method: var rec = new Record({ save: 'whoops' }); rec.save() // TypeError: Property 'save' is not a function And thus we all fall back to the lovely Record.prototype.save.call(rec) pattern. Unique names neatly sidestep this, giving us back our prototype chains. This could also be designed to use a WeakMap as the store for the data :) https://gist.github.com/3716743 Rick ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
On Thu, Sep 13, 2012 at 2:59 PM, Rick Waldron waldron.r...@gmail.comwrote: On Thu, Sep 13, 2012 at 1:46 PM, Dean Landolt d...@deanlandolt.comwrote: On Thu, Sep 13, 2012 at 12:09 PM, Erik Arvidsson erik.arvids...@gmail.com wrote: On Thu, Sep 13, 2012 at 8:37 AM, Kevin Smith khs4...@gmail.com wrote: 1) Is method name-collision a practical problem, or just a theoretical problem? If it's just a theoretical problem, then we don't need unique names, and in teaching the language we can simply guide users away from trying to create private methods. In fact, without supporting syntax it's unlikely that users would even bother trying to create them in the first place. Yes. This is a real problem. It is a common problem that we see a lot with private members using naming conventions. class Base { constructor() { this._element = ...; } } class Derived extends Base { constructor() { this._element = ...; // OOPS! } } Another good example where this is a problem is on prototype chains, a good example of which you parenthetically noted (iterators). With unique names it becomes feasible to hang any properties and methods you want off of prototypes without worrying about collision. For instance, imagine an persistance lib with a Record.prototype.save method: var rec = new Record({ save: 'whoops' }); rec.save() // TypeError: Property 'save' is not a function And thus we all fall back to the lovely Record.prototype.save.call(rec) pattern. Unique names neatly sidestep this, giving us back our prototype chains. This could also be designed to use a WeakMap as the store for the data :) https://gist.github.com/3716743 Sure, but now we're back to the whole object.get/set pattern -- to be otherwise rendered irrelevant by the Object.observe proposal (fingers crossed). There's clearly demand for treating objects as records instead of playing interface gymnastics. And when writing generic code we don't always have that luxury. Names (or Symbols, or whatever we're calling them these days) finally allow us to use the prototype chain safely w/ high integrity lookups. The real point I'm trying to make is that Name objects give us something akin to clojure's protocols. Imagine an orm protocol -- this is just a set of names that must exist on an object (or its proto chain). An object can implement any number of protocols (or interfaces, or whatever) without fear of conflict. You can easily override any implementation so long as you have a handle on the appropriate name object. This is easier, better looking and more correct than anything we can do today. It's not too disimilar from using using instanceof as a brand, but without the pitfalls (it doesn't fall flat crossing sandbox boundaries). This is a safe and flexible inheritance model that works just as a js programmer would expect, all without begging for mutable or multiple prototypes. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
2012/8/27 David Bruant bruan...@gmail.com Le 27/08/2012 21:22, Kevin Smith a écrit : On the other hand, private names seem to add complexity to proxies A huge share of this complexity has been removed in recent discussions [1]. Conclusions seem to have reach consensus on es-discuss, but nothing has been officially accepted by TC39 I'm planning to bring it up at the next meeting. Cheers, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
Apologies in advance for the length... A huge share of this complexity has been removed in recent discussions [1]. Conclusions seem to have reach consensus on es-discuss, but nothing has been officially accepted by TC39 As I understand it, the solution arrived at was to provide a (possibly updatable) collection of private name objects to the Proxy constructor and let the engine take care of the details. That sounds good, and good work! What do you mean? Private name allow to do mixins without collision. It seems to reduce the complexity than increasing it in my opinion. Unique (non-private) names offer mixins without collisions. But any general mixin utility will fail if the source object relies on privately named methods for its functionality: // Create a private name let privateMethodName = new Name(); // Create a class that naively defines and uses a privately-named method function A() {} A.prototype.doSomething = function() { this[privateMethodName](); }; A.prototype[privateMethodName] = function() {}; // Create another class function B() {} // Attempt to mix A's functionality into B using a library function mixin(A, B); // Fails: privateMethodName is undefined new B().doSomething(); Neither the destination object nor the library function mixin has access to the private name, and therefore the privately named method will not get copied to the destination object, and the mixin will fail. Clearly the solution above would be to use a unique name, instead of a private name. But that begs the question: why do we need private, secured names at all? They complicate the object model without a compelling use case, as far as I can tell. If there are use cases, let's see them. In any situation where you want to *really* secure access to data or code, the ergonomics of your code is going to be the least of your worries. Security is just generally difficult, and that soft-tissue cost will have to be borne by the developer whether they use WeakMaps or private names or closures or whatever. Why complicate the object model, and in the process invalidate the current maxim that all properties are reflective, when the weight will still fall on the developer anyway? Just an argument to consider... Kevin ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
Le 28/08/2012 15:38, Kevin Smith a écrit : Apologies in advance for the length... Don't. We're here to discuss as the mailing-list name suggests. And if what you need to say is long, so be it. A huge share of this complexity has been removed in recent discussions [1]. Conclusions seem to have reach consensus on es-discuss, but nothing has been officially accepted by TC39 As I understand it, the solution arrived at was to provide a (possibly updatable) collection of private name objects to the Proxy constructor and let the engine take care of the details. That sounds good, and good work! Exactly. I'm glad there is one more fan of the proposal :-) What do you mean? Private name allow to do mixins without collision. It seems to reduce the complexity than increasing it in my opinion. Unique (non-private) names offer mixins without collisions. But any general mixin utility will fail if the source object relies on privately named methods for its functionality: (code snippet) Neither the destination object nor the library function mixin has access to the private name, and therefore the privately named method will not get copied to the destination object, and the mixin will fail. Clearly the solution above would be to use a unique name, instead of a private name. Indeed. But that begs the question: why do we need private, secured names at all? They complicate the object model without a compelling use case, as far as I can tell. If there are use cases, let's see them. Private names enable easy encapsulation code sharing at the same time (which is awkward at best nowadays). As a result of the current awkwardness, developer sacrifice encapsulation by using publicly accessible fields using the _field convention. I could name dozens of Node.js library doing that. And sometimes, developers use a private field while they shouldn't, but it makes their life easier, and abstraction leak, etc. It all start because of a fundamental missing piece in the language that is the ability to add a private property to an object. Not socially private as per the _field convention. I mean actually private, enforced by the runtime. In any situation where you want to *really* secure access to data or code, the ergonomics of your code is going to be the least of your worries. I disagree. A good part of the work toward securing an application is reviewing it. The easier the review is, the less likely you are to leave holes behind. The ergonomics of the code is a security feature. Security is just generally difficult, and that soft-tissue cost will have to be borne by the developer whether they use WeakMaps or private names or closures or whatever. Why complicate the object model, and in the process invalidate the current maxim that all properties are reflective, when the weight will still fall on the developer anyway? I arrived on es-discuss at a time where private names had been decided to be the mecanism that answer all above-listed constraints. It seems to do the job. I have intuitive concerns about how to use them in large scale applications and preserve proper code sharing, but nothing concrete to either validate nor invalidate this intuition. In a nutshell, I'm wondering whether private names will be easy to use in complex cases. I'm not specifically against the idea of complicating the object model if the benefit is developers stopping _fields. I am open anyway to see if there is an idea that's alternative to private name and would solve all above constraints. There is still time since no one has implemented private names (or symbols as it's their new name which I'm still not used to) yet. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
Unique (non-private) names offer mixins without collisions. But any general mixin utility will fail if the source object relies on privately named methods for its functionality: ... Neither the destination object nor the library function mixin has access to the private name, and therefore the privately named method will not get copied to the destination object, and the mixin will fail. Clearly the solution above would be to use a unique name, instead of a private name. Alternatively, and this has a more OOP feeling to it, one could put the objects in control of iterations, with separate, overridable iterators for separate purposes. One such purpose would be an iterator to be used for an object clone/extend operator. The default clone iterator would skip private properties, but those could be added by overriding. Such a clone operator would itself need to be private, only callable for property copying (eg, with a built-in extend), but with this caveat, it should be possible to copy private properties without exposing their keys, and with the source object in full control of whether or not private properties may be copied. Is this line of reasoning too far off, or has it been considered to add such extend/clone iterators? Claus ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
Le 27/08/2012 15:34, Matthew Robb a écrit : I'm trying to determine whether when compiling into ES3/5 you could get away with not attaching some .__privates__ property to the object and instead just put a closure around the definitions. For that question, the answer is you cannot. You cannot faithfully polyfill private names. Interesting experiment by Brandon Benvie : http://bbenvie.com/articles/2012-06-06/ES6-Private-Names-Shim One of these things we need the platform to do for us. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
A name object is not much different from using a string: let myname1 = S4u-1_tlzUI; let myname2 = new Name(); someobj[myname1] = 123; someobj[myname2] = 123; // In a constructor or method: this[myname1] = abc; this[myname2] = abc; You can pass both around and create properties on any (non-frozen and extensible) object. The main difference is that if you use myname2 then the property won’t be detected via the usual means (Object.keys, Object.getOwnPropertyNames, in operator, for-in loop, etc.). You need the value in myname2 to access properties created via it. But you can let other parties know about that value. That’s what makes it impossible to use closures to simulate this feature. On Aug 27, 2012, at 15:34 , Matthew Robb matthewwr...@gmail.com wrote: So I have been trying to figure out from the wiki precisely how Private Name Objects work. When assigned/defined does it expose that property to all sibling properties/methods or just those present at the time of assign/define? If you add on to the object later to the new properties get access? var Person = { [hunger]: 100, eat: function(){ --this[hunger]; } } ? Person.getHunger = function() { return this[hunger] } class Person { constructor(){ this[hunger] = 100; } } Person.prototype.getHunger = function(){ return this[hunger]; } Does it make a difference wether it is a 'method' vs a property with a function value? var Person = { [hunger]: 100, eat: function(){ --this[hunger]; } isHungry: function() { return this[hunger] 0; } getHunger() { return this[hunger]; } } I'm trying to determine whether when compiling into ES3/5 you could get away with not attaching some .__privates__ property to the object and instead just put a closure around the definitions. Thanks ahead of time! Matthew Robb ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Dr. Axel Rauschmayer a...@rauschma.de home: rauschma.de twitter: twitter.com/rauschma blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
SO it has to be constructed via new Name() or will it automatically create Name objects when it encounters an assignment of that form? If you do have to create it does that mean in order to access it at all you would need to be in scope of myname2? My question I think boils down to whether access is SCOPE gated or OBJECT gated: var myClass = (function(){ class myClass { constructor(){ this[test] = 0; } } return myClass; })() myClass.prototype.getTest = function() { return this[test] } Is the above perfectly valid? On Mon, Aug 27, 2012 at 10:46 AM, Axel Rauschmayer a...@rauschma.de wrote: A name object is not much different from using a string: let myname1 = S4u-1_tlzUI; let myname2 = new Name(); someobj[myname1] = 123; someobj[myname2] = 123; // In a constructor or method: this[myname1] = abc; this[myname2] = abc; You can pass both around and create properties on any (non-frozen and extensible) object. The main difference is that if you use myname2 then the property won’t be detected via the usual means (Object.keys, Object.getOwnPropertyNames, in operator, for-in loop, etc.). You need the value in myname2 to access properties created via it. But you can let other parties know about that value. That’s what makes it impossible to use closures to simulate this feature. On Aug 27, 2012, at 15:34 , Matthew Robb matthewwr...@gmail.com wrote: So I have been trying to figure out from the wiki precisely how Private Name Objects work. When assigned/defined does it expose that property to all sibling properties/methods or just those present at the time of assign/define? If you add on to the object later to the new properties get access? var Person = { [hunger]: 100, eat: function(){ --this[hunger]; } } ? Person.getHunger = function() { return this[hunger] } class Person { constructor(){ this[hunger] = 100; } } Person.prototype.getHunger = function(){ return this[hunger]; } Does it make a difference wether it is a 'method' vs a property with a function value? var Person = { [hunger]: 100, eat: function(){ --this[hunger]; } isHungry: function() { return this[hunger] 0; } getHunger() { return this[hunger]; } } I'm trying to determine whether when compiling into ES3/5 you could get away with not attaching some .__privates__ property to the object and instead just put a closure around the definitions. Thanks ahead of time! Matthew Robb ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Dr. Axel Rauschmayer a...@rauschma.de home: rauschma.de twitter: twitter.com/rauschma blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
On Aug 27, 2012, at 16:55 , Matthew Robb matthewwr...@gmail.com wrote: SO it has to be constructed via new Name() or will it automatically create Name objects when it encounters an assignment of that form? If you do have to create it does that mean in order to access it at all you would need to be in scope of myname2? My question I think boils down to whether access is SCOPE gated or OBJECT gated: var myClass = (function(){ class myClass { constructor(){ this[test] = 0; } } return myClass; })() myClass.prototype.getTest = function() { return this[test] } Is the above perfectly valid? No, ES.next would complain about the undeclared variable `test` (variable scope, not object). The closest you can get to simulating is by using strings with UUIDs. That avoids the name clashes, but doesn’t hide the properties. -- Dr. Axel Rauschmayer a...@rauschma.de home: rauschma.de twitter: twitter.com/rauschma blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
AH okay thanks guys, questions answered! On Mon, Aug 27, 2012 at 11:03 AM, Axel Rauschmayer a...@rauschma.de wrote: On Aug 27, 2012, at 16:55 , Matthew Robb matthewwr...@gmail.com wrote: SO it has to be constructed via new Name() or will it automatically create Name objects when it encounters an assignment of that form? If you do have to create it does that mean in order to access it at all you would need to be in scope of myname2? My question I think boils down to whether access is SCOPE gated or OBJECT gated: var myClass = (function(){ class myClass { constructor(){ this[test] = 0; } } return myClass; })() myClass.prototype.getTest = function() { return this[test] } Is the above perfectly valid? No, ES.next would complain about the undeclared variable `test` (variable scope, not object). The closest you can get to simulating is by using strings with UUIDs. That avoids the name clashes, but doesn’t hide the properties. -- Dr. Axel Rauschmayer a...@rauschma.de home: rauschma.de twitter: twitter.com/rauschma blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
So why could this not desugar to?: var myClass = (function(){ var __test; function myClass() { __test = 0; } myClass.prototype.getTest = function(){ return __test; } return myClass; })(); On Mon, Aug 27, 2012 at 11:01 AM, David Bruant bruan...@gmail.com wrote: Le 27/08/2012 16:55, Matthew Robb a écrit : SO it has to be constructed via new Name() or will it automatically create Name objects when it encounters an assignment of that form? If you do have to create it does that mean in order to access it at all you would need to be in scope of myname2? My question I think boils down to whether access is SCOPE gated or OBJECT gated: var myClass = (function(){ class myClass { constructor(){ this[test] = 0; } } return myClass; })() myClass.prototype.getTest = function() { return this[test] } Is the above perfectly valid? This cannot work, because your inherited method needs an access to the private name in your variable 'test' (which in your example is neither declared nor initialized). To rewrite your example: var myClass = (function(){ var test = new Name(); class myClass { constructor(){ this[test] = 0; } getTest: function(){return this[test]}; } return myClass; })(); In this rewritten version, test is being declared in an encapsulating function scope, getTest will naturally gets in myClass.prototype (by definition of what the class syntax desugars to IIRC) and your inherited method will have access to your private name. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
Hi Matthew, Sorry, I mislead you. Let me retry: class myClass{ private test; constructor(){ this[test] = 0; } getTest(){return this[test]}; } desugars to: var myClass = (function(){ var test = new Name(); function myClass(){ this[test] = 0; } myClass.prototype.getTest = function(){return this[test]}; return myClass; })(); I'm not up-to-date on exact syntax, but that's more or less what you'd get. An interesting point you're bringing is that the desugared version could just use variables in method scopes instead of private names. It could yield in this alternative desugaring: var myClass = (function(){ var test; function myClass(){ test = 0; } myClass.prototype.getTest = function(){return test}; return myClass; })(); It can be read in the code why it doesn't work. There is a unique 'test' variable for all instances and not a test variable for each, this makes the getTest method pointless in this example (because it gets the last set value and not the value of the current instance). Being able to attach private data to individual objects and being able to access this data in inherited method is one of the use case that require private names. I hope I have make things more clear. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
I know this has some serious ugly to it but in the spirit of knowing what COULD potentially create the expected behavior, would this not do the trick? var myClass = (function(){ function myClass(){ var __priv = Object.create(this); var __this = __priv.__this = this; this.getTest = function(){ return myClass.prototype.getTest.apply((this ===__this)?__priv:this, arguments); } __priv.test = 0; } myClass.prototype.getTest = function() { var __this = this.__this || this, __private = this; return __private.test; } return myClass; })(); On Mon, Aug 27, 2012 at 11:43 AM, David Bruant bruan...@gmail.com wrote: Hi Matthew, Sorry, I mislead you. Let me retry: class myClass{ private test; constructor(){ this[test] = 0; } getTest(){return this[test]}; } desugars to: var myClass = (function(){ var test = new Name(); function myClass(){ this[test] = 0; } myClass.prototype.getTest = function(){return this[test]}; return myClass; })(); I'm not up-to-date on exact syntax, but that's more or less what you'd get. An interesting point you're bringing is that the desugared version could just use variables in method scopes instead of private names. It could yield in this alternative desugaring: var myClass = (function(){ var test; function myClass(){ test = 0; } myClass.prototype.getTest = function(){return test}; return myClass; })(); It can be read in the code why it doesn't work. There is a unique 'test' variable for all instances and not a test variable for each, this makes the getTest method pointless in this example (because it gets the last set value and not the value of the current instance). Being able to attach private data to individual objects and being able to access this data in inherited method is one of the use case that require private names. I hope I have make things more clear. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
Le 27/08/2012 19:54, Matthew Robb a écrit : I know this has some serious ugly to it but in the spirit of knowing what COULD potentially create the expected behavior, would this not do the trick? var myClass = (function(){ function myClass(){ var __priv = Object.create(this); var __this = __priv.__this = this; this.getTest = function(){ If you're willing to have functions as own properties in each instance, you need the method on the prototype any longer. If JS engines do their job properly, they will store the function body once and just create new function objects for each instance (which you do anyway, so it has no extra cost) return myClass.prototype.getTest.apply((this ===__this)?__priv:this, arguments); } __priv.test = 0; } myClass.prototype.getTest = function() { var __this = this.__this || this, __private = this; return __private.test; } return myClass; })(); Version with having a function on each instance: function myClass(){ var test = 0; this.getTest = function(){ return test; }; } No underscore ;-) Through the different messages we've shared, you've covered the different ways to do encapsulation and code sharing and the conclusion is that either you need to add a function to each object (which yield a linear cost for no reason) or your abstaction leaks if you want to prototype function to access per-object data. A last alternative is to associate private data via a WeakMap (it can be shimmed in ES5 with the same garbage collection properties and with good performances) that inherited functions all have access to. It works, but it's burdensome and doesn't read as well as object properties. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
A last alternative is to associate private data via a WeakMap (it can be shimmed in ES5 with the same garbage collection properties and with good performances) that inherited functions all have access to. It works, but it's burdensome and doesn't read as well as object properties. On the other hand, private names seem to add complexity to proxies and mixin composition. Kevin ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
In the end I am not looking for reads well, I am looking for minimal semantic difference that can ideally work as a target for compiling to es3. I am PREFERRING to not have functions as ownProperties. I can't use hard binding because if the function is assigned to some place else it should no longer be given access to the private name's it would have had as an instance method/property (I'm assuming this actually). I have done a little more playing around and am currently right about here: class myClass { private test; constructor() { this[test] = 0; } getTest() this[test]; doNothing(){} } COMPILES TO: var myClass = (function(){ var __myClass = function __myClass(__privates, __this) { // All class methods using private names would be defined here this.getTest = function() { // All appearances of this[test] would be replaced by the below ternary operation return (this === __this ? __privates : this).test; } return (__this (__this.__proto__ = this)) ? __privates : this; } var myClass = __myClass.prototype.constructor = function myClass() { var __privates = new __myClass({}, this); // Constructor body __privates.test = 0; } myClass.prototype = __myClass.prototype = new __myClass() myClass.prototype.doNothing = function(){} return myClass; })(); On Mon, Aug 27, 2012 at 3:17 PM, David Bruant bruan...@gmail.com wrote: Le 27/08/2012 19:54, Matthew Robb a écrit : I know this has some serious ugly to it but in the spirit of knowing what COULD potentially create the expected behavior, would this not do the trick? var myClass = (function(){ function myClass(){ var __priv = Object.create(this); var __this = __priv.__this = this; this.getTest = function(){ If you're willing to have functions as own properties in each instance, you need the method on the prototype any longer. If JS engines do their job properly, they will store the function body once and just create new function objects for each instance (which you do anyway, so it has no extra cost) return myClass.prototype.getTest.apply((this ===__this)?__priv:this, arguments); } __priv.test = 0; } myClass.prototype.getTest = function() { var __this = this.__this || this, __private = this; return __private.test; } return myClass; })(); Version with having a function on each instance: function myClass(){ var test = 0; this.getTest = function(){ return test; }; } No underscore ;-) Through the different messages we've shared, you've covered the different ways to do encapsulation and code sharing and the conclusion is that either you need to add a function to each object (which yield a linear cost for no reason) or your abstaction leaks if you want to prototype function to access per-object data. A last alternative is to associate private data via a WeakMap (it can be shimmed in ES5 with the same garbage collection properties and with good performances) that inherited functions all have access to. It works, but it's burdensome and doesn't read as well as object properties. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
Le 27/08/2012 21:22, Kevin Smith a écrit : A last alternative is to associate private data via a WeakMap (it can be shimmed in ES5 with the same garbage collection properties and with good performances) that inherited functions all have access to. It works, but it's burdensome and doesn't read as well as object properties. On the other hand, private names seem to add complexity to proxies A huge share of this complexity has been removed in recent discussions [1]. Conclusions seem to have reach consensus on es-discuss, but nothing has been officially accepted by TC39 and mixin composition. What do you mean? Private name allow to do mixins without collision. It seems to reduce the complexity than increasing it in my opinion. David [1] See discussion starting at https://mail.mozilla.org/pipermail/es-discuss/2012-July/024212.html ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Some questions about Private Name Objects
On Monday, August 27, 2012 at 3:34 PM, Matthew Robb wrote: In the end I am not looking for reads well, I am looking for minimal semantic difference that can ideally work as a target for compiling to es3. I am PREFERRING to not have functions as ownProperties. I can't use hard binding because if the function is assigned to some place else it should no longer be given access to the private name's it would have had as an instance method/property (I'm assuming this actually). I have done a little more playing around and am currently right about here: class myClass { private test; Just a heads up: max-min classes do not include support for declaring data properties or private variables in the class body. On a broader note, we discussed renaming Name to Symbol, here: https://mail.mozilla.org/pipermail/es-discuss/2012-August/024278.html Rick constructor() { this[test] = 0; } getTest() this[test]; doNothing(){} } COMPILES TO: var myClass = (function(){ var __myClass = function __myClass(__privates, __this) { // All class methods using private names would be defined here this.getTest = function() { // All appearances of this[test] would be replaced by the below ternary operation return (this === __this ? __privates : this).test; } return (__this (__this.__proto__ = this)) ? __privates : this; } var myClass = __myClass.prototype.constructor = function myClass() { var __privates = new __myClass({}, this); // Constructor body __privates.test = 0; } myClass.prototype = __myClass.prototype = new __myClass() myClass.prototype.doNothing = function(){} return myClass; })(); On Mon, Aug 27, 2012 at 3:17 PM, David Bruant bruan...@gmail.com (mailto:bruan...@gmail.com) wrote: Le 27/08/2012 19:54, Matthew Robb a écrit : I know this has some serious ugly to it but in the spirit of knowing what COULD potentially create the expected behavior, would this not do the trick? var myClass = (function(){ function myClass(){ var __priv = Object.create(this); var __this = __priv.__this = this; this.getTest = function(){ If you're willing to have functions as own properties in each instance, you need the method on the prototype any longer. If JS engines do their job properly, they will store the function body once and just create new function objects for each instance (which you do anyway, so it has no extra cost) return myClass.prototype.getTest.apply((this ===__this)?__priv:this, arguments); } __priv.test = 0; } myClass.prototype.getTest = function() { var __this = this.__this || this, __private = this; return __private.test; } return myClass; })(); Version with having a function on each instance: function myClass(){ var test = 0; this.getTest = function(){ return test; }; } No underscore ;-) Through the different messages we've shared, you've covered the different ways to do encapsulation and code sharing and the conclusion is that either you need to add a function to each object (which yield a linear cost for no reason) or your abstaction leaks if you want to prototype function to access per-object data. A last alternative is to associate private data via a WeakMap (it can be shimmed in ES5 with the same garbage collection properties and with good performances) that inherited functions all have access to. It works, but it's burdensome and doesn't read as well as object properties. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss