Also throwing this out there, symbols would now carry additional information: private or normal. Would it be better to configure this on objects instead?
E.g. `Object.setPropertySymbolVisibility(object, symbol, true / false)` (and then ideally sugar for this) That way a symbol's visibility on an object is information held on the object rather than the primitive. A little more work involved, but lines up with Object.defineProperty and symbols remain purely unique identifiers. On Monday, July 30, 2018, Isiah Meadows <[email protected]> wrote: > I'm aware it's possible to misuse, but if concerns of misuse were a > serious issue, we wouldn't have iterators, for example [1] [2]. But > IMHO freeing weak maps from a role they weren't designed for > substantially outweighs the risks of abusing them further (and the > abuses are incredibly frequent). > > [1]: https://esdiscuss.org/topic/iterators-generators-finally- > and-scarce-resources-was-april-10-2014-meeting-notes > [2]: https://esdiscuss.org/topic/resource-management > > ----- > > Isiah Meadows > [email protected] > www.isiahmeadows.com > > > On Sun, Jul 29, 2018 at 10:55 PM, Michael Theriot > <[email protected]> wrote: > > Right, I wouldn't, but I'm concerned others would misuse it. I don't > think > > it's a blocker though, and actually frees weakmaps from trying to fill > this > > role. > > > > > > On Sunday, July 29, 2018, Isiah Meadows <[email protected]> wrote: > >> > >> It will, but weak maps will still remain useful for cases when you're > >> semantically dealing with a key/value map. In theory, you could > >> implement a weak map on top of this [1], but in practice, it doesn't > >> always make sense to do it. A good example of this is if you are > >> "tagging" an object with data. If this data isn't really part of the > >> object itself, you shouldn't be using a private symbol for it. Another > >> good example is if you're doing simple caching and you need to clear > >> the weak map by replacing it. Using private symbols for this doesn't > >> really fit with the domain here, so you're more likely just to confuse > >> future readers (including yourself) if you do this. > >> > >> [1]: https://gist.github.com/isiahmeadows/ > a8494868c4b193dfbf7139589f472ad8 > >> ----- > >> > >> Isiah Meadows > >> [email protected] > >> www.isiahmeadows.com > >> > >> > >> On Sun, Jul 29, 2018 at 10:05 PM, Michael Theriot > >> <[email protected]> wrote: > >> > Private symbols sounds like an easy win. They would be painfully > simple, > >> > real properties, not just variables with property imitation syntax > that > >> > undoubtedly confuses people. With the added benefit that children can > >> > truly > >> > override the base class, freedom to define private members shared > across > >> > otherwise unrelated objects, and even injection. My only concern is > that > >> > it > >> > could cross into WeakMap use cases. > >> > > >> > > >> > On Sunday, July 29, 2018, Isiah Meadows <[email protected]> > wrote: > >> >> > >> >> BTW, I came up with an alternate proposal for privacy altogether: > >> >> https://github.com/tc39/proposal-class-fields/issues/115 > >> >> > >> >> TL;DR: private symbols that proxies can't see and that can't be > >> >> enumerated. > >> >> ----- > >> >> > >> >> Isiah Meadows > >> >> [email protected] > >> >> www.isiahmeadows.com > >> >> > >> >> > >> >> On Sun, Jul 29, 2018 at 12:23 AM, Darien Valentine > >> >> <[email protected]> wrote: > >> >> >> What you're essentially asking for is a violatable private field, > or > >> >> >> as > >> >> >> has been described by others, a "soft private". > >> >> > > >> >> > We might have different definitions here, but I would describe what > >> >> > I’m > >> >> > talking about as hard private. Soft private, at least as it appears > >> >> > to > >> >> > have > >> >> > been defined in [prior > >> >> > > >> >> > discussions](https://github.com/tc39/proposal-private- > fields/issues/33), > >> >> > described an avenue where symbol keyed properties were given a new > >> >> > syntactic > >> >> > form — but they were still just regular symbol keys, and therefore > >> >> > could > >> >> > be > >> >> > introspected by outside agents who had not been given express > >> >> > privilege > >> >> > to > >> >> > do so: > >> >> > > >> >> >> [...] the core would be that "private state" is simply (public) > >> >> >> symbol-named properties, with syntactic sugar for those symbols, > and > >> >> >> possibly some kind of introspection over them [...] > >> >> > > >> >> > The thread goes on to contrast the soft model with an earlier > version > >> >> > of > >> >> > the > >> >> > private fields proposal seen today. The hard private example uses > the > >> >> > class > >> >> > declaration as a pseudo-scope, but contrasting these two options as > >> >> > if > >> >> > they > >> >> > are binary is not accurate: hard private through > >> >> > module/function/block > >> >> > scope > >> >> > already exists, it is just difficult to work with in the context of > >> >> > shared > >> >> > prototypes — one must either use WeakMaps, technically giving > >> >> > _hardness_ > >> >> > because of the forgeability of `global.WeakMap` / > `WeakMap.prototype` > >> >> > / > >> >> > `WeakMap.prototype.get|has|set`, or be willing to either not worry > >> >> > about > >> >> > garbage collection or implement it manually. This could be solved > for > >> >> > with a > >> >> > few rather undramatic changes, though. > >> >> > > >> >> > Notably, the first post there lists the following as a disadvantage > >> >> > of > >> >> > the > >> >> > soft model it describes: > >> >> > > >> >> >> Platform objects, both within ECMAScript and in embedding > >> >> >> environments, > >> >> >> contain hard private state. If a library wants to be high-fidelity > >> >> >> and > >> >> >> just > >> >> >> like a platform object, soft-private state does not provide this > >> >> >> (@domenic) > >> >> > > >> >> > ...but neither model there quite covers that use case. Platform > >> >> > objects > >> >> > _can_ see each other’s private state (cf the `isView` example > >> >> > earlier, > >> >> > or > >> >> > scan the DOM API specs / Chrome source a bit to find numerous > >> >> > examples). > >> >> > It’s only the ES layer interacting with their interfaces that > cannot. > >> >> > > >> >> > Such things can be achieved with ordinary scope, which is why the > >> >> > WeakMap > >> >> > pattern has worked in practice in my experience to date, while > >> >> > class-declaration-scoped privacy has not. It isn’t uncommon for a > >> >> > library’s > >> >> > exposed interface to be composed of an object graph, where privacy > is > >> >> > a > >> >> > concern at this public interface level, but library internal state > >> >> > may > >> >> > be > >> >> > interconnected in unexposed ways under the hood. The most familiar > >> >> > example > >> >> > of this is a DOM node tree. As an experiment, perhaps try to > >> >> > implement > >> >> > the > >> >> > relationships between HTMLFormElement, HTMLFormControlsCollection > and > >> >> > the > >> >> > various form control elements using either the main private fields > >> >> > proposal > >> >> > or your alternative proposal and see what happens. > >> >> > > >> >> >> However, the guardian logic tries to verify that the function > trying > >> >> >> to > >> >> >> access the private fields of an instance is a member of the same > or > >> >> >> descending prototype that was used to create that instance. > >> >> > > >> >> > Because I’m looking at this in terms of slots, I’d first point out > >> >> > that > >> >> > prototypes don’t determine slottedness, the execution of some > >> >> > specific > >> >> > constructor does. It’s during this process that slots are > associated > >> >> > with > >> >> > the newly minted object by its identity. But even the current > private > >> >> > fields > >> >> > proposal tracks this behavior closely, and I’m not sure how else it > >> >> > could > >> >> > work. The [[Prototype]] slot of an object is typically mutable > >> >> > (`R|O.setPrototypeOf`, `__proto__`) and forgeable (Proxy’s > >> >> > `getPrototypeOf` > >> >> > trap). Why/how would its value matter when it comes to accessing > >> >> > private > >> >> > state? > >> >> > > >> >> > ```js > >> >> > const pattern = /foo/; > >> >> > Reflect.setPrototypeOf(pattern, Date.prototype); > >> >> > pattern instanceof Date; // true > >> >> > pattern instanceof RegExp; // false > >> >> > pattern.getMinutes(); // throws TypeError because [[DateValue]] > slot > >> >> > is > >> >> > missing > >> >> > RegExp.prototype.exec.call(pattern, 'foo'); // works; object has > >> >> > RegExp > >> >> > private slots > >> >> > ``` > >> >> > > >> >> >> If I removed that requirement, it would work. However, there'd be > no > >> >> >> way > >> >> >> to keep the private data from being leaked. Sadly, it's all or > >> >> >> nothing > >> >> >> with > >> >> >> this approach. Hard private or soft private, those are the only > >> >> >> choices. > >> >> > > >> >> > In the context of what you’ve described here this may be true, but > no > >> >> > such > >> >> > limitation presently exists. We can already do all this — hard, > >> >> > leak-free > >> >> > privacy, brandedness, “friends” etc — with scopes and WeakMaps, but > >> >> > for > >> >> > the > >> >> > fact that the `WeakMap` intrinsics may be forged. So what’s baffled > >> >> > me > >> >> > is > >> >> > this: why are all the proposals exploring this space not addressing > >> >> > that > >> >> > relatively simple existing problem, and instead starting off from a > >> >> > place of > >> >> > significant new complexity? You said “maybe after the private > fields > >> >> > problem > >> >> > has been resolved, someone will figure out a better way to handle > >> >> > your > >> >> > use > >> >> > cases,” but I’d have hoped for the opposite — I want the primitive > >> >> > building > >> >> > blocks which things like class field syntax could be built over, if > >> >> > it > >> >> > is > >> >> > found that they are still necessary once the root issue is solved > >> >> > for. > >> >> > > >> >> >> The main reason the privacy is set on a declaration level is > because > >> >> >> scope-level inheritance isn't very good for class-oriented > >> >> >> inheritance. > >> >> > > >> >> > Can you explain this more? I’m not sure what’s meant by > “scope-level > >> >> > inheritance” here. > >> >> > > >> >> >> I don't intend to stop [...] > >> >> > > >> >> > I very much admire your dedication! I’m also digging the > discussion. > >> >> > I > >> >> > think > >> >> > we may be representing viewpoints at opposite extremes here, so > it’s > >> >> > an > >> >> > interesting contrast, but it also probably means we may be lacking > >> >> > some > >> >> > context for understanding one another’s angles. I’d be curious to > >> >> > hear > >> >> > more > >> >> > about what you see as the problems with the current fields > proposal + > >> >> > how > >> >> > your members proposal would solve them; the repo readme didn’t seem > >> >> > to > >> >> > include a rationale section. > >> >> > > >> >> > On Sat, Jul 28, 2018 at 10:30 PM Ranando King <[email protected]> > >> >> > wrote: > >> >> >> > >> >> >> I've almost given up on making any significant headway in either > >> >> >> adjusting > >> >> >> or flat-out correcting the flaws in that proposal, but I don't > >> >> >> intend > >> >> >> to > >> >> >> stop trying until either we get stuck with that proposal, or they > >> >> >> understand > >> >> >> and accept what I'm telling them, or logically prove that my > >> >> >> concerns > >> >> >> are > >> >> >> either irrational or inconsequential. > >> >> >> > >> >> >> > Private object state in particular is only _made complex_ by > >> >> >> > associating > >> >> >> > it with declarations instead of scopes that happen to contain > >> >> >> > declarations > >> >> >> > (or into which constructors are passed, etc). The complexity is > >> >> >> > artificial — > >> >> >> > not a good sign imo. > >> >> >> > >> >> >> That's not quite right. What you're essentially asking for is a > >> >> >> violatable > >> >> >> private field, or as has been described by others, a "soft > private". > >> >> >> Since > >> >> >> we agree that the "friendly" & "befriend" pair is a somewhat (if > not > >> >> >> completely) bad idea, I'm going to take 1 more pass at your 3 > >> >> >> requests > >> >> >> with > >> >> >> a different angle. > >> >> >> > >> >> >> > Adding the same “slot” to multiple classes which don’t inherit > >> >> >> > from > >> >> >> > each > >> >> >> > other > >> >> >> > Selectively sharing access to private state through functions > >> >> >> > declared > >> >> >> > outside the class body > >> >> >> > >> >> >> ```js > >> >> >> //Using my proposal > >> >> >> var {A, B, C} = (() => { > >> >> >> const common = Symbol("common"); > >> >> >> > >> >> >> class A { > >> >> >> private [common] = 1; > >> >> >> add(...args) { > >> >> >> var retval = this#[common]; > >> >> >> for (let obj of args) { > >> >> >> retval += obj#[common]; > >> >> >> } > >> >> >> return retval; > >> >> >> } > >> >> >> } > >> >> >> class B { > >> >> >> private [common] = 2; > >> >> >> optional() { > >> >> >> console.log(`common member = ${this#[common]}`); > >> >> >> } > >> >> >> } > >> >> >> var C = { > >> >> >> private [common]: 3, > >> >> >> required() { > >> >> >> console.log(`common member = ${this#[common]}`); > >> >> >> } > >> >> >> } > >> >> >> > >> >> >> return { A, B, C }; > >> >> >> })(); > >> >> >> > >> >> >> //So you want the following statement to not throw a TypeError and > >> >> >> return > >> >> >> 6 > >> >> >> (new A()).add(new B(), C); > >> >> >> ``` > >> >> >> I'm not sure I can make this work in my proposal, and I'm > absolutely > >> >> >> sure > >> >> >> you'd be flatly refused by the other proposal. If a `Symbol` is > >> >> >> provided as > >> >> >> the `[[IdentifierName]]` of a private or protected field, then I > can > >> >> >> let > >> >> >> that `Symbol` be both the key and value that are added to the > >> >> >> `[[DeclarationInfo]]` and `[[InheritanceInfo]]` records. That way > >> >> >> there > >> >> >> will > >> >> >> be a common private field name usable by all 3 objects. However, > the > >> >> >> guardian logic tries to verify that the function trying to access > >> >> >> the > >> >> >> private fields of an instance is a member of the same or > descending > >> >> >> prototype that was used to create that instance. If I removed that > >> >> >> requirement, it would work. However, there'd be no way to keep the > >> >> >> private > >> >> >> data from being leaked. Sadly, it's all or nothing with this > >> >> >> approach. > >> >> >> Hard > >> >> >> private or soft private, those are the only choices. The TC39 > board > >> >> >> has > >> >> >> already decided that what they want new syntax for is hard > private. > >> >> >> > >> >> >> > Adding slots dynamically, e.g. when adding mix-in methods that > may > >> >> >> > initialize a new slot if necessary when called, since > subclassing > >> >> >> > is > >> >> >> > not > >> >> >> > always appropriate > >> >> >> > >> >> >> Because the TC39 board has set their sights on hard private, this > >> >> >> will > >> >> >> require new syntax like what I suggested earlier Adding private > >> >> >> members > >> >> >> dynamically would also pose a leak risk if it could be done after > >> >> >> the > >> >> >> prototype has been fully constructed. The main reason the privacy > is > >> >> >> set on > >> >> >> a declaration level is because scope-level inheritance isn't very > >> >> >> good > >> >> >> for > >> >> >> `class`-oriented inheritance. The `class` keyword was provided to > >> >> >> simplify > >> >> >> the vertical inheritance model, along with some API to enable > >> >> >> inheritance > >> >> >> from native objects even without using `class`. The syntax changes > >> >> >> for > >> >> >> simplifying private field declaration are just an extension of > that. > >> >> >> Even > >> >> >> though it's not unusual for some developers to spend a lot of time > >> >> >> working > >> >> >> with fringe use-cases, syntax changes are almost always going to > be > >> >> >> made for > >> >> >> the most common use cases first. Maybe after the private fields > >> >> >> problem > >> >> >> has > >> >> >> been resolved, someone will figure out a better way to handle your > >> >> >> use > >> >> >> cases. > >> >> >> > >> >> >> > >> >> >> On Sat, Jul 28, 2018 at 3:52 PM Darien Valentine > >> >> >> <[email protected]> > >> >> >> wrote: > >> >> >>> > >> >> >>> > Are you saying you want multiple non-hierarchally related > classes > >> >> >>> > to > >> >> >>> > have an instance private field with shared name [...] > >> >> >>> > >> >> >>> Yeah. This is a hard problem to solve when trying to integrate > >> >> >>> private > >> >> >>> fields with class syntax, but it’s not a problem at all when > >> >> >>> privacy > >> >> >>> is a > >> >> >>> more generic tool based on scope. This also isn’t a foreign > concept > >> >> >>> in > >> >> >>> ES: > >> >> >>> consider this intrinsic method: > >> >> >>> > >> >> >>> https://tc39.github.io/ecma262/#sec-arraybuffer.isview > >> >> >>> > >> >> >>> This method returns true if the argument has the > >> >> >>> `[[ViewedArrayBuffer]]` > >> >> >>> slot. This slot exists on genuine instances of both > `%TypedArray%` > >> >> >>> and > >> >> >>> `%DataView%`, but they do not receive these slots by way of > >> >> >>> inheritance from > >> >> >>> a common constructor. There are similar cases in HTML host APIs. > >> >> >>> > >> >> >>> > The befriend keyword would allow an object to request > friendship > >> >> >>> > with > >> >> >>> > an existing friendly object. I'm not sure this is a good idea, > >> >> >>> > though. > >> >> >>> > >> >> >>> I don’t think it is either, no. It’s too much complexity for too > >> >> >>> little > >> >> >>> gain. But again, this is achievable “for free” just by divorcing > >> >> >>> “private > >> >> >>> object state” from class declarations (or object literals). I > would > >> >> >>> ask: > >> >> >>> what problem is solved by making this a feature of the > declarations > >> >> >>> themselves? Does it merit the complexity and the hoop jumping > >> >> >>> needed > >> >> >>> to > >> >> >>> handle edge cases?\* > >> >> >>> > >> >> >>> \* One person’s edge case; another’s everyday concern haha. > >> >> >>> > >> >> >>> > The example you gave above still declares the functions in > >> >> >>> > question > >> >> >>> > inside the class body, so that's not really a solution. > >> >> >>> > >> >> >>> If you’re referring to the first example, that is a demonstration > >> >> >>> of > >> >> >>> what > >> >> >>> is possible using the existing stage 3 class fields proposal as > >> >> >>> implemented > >> >> >>> in Chrome. It isn’t what I want; it’s what’s necessary to achieve > >> >> >>> this > >> >> >>> with > >> >> >>> the current stage 3 proposed model. > >> >> >>> > >> >> >>> > Sounds to me like you'd love for class syntax to look like this > >> >> >>> > [[example with mixin syntax in declaration]] > >> >> >>> > >> >> >>> Perhaps — it’s interesting for sure! But the pattern that already > >> >> >>> works, > >> >> >>> `mixin(Cstr)`, is not presently a source of problems for me. > >> >> >>> Private > >> >> >>> object > >> >> >>> state in particular is only _made complex_ by associating it with > >> >> >>> declarations instead of scopes that happen to contain > declarations > >> >> >>> (or > >> >> >>> into > >> >> >>> which constructors are passed, etc). The complexity is > artificial — > >> >> >>> not a > >> >> >>> good sign imo. > >> >> >>> > >> >> >>> > One thing both proposal-class-fields and > proposal-object-members > >> >> >>> > have > >> >> >>> > in common is that the focus is on producing instance-private > >> >> >>> > fields. > >> >> >>> > All 3 > >> >> >>> > of the scenarios you presented lay outside of that focus for > one > >> >> >>> > reason or > >> >> >>> > another. > >> >> >>> > >> >> >>> Both the WeakMap solution and the stub concept I provided after > are > >> >> >>> more > >> >> >>> generic than privacy in either of those proposals. When I say > >> >> >>> "object > >> >> >>> private state," it’s true that the object in question could be > any > >> >> >>> object. > >> >> >>> But in practice, any realization of the feature would pertain > >> >> >>> chiefly > >> >> >>> to > >> >> >>> class instances, and the examples I gave, though contrived, do > >> >> >>> concern > >> >> >>> class > >> >> >>> instances. The reason private object state is chiefly an issue of > >> >> >>> class > >> >> >>> instances stems directly from the nature of prototype methods and > >> >> >>> accessors, > >> >> >>> so if you are not making use of prototypes, you could instead > have > >> >> >>> used a > >> >> >>> closure+factory directly. > >> >> >>> > >> >> >>> --- > >> >> >>> > >> >> >>> In a nutshell, my issue with existing proposals could probably be > >> >> >>> summarized as a concern that they are neither as generic nor as > >> >> >>> simple > >> >> >>> as > >> >> >>> native slots. To be clear, proper “slots” are an internal > concept, > >> >> >>> only > >> >> >>> observable indirectly — but they are the special sauce > underlying a > >> >> >>> number > >> >> >>> of behaviors which are presently awkward to achieve in ES code > >> >> >>> itself, > >> >> >>> and > >> >> >>> they are a nice simple model of private object state which is > >> >> >>> tantalizingly > >> >> >>> close to, but not _exactly_ the same as in two critical ways, > >> >> >>> symbol > >> >> >>> keyed > >> >> >>> properties. That said, “real” slots would continue to have an > >> >> >>> advantage with > >> >> >>> regard to cross-realm stuff even if private symbol keys existed. > >> >> >>> > >> >> >>> That such a model is radically simpler — minmax and all that — > >> >> >>> feels > >> >> >>> very > >> >> >>> important to me, but I dunno. I’m not holding my breath for big > >> >> >>> changes > >> >> >>> here. The current stage 3 proposal seems to be unstoppable; much > >> >> >>> smarter / > >> >> >>> more important people than me have already tried and failed. :) > >> >> >>> > >> >> >>> > >> >> >>> On Sat, Jul 28, 2018 at 3:14 PM Ranando King <[email protected]> > >> >> >>> wrote: > >> >> >>>> > >> >> >>>> In a word... wow. You've got me thinking hard here. Those are > some > >> >> >>>> peculiar use cases, and they do a great job of highlighting why > >> >> >>>> someone > >> >> >>>> might forego using `class`. One thing both proposal-class-fields > >> >> >>>> and > >> >> >>>> proposal-object-members have in common is that the focus is on > >> >> >>>> producing > >> >> >>>> instance-private fields. All 3 of the scenarios you presented > lay > >> >> >>>> outside of > >> >> >>>> that focus for one reason or another. > >> >> >>>> > >> >> >>>> > Adding the same “slot” to multiple classes which don’t inherit > >> >> >>>> > from > >> >> >>>> > each other > >> >> >>>> > >> >> >>>> I'm a little confused by this one. Are you saying you want > >> >> >>>> multiple > >> >> >>>> non-hierarchally related classes to have an instance private > field > >> >> >>>> with > >> >> >>>> shared name, such that the same private field name refers to a > >> >> >>>> distinct and > >> >> >>>> separate field on each instance of every such class, but where > any > >> >> >>>> such > >> >> >>>> instance can have that field referenced by that shared name from > >> >> >>>> any > >> >> >>>> member > >> >> >>>> function of the corresponding classes? (Wow that was wordy to > >> >> >>>> write > >> >> >>>> out...) > >> >> >>>> If this is what you meant, you're describing friend classes. The > >> >> >>>> top-down > >> >> >>>> processing nature of ES makes this a difficult thing to create a > >> >> >>>> clean > >> >> >>>> syntax for without risking leaking the private state or > >> >> >>>> fundamentally > >> >> >>>> altering how ES is processed. Mutual friendship is even harder. > >> >> >>>> > >> >> >>>> ... and yet I just thought of a way to do it. By telling you > this > >> >> >>>> I'm > >> >> >>>> leaving myself to consider writing a proposal containing 2 new > >> >> >>>> keywords: > >> >> >>>> `befriend` and `friendly`. I don't know if this can be done with > >> >> >>>> the > >> >> >>>> existing proposal being what it is. However, with my proposal, > >> >> >>>> there's a > >> >> >>>> chance. The `friendly` keyword would declare that an object is > >> >> >>>> prepared to > >> >> >>>> share select information with any object that befriends it. The > >> >> >>>> `befriend` > >> >> >>>> keyword would allow an object to request friendship with an > >> >> >>>> existing > >> >> >>>> friendly object. I'm not sure this is a good idea, though. This > >> >> >>>> means > >> >> >>>> that > >> >> >>>> any object declared 'friendly' is automatically insecure as all > it > >> >> >>>> takes to > >> >> >>>> gain access to the selected members of its private space would > be > >> >> >>>> to > >> >> >>>> 'befriend' it. > >> >> >>>> > >> >> >>>> > Selectively sharing access to private state through functions > >> >> >>>> > declared > >> >> >>>> > outside the class body > >> >> >>>> > >> >> >>>> The example you gave above still declares the functions in > >> >> >>>> question > >> >> >>>> inside the `class` body, so that's not really a solution. If the > >> >> >>>> example you > >> >> >>>> gave actually solves your use case, then what you're asking for > >> >> >>>> here > >> >> >>>> isn't > >> >> >>>> even needed. If, however, that was a bad example, then it sounds > >> >> >>>> like > >> >> >>>> you're > >> >> >>>> looking for friend functions. See the previous section. > >> >> >>>> > >> >> >>>> > Adding slots dynamically, e.g. when adding mix-in methods that > >> >> >>>> > may > >> >> >>>> > initialize a new slot if necessary when called, since > >> >> >>>> > subclassing > >> >> >>>> > is not > >> >> >>>> > always appropriate > >> >> >>>> > >> >> >>>> Sounds to me like you'd love for `class` syntax to look like > this: > >> >> >>>> > >> >> >>>> ```js > >> >> >>>> class [<identifierName1>] [extends <identifierName2>] [mixes > >> >> >>>> <identifierName3>[, <identifierName3>[, ...]]] { ... } > >> >> >>>> ``` > >> >> >>>> so that the private fields of the objects in the `mixes` list > are > >> >> >>>> added > >> >> >>>> to the set of private fields provided by the `class` definition > >> >> >>>> directly. > >> >> >>>> That would also require another proposal, but I think that can > be > >> >> >>>> done > >> >> >>>> regardless of which instance-private fields proposal gets > >> >> >>>> accepted. > >> >> >>>> > >> >> >>>> On Sat, Jul 28, 2018 at 12:49 PM Darien Valentine > >> >> >>>> <[email protected]> wrote: > >> >> >>>>> > >> >> >>>>> To put this another, much briefer way, here’s a hypothetical > >> >> >>>>> model > >> >> >>>>> for > >> >> >>>>> associating private state with objects that would cover me. > >> >> >>>>> Privacy > >> >> >>>>> would be > >> >> >>>>> provided... > >> >> >>>>> > >> >> >>>>> 1. in the form of symbolic keys whose presence cannot be > observed > >> >> >>>>> (i.e., they would not be exposed by `getOwnPropertySymbols`) > >> >> >>>>> 2. and which have a syntactic declaration so that one can be > sure > >> >> >>>>> they > >> >> >>>>> are really getting private keys (i.e., an api like > >> >> >>>>> `Symbol.private()` > >> >> >>>>> wouldn’t work) > >> >> >>>>> > >> >> >>>>> ``` > >> >> >>>>> const bar = private(); > >> >> >>>>> > >> >> >>>>> // alternatively: const #bar; could be anything so long as it’s > >> >> >>>>> syntactic > >> >> >>>>> > >> >> >>>>> class Foo { > >> >> >>>>> constructor() { > >> >> >>>>> this[bar] = 1; > >> >> >>>>> } > >> >> >>>>> } > >> >> >>>>> > >> >> >>>>> // etc > >> >> >>>>> ``` > >> >> >>>>> > >> >> >>>>> The keys would be typeof 'symbol'; the only difference being > that > >> >> >>>>> they > >> >> >>>>> are symbols which are flagged as private when created. They > would > >> >> >>>>> be > >> >> >>>>> permitted only in syntactic property assignments and accesses. > >> >> >>>>> Existing > >> >> >>>>> reflection utilities would disallow the use or appearance of > such > >> >> >>>>> symbols > >> >> >>>>> both to ensure privacy and to maintain the invariant that they > >> >> >>>>> are > >> >> >>>>> always > >> >> >>>>> simple data properties: > >> >> >>>>> > >> >> >>>>> ```js > >> >> >>>>> Reflect.defineProperty({}, #bar, { ... }); // throws type error > >> >> >>>>> Object.getOwnPropertyDescriptors(someObjWithAPrivateSlot); // > >> >> >>>>> does > >> >> >>>>> not > >> >> >>>>> include it > >> >> >>>>> foo[bar] = 2; // fine > >> >> >>>>> ``` > >> >> >>>>> > >> >> >>>>> This is significantly simpler than what’s in flight both in > terms > >> >> >>>>> of > >> >> >>>>> syntax and mechanics, which makes me suspicious that I’m > probably > >> >> >>>>> ignoring > >> >> >>>>> things that other people find important. However it would bring > >> >> >>>>> parity to ES > >> >> >>>>> objects wrt being able to implement genuinely private slots in > >> >> >>>>> userland with > >> >> >>>>> the same flexibility as what is done internally. > >> >> >>>>> > >> >> >>>>> In total, this entails a new primary expression, a boolean flag > >> >> >>>>> associated with symbol values, and an extra step added to > several > >> >> >>>>> algorithms > >> >> >>>>> associated with Object and Reflect. > >> >> >>>>> _______________________________________________ > >> >> >>>>> 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 > >> >> > > >> >> _______________________________________________ > >> >> 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

