Re: !Re: proposal: Object Members
> To discover what's written into the supposedly private x, just call SetX on an object that's not an instance of Foo. Actually, it's fairly trivial to avoid that issue in the engine. As long as both objects and functions know what private data they have access to, then all you need is a check to determine whether or not the object instance has access to the same private data as the function. If not, throw a TypeError et voilà, no leaks. That's part of how my POC works. The real difficulty with not having a marker on the access comes only because JS programmers are so very used to being able to tack a new property on to any object they see, and readily abuse this capability to amazing effect. Given that only the creator of an object should be able to manage its private properties, and that these properties must always exist even if undefined (they're considered implementation details), property access quickly becomes a minefield as objects with private members pass through code intent on attaching new public members, even if they're just temporary. On Tue, Aug 7, 2018 at 4:29 PM Waldemar Horwat wrote: > On 08/03/2018 08:30 PM, Bob Myers wrote: > > > `private`, `protected`, `class`, and a few other such keywords have > all been part of ES since long be for the TC39 board got their hands on it. > They hadn't been implemented, but they were all a very real part of ES. > > > > Whoa. Is that just misinformed or intentionally misleading? They have > never been "part of ES" in any meaningful sense. It was not that they had > not been implemented; it was that they had not even been defined. To say > they are a "real part of ES" is a strange interpretation of the meaning of > the word "real". The notion that we would choose features to work on based > on some designation of certain keywords as reserved long ago, and that they > are now "languishing", is odd. Why not focus on "implementing" enum, or > final, or throws, or any other of the dozens of reserved words? > > > > Having said that, I think it is a valid general principle that as > language designers we should be very reluctant to use magic characters. > `**` is fine, of course, as is `=>`, or even `@` for decorators. > Personally, I don't think the problem of access modifiers rises to the > level of commonality and need for conciseness that would justify eating up > another magic character. We also don't want JS to start looking like Perl > or APL. > > > > Speaking as a self-appointed representative of Plain Old Programmers, I > do feel a need for private fields, although it was probably starting to > program more in TS that got me thinking that way. However, to me it feels > odd to tie this directly to `class` syntax. Why can't I have a private > field in a plain old object like `{a: 1}` (i.e., that would only be > accessible via a method on that object? We already have properties which > are enumerable and writable, for example, independent of the class > mechanism. Why not have properties which are private in the same way? > > > > The problem,of course, is that even assuming the engines implemented the > `private` property on descriptors, I obviously don't want to have to write > `Object.create({}, {a: {value: 22, private: true})`. So the problem can be > restated as trying to find some nice sugar for writing the above. You > know, something like `{a: 22}`. That's obviously a completely > random syntax suggestion, just to show the idea. Perhaps we'd prefer to > have the access modifiers be specifiable under program control as an object > itself, to allow something like > > > > ``` > > const PRIVATE = {private: true}; > > > > const myObject = {a(: 2; } > > ``` > > > > But what would the precise meaning of such as `private` descriptor > property be? In operational terms, it could suffice to imagine (as a > behavior, not as an implementation strategy) that objects would have a flag > that would skip over private properties when doing property lookups. I > think the right implementation is to have a private property look like it's > not there at all when access is attempted from outside the object (in other > words, is undefined), rather than some kind of `PrivatePropertyAccessError`. > > > > The above approach ought to be extensible to class notation: > > > > ``` > > class Foo ( > >bar(): { return 22; } > > } > > ``` > > > > which would end up being something like > `Object.defineProperty(Foo.prototype, "bar", {value() {return 22; }, > private: true})`. > > > > Or when classes get instance variables: > > > > ``` > > class Foo { > >bar = 22; > > ``` > > > > Was anything along these lines already brought up in this discussion? > > Yes. There are a couple answers: > > - If you have the marker on both definitions and accesses of the > property, then you get a proposal that's essentially isomorphic to the > committee's current private proposal. > > - If you have the marker on definitions but not accesses of the > property, then the proposal lea
Re: !Re: proposal: Object Members
On 08/03/2018 08:30 PM, Bob Myers wrote: > `private`, `protected`, `class`, and a few other such keywords have all been part of ES since long be for the TC39 board got their hands on it. They hadn't been implemented, but they were all a very real part of ES. Whoa. Is that just misinformed or intentionally misleading? They have never been "part of ES" in any meaningful sense. It was not that they had not been implemented; it was that they had not even been defined. To say they are a "real part of ES" is a strange interpretation of the meaning of the word "real". The notion that we would choose features to work on based on some designation of certain keywords as reserved long ago, and that they are now "languishing", is odd. Why not focus on "implementing" enum, or final, or throws, or any other of the dozens of reserved words? Having said that, I think it is a valid general principle that as language designers we should be very reluctant to use magic characters. `**` is fine, of course, as is `=>`, or even `@` for decorators. Personally, I don't think the problem of access modifiers rises to the level of commonality and need for conciseness that would justify eating up another magic character. We also don't want JS to start looking like Perl or APL. Speaking as a self-appointed representative of Plain Old Programmers, I do feel a need for private fields, although it was probably starting to program more in TS that got me thinking that way. However, to me it feels odd to tie this directly to `class` syntax. Why can't I have a private field in a plain old object like `{a: 1}` (i.e., that would only be accessible via a method on that object? We already have properties which are enumerable and writable, for example, independent of the class mechanism. Why not have properties which are private in the same way? The problem,of course, is that even assuming the engines implemented the `private` property on descriptors, I obviously don't want to have to write `Object.create({}, {a: {value: 22, private: true})`. So the problem can be restated as trying to find some nice sugar for writing the above. You know, something like `{a: 22}`. That's obviously a completely random syntax suggestion, just to show the idea. Perhaps we'd prefer to have the access modifiers be specifiable under program control as an object itself, to allow something like ``` const PRIVATE = {private: true}; const myObject = {a(: 2; } ``` But what would the precise meaning of such as `private` descriptor property be? In operational terms, it could suffice to imagine (as a behavior, not as an implementation strategy) that objects would have a flag that would skip over private properties when doing property lookups. I think the right implementation is to have a private property look like it's not there at all when access is attempted from outside the object (in other words, is undefined), rather than some kind of `PrivatePropertyAccessError`. The above approach ought to be extensible to class notation: ``` class Foo ( bar(): { return 22; } } ``` which would end up being something like `Object.defineProperty(Foo.prototype, "bar", {value() {return 22; }, private: true})`. Or when classes get instance variables: ``` class Foo { bar = 22; ``` Was anything along these lines already brought up in this discussion? Yes. There are a couple answers: - If you have the marker on both definitions and accesses of the property, then you get a proposal that's essentially isomorphic to the committee's current private proposal. - If you have the marker on definitions but not accesses of the property, then the proposal leaks private state like a sieve: For example: class Foo ( x; SetX() {this.x = ;} } To discover what's written into the supposedly private x, just call SetX on an object that's not an instance of Foo. There are analogous examples for reading instead of writing. Waldemar ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: !Re: proposal: Object Members
You might want to consider it "intentionally misleading", but when I say that they are a "real part of ES", I mean that when they are present under certain circumstances, ES will take on behavior it wouldn't have if the words had not been reserved. Does that mean those words are of any practical use in the language? **NO**. However, the simple fact that the behavior of the language changes as a result of their appearance makes them a part of the language, albeit useless. However, all this has no logical merit for my reason to use them. So believe what you will. I just wanted to see how people would respond. That gives me a bit of useful information about how to word my proposal as I make adjustments. On Fri, Aug 3, 2018 at 10:32 PM Bob Myers wrote: > > `private`, `protected`, `class`, and a few other such keywords have all > been part of ES since long be for the TC39 board got their hands on it. > They hadn't been implemented, but they were all a very real part of ES. > > Whoa. Is that just misinformed or intentionally misleading? They have > never been "part of ES" in any meaningful sense. It was not that they had > not been implemented; it was that they had not even been defined. To say > they are a "real part of ES" is a strange interpretation of the meaning of > the word "real". The notion that we would choose features to work on based > on some designation of certain keywords as reserved long ago, and that they > are now "languishing", is odd. Why not focus on "implementing" enum, or > final, or throws, or any other of the dozens of reserved words? > > Having said that, I think it is a valid general principle that as language > designers we should be very reluctant to use magic characters. `**` is > fine, of course, as is `=>`, or even `@` for decorators. Personally, I > don't think the problem of access modifiers rises to the level of > commonality and need for conciseness that would justify eating up another > magic character. We also don't want JS to start looking like Perl or APL. > > Speaking as a self-appointed representative of Plain Old Programmers, I do > feel a need for private fields, although it was probably starting to > program more in TS that got me thinking that way. However, to me it feels > odd to tie this directly to `class` syntax. Why can't I have a private > field in a plain old object like `{a: 1}` (i.e., that would only be > accessible via a method on that object? We already have properties which > are enumerable and writable, for example, independent of the class > mechanism. Why not have properties which are private in the same way? > > The problem,of course, is that even assuming the engines implemented the > `private` property on descriptors, I obviously don't want to have to write > `Object.create({}, {a: {value: 22, private: true})`. So the problem can be > restated as trying to find some nice sugar for writing the above. You > know, something like `{a: 22}`. That's obviously a completely > random syntax suggestion, just to show the idea. Perhaps we'd prefer to > have the access modifiers be specifiable under program control as an object > itself, to allow something like > > ``` > const PRIVATE = {private: true}; > > const myObject = {a(: 2; } > ``` > > But what would the precise meaning of such as `private` descriptor > property be? In operational terms, it could suffice to imagine (as a > behavior, not as an implementation strategy) that objects would have a flag > that would skip over private properties when doing property lookups. I > think the right implementation is to have a private property look like it's > not there at all when access is attempted from outside the object (in other > words, is undefined), rather than some kind of `PrivatePropertyAccessError`. > > The above approach ought to be extensible to class notation: > > ``` > class Foo ( > bar(): { return 22; } > } > ``` > > which would end up being something like > `Object.defineProperty(Foo.prototype, "bar", {value() {return 22; }, > private: true})`. > > Or when classes get instance variables: > > ``` > class Foo { > bar = 22; > ``` > > Was anything along these lines already brought up in this discussion? > > Bob > > > On Sat, Aug 4, 2018 at 12:30 AM Ranando King wrote: > >> > It certainly doesn't look or feel like JS - it feels more like Java or >> C#. >> >> `private`, `protected`, `class`, and a few other such keywords have all >> been part of ES since long be for the TC39 board got their hands on it. >> They hadn't been implemented, but they were all a very real part of ES. Now >> that `class` has been implemented, it makes little sense to leave behind >> the `private` and `protected` keywords when we are trying to implement >> their functionality. >> >> > `private` looks like an identifier, and IMHO getters, setters, and >> async functions suffer the same issue of the keyword seeming to blend in a >> little with surrounding code. >> >> Have you ever thought that `var` or `let` look like id
Re: !Re: proposal: Object Members
to Bob: Minor correction. One other thing both proposals agree on is that dynamic addition of private properties is a bad idea. So the use of Object.defineProperty() is simply a non-starter. On Sat, Aug 4, 2018 at 2:40 PM Ranando King wrote: > to Bob Myers: > This is exactly the kind of private both proposal-class-fields and > proposal-object-members is proposing. The main differences between the two > are the syntax and the fact that mine also allows such fields to be defined > directly on objects. > > to Michael Theriot: > Turns out that if the implementation is sound, the same mechanism that > works for class declarations also works for object declarations. The only > extra bit required is that the language parser has to recognize the feature. > > On Sat, Aug 4, 2018 at 2:29 PM Michael Theriot < > michael.lee.ther...@gmail.com> wrote: > >> I also agree private properties / instance variables should not be >> class-exclusive. >> >> I was a big fan of the syntax used in the JavaScript Classes 1.1 proposal >> (https://github.com/zenparsing/js-classes-1.1#1-instance-variables) and >> always felt like it could have been painlessly extended to plain old >> objects. >> >> On Fri, Aug 3, 2018 at 11:30 PM, Bob Myers wrote: >> >>> > `private`, `protected`, `class`, and a few other such keywords have >>> all been part of ES since long be for the TC39 board got their hands on >>> it. They hadn't been implemented, but they were all a very real part of >>> ES. >>> >>> Whoa. Is that just misinformed or intentionally misleading? They have >>> never been "part of ES" in any meaningful sense. It was not that they had >>> not been implemented; it was that they had not even been defined. To say >>> they are a "real part of ES" is a strange interpretation of the meaning of >>> the word "real". The notion that we would choose features to work on based >>> on some designation of certain keywords as reserved long ago, and that they >>> are now "languishing", is odd. Why not focus on "implementing" enum, or >>> final, or throws, or any other of the dozens of reserved words? >>> >>> Having said that, I think it is a valid general principle that as >>> language designers we should be very reluctant to use magic characters. >>> `**` is fine, of course, as is `=>`, or even `@` for decorators. >>> Personally, I don't think the problem of access modifiers rises to the >>> level of commonality and need for conciseness that would justify eating up >>> another magic character. We also don't want JS to start looking like Perl >>> or APL. >>> >>> Speaking as a self-appointed representative of Plain Old Programmers, I >>> do feel a need for private fields, although it was probably starting to >>> program more in TS that got me thinking that way. However, to me it feels >>> odd to tie this directly to `class` syntax. Why can't I have a private >>> field in a plain old object like `{a: 1}` (i.e., that would only be >>> accessible via a method on that object? We already have properties which >>> are enumerable and writable, for example, independent of the class >>> mechanism. Why not have properties which are private in the same way? >>> >>> The problem,of course, is that even assuming the engines implemented the >>> `private` property on descriptors, I obviously don't want to have to write >>> `Object.create({}, {a: {value: 22, private: true})`. So the problem can be >>> restated as trying to find some nice sugar for writing the above. You >>> know, something like `{a: 22}`. That's obviously a completely >>> random syntax suggestion, just to show the idea. Perhaps we'd prefer to >>> have the access modifiers be specifiable under program control as an object >>> itself, to allow something like >>> >>> ``` >>> const PRIVATE = {private: true}; >>> >>> const myObject = {a(: 2; } >>> ``` >>> >>> But what would the precise meaning of such as `private` descriptor >>> property be? In operational terms, it could suffice to imagine (as a >>> behavior, not as an implementation strategy) that objects would have a flag >>> that would skip over private properties when doing property lookups. I >>> think the right implementation is to have a private property look like it's >>> not there at all when access is attempted from outside the object (in other >>> words, is undefined), rather than some kind of `PrivatePropertyAccessError`. >>> >>> The above approach ought to be extensible to class notation: >>> >>> ``` >>> class Foo ( >>> bar(): { return 22; } >>> } >>> ``` >>> >>> which would end up being something like >>> `Object.defineProperty(Foo.prototype, "bar", {value() {return 22; }, >>> private: true})`. >>> >>> Or when classes get instance variables: >>> >>> ``` >>> class Foo { >>> bar = 22; >>> ``` >>> >>> Was anything along these lines already brought up in this discussion? >>> >>> Bob >>> >>> >>> On Sat, Aug 4, 2018 at 12:30 AM Ranando King wrote: >>> > It certainly doesn't look or feel like JS - it feels more like Java or C#.
Re: !Re: proposal: Object Members
to Bob Myers: This is exactly the kind of private both proposal-class-fields and proposal-object-members is proposing. The main differences between the two are the syntax and the fact that mine also allows such fields to be defined directly on objects. to Michael Theriot: Turns out that if the implementation is sound, the same mechanism that works for class declarations also works for object declarations. The only extra bit required is that the language parser has to recognize the feature. On Sat, Aug 4, 2018 at 2:29 PM Michael Theriot < michael.lee.ther...@gmail.com> wrote: > I also agree private properties / instance variables should not be > class-exclusive. > > I was a big fan of the syntax used in the JavaScript Classes 1.1 proposal ( > https://github.com/zenparsing/js-classes-1.1#1-instance-variables) and > always felt like it could have been painlessly extended to plain old > objects. > > On Fri, Aug 3, 2018 at 11:30 PM, Bob Myers wrote: > >> > `private`, `protected`, `class`, and a few other such keywords have >> all been part of ES since long be for the TC39 board got their hands on >> it. They hadn't been implemented, but they were all a very real part of >> ES. >> >> Whoa. Is that just misinformed or intentionally misleading? They have >> never been "part of ES" in any meaningful sense. It was not that they had >> not been implemented; it was that they had not even been defined. To say >> they are a "real part of ES" is a strange interpretation of the meaning of >> the word "real". The notion that we would choose features to work on based >> on some designation of certain keywords as reserved long ago, and that they >> are now "languishing", is odd. Why not focus on "implementing" enum, or >> final, or throws, or any other of the dozens of reserved words? >> >> Having said that, I think it is a valid general principle that as >> language designers we should be very reluctant to use magic characters. >> `**` is fine, of course, as is `=>`, or even `@` for decorators. >> Personally, I don't think the problem of access modifiers rises to the >> level of commonality and need for conciseness that would justify eating up >> another magic character. We also don't want JS to start looking like Perl >> or APL. >> >> Speaking as a self-appointed representative of Plain Old Programmers, I >> do feel a need for private fields, although it was probably starting to >> program more in TS that got me thinking that way. However, to me it feels >> odd to tie this directly to `class` syntax. Why can't I have a private >> field in a plain old object like `{a: 1}` (i.e., that would only be >> accessible via a method on that object? We already have properties which >> are enumerable and writable, for example, independent of the class >> mechanism. Why not have properties which are private in the same way? >> >> The problem,of course, is that even assuming the engines implemented the >> `private` property on descriptors, I obviously don't want to have to write >> `Object.create({}, {a: {value: 22, private: true})`. So the problem can be >> restated as trying to find some nice sugar for writing the above. You >> know, something like `{a: 22}`. That's obviously a completely >> random syntax suggestion, just to show the idea. Perhaps we'd prefer to >> have the access modifiers be specifiable under program control as an object >> itself, to allow something like >> >> ``` >> const PRIVATE = {private: true}; >> >> const myObject = {a(: 2; } >> ``` >> >> But what would the precise meaning of such as `private` descriptor >> property be? In operational terms, it could suffice to imagine (as a >> behavior, not as an implementation strategy) that objects would have a flag >> that would skip over private properties when doing property lookups. I >> think the right implementation is to have a private property look like it's >> not there at all when access is attempted from outside the object (in other >> words, is undefined), rather than some kind of `PrivatePropertyAccessError`. >> >> The above approach ought to be extensible to class notation: >> >> ``` >> class Foo ( >> bar(): { return 22; } >> } >> ``` >> >> which would end up being something like >> `Object.defineProperty(Foo.prototype, "bar", {value() {return 22; }, >> private: true})`. >> >> Or when classes get instance variables: >> >> ``` >> class Foo { >> bar = 22; >> ``` >> >> Was anything along these lines already brought up in this discussion? >> >> Bob >> >> >> On Sat, Aug 4, 2018 at 12:30 AM Ranando King wrote: >> >>> > It certainly doesn't look or feel like JS - it feels more like Java >>> or C#. >>> >>> `private`, `protected`, `class`, and a few other such keywords have all >>> been part of ES since long be for the TC39 board got their hands on it. >>> They hadn't been implemented, but they were all a very real part of ES. Now >>> that `class` has been implemented, it makes little sense to leave behind >>> the `private` and `protected` keywords when w
Re: !Re: proposal: Object Members
I also agree private properties / instance variables should not be class-exclusive. I was a big fan of the syntax used in the JavaScript Classes 1.1 proposal ( https://github.com/zenparsing/js-classes-1.1#1-instance-variables) and always felt like it could have been painlessly extended to plain old objects. On Fri, Aug 3, 2018 at 11:30 PM, Bob Myers wrote: > > `private`, `protected`, `class`, and a few other such keywords have all > been part of ES since long be for the TC39 board got their hands on it. > They hadn't been implemented, but they were all a very real part of ES. > > Whoa. Is that just misinformed or intentionally misleading? They have > never been "part of ES" in any meaningful sense. It was not that they had > not been implemented; it was that they had not even been defined. To say > they are a "real part of ES" is a strange interpretation of the meaning of > the word "real". The notion that we would choose features to work on based > on some designation of certain keywords as reserved long ago, and that they > are now "languishing", is odd. Why not focus on "implementing" enum, or > final, or throws, or any other of the dozens of reserved words? > > Having said that, I think it is a valid general principle that as language > designers we should be very reluctant to use magic characters. `**` is > fine, of course, as is `=>`, or even `@` for decorators. Personally, I > don't think the problem of access modifiers rises to the level of > commonality and need for conciseness that would justify eating up another > magic character. We also don't want JS to start looking like Perl or APL. > > Speaking as a self-appointed representative of Plain Old Programmers, I do > feel a need for private fields, although it was probably starting to > program more in TS that got me thinking that way. However, to me it feels > odd to tie this directly to `class` syntax. Why can't I have a private > field in a plain old object like `{a: 1}` (i.e., that would only be > accessible via a method on that object? We already have properties which > are enumerable and writable, for example, independent of the class > mechanism. Why not have properties which are private in the same way? > > The problem,of course, is that even assuming the engines implemented the > `private` property on descriptors, I obviously don't want to have to write > `Object.create({}, {a: {value: 22, private: true})`. So the problem can be > restated as trying to find some nice sugar for writing the above. You > know, something like `{a: 22}`. That's obviously a completely > random syntax suggestion, just to show the idea. Perhaps we'd prefer to > have the access modifiers be specifiable under program control as an object > itself, to allow something like > > ``` > const PRIVATE = {private: true}; > > const myObject = {a(: 2; } > ``` > > But what would the precise meaning of such as `private` descriptor > property be? In operational terms, it could suffice to imagine (as a > behavior, not as an implementation strategy) that objects would have a flag > that would skip over private properties when doing property lookups. I > think the right implementation is to have a private property look like it's > not there at all when access is attempted from outside the object (in other > words, is undefined), rather than some kind of `PrivatePropertyAccessError`. > > The above approach ought to be extensible to class notation: > > ``` > class Foo ( > bar(): { return 22; } > } > ``` > > which would end up being something like `Object.defineProperty(Foo.prototype, > "bar", {value() {return 22; }, private: true})`. > > Or when classes get instance variables: > > ``` > class Foo { > bar = 22; > ``` > > Was anything along these lines already brought up in this discussion? > > Bob > > > On Sat, Aug 4, 2018 at 12:30 AM Ranando King wrote: > >> > It certainly doesn't look or feel like JS - it feels more like Java or >> C#. >> >> `private`, `protected`, `class`, and a few other such keywords have all >> been part of ES since long be for the TC39 board got their hands on it. >> They hadn't been implemented, but they were all a very real part of ES. Now >> that `class` has been implemented, it makes little sense to leave behind >> the `private` and `protected` keywords when we are trying to implement >> their functionality. >> >> > `private` looks like an identifier, and IMHO getters, setters, and >> async functions suffer the same issue of the keyword seeming to blend in a >> little with surrounding code. >> >> Have you ever thought that `var` or `let` look like identifiers? The >> `private` and `protected` keywords serve the same role as `var` and `let`: >> declaring a variable within a given scope or context. If you think there is >> a good logical or rational reason to avoid using the keywords that have >> been embedded in the language and left languishing, waiting for their >> meaning to be implemented, then I'm willing to entertain that. If the >> reaso
Re: !Re: proposal: Object Members
> `private`, `protected`, `class`, and a few other such keywords have all been part of ES since long be for the TC39 board got their hands on it. They hadn't been implemented, but they were all a very real part of ES. Whoa. Is that just misinformed or intentionally misleading? They have never been "part of ES" in any meaningful sense. It was not that they had not been implemented; it was that they had not even been defined. To say they are a "real part of ES" is a strange interpretation of the meaning of the word "real". The notion that we would choose features to work on based on some designation of certain keywords as reserved long ago, and that they are now "languishing", is odd. Why not focus on "implementing" enum, or final, or throws, or any other of the dozens of reserved words? Having said that, I think it is a valid general principle that as language designers we should be very reluctant to use magic characters. `**` is fine, of course, as is `=>`, or even `@` for decorators. Personally, I don't think the problem of access modifiers rises to the level of commonality and need for conciseness that would justify eating up another magic character. We also don't want JS to start looking like Perl or APL. Speaking as a self-appointed representative of Plain Old Programmers, I do feel a need for private fields, although it was probably starting to program more in TS that got me thinking that way. However, to me it feels odd to tie this directly to `class` syntax. Why can't I have a private field in a plain old object like `{a: 1}` (i.e., that would only be accessible via a method on that object? We already have properties which are enumerable and writable, for example, independent of the class mechanism. Why not have properties which are private in the same way? The problem,of course, is that even assuming the engines implemented the `private` property on descriptors, I obviously don't want to have to write `Object.create({}, {a: {value: 22, private: true})`. So the problem can be restated as trying to find some nice sugar for writing the above. You know, something like `{a: 22}`. That's obviously a completely random syntax suggestion, just to show the idea. Perhaps we'd prefer to have the access modifiers be specifiable under program control as an object itself, to allow something like ``` const PRIVATE = {private: true}; const myObject = {a(: 2; } ``` But what would the precise meaning of such as `private` descriptor property be? In operational terms, it could suffice to imagine (as a behavior, not as an implementation strategy) that objects would have a flag that would skip over private properties when doing property lookups. I think the right implementation is to have a private property look like it's not there at all when access is attempted from outside the object (in other words, is undefined), rather than some kind of `PrivatePropertyAccessError`. The above approach ought to be extensible to class notation: ``` class Foo ( bar(): { return 22; } } ``` which would end up being something like `Object.defineProperty(Foo.prototype, "bar", {value() {return 22; }, private: true})`. Or when classes get instance variables: ``` class Foo { bar = 22; ``` Was anything along these lines already brought up in this discussion? Bob On Sat, Aug 4, 2018 at 12:30 AM Ranando King wrote: > > It certainly doesn't look or feel like JS - it feels more like Java or > C#. > > `private`, `protected`, `class`, and a few other such keywords have all > been part of ES since long be for the TC39 board got their hands on it. > They hadn't been implemented, but they were all a very real part of ES. Now > that `class` has been implemented, it makes little sense to leave behind > the `private` and `protected` keywords when we are trying to implement > their functionality. > > > `private` looks like an identifier, and IMHO getters, setters, and > async functions suffer the same issue of the keyword seeming to blend in a > little with surrounding code. > > Have you ever thought that `var` or `let` look like identifiers? The > `private` and `protected` keywords serve the same role as `var` and `let`: > declaring a variable within a given scope or context. If you think there is > a good logical or rational reason to avoid using the keywords that have > been embedded in the language and left languishing, waiting for their > meaning to be implemented, then I'm willing to entertain that. If the > reason is based on mere feeling or emotion, well. I will only entertain > such arguments if my reason for doing things a certain way is equally > emotion based. Nothing I'm aware of in this proposal falls into that > category. I have logical reasons for every choice I've made. > > >> 2. `protected` on an object literal is next to useless. I've used that kind > of feature almost never. > > > And how would that be accessible? > > As you said, the vast majority of the time, this feature will go unused. > However, when it's
Re: !Re: proposal: Object Members
On 08/03/2018 02:37 PM, Tab Atkins Jr. wrote: Yes, they were reserved because they were the Java reserved keywords, with the intention that we might add more Java features later in the langauge's evolution. That has no bearing on their use today. That's exactly what we did. In the early days of ECMAScript we had no plans to use those but reserved them just in case. Some of the ones we reserved later accidentally became unreserved. Introducing a new keyword-based feature when that keyword isn't reserved leads to severe complications and arbitrary [no linebreak here] rules. The nastiest cover grammars are some of the consequences of things like being able to use "async" as a function name. Waldemar ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: !Re: proposal: Object Members
On Fri, Aug 3, 2018 at 2:33 PM Ranando King wrote: > > A side thought: > > If a language reserving certain words, even to the point of generating error > messages related to using them under certain circumstances, doesn't > constitute at least part of a justification for using them, then why do > languages so often reserve keywords for future use? Isn't precisely the case > with `private`, `protected`, `public`, and `package` (and `class` prior to > ES6). Weren't they all holdovers from the fact that the syntax for ES was > mostly borrowed from Java, and kept in reserve just in case the concepts > behind these keywords became language features? > > If that's not the case, then there's no point in keeping these (or indeed > any) keywords in reserve. Yes, they were reserved because they were the Java reserved keywords, with the intention that we might add more Java features later in the langauge's evolution. That has no bearing on their use today. Unreserving them wouldn't provide much benefit now. But keeping them reserved still doesn't mean we have any particular need to use them. ~TJ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: !Re: proposal: Object Members
A side thought: If a language reserving certain words, even to the point of generating error messages related to using them under certain circumstances, doesn't constitute at least part of a justification for using them, then why do languages so often reserve keywords for future use? Isn't precisely the case with `private`, `protected`, `public`, and `package` (and `class` prior to ES6). Weren't they all holdovers from the fact that the syntax for ES was mostly borrowed from Java, and kept in reserve just in case the concepts behind these keywords became language features? If that's not the case, then there's no point in keeping these (or indeed any) keywords in reserve. On Fri, Aug 3, 2018 at 4:24 PM Ranando King wrote: > Good argument. However, the fact that the wide adoption `private` and > `public` in other languages constitutes an immediately understood, > well-recognized syntax for declaring privilege levels in languages with > classes is my primary reason for adopting those already reserved keywords. > The fact that I also think it would be a waste not to use them is just a > personal bias I'm willing to disregard in the face of a good, sound, > logical reason for not using them. > > On Fri, Aug 3, 2018 at 4:07 PM Jordan Harband wrote: > >> A keyword being reserved is NOT the same as "being a part of ES". >> `package` is reserved too, but there's zero concept of packages in the >> language, and absolutely no obligation for there ever to be one. >> >> To reiterate, the existence of `private`, `public`, and `protected` as >> reserved keywords in *no way* justifies including any, or all, of these >> keywords in any language feature. >> >> On Fri, Aug 3, 2018 at 12:36 PM, Isiah Meadows >> wrote: >> >>> My "private symbols" proposal supports it, but that's about it. >>> >>> I think the main thing is that the use case isn't really that large, >>> so nobody's really thought about it. (You can always "pretend" it >>> exists by creating a single private key that's just an object >>> dictionary.) >>> - >>> >>> Isiah Meadows >>> cont...@isiahmeadows.com >>> www.isiahmeadows.com >>> >>> >>> On Fri, Aug 3, 2018 at 8:34 AM, Michael Theriot >>> wrote: >>> > If I understand the terminology, "private dynamic properties" are >>> easily >>> > polyfilled via weakmaps? >>> > >>> > I actually think it's odd there is no attempt to implement dynamic >>> > properties in the other "private properties" proposals. >>> > >>> > >>> > On Friday, August 3, 2018, Isiah Meadows >>> wrote: >>> >> >>> >> Okay, now that I look at that proposal, I see two issues right off: >>> >> >>> >> 1. It's *super incredibly boilerplatey* and verbose syntactically. I >>> >> don't know very many people who'd be willing to downgrade very far >>> >> from even what TypeScript has. (I'm specifically referring to the >>> >> declarations here.) >>> >> 2. `protected` on an object literal is next to useless. I've used that >>> >> kind of feature almost never. >>> >> >>> >> I also find it odd you're supporting private dynamic properties. It >>> >> does make polyfilling next to impossible, though. >>> >> >>> >> Just my 2 cents on it. (I glanced over this while very tired, so I >>> >> probably missed several highlights. These are what stuck out to me.) >>> >> >>> >> - >>> >> >>> >> Isiah Meadows >>> >> cont...@isiahmeadows.com >>> >> www.isiahmeadows.com >>> >> >>> >> >>> >> On Wed, Aug 1, 2018 at 11:54 PM, Ranando King >>> wrote: >>> >> > >>> https://github.com/rdking/proposal-object-members/blob/master/README.md >>> >> > >>> >> > On Wed, Aug 1, 2018 at 2:01 AM Isiah Meadows < >>> isiahmead...@gmail.com> >>> >> > wrote: >>> >> >> >>> >> >> Do you have a link to this proposal so I can take a look at it? >>> It'd >>> >> >> be much easier to critique it if I could see the proposal text. >>> >> >> - >>> >> >> >>> >> >> Isiah Meadows >>> >> >> cont...@isiahmeadows.com >>> >> >> www.isiahmeadows.com >>> >> >> >>> >> >> >>> >> >> On Wed, Aug 1, 2018 at 2:18 AM, Ranando King >>> wrote: >>> >> >> >> If you go back a few months, what you're proposing is *very* >>> >> >> >> similar, >>> >> >> >> at >>> >> >> >> least functionally, to my previous iteration of my proposal: >>> >> >> > >>> >> >> > That functional similarity is intentional. After pouring over >>> years >>> >> >> > worth of >>> >> >> > posts, I figured out what the vast majority of the >>> >> >> > proposal-class-fields >>> >> >> > detractors actually wanted: an elegant, easily recognized syntax >>> for >>> >> >> > adding >>> >> >> > private members to objects. >>> >> >> > >>> >> >> >> My main problem was that trying to limit private properties to >>> >> >> >> objects >>> >> >> >> created within a scope got complicated in a hurry once you >>> >> >> >> considered >>> >> >> >> all >>> >> >> >> the small details, and it just didn't seem simple anymore. >>> >> >> > >>> >> >> > I noticed that about your proposal too. I'm also pretty sure that >>> >> >> > Daniel >>> >> >> > E. >>> >> >> > and
Re: !Re: proposal: Object Members
Good argument. However, the fact that the wide adoption `private` and `public` in other languages constitutes an immediately understood, well-recognized syntax for declaring privilege levels in languages with classes is my primary reason for adopting those already reserved keywords. The fact that I also think it would be a waste not to use them is just a personal bias I'm willing to disregard in the face of a good, sound, logical reason for not using them. On Fri, Aug 3, 2018 at 4:07 PM Jordan Harband wrote: > A keyword being reserved is NOT the same as "being a part of ES". > `package` is reserved too, but there's zero concept of packages in the > language, and absolutely no obligation for there ever to be one. > > To reiterate, the existence of `private`, `public`, and `protected` as > reserved keywords in *no way* justifies including any, or all, of these > keywords in any language feature. > > On Fri, Aug 3, 2018 at 12:36 PM, Isiah Meadows > wrote: > >> My "private symbols" proposal supports it, but that's about it. >> >> I think the main thing is that the use case isn't really that large, >> so nobody's really thought about it. (You can always "pretend" it >> exists by creating a single private key that's just an object >> dictionary.) >> - >> >> Isiah Meadows >> cont...@isiahmeadows.com >> www.isiahmeadows.com >> >> >> On Fri, Aug 3, 2018 at 8:34 AM, Michael Theriot >> wrote: >> > If I understand the terminology, "private dynamic properties" are easily >> > polyfilled via weakmaps? >> > >> > I actually think it's odd there is no attempt to implement dynamic >> > properties in the other "private properties" proposals. >> > >> > >> > On Friday, August 3, 2018, Isiah Meadows >> wrote: >> >> >> >> Okay, now that I look at that proposal, I see two issues right off: >> >> >> >> 1. It's *super incredibly boilerplatey* and verbose syntactically. I >> >> don't know very many people who'd be willing to downgrade very far >> >> from even what TypeScript has. (I'm specifically referring to the >> >> declarations here.) >> >> 2. `protected` on an object literal is next to useless. I've used that >> >> kind of feature almost never. >> >> >> >> I also find it odd you're supporting private dynamic properties. It >> >> does make polyfilling next to impossible, though. >> >> >> >> Just my 2 cents on it. (I glanced over this while very tired, so I >> >> probably missed several highlights. These are what stuck out to me.) >> >> >> >> - >> >> >> >> Isiah Meadows >> >> cont...@isiahmeadows.com >> >> www.isiahmeadows.com >> >> >> >> >> >> On Wed, Aug 1, 2018 at 11:54 PM, Ranando King >> wrote: >> >> > >> https://github.com/rdking/proposal-object-members/blob/master/README.md >> >> > >> >> > On Wed, Aug 1, 2018 at 2:01 AM Isiah Meadows > > >> >> > wrote: >> >> >> >> >> >> Do you have a link to this proposal so I can take a look at it? It'd >> >> >> be much easier to critique it if I could see the proposal text. >> >> >> - >> >> >> >> >> >> Isiah Meadows >> >> >> cont...@isiahmeadows.com >> >> >> www.isiahmeadows.com >> >> >> >> >> >> >> >> >> On Wed, Aug 1, 2018 at 2:18 AM, Ranando King >> wrote: >> >> >> >> If you go back a few months, what you're proposing is *very* >> >> >> >> similar, >> >> >> >> at >> >> >> >> least functionally, to my previous iteration of my proposal: >> >> >> > >> >> >> > That functional similarity is intentional. After pouring over >> years >> >> >> > worth of >> >> >> > posts, I figured out what the vast majority of the >> >> >> > proposal-class-fields >> >> >> > detractors actually wanted: an elegant, easily recognized syntax >> for >> >> >> > adding >> >> >> > private members to objects. >> >> >> > >> >> >> >> My main problem was that trying to limit private properties to >> >> >> >> objects >> >> >> >> created within a scope got complicated in a hurry once you >> >> >> >> considered >> >> >> >> all >> >> >> >> the small details, and it just didn't seem simple anymore. >> >> >> > >> >> >> > I noticed that about your proposal too. I'm also pretty sure that >> >> >> > Daniel >> >> >> > E. >> >> >> > and Kevin G. ran into the same issues back during the >> >> >> > proposal-private-names >> >> >> > days which is why the private names concept is just an >> implementation >> >> >> > detail >> >> >> > in their current proposal. My proposal is made less complicated by >> >> >> > breaking >> >> >> > the problem down into the 3 pieces required to make it all work: >> >> >> > 1. a record to store private data >> >> >> > 2. an array to hold references to the schema records of accessible >> >> >> > private >> >> >> > data >> >> >> > 3. a schema record for the sharable data. >> >> >> > >> >> >> > In this way private = encapsulated on a non-function, protected = >> >> >> > private + >> >> >> > shared, and static = encapsulated on a function. It should be >> easy to >> >> >> > sort >> >> >> > out how the data would be stored given such simple definitions. >> These >> >> >> > simple >> >> >>
Re: !Re: proposal: Object Members
A keyword being reserved is NOT the same as "being a part of ES". `package` is reserved too, but there's zero concept of packages in the language, and absolutely no obligation for there ever to be one. To reiterate, the existence of `private`, `public`, and `protected` as reserved keywords in *no way* justifies including any, or all, of these keywords in any language feature. On Fri, Aug 3, 2018 at 12:36 PM, Isiah Meadows wrote: > My "private symbols" proposal supports it, but that's about it. > > I think the main thing is that the use case isn't really that large, > so nobody's really thought about it. (You can always "pretend" it > exists by creating a single private key that's just an object > dictionary.) > - > > Isiah Meadows > cont...@isiahmeadows.com > www.isiahmeadows.com > > > On Fri, Aug 3, 2018 at 8:34 AM, Michael Theriot > wrote: > > If I understand the terminology, "private dynamic properties" are easily > > polyfilled via weakmaps? > > > > I actually think it's odd there is no attempt to implement dynamic > > properties in the other "private properties" proposals. > > > > > > On Friday, August 3, 2018, Isiah Meadows wrote: > >> > >> Okay, now that I look at that proposal, I see two issues right off: > >> > >> 1. It's *super incredibly boilerplatey* and verbose syntactically. I > >> don't know very many people who'd be willing to downgrade very far > >> from even what TypeScript has. (I'm specifically referring to the > >> declarations here.) > >> 2. `protected` on an object literal is next to useless. I've used that > >> kind of feature almost never. > >> > >> I also find it odd you're supporting private dynamic properties. It > >> does make polyfilling next to impossible, though. > >> > >> Just my 2 cents on it. (I glanced over this while very tired, so I > >> probably missed several highlights. These are what stuck out to me.) > >> > >> - > >> > >> Isiah Meadows > >> cont...@isiahmeadows.com > >> www.isiahmeadows.com > >> > >> > >> On Wed, Aug 1, 2018 at 11:54 PM, Ranando King > wrote: > >> > https://github.com/rdking/proposal-object-members/blob/ > master/README.md > >> > > >> > On Wed, Aug 1, 2018 at 2:01 AM Isiah Meadows > >> > wrote: > >> >> > >> >> Do you have a link to this proposal so I can take a look at it? It'd > >> >> be much easier to critique it if I could see the proposal text. > >> >> - > >> >> > >> >> Isiah Meadows > >> >> cont...@isiahmeadows.com > >> >> www.isiahmeadows.com > >> >> > >> >> > >> >> On Wed, Aug 1, 2018 at 2:18 AM, Ranando King > wrote: > >> >> >> If you go back a few months, what you're proposing is *very* > >> >> >> similar, > >> >> >> at > >> >> >> least functionally, to my previous iteration of my proposal: > >> >> > > >> >> > That functional similarity is intentional. After pouring over years > >> >> > worth of > >> >> > posts, I figured out what the vast majority of the > >> >> > proposal-class-fields > >> >> > detractors actually wanted: an elegant, easily recognized syntax > for > >> >> > adding > >> >> > private members to objects. > >> >> > > >> >> >> My main problem was that trying to limit private properties to > >> >> >> objects > >> >> >> created within a scope got complicated in a hurry once you > >> >> >> considered > >> >> >> all > >> >> >> the small details, and it just didn't seem simple anymore. > >> >> > > >> >> > I noticed that about your proposal too. I'm also pretty sure that > >> >> > Daniel > >> >> > E. > >> >> > and Kevin G. ran into the same issues back during the > >> >> > proposal-private-names > >> >> > days which is why the private names concept is just an > implementation > >> >> > detail > >> >> > in their current proposal. My proposal is made less complicated by > >> >> > breaking > >> >> > the problem down into the 3 pieces required to make it all work: > >> >> > 1. a record to store private data > >> >> > 2. an array to hold references to the schema records of accessible > >> >> > private > >> >> > data > >> >> > 3. a schema record for the sharable data. > >> >> > > >> >> > In this way private = encapsulated on a non-function, protected = > >> >> > private + > >> >> > shared, and static = encapsulated on a function. It should be easy > to > >> >> > sort > >> >> > out how the data would be stored given such simple definitions. > These > >> >> > simple > >> >> > definitions also mean that encapsulation is naturally confined to > >> >> > definitions. Attempts to alter that state lead to strange logical > >> >> > contradictions and potential leaks of encapsulated data. I have > >> >> > thought > >> >> > of > >> >> > the possibility that private data could be added after definition, > >> >> > but > >> >> > every > >> >> > attempt I make to consider such a thing has so far led to a risk of > >> >> > leaking. > >> >> > > >> >> > I've been working on some code that can serve as a proof-of-concept > >> >> > in > >> >> > ES6. > >> >> > It will implement all of my proposal that can reasonably be > >> >> > impleme
Re: !Re: proposal: Object Members
My "private symbols" proposal supports it, but that's about it. I think the main thing is that the use case isn't really that large, so nobody's really thought about it. (You can always "pretend" it exists by creating a single private key that's just an object dictionary.) - Isiah Meadows cont...@isiahmeadows.com www.isiahmeadows.com On Fri, Aug 3, 2018 at 8:34 AM, Michael Theriot wrote: > If I understand the terminology, "private dynamic properties" are easily > polyfilled via weakmaps? > > I actually think it's odd there is no attempt to implement dynamic > properties in the other "private properties" proposals. > > > On Friday, August 3, 2018, Isiah Meadows wrote: >> >> Okay, now that I look at that proposal, I see two issues right off: >> >> 1. It's *super incredibly boilerplatey* and verbose syntactically. I >> don't know very many people who'd be willing to downgrade very far >> from even what TypeScript has. (I'm specifically referring to the >> declarations here.) >> 2. `protected` on an object literal is next to useless. I've used that >> kind of feature almost never. >> >> I also find it odd you're supporting private dynamic properties. It >> does make polyfilling next to impossible, though. >> >> Just my 2 cents on it. (I glanced over this while very tired, so I >> probably missed several highlights. These are what stuck out to me.) >> >> - >> >> Isiah Meadows >> cont...@isiahmeadows.com >> www.isiahmeadows.com >> >> >> On Wed, Aug 1, 2018 at 11:54 PM, Ranando King wrote: >> > https://github.com/rdking/proposal-object-members/blob/master/README.md >> > >> > On Wed, Aug 1, 2018 at 2:01 AM Isiah Meadows >> > wrote: >> >> >> >> Do you have a link to this proposal so I can take a look at it? It'd >> >> be much easier to critique it if I could see the proposal text. >> >> - >> >> >> >> Isiah Meadows >> >> cont...@isiahmeadows.com >> >> www.isiahmeadows.com >> >> >> >> >> >> On Wed, Aug 1, 2018 at 2:18 AM, Ranando King wrote: >> >> >> If you go back a few months, what you're proposing is *very* >> >> >> similar, >> >> >> at >> >> >> least functionally, to my previous iteration of my proposal: >> >> > >> >> > That functional similarity is intentional. After pouring over years >> >> > worth of >> >> > posts, I figured out what the vast majority of the >> >> > proposal-class-fields >> >> > detractors actually wanted: an elegant, easily recognized syntax for >> >> > adding >> >> > private members to objects. >> >> > >> >> >> My main problem was that trying to limit private properties to >> >> >> objects >> >> >> created within a scope got complicated in a hurry once you >> >> >> considered >> >> >> all >> >> >> the small details, and it just didn't seem simple anymore. >> >> > >> >> > I noticed that about your proposal too. I'm also pretty sure that >> >> > Daniel >> >> > E. >> >> > and Kevin G. ran into the same issues back during the >> >> > proposal-private-names >> >> > days which is why the private names concept is just an implementation >> >> > detail >> >> > in their current proposal. My proposal is made less complicated by >> >> > breaking >> >> > the problem down into the 3 pieces required to make it all work: >> >> > 1. a record to store private data >> >> > 2. an array to hold references to the schema records of accessible >> >> > private >> >> > data >> >> > 3. a schema record for the sharable data. >> >> > >> >> > In this way private = encapsulated on a non-function, protected = >> >> > private + >> >> > shared, and static = encapsulated on a function. It should be easy to >> >> > sort >> >> > out how the data would be stored given such simple definitions. These >> >> > simple >> >> > definitions also mean that encapsulation is naturally confined to >> >> > definitions. Attempts to alter that state lead to strange logical >> >> > contradictions and potential leaks of encapsulated data. I have >> >> > thought >> >> > of >> >> > the possibility that private data could be added after definition, >> >> > but >> >> > every >> >> > attempt I make to consider such a thing has so far led to a risk of >> >> > leaking. >> >> > >> >> > I've been working on some code that can serve as a proof-of-concept >> >> > in >> >> > ES6. >> >> > It will implement all of my proposal that can reasonably be >> >> > implemented >> >> > in >> >> > ES6 using Proxy. It's already in the proposal repository under the >> >> > POC >> >> > branch, but it's still a WIP. For now, it already supports inheriting >> >> > from >> >> > native objects. I'm working on subclassing right now. By the time I >> >> > get >> >> > done >> >> > (likely this coming Monday), it should support every feature in my >> >> > proposal. >> >> > I'm basically using it as a means to check the viability of my >> >> > proposal. >> >> > >> >> > On Tue, Jul 31, 2018 at 4:35 PM Isiah Meadows >> >> > >> >> > wrote: >> >> >> >> >> >> If you go back a few months, what you're proposing is *very* >> >> >> similar, >> >> >> at least functional
Re: !Re: proposal: Object Members
> It certainly doesn't look or feel like JS - it feels more like Java or C#. `private`, `protected`, `class`, and a few other such keywords have all been part of ES since long be for the TC39 board got their hands on it. They hadn't been implemented, but they were all a very real part of ES. Now that `class` has been implemented, it makes little sense to leave behind the `private` and `protected` keywords when we are trying to implement their functionality. > `private` looks like an identifier, and IMHO getters, setters, and async functions suffer the same issue of the keyword seeming to blend in a little with surrounding code. Have you ever thought that `var` or `let` look like identifiers? The `private` and `protected` keywords serve the same role as `var` and `let`: declaring a variable within a given scope or context. If you think there is a good logical or rational reason to avoid using the keywords that have been embedded in the language and left languishing, waiting for their meaning to be implemented, then I'm willing to entertain that. If the reason is based on mere feeling or emotion, well. I will only entertain such arguments if my reason for doing things a certain way is equally emotion based. Nothing I'm aware of in this proposal falls into that category. I have logical reasons for every choice I've made. >> 2. `protected` on an object literal is next to useless. I've used that kind of feature almost never. > And how would that be accessible? As you said, the vast majority of the time, this feature will go unused. However, when it's needed, it would look something like this: ```js var a = { protected sharedData: 1, increment() { ++this#.sharedData; }, print() { console.log(`sharedData = ${this#.sharedData}`); } }; var b = { __proto__: a, decrement() { --this#.sharedData; } }; ``` Setting `b.__proto__ = a` causes `b.[[PrivateValues]].__proto__ = a.[[PrivateValues]]`, `b.[[DeclarationInfo]].__proto__ = a.[[InheritanceInfo]]`, and `b.[[InheritanceInfo]].proto = a.[[InheritanceInfo]]`. So it all just works. > I saw `obj#['key']`, which *strongly* suggests dynamic keys are supported. Dynamic **_keys_** are supported. Dynamic **_properties_** are not! Please don't conflate the two. Dynamic keys are calculated property names. I am definitely supporting that. Dynamic properties refers to the ability to add and remove properties from an object at any time. I am not supporting that for private/protected members (unless someone can logically convince me it's a good idea). On Fri, Aug 3, 2018 at 1:02 PM Isiah Meadows wrote: > Inline > > On Fri, Aug 3, 2018, 11:12 Ranando King wrote: > >> > 1. It's *super incredibly boilerplatey* and verbose syntactically. >> >> I'm not sure what you mean by "boilerplatey". As for being verbose, I'm >> just using the keywords everyone understands for this purpose. IMO, there's >> no advantage in trying to find some shorthand to do the same thing just >> because it saves a keystroke or two when it makes the code significantly >> more difficult to understand. >> > > But on the same token, it's verbose enough that I feel readability starts > to suffer substantiallly. `private` looks like an identifier, and IMHO > getters, setters, and async functions suffer the same issue of the keyword > seeming to blend in a little with surrounding code. But those are more like > decorating the function than the name. > > Based on reading the several meeting notes, I don't believe the keyword > has been especially popular there, either. It certainly doesn't look or > feel like JS - it feels more like Java or C#. > > >> > 2. `protected` on an object literal is next to useless. I've used that kind >> of feature almost never. >> >> I get where you're coming from with that. I don't see it being used very >> often (kinda like `with`), but it has to be there. If someone wants to use >> the facilities of `class` without the limitations of the keyword, and the >> intent is to build vertical hierarchies, they'll need the "protected" >> keyword on their prototype definition to share private data with descendant >> factories. >> > > And how would that be accessible? Because you can't expose it via the same > way you do in classes without basically making them public (and several > workarounds suffer similar issues). > > > I also find it odd you're supporting private dynamic properties. >> >> How'd you get to the idea that I'm supporting dynamic private properties? >> > > I saw `obj#['key']`, which *strongly* suggests dynamic keys are supported. > > > I actually think it's odd there is no attempt to implement dynamic >> properties in the other "private properties" proposals. >> > >> It's not that odd. There are issues around inheritance when a subclass >> can remove the `protected` properties of its base. Further, exactly how do >> you add a new `protected` property at runtime? Under both >> proposal-class-fields and proposal-object-members, there is never any >> direct ac
Re: !Re: proposal: Object Members
I'm glad someone other than myself can appreciate it. I trudged my way through a lot of variations on the theme to find the implementation that would make the most sense and still behave properly. It really is rather simple. The POC will more or less show how it can be implemented. The only issue I'm having at the moment is trying to capture access to `super` properties. Apparently V8 doesn't redirect `super` through prototypes like I was expecting, so I'm beginning to think that I won't be able to implement calls to protected methods of the base in this POC. On Fri, Aug 3, 2018 at 11:38 AM Michael Theriot < michael.lee.ther...@gmail.com> wrote: > I'd argue that is 1:1 with the way subclasses work today. > > Protected properties can be implemented by sharing the weakmap instance > with the parent. > > Private properties can be implemented by using a unique weakmap instance > for the subclass. > > I actually think it's pretty straightforward and simple. > > On Friday, August 3, 2018, Ranando King wrote: > >> > 1. It's *super incredibly boilerplatey* and verbose syntactically. >> >> I'm not sure what you mean by "boilerplatey". As for being verbose, I'm >> just using the keywords everyone understands for this purpose. IMO, there's >> no advantage in trying to find some shorthand to do the same thing just >> because it saves a keystroke or two when it makes the code significantly >> more difficult to understand. >> >> > 2. `protected` on an object literal is next to useless. I've used that kind >> of feature almost never. >> >> I get where you're coming from with that. I don't see it being used very >> often (kinda like `with`), but it has to be there. If someone wants to use >> the facilities of `class` without the limitations of the keyword, and the >> intent is to build vertical hierarchies, they'll need the "protected" >> keyword on their prototype definition to share private data with descendant >> factories. It's even more necessary for people writing factory factories. >> The only other way to achieve the same thing would be to force them to use >> `Function()` or `eval` and build up the code as strings. I'd rather avoid >> that. >> >> > I also find it odd you're supporting private dynamic properties. >> >> How'd you get to the idea that I'm supporting dynamic private properties? >> The first 2 paragraphs in the implementation say that all private container >> records are sealed, and all fields in info records are added read-only. If >> it wasn't clear from that, I'm going to have to re-write that section. >> However, the intent is that after the declaration process is complete, what >> you have is all you can get. No additional private fields can be added >> later. I considered dynamic private data, but that can get very messy very >> quickly. >> >> > I actually think it's odd there is no attempt to implement dynamic >> properties in the other "private properties" proposals. >> >> It's not that odd. There are issues around inheritance when a subclass >> can remove the `protected` properties of its base. Further, exactly how do >> you add a new `protected` property at runtime? Under both >> proposal-class-fields and proposal-object-members, there is never any >> direct access to the private container record, so use of >> `Object.defineProperty` will never work. IMO, any attempt to implement >> dynamic private properties in any sensible and consistent fashion would >> require somehow exposing the private data record to the code. That's a >> recipe for a private data leak. Not worth it. >> > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: !Re: proposal: Object Members
I'd argue that is 1:1 with the way subclasses work today. Protected properties can be implemented by sharing the weakmap instance with the parent. Private properties can be implemented by using a unique weakmap instance for the subclass. I actually think it's pretty straightforward and simple. On Friday, August 3, 2018, Ranando King wrote: > > 1. It's *super incredibly boilerplatey* and verbose syntactically. > > I'm not sure what you mean by "boilerplatey". As for being verbose, I'm > just using the keywords everyone understands for this purpose. IMO, there's > no advantage in trying to find some shorthand to do the same thing just > because it saves a keystroke or two when it makes the code significantly > more difficult to understand. > > > 2. `protected` on an object literal is next to useless. I've used that kind > of feature almost never. > > I get where you're coming from with that. I don't see it being used very > often (kinda like `with`), but it has to be there. If someone wants to use > the facilities of `class` without the limitations of the keyword, and the > intent is to build vertical hierarchies, they'll need the "protected" > keyword on their prototype definition to share private data with descendant > factories. It's even more necessary for people writing factory factories. > The only other way to achieve the same thing would be to force them to use > `Function()` or `eval` and build up the code as strings. I'd rather avoid > that. > > > I also find it odd you're supporting private dynamic properties. > > How'd you get to the idea that I'm supporting dynamic private properties? > The first 2 paragraphs in the implementation say that all private container > records are sealed, and all fields in info records are added read-only. If > it wasn't clear from that, I'm going to have to re-write that section. > However, the intent is that after the declaration process is complete, what > you have is all you can get. No additional private fields can be added > later. I considered dynamic private data, but that can get very messy very > quickly. > > > I actually think it's odd there is no attempt to implement dynamic > properties in the other "private properties" proposals. > > It's not that odd. There are issues around inheritance when a subclass can > remove the `protected` properties of its base. Further, exactly how do you > add a new `protected` property at runtime? Under both proposal-class-fields > and proposal-object-members, there is never any direct access to the > private container record, so use of `Object.defineProperty` will never > work. IMO, any attempt to implement dynamic private properties in any > sensible and consistent fashion would require somehow exposing the private > data record to the code. That's a recipe for a private data leak. Not worth > it. > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: !Re: proposal: Object Members
> 1. It's *super incredibly boilerplatey* and verbose syntactically. I'm not sure what you mean by "boilerplatey". As for being verbose, I'm just using the keywords everyone understands for this purpose. IMO, there's no advantage in trying to find some shorthand to do the same thing just because it saves a keystroke or two when it makes the code significantly more difficult to understand. > 2. `protected` on an object literal is next to useless. I've used that kind of feature almost never. I get where you're coming from with that. I don't see it being used very often (kinda like `with`), but it has to be there. If someone wants to use the facilities of `class` without the limitations of the keyword, and the intent is to build vertical hierarchies, they'll need the "protected" keyword on their prototype definition to share private data with descendant factories. It's even more necessary for people writing factory factories. The only other way to achieve the same thing would be to force them to use `Function()` or `eval` and build up the code as strings. I'd rather avoid that. > I also find it odd you're supporting private dynamic properties. How'd you get to the idea that I'm supporting dynamic private properties? The first 2 paragraphs in the implementation say that all private container records are sealed, and all fields in info records are added read-only. If it wasn't clear from that, I'm going to have to re-write that section. However, the intent is that after the declaration process is complete, what you have is all you can get. No additional private fields can be added later. I considered dynamic private data, but that can get very messy very quickly. > I actually think it's odd there is no attempt to implement dynamic properties in the other "private properties" proposals. It's not that odd. There are issues around inheritance when a subclass can remove the `protected` properties of its base. Further, exactly how do you add a new `protected` property at runtime? Under both proposal-class-fields and proposal-object-members, there is never any direct access to the private container record, so use of `Object.defineProperty` will never work. IMO, any attempt to implement dynamic private properties in any sensible and consistent fashion would require somehow exposing the private data record to the code. That's a recipe for a private data leak. Not worth it. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: !Re: proposal: Object Members
If I understand the terminology, "private dynamic properties" are easily polyfilled via weakmaps? I actually think it's odd there is no attempt to implement dynamic properties in the other "private properties" proposals. On Friday, August 3, 2018, Isiah Meadows wrote: > Okay, now that I look at that proposal, I see two issues right off: > > 1. It's *super incredibly boilerplatey* and verbose syntactically. I > don't know very many people who'd be willing to downgrade very far > from even what TypeScript has. (I'm specifically referring to the > declarations here.) > 2. `protected` on an object literal is next to useless. I've used that > kind of feature almost never. > > I also find it odd you're supporting private dynamic properties. It > does make polyfilling next to impossible, though. > > Just my 2 cents on it. (I glanced over this while very tired, so I > probably missed several highlights. These are what stuck out to me.) > > - > > Isiah Meadows > cont...@isiahmeadows.com > www.isiahmeadows.com > > > On Wed, Aug 1, 2018 at 11:54 PM, Ranando King wrote: > > https://github.com/rdking/proposal-object-members/blob/master/README.md > > > > On Wed, Aug 1, 2018 at 2:01 AM Isiah Meadows > wrote: > >> > >> Do you have a link to this proposal so I can take a look at it? It'd > >> be much easier to critique it if I could see the proposal text. > >> - > >> > >> Isiah Meadows > >> cont...@isiahmeadows.com > >> www.isiahmeadows.com > >> > >> > >> On Wed, Aug 1, 2018 at 2:18 AM, Ranando King wrote: > >> >> If you go back a few months, what you're proposing is *very* similar, > >> >> at > >> >> least functionally, to my previous iteration of my proposal: > >> > > >> > That functional similarity is intentional. After pouring over years > >> > worth of > >> > posts, I figured out what the vast majority of the > proposal-class-fields > >> > detractors actually wanted: an elegant, easily recognized syntax for > >> > adding > >> > private members to objects. > >> > > >> >> My main problem was that trying to limit private properties to > objects > >> >> created within a scope got complicated in a hurry once you considered > >> >> all > >> >> the small details, and it just didn't seem simple anymore. > >> > > >> > I noticed that about your proposal too. I'm also pretty sure that > Daniel > >> > E. > >> > and Kevin G. ran into the same issues back during the > >> > proposal-private-names > >> > days which is why the private names concept is just an implementation > >> > detail > >> > in their current proposal. My proposal is made less complicated by > >> > breaking > >> > the problem down into the 3 pieces required to make it all work: > >> > 1. a record to store private data > >> > 2. an array to hold references to the schema records of accessible > >> > private > >> > data > >> > 3. a schema record for the sharable data. > >> > > >> > In this way private = encapsulated on a non-function, protected = > >> > private + > >> > shared, and static = encapsulated on a function. It should be easy to > >> > sort > >> > out how the data would be stored given such simple definitions. These > >> > simple > >> > definitions also mean that encapsulation is naturally confined to > >> > definitions. Attempts to alter that state lead to strange logical > >> > contradictions and potential leaks of encapsulated data. I have > thought > >> > of > >> > the possibility that private data could be added after definition, but > >> > every > >> > attempt I make to consider such a thing has so far led to a risk of > >> > leaking. > >> > > >> > I've been working on some code that can serve as a proof-of-concept in > >> > ES6. > >> > It will implement all of my proposal that can reasonably be > implemented > >> > in > >> > ES6 using Proxy. It's already in the proposal repository under the POC > >> > branch, but it's still a WIP. For now, it already supports inheriting > >> > from > >> > native objects. I'm working on subclassing right now. By the time I > get > >> > done > >> > (likely this coming Monday), it should support every feature in my > >> > proposal. > >> > I'm basically using it as a means to check the viability of my > proposal. > >> > > >> > On Tue, Jul 31, 2018 at 4:35 PM Isiah Meadows > > >> > wrote: > >> >> > >> >> If you go back a few months, what you're proposing is *very* similar, > >> >> at least functionally, to my previous iteration of my proposal: > >> >> > >> >> > >> >> https://github.com/isiahmeadows/private-symbol-proposal/blob/ > c5c9781d9e76123c92d8fbc83681fdd3a9b0b319/README.md > >> >> > >> >> My main problem was that trying to limit private properties to > objects > >> >> created within a scope got complicated in a hurry once you considered > >> >> all the small details, and it just didn't seem simple anymore. It > only > >> >> got more complicated when you started getting into the logistics of > >> >> integrating with modules. > >> >> > >> >> So I've considered the issue and explored it pretty thoroughly
Re: !Re: proposal: Object Members
Okay, now that I look at that proposal, I see two issues right off: 1. It's *super incredibly boilerplatey* and verbose syntactically. I don't know very many people who'd be willing to downgrade very far from even what TypeScript has. (I'm specifically referring to the declarations here.) 2. `protected` on an object literal is next to useless. I've used that kind of feature almost never. I also find it odd you're supporting private dynamic properties. It does make polyfilling next to impossible, though. Just my 2 cents on it. (I glanced over this while very tired, so I probably missed several highlights. These are what stuck out to me.) - Isiah Meadows cont...@isiahmeadows.com www.isiahmeadows.com On Wed, Aug 1, 2018 at 11:54 PM, Ranando King wrote: > https://github.com/rdking/proposal-object-members/blob/master/README.md > > On Wed, Aug 1, 2018 at 2:01 AM Isiah Meadows wrote: >> >> Do you have a link to this proposal so I can take a look at it? It'd >> be much easier to critique it if I could see the proposal text. >> - >> >> Isiah Meadows >> cont...@isiahmeadows.com >> www.isiahmeadows.com >> >> >> On Wed, Aug 1, 2018 at 2:18 AM, Ranando King wrote: >> >> If you go back a few months, what you're proposing is *very* similar, >> >> at >> >> least functionally, to my previous iteration of my proposal: >> > >> > That functional similarity is intentional. After pouring over years >> > worth of >> > posts, I figured out what the vast majority of the proposal-class-fields >> > detractors actually wanted: an elegant, easily recognized syntax for >> > adding >> > private members to objects. >> > >> >> My main problem was that trying to limit private properties to objects >> >> created within a scope got complicated in a hurry once you considered >> >> all >> >> the small details, and it just didn't seem simple anymore. >> > >> > I noticed that about your proposal too. I'm also pretty sure that Daniel >> > E. >> > and Kevin G. ran into the same issues back during the >> > proposal-private-names >> > days which is why the private names concept is just an implementation >> > detail >> > in their current proposal. My proposal is made less complicated by >> > breaking >> > the problem down into the 3 pieces required to make it all work: >> > 1. a record to store private data >> > 2. an array to hold references to the schema records of accessible >> > private >> > data >> > 3. a schema record for the sharable data. >> > >> > In this way private = encapsulated on a non-function, protected = >> > private + >> > shared, and static = encapsulated on a function. It should be easy to >> > sort >> > out how the data would be stored given such simple definitions. These >> > simple >> > definitions also mean that encapsulation is naturally confined to >> > definitions. Attempts to alter that state lead to strange logical >> > contradictions and potential leaks of encapsulated data. I have thought >> > of >> > the possibility that private data could be added after definition, but >> > every >> > attempt I make to consider such a thing has so far led to a risk of >> > leaking. >> > >> > I've been working on some code that can serve as a proof-of-concept in >> > ES6. >> > It will implement all of my proposal that can reasonably be implemented >> > in >> > ES6 using Proxy. It's already in the proposal repository under the POC >> > branch, but it's still a WIP. For now, it already supports inheriting >> > from >> > native objects. I'm working on subclassing right now. By the time I get >> > done >> > (likely this coming Monday), it should support every feature in my >> > proposal. >> > I'm basically using it as a means to check the viability of my proposal. >> > >> > On Tue, Jul 31, 2018 at 4:35 PM Isiah Meadows >> > wrote: >> >> >> >> If you go back a few months, what you're proposing is *very* similar, >> >> at least functionally, to my previous iteration of my proposal: >> >> >> >> >> >> https://github.com/isiahmeadows/private-symbol-proposal/blob/c5c9781d9e76123c92d8fbc83681fdd3a9b0b319/README.md >> >> >> >> My main problem was that trying to limit private properties to objects >> >> created within a scope got complicated in a hurry once you considered >> >> all the small details, and it just didn't seem simple anymore. It only >> >> got more complicated when you started getting into the logistics of >> >> integrating with modules. >> >> >> >> So I've considered the issue and explored it pretty thoroughly - I >> >> *really* don't want private data to be limited to classes (which I >> >> dislike), but I did also previously have the concern of trying to >> >> limit who could define properties where. >> >> >> >> I will point out that you can prevent arbitrary private extension by >> >> simply doing `Object.preventExtensions(object)`. Because properties >> >> defined using private symbols are otherwise just normal properties, >> >> they still have to go through the same access checks normal properties >> >> have t
Re: !Re: proposal: Object Members
https://github.com/rdking/proposal-object-members/blob/master/README.md On Wed, Aug 1, 2018 at 2:01 AM Isiah Meadows wrote: > Do you have a link to this proposal so I can take a look at it? It'd > be much easier to critique it if I could see the proposal text. > - > > Isiah Meadows > cont...@isiahmeadows.com > www.isiahmeadows.com > > > On Wed, Aug 1, 2018 at 2:18 AM, Ranando King wrote: > >> If you go back a few months, what you're proposing is *very* similar, at > >> least functionally, to my previous iteration of my proposal: > > > > That functional similarity is intentional. After pouring over years > worth of > > posts, I figured out what the vast majority of the proposal-class-fields > > detractors actually wanted: an elegant, easily recognized syntax for > adding > > private members to objects. > > > >> My main problem was that trying to limit private properties to objects > >> created within a scope got complicated in a hurry once you considered > all > >> the small details, and it just didn't seem simple anymore. > > > > I noticed that about your proposal too. I'm also pretty sure that Daniel > E. > > and Kevin G. ran into the same issues back during the > proposal-private-names > > days which is why the private names concept is just an implementation > detail > > in their current proposal. My proposal is made less complicated by > breaking > > the problem down into the 3 pieces required to make it all work: > > 1. a record to store private data > > 2. an array to hold references to the schema records of accessible > private > > data > > 3. a schema record for the sharable data. > > > > In this way private = encapsulated on a non-function, protected = > private + > > shared, and static = encapsulated on a function. It should be easy to > sort > > out how the data would be stored given such simple definitions. These > simple > > definitions also mean that encapsulation is naturally confined to > > definitions. Attempts to alter that state lead to strange logical > > contradictions and potential leaks of encapsulated data. I have thought > of > > the possibility that private data could be added after definition, but > every > > attempt I make to consider such a thing has so far led to a risk of > leaking. > > > > I've been working on some code that can serve as a proof-of-concept in > ES6. > > It will implement all of my proposal that can reasonably be implemented > in > > ES6 using Proxy. It's already in the proposal repository under the POC > > branch, but it's still a WIP. For now, it already supports inheriting > from > > native objects. I'm working on subclassing right now. By the time I get > done > > (likely this coming Monday), it should support every feature in my > proposal. > > I'm basically using it as a means to check the viability of my proposal. > > > > On Tue, Jul 31, 2018 at 4:35 PM Isiah Meadows > > wrote: > >> > >> If you go back a few months, what you're proposing is *very* similar, > >> at least functionally, to my previous iteration of my proposal: > >> > >> > https://github.com/isiahmeadows/private-symbol-proposal/blob/c5c9781d9e76123c92d8fbc83681fdd3a9b0b319/README.md > >> > >> My main problem was that trying to limit private properties to objects > >> created within a scope got complicated in a hurry once you considered > >> all the small details, and it just didn't seem simple anymore. It only > >> got more complicated when you started getting into the logistics of > >> integrating with modules. > >> > >> So I've considered the issue and explored it pretty thoroughly - I > >> *really* don't want private data to be limited to classes (which I > >> dislike), but I did also previously have the concern of trying to > >> limit who could define properties where. > >> > >> I will point out that you can prevent arbitrary private extension by > >> simply doing `Object.preventExtensions(object)`. Because properties > >> defined using private symbols are otherwise just normal properties, > >> they still have to go through the same access checks normal properties > >> have to, like [[IsExtensible]]. The only other concrete difference is > >> that proxy hooks don't fire when you do things with private symbols. > >> > >> - > >> > >> Isiah Meadows > >> cont...@isiahmeadows.com > >> www.isiahmeadows.com > >> > >> > >> On Tue, Jul 31, 2018 at 3:09 PM, Ranando King > wrote: > >> >> What use case are you referring to here? > >> > > >> > In the case of SymbolTree, the objects in use are external. > >> > > >> >> I think there’s been a misunderstanding. Everybody agrees that > that’s a > >> >> bad pattern. It’s not what the point of private symbols would be. > It’s > >> >> not a > >> >> target use case. > >> > > >> > That certainly puts my mind at ease. > >> > > >> >> As Isiah said, “all of the examples here I've presented are for > >> >> scenarios > >> >> where the state is related to the factory that created the objects.” > >> > > >> > If the factory that creates the objects is t
Re: !Re: proposal: Object Members
Do you have a link to this proposal so I can take a look at it? It'd be much easier to critique it if I could see the proposal text. - Isiah Meadows cont...@isiahmeadows.com www.isiahmeadows.com On Wed, Aug 1, 2018 at 2:18 AM, Ranando King wrote: >> If you go back a few months, what you're proposing is *very* similar, at >> least functionally, to my previous iteration of my proposal: > > That functional similarity is intentional. After pouring over years worth of > posts, I figured out what the vast majority of the proposal-class-fields > detractors actually wanted: an elegant, easily recognized syntax for adding > private members to objects. > >> My main problem was that trying to limit private properties to objects >> created within a scope got complicated in a hurry once you considered all >> the small details, and it just didn't seem simple anymore. > > I noticed that about your proposal too. I'm also pretty sure that Daniel E. > and Kevin G. ran into the same issues back during the proposal-private-names > days which is why the private names concept is just an implementation detail > in their current proposal. My proposal is made less complicated by breaking > the problem down into the 3 pieces required to make it all work: > 1. a record to store private data > 2. an array to hold references to the schema records of accessible private > data > 3. a schema record for the sharable data. > > In this way private = encapsulated on a non-function, protected = private + > shared, and static = encapsulated on a function. It should be easy to sort > out how the data would be stored given such simple definitions. These simple > definitions also mean that encapsulation is naturally confined to > definitions. Attempts to alter that state lead to strange logical > contradictions and potential leaks of encapsulated data. I have thought of > the possibility that private data could be added after definition, but every > attempt I make to consider such a thing has so far led to a risk of leaking. > > I've been working on some code that can serve as a proof-of-concept in ES6. > It will implement all of my proposal that can reasonably be implemented in > ES6 using Proxy. It's already in the proposal repository under the POC > branch, but it's still a WIP. For now, it already supports inheriting from > native objects. I'm working on subclassing right now. By the time I get done > (likely this coming Monday), it should support every feature in my proposal. > I'm basically using it as a means to check the viability of my proposal. > > On Tue, Jul 31, 2018 at 4:35 PM Isiah Meadows > wrote: >> >> If you go back a few months, what you're proposing is *very* similar, >> at least functionally, to my previous iteration of my proposal: >> >> https://github.com/isiahmeadows/private-symbol-proposal/blob/c5c9781d9e76123c92d8fbc83681fdd3a9b0b319/README.md >> >> My main problem was that trying to limit private properties to objects >> created within a scope got complicated in a hurry once you considered >> all the small details, and it just didn't seem simple anymore. It only >> got more complicated when you started getting into the logistics of >> integrating with modules. >> >> So I've considered the issue and explored it pretty thoroughly - I >> *really* don't want private data to be limited to classes (which I >> dislike), but I did also previously have the concern of trying to >> limit who could define properties where. >> >> I will point out that you can prevent arbitrary private extension by >> simply doing `Object.preventExtensions(object)`. Because properties >> defined using private symbols are otherwise just normal properties, >> they still have to go through the same access checks normal properties >> have to, like [[IsExtensible]]. The only other concrete difference is >> that proxy hooks don't fire when you do things with private symbols. >> >> - >> >> Isiah Meadows >> cont...@isiahmeadows.com >> www.isiahmeadows.com >> >> >> On Tue, Jul 31, 2018 at 3:09 PM, Ranando King wrote: >> >> What use case are you referring to here? >> > >> > In the case of SymbolTree, the objects in use are external. >> > >> >> I think there’s been a misunderstanding. Everybody agrees that that’s a >> >> bad pattern. It’s not what the point of private symbols would be. It’s >> >> not a >> >> target use case. >> > >> > That certainly puts my mind at ease. >> > >> >> As Isiah said, “all of the examples here I've presented are for >> >> scenarios >> >> where the state is related to the factory that created the objects.” >> > >> > If the factory that creates the objects is the also the only thing >> > trying to >> > store private information on those objects, then I understand you're >> > only >> > looking for per-instance module-private data, possibly with the ability >> > to >> > use common private names. If that's the case, then it really is just 2 >> > simple extensions of my proposal: >> > * allow a Symbol when used as a private o
Re: !Re: proposal: Object Members
> If you go back a few months, what you're proposing is *very* similar, at least functionally, to my previous iteration of my proposal: That functional similarity is intentional. After pouring over years worth of posts, I figured out what the vast majority of the proposal-class-fields detractors actually wanted: an elegant, easily recognized syntax for adding private members to objects. > My main problem was that trying to limit private properties to objects created within a scope got complicated in a hurry once you considered all the small details, and it just didn't seem simple anymore. I noticed that about your proposal too. I'm also pretty sure that Daniel E. and Kevin G. ran into the same issues back during the proposal-private-names days which is why the private names concept is just an implementation detail in their current proposal. My proposal is made less complicated by breaking the problem down into the 3 pieces required to make it all work: 1. a record to store private data 2. an array to hold references to the schema records of accessible private data 3. a schema record for the sharable data. In this way private = encapsulated on a non-function, protected = private + shared, and static = encapsulated on a function. It should be easy to sort out how the data would be stored given such simple definitions. These simple definitions also mean that encapsulation is naturally confined to definitions. Attempts to alter that state lead to strange logical contradictions and potential leaks of encapsulated data. I have thought of the possibility that private data could be added after definition, but every attempt I make to consider such a thing has so far led to a risk of leaking. I've been working on some code that can serve as a proof-of-concept in ES6. It will implement all of my proposal that can reasonably be implemented in ES6 using Proxy. It's already in the proposal repository under the POC branch, but it's still a WIP. For now, it already supports inheriting from native objects. I'm working on subclassing right now. By the time I get done (likely this coming Monday), it should support every feature in my proposal. I'm basically using it as a means to check the viability of my proposal. On Tue, Jul 31, 2018 at 4:35 PM Isiah Meadows wrote: > If you go back a few months, what you're proposing is *very* similar, > at least functionally, to my previous iteration of my proposal: > > https://github.com/isiahmeadows/private-symbol-proposal/blob/c5c9781d9e76123c92d8fbc83681fdd3a9b0b319/README.md > > My main problem was that trying to limit private properties to objects > created within a scope got complicated in a hurry once you considered > all the small details, and it just didn't seem simple anymore. It only > got more complicated when you started getting into the logistics of > integrating with modules. > > So I've considered the issue and explored it pretty thoroughly - I > *really* don't want private data to be limited to classes (which I > dislike), but I did also previously have the concern of trying to > limit who could define properties where. > > I will point out that you can prevent arbitrary private extension by > simply doing `Object.preventExtensions(object)`. Because properties > defined using private symbols are otherwise just normal properties, > they still have to go through the same access checks normal properties > have to, like [[IsExtensible]]. The only other concrete difference is > that proxy hooks don't fire when you do things with private symbols. > > - > > Isiah Meadows > cont...@isiahmeadows.com > www.isiahmeadows.com > > > On Tue, Jul 31, 2018 at 3:09 PM, Ranando King wrote: > >> What use case are you referring to here? > > > > In the case of SymbolTree, the objects in use are external. > > > >> I think there’s been a misunderstanding. Everybody agrees that that’s a > >> bad pattern. It’s not what the point of private symbols would be. It’s > not a > >> target use case. > > > > That certainly puts my mind at ease. > > > >> As Isiah said, “all of the examples here I've presented are for > scenarios > >> where the state is related to the factory that created the objects.” > > > > If the factory that creates the objects is the also the only thing > trying to > > store private information on those objects, then I understand you're only > > looking for per-instance module-private data, possibly with the ability > to > > use common private names. If that's the case, then it really is just 2 > > simple extensions of my proposal: > > * allow a Symbol when used as a private or protected property name to > > persist as the private Symbol name for the private instance field on each > > object for which it is used. > > * create an additional privilege level (internal) that places the new > > field's name in the [[DeclarationInfo]] of the function containing the > > declaration. > > > > The effect of using these 2 features together is that anything within the > > same functi
Re: !Re: proposal: Object Members
Thanks for that information. I wasn't yet sure how to handle it. A parallel question is this: Is there any particular reason that the private container itself shouldn't be mutable? Or more directly, is there a good reason for private fields to only be create-able at declaration time? So far, all the logic I've created hinges on the reference to [[DeclarationInfo]] (which keeps all the known private names). Since that container is created at declaration time, it's not unfeasible for private properties to be appended after the declaration. I'm not particularly fond of the idea, but I'm also trying not to let my own biases commit me to a decision. On Tue, Jul 31, 2018 at 4:41 PM Jordan Harband wrote: > Note that builtins with internal slots, like Map, Set, and Promise, are > still mutable after being frozen - so if one is trying to model internal > slots with some kind of property stored on the object, then freezing *must* > have no effect on the ability to alter their contents. > > On Tue, Jul 31, 2018 at 2:34 PM, Isiah Meadows > wrote: > >> If you go back a few months, what you're proposing is *very* similar, >> at least functionally, to my previous iteration of my proposal: >> >> https://github.com/isiahmeadows/private-symbol-proposal/blob/c5c9781d9e76123c92d8fbc83681fdd3a9b0b319/README.md >> >> My main problem was that trying to limit private properties to objects >> created within a scope got complicated in a hurry once you considered >> all the small details, and it just didn't seem simple anymore. It only >> got more complicated when you started getting into the logistics of >> integrating with modules. >> >> So I've considered the issue and explored it pretty thoroughly - I >> *really* don't want private data to be limited to classes (which I >> dislike), but I did also previously have the concern of trying to >> limit who could define properties where. >> >> I will point out that you can prevent arbitrary private extension by >> simply doing `Object.preventExtensions(object)`. Because properties >> defined using private symbols are otherwise just normal properties, >> they still have to go through the same access checks normal properties >> have to, like [[IsExtensible]]. The only other concrete difference is >> that proxy hooks don't fire when you do things with private symbols. >> >> - >> >> Isiah Meadows >> cont...@isiahmeadows.com >> www.isiahmeadows.com >> >> >> On Tue, Jul 31, 2018 at 3:09 PM, Ranando King wrote: >> >> What use case are you referring to here? >> > >> > In the case of SymbolTree, the objects in use are external. >> > >> >> I think there’s been a misunderstanding. Everybody agrees that that’s a >> >> bad pattern. It’s not what the point of private symbols would be. It’s >> not a >> >> target use case. >> > >> > That certainly puts my mind at ease. >> > >> >> As Isiah said, “all of the examples here I've presented are for >> scenarios >> >> where the state is related to the factory that created the objects.” >> > >> > If the factory that creates the objects is the also the only thing >> trying to >> > store private information on those objects, then I understand you're >> only >> > looking for per-instance module-private data, possibly with the ability >> to >> > use common private names. If that's the case, then it really is just 2 >> > simple extensions of my proposal: >> > * allow a Symbol when used as a private or protected property name to >> > persist as the private Symbol name for the private instance field on >> each >> > object for which it is used. >> > * create an additional privilege level (internal) that places the new >> > field's name in the [[DeclarationInfo]] of the function containing the >> > declaration. >> > >> > The effect of using these 2 features together is that anything within >> the >> > same function as the declared Symbol will gain access to the internal >> field >> > of all objects using that Symbol as a field name. >> > >> > On Tue, Jul 31, 2018 at 1:36 PM Darien Valentine > > >> > wrote: >> >> >> >> > I'd say you've identified the common pattern, but that pattern >> itself is >> >> > a bad use case, and the use of private symbols as you have defined >> them >> >> > doesn't do anything to correct the technical issue. >> >> >> >> I think there’s been a misunderstanding. Everybody agrees that that’s a >> >> bad pattern. It’s not what the point of private symbols would be. It’s >> not a >> >> target use case. >> >> >> >> > Since you cannot stick new properties onto a non-extensible object, >> even >> >> > private symbols won't solve the problem with your use case. >> >> >> >> That appending private symbols to external objects which are frozen >> >> wouldn’t work doesn’t matter precisely because it’s not a target use >> case. >> >> That it doesn’t work reliably might even be considered a positive, >> since it >> >> discourages something we all seem to agree is not good practice. >> >> >> >> It’s also not related to private symbols; this is alrea
Re: !Re: proposal: Object Members
Yeah, I left it without saying that you could just model them as having their state as a single private symbol field with all the relevant data for it. I assumed it would be obvious enough for those who really pay attention to the spec, so I just left it implied. - Isiah Meadows cont...@isiahmeadows.com www.isiahmeadows.com On Tue, Jul 31, 2018 at 5:40 PM, Jordan Harband wrote: > Note that builtins with internal slots, like Map, Set, and Promise, are > still mutable after being frozen - so if one is trying to model internal > slots with some kind of property stored on the object, then freezing *must* > have no effect on the ability to alter their contents. > > On Tue, Jul 31, 2018 at 2:34 PM, Isiah Meadows > wrote: >> >> If you go back a few months, what you're proposing is *very* similar, >> at least functionally, to my previous iteration of my proposal: >> >> https://github.com/isiahmeadows/private-symbol-proposal/blob/c5c9781d9e76123c92d8fbc83681fdd3a9b0b319/README.md >> >> My main problem was that trying to limit private properties to objects >> created within a scope got complicated in a hurry once you considered >> all the small details, and it just didn't seem simple anymore. It only >> got more complicated when you started getting into the logistics of >> integrating with modules. >> >> So I've considered the issue and explored it pretty thoroughly - I >> *really* don't want private data to be limited to classes (which I >> dislike), but I did also previously have the concern of trying to >> limit who could define properties where. >> >> I will point out that you can prevent arbitrary private extension by >> simply doing `Object.preventExtensions(object)`. Because properties >> defined using private symbols are otherwise just normal properties, >> they still have to go through the same access checks normal properties >> have to, like [[IsExtensible]]. The only other concrete difference is >> that proxy hooks don't fire when you do things with private symbols. >> >> - >> >> Isiah Meadows >> cont...@isiahmeadows.com >> www.isiahmeadows.com >> >> >> On Tue, Jul 31, 2018 at 3:09 PM, Ranando King wrote: >> >> What use case are you referring to here? >> > >> > In the case of SymbolTree, the objects in use are external. >> > >> >> I think there’s been a misunderstanding. Everybody agrees that that’s a >> >> bad pattern. It’s not what the point of private symbols would be. It’s >> >> not a >> >> target use case. >> > >> > That certainly puts my mind at ease. >> > >> >> As Isiah said, “all of the examples here I've presented are for >> >> scenarios >> >> where the state is related to the factory that created the objects.” >> > >> > If the factory that creates the objects is the also the only thing >> > trying to >> > store private information on those objects, then I understand you're >> > only >> > looking for per-instance module-private data, possibly with the ability >> > to >> > use common private names. If that's the case, then it really is just 2 >> > simple extensions of my proposal: >> > * allow a Symbol when used as a private or protected property name to >> > persist as the private Symbol name for the private instance field on >> > each >> > object for which it is used. >> > * create an additional privilege level (internal) that places the new >> > field's name in the [[DeclarationInfo]] of the function containing the >> > declaration. >> > >> > The effect of using these 2 features together is that anything within >> > the >> > same function as the declared Symbol will gain access to the internal >> > field >> > of all objects using that Symbol as a field name. >> > >> > On Tue, Jul 31, 2018 at 1:36 PM Darien Valentine >> > wrote: >> >> >> >> > I'd say you've identified the common pattern, but that pattern itself >> >> > is >> >> > a bad use case, and the use of private symbols as you have defined >> >> > them >> >> > doesn't do anything to correct the technical issue. >> >> >> >> I think there’s been a misunderstanding. Everybody agrees that that’s a >> >> bad pattern. It’s not what the point of private symbols would be. It’s >> >> not a >> >> target use case. >> >> >> >> > Since you cannot stick new properties onto a non-extensible object, >> >> > even >> >> > private symbols won't solve the problem with your use case. >> >> >> >> That appending private symbols to external objects which are frozen >> >> wouldn’t work doesn’t matter precisely because it’s not a target use >> >> case. >> >> That it doesn’t work reliably might even be considered a positive, >> >> since it >> >> discourages something we all seem to agree is not good practice. >> >> >> >> It’s also not related to private symbols; this is already how >> >> properties >> >> work, regardless of what kind of key they have. >> >> >> >> > The difference here is that in your use cases, library A is >> >> > "sneakily" >> >> > storing information on object B. >> >> >> >> What use case are you referring to here? I can’t find any
Re: !Re: proposal: Object Members
> The argument I raised with Isiah was just 1 example of a bad pattern that > being too generic can open up. BTW, the risk for bad patterns doesn't necessarily justify exclusion of a feature. As I've brought up here before, iterators can be seriously abused similarly [1], thanks to the availability of `throw` + `return`, and you can always make a deferred out of a promise by simply pulling the `resolve`/`reject` out of the promise callback's scope. As long as it looks strange and weird enough and we have more semantically appropriate alternatives, I don't think we have an issue with potential abuse, and I feel private symbols as I have them meet this threshold. [1]: https://github.com/tc39/proposal-async-iteration/issues/68 - Isiah Meadows cont...@isiahmeadows.com www.isiahmeadows.com On Tue, Jul 31, 2018 at 5:10 PM, Ranando King wrote: > I get where you're coming from. The main reasons I've written my proposal > this way are: > > * Prior art: > - Many ES developers come from other, class-based, object-oriented > languages where keywords are the primary way of controlling data > accessibility. This means using the well known keywords will lower the > learning curve and increase adoption. > * Future expansion: > - Careful and narrow definition of the keywords and their corresponding > actions allows undesirable patterns to be avoided while leaving room for > future extensibility. > > The argument I raised with Isiah was just 1 example of a bad pattern that > being too generic can open up. These are also part of the reasons why I am > against proposal-class-fields. It seems so simple on the surface, but > effectively makes an already limited keyword even more limited than is > should be. Plus it adds difficulty to creating new features around those > concepts in a way that will be easily understood by developers migrating > from other languages. > > > On Tue, Jul 31, 2018 at 3:43 PM Darien Valentine > wrote: >> >> You’re right, sorry — the SymbolTree example does operate on objects not >> created in the module itself, so my statement wasn’t accurate. >> >> More carefully I ought to have said that the use cases concern object >> creation. Decorators and mixin functionality can fall in this bucket, where >> the object is likely not literally “birthed” by the library that is doing >> the decorating, yet the functionality is intended to be attached during that >> process by a consumer of the library. >> >> In my own experience to date, all cases where I have run into the >> class-declaration scope limitation did concern locally created objects >> (class instances specifically), so yes, the adjustments you are talking >> about wrt the object members proposal probably would be able to cover them, >> though I would still tend to favor a more generic and simple solution. >> >> On Tue, Jul 31, 2018 at 3:09 PM Ranando King wrote: >>> >>> > What use case are you referring to here? >>> >>> In the case of SymbolTree, the objects in use are external. >>> >>> > I think there’s been a misunderstanding. Everybody agrees that that’s a >>> > bad pattern. It’s not what the point of private symbols would be. It’s >>> > not a >>> > target use case. >>> >>> That certainly puts my mind at ease. >>> >>> > As Isiah said, “all of the examples here I've presented are for >>> > scenarios where the state is related to the factory that created the >>> > objects.” >>> >>> If the factory that creates the objects is the also the only thing trying >>> to store private information on those objects, then I understand you're only >>> looking for per-instance module-private data, possibly with the ability to >>> use common private names. If that's the case, then it really is just 2 >>> simple extensions of my proposal: >>> * allow a Symbol when used as a private or protected property name to >>> persist as the private Symbol name for the private instance field on each >>> object for which it is used. >>> * create an additional privilege level (internal) that places the new >>> field's name in the [[DeclarationInfo]] of the function containing the >>> declaration. >>> >>> The effect of using these 2 features together is that anything within the >>> same function as the declared Symbol will gain access to the internal field >>> of all objects using that Symbol as a field name. >>> >>> On Tue, Jul 31, 2018 at 1:36 PM Darien Valentine >>> wrote: > I'd say you've identified the common pattern, but that pattern itself > is a bad use case, and the use of private symbols as you have defined > them > doesn't do anything to correct the technical issue. I think there’s been a misunderstanding. Everybody agrees that that’s a bad pattern. It’s not what the point of private symbols would be. It’s not a target use case. > Since you cannot stick new properties onto a non-extensible object, > even private symbols won't solve the problem with your use case. That appendi
Re: !Re: proposal: Object Members
Note that builtins with internal slots, like Map, Set, and Promise, are still mutable after being frozen - so if one is trying to model internal slots with some kind of property stored on the object, then freezing *must* have no effect on the ability to alter their contents. On Tue, Jul 31, 2018 at 2:34 PM, Isiah Meadows wrote: > If you go back a few months, what you're proposing is *very* similar, > at least functionally, to my previous iteration of my proposal: > https://github.com/isiahmeadows/private-symbol-proposal/blob/ > c5c9781d9e76123c92d8fbc83681fdd3a9b0b319/README.md > > My main problem was that trying to limit private properties to objects > created within a scope got complicated in a hurry once you considered > all the small details, and it just didn't seem simple anymore. It only > got more complicated when you started getting into the logistics of > integrating with modules. > > So I've considered the issue and explored it pretty thoroughly - I > *really* don't want private data to be limited to classes (which I > dislike), but I did also previously have the concern of trying to > limit who could define properties where. > > I will point out that you can prevent arbitrary private extension by > simply doing `Object.preventExtensions(object)`. Because properties > defined using private symbols are otherwise just normal properties, > they still have to go through the same access checks normal properties > have to, like [[IsExtensible]]. The only other concrete difference is > that proxy hooks don't fire when you do things with private symbols. > > - > > Isiah Meadows > cont...@isiahmeadows.com > www.isiahmeadows.com > > > On Tue, Jul 31, 2018 at 3:09 PM, Ranando King wrote: > >> What use case are you referring to here? > > > > In the case of SymbolTree, the objects in use are external. > > > >> I think there’s been a misunderstanding. Everybody agrees that that’s a > >> bad pattern. It’s not what the point of private symbols would be. It’s > not a > >> target use case. > > > > That certainly puts my mind at ease. > > > >> As Isiah said, “all of the examples here I've presented are for > scenarios > >> where the state is related to the factory that created the objects.” > > > > If the factory that creates the objects is the also the only thing > trying to > > store private information on those objects, then I understand you're only > > looking for per-instance module-private data, possibly with the ability > to > > use common private names. If that's the case, then it really is just 2 > > simple extensions of my proposal: > > * allow a Symbol when used as a private or protected property name to > > persist as the private Symbol name for the private instance field on each > > object for which it is used. > > * create an additional privilege level (internal) that places the new > > field's name in the [[DeclarationInfo]] of the function containing the > > declaration. > > > > The effect of using these 2 features together is that anything within the > > same function as the declared Symbol will gain access to the internal > field > > of all objects using that Symbol as a field name. > > > > On Tue, Jul 31, 2018 at 1:36 PM Darien Valentine > > wrote: > >> > >> > I'd say you've identified the common pattern, but that pattern itself > is > >> > a bad use case, and the use of private symbols as you have defined > them > >> > doesn't do anything to correct the technical issue. > >> > >> I think there’s been a misunderstanding. Everybody agrees that that’s a > >> bad pattern. It’s not what the point of private symbols would be. It’s > not a > >> target use case. > >> > >> > Since you cannot stick new properties onto a non-extensible object, > even > >> > private symbols won't solve the problem with your use case. > >> > >> That appending private symbols to external objects which are frozen > >> wouldn’t work doesn’t matter precisely because it’s not a target use > case. > >> That it doesn’t work reliably might even be considered a positive, > since it > >> discourages something we all seem to agree is not good practice. > >> > >> It’s also not related to private symbols; this is already how properties > >> work, regardless of what kind of key they have. > >> > >> > The difference here is that in your use cases, library A is "sneakily" > >> > storing information on object B. > >> > >> What use case are you referring to here? I can’t find any example in the > >> previous posts that matches these descriptions. As Isiah said, “all of > the > >> examples here I've presented are for scenarios where the state is > related to > >> the factory that created the objects.” The same is true of my examples. > >> Everybody’s on the same page regarding not wanting to add properties to > >> objects their own libraries do not create. > ___ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > ___
Re: !Re: proposal: Object Members
If you go back a few months, what you're proposing is *very* similar, at least functionally, to my previous iteration of my proposal: https://github.com/isiahmeadows/private-symbol-proposal/blob/c5c9781d9e76123c92d8fbc83681fdd3a9b0b319/README.md My main problem was that trying to limit private properties to objects created within a scope got complicated in a hurry once you considered all the small details, and it just didn't seem simple anymore. It only got more complicated when you started getting into the logistics of integrating with modules. So I've considered the issue and explored it pretty thoroughly - I *really* don't want private data to be limited to classes (which I dislike), but I did also previously have the concern of trying to limit who could define properties where. I will point out that you can prevent arbitrary private extension by simply doing `Object.preventExtensions(object)`. Because properties defined using private symbols are otherwise just normal properties, they still have to go through the same access checks normal properties have to, like [[IsExtensible]]. The only other concrete difference is that proxy hooks don't fire when you do things with private symbols. - Isiah Meadows cont...@isiahmeadows.com www.isiahmeadows.com On Tue, Jul 31, 2018 at 3:09 PM, Ranando King wrote: >> What use case are you referring to here? > > In the case of SymbolTree, the objects in use are external. > >> I think there’s been a misunderstanding. Everybody agrees that that’s a >> bad pattern. It’s not what the point of private symbols would be. It’s not a >> target use case. > > That certainly puts my mind at ease. > >> As Isiah said, “all of the examples here I've presented are for scenarios >> where the state is related to the factory that created the objects.” > > If the factory that creates the objects is the also the only thing trying to > store private information on those objects, then I understand you're only > looking for per-instance module-private data, possibly with the ability to > use common private names. If that's the case, then it really is just 2 > simple extensions of my proposal: > * allow a Symbol when used as a private or protected property name to > persist as the private Symbol name for the private instance field on each > object for which it is used. > * create an additional privilege level (internal) that places the new > field's name in the [[DeclarationInfo]] of the function containing the > declaration. > > The effect of using these 2 features together is that anything within the > same function as the declared Symbol will gain access to the internal field > of all objects using that Symbol as a field name. > > On Tue, Jul 31, 2018 at 1:36 PM Darien Valentine > wrote: >> >> > I'd say you've identified the common pattern, but that pattern itself is >> > a bad use case, and the use of private symbols as you have defined them >> > doesn't do anything to correct the technical issue. >> >> I think there’s been a misunderstanding. Everybody agrees that that’s a >> bad pattern. It’s not what the point of private symbols would be. It’s not a >> target use case. >> >> > Since you cannot stick new properties onto a non-extensible object, even >> > private symbols won't solve the problem with your use case. >> >> That appending private symbols to external objects which are frozen >> wouldn’t work doesn’t matter precisely because it’s not a target use case. >> That it doesn’t work reliably might even be considered a positive, since it >> discourages something we all seem to agree is not good practice. >> >> It’s also not related to private symbols; this is already how properties >> work, regardless of what kind of key they have. >> >> > The difference here is that in your use cases, library A is "sneakily" >> > storing information on object B. >> >> What use case are you referring to here? I can’t find any example in the >> previous posts that matches these descriptions. As Isiah said, “all of the >> examples here I've presented are for scenarios where the state is related to >> the factory that created the objects.” The same is true of my examples. >> Everybody’s on the same page regarding not wanting to add properties to >> objects their own libraries do not create. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: !Re: proposal: Object Members
If you look at my proposal, it would be a "no" for the same reasons you can't add normal properties to them. - Isiah Meadows cont...@isiahmeadows.com www.isiahmeadows.com On Tue, Jul 31, 2018 at 1:17 PM, Michael Theriot wrote: > Should a sealed/frozen object be privately extensible? I don't actually > know, but interesting point. > > > On Tuesday, July 31, 2018, Ranando King wrote: >> >> > Consider what people often use public symbols for now. >> >> I know that I use them as fixed-value unique keys (module globals) for >> properties on objects that I export and don't want others to be aware of or >> able to touch. >> >> > For example, consider this library [1]. In this case, they use a public >> > symbol for their stuff in this file [2]. >> >> And as I said before, if someone passes a non-extensible object to this >> library, it breaks. Since any library can request any object be sealed or >> frozen, the implementation of this library is too fragile. >> >> > Because here, it's not a cache, but it's literally extra associated data >> > in the object. And also, in that case, you *want* the engine to see it as a >> > property, since it can employ relevant IC caching for it. >> >> Here's a parallel for you. Right now, Google has a database with >> information about me on it. I don't have access to that information (module >> privacy) and that information isn't stored anywhere on me or my devices >> (module locality). This is a proper conceptual model. The information Google >> is keeping about me is information they generated. Why should I have to pay >> to store their information? Thankfully I don't. However, this is precisely >> what you're claiming to be a good use case. You want module privacy without >> module locality. If I were to play at a Kevin Gibbons-like response, I'd say >> you've identified the common pattern, but that pattern itself is a bad use >> case, and the use of private symbols as you have defined them doesn't do >> anything to correct the technical issue. Since you cannot stick new >> properties onto a non-extensible object, even private symbols won't solve >> the problem with your use case. >> >> > No, I'm not. I'm drawing a distinction between a pure many-to-one >> > association (weak maps) and a "has a" relationship (private symbol >> > properties). >> >> First, for any given property bag, the keys will need to be unique, but >> that doesn't force uniqueness onto the values. As such, even properties on >> an object provided by your "private Symbol" would still be many-1. When a >> 3rd party library wants to keep information associated with an arbitrary >> object, there are only 3 choices: >> * try to store that information on the object >> * this is what you're advocating, but it's not a good pattern. It's too >> fragile, being subject to break if the incoming object is not extensible. >> * store the information as being associated to the object (WeakMap) >> * this is the pattern that works in all cases (but the syntax is >> cumbersome and the implementation somewhat slow) >> * return a wrapper containing the original object and the new information >> (Proxy or custom wrapper) >> * this is another possibility, but requires that any users accept and >> use the new Proxy or wrapper object in lieu of the original. >> >> > Another scenario is for JSDOM's `Window` implementation, where they have >> > a few underscore-private variables like this [3]. That particular variable >> > is used in several disparate parts throughout the code base [4], but is >> > still conceptually a property. This is a case where a private symbol >> > property is appropriate. >> >> It's not just "conceptually" a property. It's logically a property. Why? >> Because all the objects that it exists on were constructed somewhere within >> the JSDOM library. That's me putting _my_ keys in _my_ pocket. There's >> absolutely nothing wrong with that. >> >> > Conversely in this JSDOM file [5], it's just associating data with an >> > arbitrary object it happens to have, and so using the weak map makes >> > perfect >> > sense. >> >> Conceptually speaking, this is the same scenario as SymbolTree. In both >> cases, the library is generating information associated with an object it >> doesn't own and didn't create. >> >> > BTW, you could make a similar argument against superclass private fields >> > - it's like hiding valuable info in your wallet before you receive it for >> > the first time, but even after dismantling it, you can't find any evidence >> > of that valuable info. >> >> That dog don't hunt. The difference here is that in your use cases, >> library A is "sneakily" storing information on object B. In the case of >> superclass private fields, subclass B has "volunteered" to take on the >> information and functionality of class A. You've essentially compared apples >> and asteroids just because they both begin with "a". >> >> On Tue, Jul 31, 2018 at 2:15 AM Isiah Meadows >> wrote: >>> >>> > Isn't this
Re: !Re: proposal: Object Members
I get where you're coming from. The main reasons I've written my proposal this way are: * Prior art: - Many ES developers come from other, class-based, object-oriented languages where keywords are the primary way of controlling data accessibility. This means using the well known keywords will lower the learning curve and increase adoption. * Future expansion: - Careful and narrow definition of the keywords and their corresponding actions allows undesirable patterns to be avoided while leaving room for future extensibility. The argument I raised with Isiah was just 1 example of a bad pattern that being too generic can open up. These are also part of the reasons why I am against proposal-class-fields. It seems so simple on the surface, but effectively makes an already limited keyword even more limited than is should be. Plus it adds difficulty to creating new features around those concepts in a way that will be easily understood by developers migrating from other languages. On Tue, Jul 31, 2018 at 3:43 PM Darien Valentine wrote: > You’re right, sorry — the SymbolTree example does operate on objects not > created in the module itself, so my statement wasn’t accurate. > > More carefully I ought to have said that the use cases concern object > creation. Decorators and mixin functionality can fall in this bucket, where > the object is likely not literally “birthed” by the library that is doing > the decorating, yet the functionality is intended to be attached during > that process by a consumer of the library. > > In my own experience to date, all cases where I have run into the > class-declaration scope limitation did concern locally created objects > (class instances specifically), so yes, the adjustments you are talking > about wrt the object members proposal probably would be able to cover them, > though I would still tend to favor a more generic and simple solution. > > On Tue, Jul 31, 2018 at 3:09 PM Ranando King wrote: > >> > What use case are you referring to here? >> >> In the case of SymbolTree, the objects in use are external. >> >> > I think there’s been a misunderstanding. Everybody agrees that that’s >> a bad pattern. It’s not what the point of private symbols would be. It’s >> not a target use case. >> >> That certainly puts my mind at ease. >> >> > As Isiah said, “all of the examples here I've presented are for >> scenarios where the state is related to the factory that created the >> objects.” >> >> If the factory that creates the objects is the also the only thing trying >> to store private information on those objects, then I understand you're >> only looking for per-instance module-private data, possibly with the >> ability to use common private names. If that's the case, then it really is >> just 2 simple extensions of my proposal: >> * allow a Symbol when used as a private or protected property name to >> persist as the private Symbol name for the private instance field on each >> object for which it is used. >> * create an additional privilege level (internal) that places the new >> field's name in the [[DeclarationInfo]] of the function containing the >> declaration. >> >> The effect of using these 2 features together is that anything within the >> same function as the declared Symbol will gain access to the internal field >> of all objects using that Symbol as a field name. >> >> On Tue, Jul 31, 2018 at 1:36 PM Darien Valentine >> wrote: >> >>> > I'd say you've identified the common pattern, but that pattern itself >>> is a bad use case, and the use of private symbols as you have defined them >>> doesn't do anything to correct the technical issue. >>> >>> I think there’s been a misunderstanding. Everybody agrees that that’s a >>> bad pattern. It’s not what the point of private symbols would be. It’s not >>> a target use case. >>> >>> > Since you cannot stick new properties onto a non-extensible object, >>> even private symbols won't solve the problem with your use case. >>> >>> That appending private symbols to external objects which are frozen >>> wouldn’t work doesn’t matter precisely because it’s not a target use case. >>> That it doesn’t work reliably might even be considered a positive, since it >>> discourages something we all seem to agree is not good practice. >>> >>> It’s also not related to private symbols; this is already how properties >>> work, regardless of what kind of key they have. >>> >>> > The difference here is that in your use cases, library A is "sneakily" >>> storing information on object B. >>> >>> What use case are you referring to here? I can’t find any example in the >>> previous posts that matches these descriptions. As Isiah said, “all of the >>> examples here I've presented are for scenarios where the state is related >>> to the factory that created the objects.” The same is true of my examples. >>> Everybody’s on the same page regarding not wanting to add properties to >>> objects their own libraries do not create. >>> >> ___
Re: !Re: proposal: Object Members
You’re right, sorry — the SymbolTree example does operate on objects not created in the module itself, so my statement wasn’t accurate. More carefully I ought to have said that the use cases concern object creation. Decorators and mixin functionality can fall in this bucket, where the object is likely not literally “birthed” by the library that is doing the decorating, yet the functionality is intended to be attached during that process by a consumer of the library. In my own experience to date, all cases where I have run into the class-declaration scope limitation did concern locally created objects (class instances specifically), so yes, the adjustments you are talking about wrt the object members proposal probably would be able to cover them, though I would still tend to favor a more generic and simple solution. On Tue, Jul 31, 2018 at 3:09 PM Ranando King wrote: > > What use case are you referring to here? > > In the case of SymbolTree, the objects in use are external. > > > I think there’s been a misunderstanding. Everybody agrees that that’s a > bad pattern. It’s not what the point of private symbols would be. It’s not > a target use case. > > That certainly puts my mind at ease. > > > As Isiah said, “all of the examples here I've presented are for > scenarios where the state is related to the factory that created the > objects.” > > If the factory that creates the objects is the also the only thing trying > to store private information on those objects, then I understand you're > only looking for per-instance module-private data, possibly with the > ability to use common private names. If that's the case, then it really is > just 2 simple extensions of my proposal: > * allow a Symbol when used as a private or protected property name to > persist as the private Symbol name for the private instance field on each > object for which it is used. > * create an additional privilege level (internal) that places the new > field's name in the [[DeclarationInfo]] of the function containing the > declaration. > > The effect of using these 2 features together is that anything within the > same function as the declared Symbol will gain access to the internal field > of all objects using that Symbol as a field name. > > On Tue, Jul 31, 2018 at 1:36 PM Darien Valentine > wrote: > >> > I'd say you've identified the common pattern, but that pattern itself >> is a bad use case, and the use of private symbols as you have defined them >> doesn't do anything to correct the technical issue. >> >> I think there’s been a misunderstanding. Everybody agrees that that’s a >> bad pattern. It’s not what the point of private symbols would be. It’s not >> a target use case. >> >> > Since you cannot stick new properties onto a non-extensible object, >> even private symbols won't solve the problem with your use case. >> >> That appending private symbols to external objects which are frozen >> wouldn’t work doesn’t matter precisely because it’s not a target use case. >> That it doesn’t work reliably might even be considered a positive, since it >> discourages something we all seem to agree is not good practice. >> >> It’s also not related to private symbols; this is already how properties >> work, regardless of what kind of key they have. >> >> > The difference here is that in your use cases, library A is "sneakily" >> storing information on object B. >> >> What use case are you referring to here? I can’t find any example in the >> previous posts that matches these descriptions. As Isiah said, “all of the >> examples here I've presented are for scenarios where the state is related >> to the factory that created the objects.” The same is true of my examples. >> Everybody’s on the same page regarding not wanting to add properties to >> objects their own libraries do not create. >> > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: !Re: proposal: Object Members
> What use case are you referring to here? In the case of SymbolTree, the objects in use are external. > I think there’s been a misunderstanding. Everybody agrees that that’s a bad pattern. It’s not what the point of private symbols would be. It’s not a target use case. That certainly puts my mind at ease. > As Isiah said, “all of the examples here I've presented are for scenarios where the state is related to the factory that created the objects.” If the factory that creates the objects is the also the only thing trying to store private information on those objects, then I understand you're only looking for per-instance module-private data, possibly with the ability to use common private names. If that's the case, then it really is just 2 simple extensions of my proposal: * allow a Symbol when used as a private or protected property name to persist as the private Symbol name for the private instance field on each object for which it is used. * create an additional privilege level (internal) that places the new field's name in the [[DeclarationInfo]] of the function containing the declaration. The effect of using these 2 features together is that anything within the same function as the declared Symbol will gain access to the internal field of all objects using that Symbol as a field name. On Tue, Jul 31, 2018 at 1:36 PM Darien Valentine wrote: > > I'd say you've identified the common pattern, but that pattern itself is > a bad use case, and the use of private symbols as you have defined them > doesn't do anything to correct the technical issue. > > I think there’s been a misunderstanding. Everybody agrees that that’s a > bad pattern. It’s not what the point of private symbols would be. It’s not > a target use case. > > > Since you cannot stick new properties onto a non-extensible object, even > private symbols won't solve the problem with your use case. > > That appending private symbols to external objects which are frozen > wouldn’t work doesn’t matter precisely because it’s not a target use case. > That it doesn’t work reliably might even be considered a positive, since it > discourages something we all seem to agree is not good practice. > > It’s also not related to private symbols; this is already how properties > work, regardless of what kind of key they have. > > > The difference here is that in your use cases, library A is "sneakily" > storing information on object B. > > What use case are you referring to here? I can’t find any example in the > previous posts that matches these descriptions. As Isiah said, “all of the > examples here I've presented are for scenarios where the state is related > to the factory that created the objects.” The same is true of my examples. > Everybody’s on the same page regarding not wanting to add properties to > objects their own libraries do not create. > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: !Re: proposal: Object Members
> I'd say you've identified the common pattern, but that pattern itself is a bad use case, and the use of private symbols as you have defined them doesn't do anything to correct the technical issue. I think there’s been a misunderstanding. Everybody agrees that that’s a bad pattern. It’s not what the point of private symbols would be. It’s not a target use case. > Since you cannot stick new properties onto a non-extensible object, even private symbols won't solve the problem with your use case. That appending private symbols to external objects which are frozen wouldn’t work doesn’t matter precisely because it’s not a target use case. That it doesn’t work reliably might even be considered a positive, since it discourages something we all seem to agree is not good practice. It’s also not related to private symbols; this is already how properties work, regardless of what kind of key they have. > The difference here is that in your use cases, library A is "sneakily" storing information on object B. What use case are you referring to here? I can’t find any example in the previous posts that matches these descriptions. As Isiah said, “all of the examples here I've presented are for scenarios where the state is related to the factory that created the objects.” The same is true of my examples. Everybody’s on the same page regarding not wanting to add properties to objects their own libraries do not create. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: !Re: proposal: Object Members
Should a sealed/frozen object be privately extensible? I don't actually know, but interesting point. On Tuesday, July 31, 2018, Ranando King wrote: > > Consider what people often use public symbols for now. > > I know that I use them as fixed-value unique keys (module globals) for > properties on objects that I export and don't want others to be aware of or > able to touch. > > > For example, consider this library [1]. In this case, they use a public > symbol for their stuff in this file [2]. > > And as I said before, if someone passes a non-extensible object to this > library, it breaks. Since any library can request any object be sealed or > frozen, the implementation of this library is too fragile. > > > Because here, it's not a cache, but it's literally extra associated > data in the object. And also, in that case, you *want* the engine to see > it as a property, since it can employ relevant IC caching for it. > > Here's a parallel for you. Right now, Google has a database with > information about me on it. I don't have access to that information (module > privacy) and that information isn't stored anywhere on me or my devices > (module locality). This is a proper conceptual model. The information > Google is keeping about me is information they generated. Why should I have > to pay to store their information? Thankfully I don't. However, this is > precisely what you're claiming to be a good use case. You want module > privacy without module locality. If I were to play at a Kevin Gibbons-like > response, I'd say you've identified the common pattern, but that pattern > itself is a bad use case, and the use of private symbols as you have > defined them doesn't do anything to correct the technical issue. Since you > cannot stick new properties onto a non-extensible object, even private > symbols won't solve the problem with your use case. > > > No, I'm not. I'm drawing a distinction between a pure many-to-one > > association > (weak maps) and a "has a" relationship (private symbol properties). > > First, for any given property bag, the keys will need to be unique, but > that doesn't force uniqueness onto the values. As such, even properties on > an object provided by your "private Symbol" would still be many-1. When a > 3rd party library wants to keep information associated with an arbitrary > object, there are only 3 choices: > * try to store that information on the object > * this is what you're advocating, but it's not a good pattern. It's too > fragile, being subject to break if the incoming object is not extensible. > * store the information as being associated to the object (WeakMap) > * this is the pattern that works in all cases (but the syntax is > cumbersome and the implementation somewhat slow) > * return a wrapper containing the original object and the new information > (Proxy or custom wrapper) > * this is another possibility, but requires that any users accept and > use the new Proxy or wrapper object in lieu of the original. > > > Another scenario is for JSDOM's `Window` implementation, where they have > a few underscore-private variables like this [3]. That particular variable > is used in several disparate parts throughout the code base [4], but is > still conceptually a property. This is a case where a private symbol > property is appropriate. > > It's not just "conceptually" a property. It's logically a property. Why? > Because all the objects that it exists on were constructed somewhere within > the JSDOM library. That's me putting _my_ keys in _my_ pocket. There's > absolutely nothing wrong with that. > > > Conversely in this JSDOM file [5], it's just associating data with an > > arbitrary > object it happens to have, and so using the weak map makes perfect sense. > > Conceptually speaking, this is the same scenario as SymbolTree. In both > cases, the library is generating information associated with an object it > doesn't own and didn't create. > > > BTW, you could make a similar argument against superclass private fields > - it's like hiding valuable info in your wallet before you receive it for > the first time, but even after dismantling it, you can't find any > evidence of that valuable info. > > That dog don't hunt. The difference here is that in your use cases, > library A is "sneakily" storing information on object B. In the case of > superclass private fields, subclass B has "volunteered" to take on the > information and functionality of class A. You've essentially compared > apples and asteroids just because they both begin with "a". > > On Tue, Jul 31, 2018 at 2:15 AM Isiah Meadows > wrote: > >> > Isn't this precisely what WeakMaps are for? If the data is >> > "module-internal", then the module needs to be the owner of the data >> store. >> > If the data is about "arbitrary objects" (object from outside the >> module?) >> > then those objects are the keys to the data store. If any object is >> thrown >> > away, the associated data is no longer needed. If this do
Re: !Re: proposal: Object Members
> Consider what people often use public symbols for now. I know that I use them as fixed-value unique keys (module globals) for properties on objects that I export and don't want others to be aware of or able to touch. > For example, consider this library [1]. In this case, they use a public symbol for their stuff in this file [2]. And as I said before, if someone passes a non-extensible object to this library, it breaks. Since any library can request any object be sealed or frozen, the implementation of this library is too fragile. > Because here, it's not a cache, but it's literally extra associated data in the object. And also, in that case, you *want* the engine to see it as a property, since it can employ relevant IC caching for it. Here's a parallel for you. Right now, Google has a database with information about me on it. I don't have access to that information (module privacy) and that information isn't stored anywhere on me or my devices (module locality). This is a proper conceptual model. The information Google is keeping about me is information they generated. Why should I have to pay to store their information? Thankfully I don't. However, this is precisely what you're claiming to be a good use case. You want module privacy without module locality. If I were to play at a Kevin Gibbons-like response, I'd say you've identified the common pattern, but that pattern itself is a bad use case, and the use of private symbols as you have defined them doesn't do anything to correct the technical issue. Since you cannot stick new properties onto a non-extensible object, even private symbols won't solve the problem with your use case. > No, I'm not. I'm drawing a distinction between a pure many-to-one association (weak maps) and a "has a" relationship (private symbol properties). First, for any given property bag, the keys will need to be unique, but that doesn't force uniqueness onto the values. As such, even properties on an object provided by your "private Symbol" would still be many-1. When a 3rd party library wants to keep information associated with an arbitrary object, there are only 3 choices: * try to store that information on the object * this is what you're advocating, but it's not a good pattern. It's too fragile, being subject to break if the incoming object is not extensible. * store the information as being associated to the object (WeakMap) * this is the pattern that works in all cases (but the syntax is cumbersome and the implementation somewhat slow) * return a wrapper containing the original object and the new information (Proxy or custom wrapper) * this is another possibility, but requires that any users accept and use the new Proxy or wrapper object in lieu of the original. > Another scenario is for JSDOM's `Window` implementation, where they have a few underscore-private variables like this [3]. That particular variable is used in several disparate parts throughout the code base [4], but is still conceptually a property. This is a case where a private symbol property is appropriate. It's not just "conceptually" a property. It's logically a property. Why? Because all the objects that it exists on were constructed somewhere within the JSDOM library. That's me putting _my_ keys in _my_ pocket. There's absolutely nothing wrong with that. > Conversely in this JSDOM file [5], it's just associating data with an > arbitrary object it happens to have, and so using the weak map makes perfect sense. Conceptually speaking, this is the same scenario as SymbolTree. In both cases, the library is generating information associated with an object it doesn't own and didn't create. > BTW, you could make a similar argument against superclass private fields - it's like hiding valuable info in your wallet before you receive it for the first time, but even after dismantling it, you can't find any evidence of that valuable info. That dog don't hunt. The difference here is that in your use cases, library A is "sneakily" storing information on object B. In the case of superclass private fields, subclass B has "volunteered" to take on the information and functionality of class A. You've essentially compared apples and asteroids just because they both begin with "a". On Tue, Jul 31, 2018 at 2:15 AM Isiah Meadows wrote: > > Isn't this precisely what WeakMaps are for? If the data is > > "module-internal", then the module needs to be the owner of the data > store. > > If the data is about "arbitrary objects" (object from outside the > module?) > > then those objects are the keys to the data store. If any object is > thrown > > away, the associated data is no longer needed. If this doesn't fit the > > functionality of a WeakMap, I don't know what will. > > Consider what people often use public symbols for now. For example, > consider this library [1]. In this case, they use a public symbol for > their stuff in this file [2]. > > But here's the thing: that doesn't really need discoverable, and
Re: !Re: proposal: Object Members
> Isn't this precisely what WeakMaps are for? If the data is > "module-internal", then the module needs to be the owner of the data store. > If the data is about "arbitrary objects" (object from outside the module?) > then those objects are the keys to the data store. If any object is thrown > away, the associated data is no longer needed. If this doesn't fit the > functionality of a WeakMap, I don't know what will. Consider what people often use public symbols for now. For example, consider this library [1]. In this case, they use a public symbol for their stuff in this file [2]. But here's the thing: that doesn't really need discoverable, and is a pure implementation detail. Wouldn't it make more sense for them to just use a private symbol instead? Because here, it's not a cache, but it's literally extra associated data in the object. And also, in that case, you *want* the engine to see it as a property, since it can employ relevant IC caching for it. > Isn't that precisely what your question calls for? You're caching > module-internal data about external objects. No, I'm not. I'm drawing a distinction between a pure many-to-one association (weak maps) and a "has a" relationship (private symbol properties). You *could* implement one in terms of the other, but these two types of relationships are *completely* different at a conceptual level and how you model them. For js-symbol-tree, it's not simply associating a node to a value, but setting up the object so it *has* the data required for a doubly linked list tree node. Because this symbol is repeatedly accessed, it's not caching so much as it's adding data the object needs for it to do what it needs to do. Another scenario is for JSDOM's `Window` implementation, where they have a few underscore-private variables like this [3]. That particular variable is used in several disparate parts throughout the code base [4], but is still conceptually a property. This is a case where a private symbol property is appropriate. Conversely in this JSDOM file [5], it's just associating data with an arbitrary object it happens to have, and so using the weak map makes perfect sense. > Likewise, I'm specifically against the abuse of objects to store state > unrelated to the factory that created it. To me, that's as if I came to > visit you and somehow you managed to hide some valuable info in my wallet > without me noticing, and even if I completely dismantle my wallet, I > wouldn't be able to find it. But somehow you can easily retrieve it the next > time I come around. That's just conceptually weird. All of the examples here I've presented are for scenarios where the state *is* related to the factory that created the objects. It's not *directly* related (and thus encapsulation is warranted), but it's still *related*, enough so that you usually see the state initialized within the creator's constructor call. It's about as related as the superclass is to a subclass of it. BTW, you could make a similar argument against superclass private fields - it's like hiding valuable info in your wallet before you receive it for the first time, but even after dismantling it, you can't find any evidence of that valuable info. [1]: https://github.com/jsdom/js-symbol-tree [2]: https://github.com/jsdom/js-symbol-tree/blob/master/lib/SymbolTree.js#L28 [3]: https://github.com/jsdom/jsdom/blob/23d67ebec901b3471b84e63f58a96b51a36f3671/lib/jsdom/browser/Window.js#L80 [4]: https://github.com/jsdom/jsdom/search?q=_globalProxy [5]: https://github.com/jsdom/jsdom/blob/ad0e551b1b633e07d11f98d7a30287491958def3/lib/jsdom/living/websockets/WebSocket-impl.js#L49 - Isiah Meadows cont...@isiahmeadows.com www.isiahmeadows.com On Tue, Jul 31, 2018 at 1:55 AM, Ranando King wrote: >> One last thing: how would you hope to deal with module-internal data >> stored on arbitrary objects, using any means other than private symbols or >> something similar? > > Isn't this precisely what WeakMaps are for? If the data is > "module-internal", then the module needs to be the owner of the data store. > If the data is about "arbitrary objects" (object from outside the module?) > then those objects are the keys to the data store. If any object is thrown > away, the associated data is no longer needed. If this doesn't fit the > functionality of a WeakMap, I don't know what will. > >> Weak maps make sense when the weak map is the dictionary conceptually >> (think: caching). > > Isn't that precisely what your question calls for? You're caching > module-internal data about external objects. > >> Keep in mind, I'm specifically *against* the abuse of weak maps for >> private state that's conceptually (in an abstract sense, not runtime) part >> of an object. > > Likewise, I'm specifically against the abuse of objects to store state > unrelated to the factory that created it. To me, that's as if I came to > visit you and somehow you managed to hide some valuable info in my wallet > without me noticing, and eve
Re: !Re: proposal: Object Members
> One last thing: how would you hope to deal with module-internal data stored on arbitrary objects, using any means other than private symbols or something similar? Isn't this precisely what WeakMaps are for? If the data is "module-internal", then the module needs to be the owner of the data store. If the data is about "arbitrary objects" (object from outside the module?) then those objects are the keys to the data store. If any object is thrown away, the associated data is no longer needed. If this doesn't fit the functionality of a WeakMap, I don't know what will. > Weak maps make sense when the weak map is the dictionary conceptually (think: caching). Isn't that precisely what your question calls for? You're caching module-internal data about external objects. > Keep in mind, I'm specifically *against* the abuse of weak maps for private state that's conceptually (in an abstract sense, not runtime) part of an object. Likewise, I'm specifically against the abuse of objects to store state unrelated to the factory that created it. To me, that's as if I came to visit you and somehow you managed to hide some valuable info in my wallet without me noticing, and even if I completely dismantle my wallet, I wouldn't be able to find it. But somehow you can easily retrieve it the next time I come around. That's just conceptually weird. On Mon, Jul 30, 2018 at 9:42 PM Isiah Meadows wrote: > The reason private symbols are appropriate for Node's use case is > because it's conceptually a mixin, not a simple key/value map with > various utility functions (and weak map lookup is slower than property > access). JSDOM uses a similar utility [1] as a sort of mixin. > > Keep in mind, I'm specifically *against* the abuse of weak maps for > private state that's conceptually (in an abstract sense, not runtime) > part of an object. Weak maps make sense when the weak map is the > dictionary conceptually (think: caching). But if conceptually, the > object is the dictionary, putting it in a weak map is giving the > engine the wrong info - properties have inline caches and heavy > optimization, but you can't do the same for weak maps in the other > direction without literally implementing them as properties. (I would > *love* to be proven wrong here, BTW.) > > Let me draw a quick comparison: When do you use a map/set with string > keys, and when do you use an object instead? > > - Both are functionally equivalent, but engines use *very* different > algorithms for each one. > - I can almost guarantee you don't use maps when object properties work. > > One last thing: how would you hope to deal with module-internal data > stored on arbitrary objects, using any means other than private > symbols or something similar? To clarify, I'm talking of opaque object > structs [2], not simply classes. (BTW, that one is easier to manage as > a struct rather than a class, because of how many "methods" there are > operating on the state.) > > [1]: https://github.com/jsdom/js-symbol-tree > [2]: https://github.com/isiahmeadows/enigma/blob/master/src/parser.ts > > - > > Isiah Meadows > cont...@isiahmeadows.com > www.isiahmeadows.com > > > On Mon, Jul 30, 2018 at 9:00 PM, Ranando King wrote: > > I meant to say if the object passed to the 3rd party function. > > > > > > On Mon, Jul 30, 2018 at 7:59 PM Ranando King wrote: > >> > >> Just that use case alone is problematic. If the 3rd party function is > not > >> extensible, then the new private data should not be allowed. If the > library > >> cannot function without storing that data, then the function will have > no > >> choice but to fall back to WeakMaps which don't care if the key is not > >> extensible. So why not just stick with WeakMaps for that case? And if > that's > >> the case, then there would be little need for so open a means of > defining > >> private field names. The proposal I'm offering offers the room to > extend it > >> in the future to support everything else you might look for from your > >> private symbols idea unless you think I missed something. > >> > >> On Mon, Jul 30, 2018 at 7:26 PM Isiah Meadows > >> wrote: > >>> > >>> That is one supported use case, yes. But that isn't the only use case > >>> this supports. It can still extend to traditional private class data, > >>> too. > >>> > >>> - > >>> > >>> Isiah Meadows > >>> cont...@isiahmeadows.com > >>> www.isiahmeadows.com > >>> > >>> > >>> On Mon, Jul 30, 2018 at 8:04 PM, Ranando King > wrote: > >>> > So you're wanting the ability for a 3rd-party function to be able to > >>> > store > >>> > data private to that library on an object it didn't create, and that > >>> > only > >>> > that library can access? > >>> > > >>> > On Mon, Jul 30, 2018 at 6:36 PM Isiah Meadows < > isiahmead...@gmail.com> > >>> > wrote: > >>> >> > >>> >> First, my private symbols are properly *private*. The only > >>> >> "unexpected" thing that could happen is making an object larger > >>> >> memory-wise, which engines already have
Re: !Re: proposal: Object Members
The reason private symbols are appropriate for Node's use case is because it's conceptually a mixin, not a simple key/value map with various utility functions (and weak map lookup is slower than property access). JSDOM uses a similar utility [1] as a sort of mixin. Keep in mind, I'm specifically *against* the abuse of weak maps for private state that's conceptually (in an abstract sense, not runtime) part of an object. Weak maps make sense when the weak map is the dictionary conceptually (think: caching). But if conceptually, the object is the dictionary, putting it in a weak map is giving the engine the wrong info - properties have inline caches and heavy optimization, but you can't do the same for weak maps in the other direction without literally implementing them as properties. (I would *love* to be proven wrong here, BTW.) Let me draw a quick comparison: When do you use a map/set with string keys, and when do you use an object instead? - Both are functionally equivalent, but engines use *very* different algorithms for each one. - I can almost guarantee you don't use maps when object properties work. One last thing: how would you hope to deal with module-internal data stored on arbitrary objects, using any means other than private symbols or something similar? To clarify, I'm talking of opaque object structs [2], not simply classes. (BTW, that one is easier to manage as a struct rather than a class, because of how many "methods" there are operating on the state.) [1]: https://github.com/jsdom/js-symbol-tree [2]: https://github.com/isiahmeadows/enigma/blob/master/src/parser.ts - Isiah Meadows cont...@isiahmeadows.com www.isiahmeadows.com On Mon, Jul 30, 2018 at 9:00 PM, Ranando King wrote: > I meant to say if the object passed to the 3rd party function. > > > On Mon, Jul 30, 2018 at 7:59 PM Ranando King wrote: >> >> Just that use case alone is problematic. If the 3rd party function is not >> extensible, then the new private data should not be allowed. If the library >> cannot function without storing that data, then the function will have no >> choice but to fall back to WeakMaps which don't care if the key is not >> extensible. So why not just stick with WeakMaps for that case? And if that's >> the case, then there would be little need for so open a means of defining >> private field names. The proposal I'm offering offers the room to extend it >> in the future to support everything else you might look for from your >> private symbols idea unless you think I missed something. >> >> On Mon, Jul 30, 2018 at 7:26 PM Isiah Meadows >> wrote: >>> >>> That is one supported use case, yes. But that isn't the only use case >>> this supports. It can still extend to traditional private class data, >>> too. >>> >>> - >>> >>> Isiah Meadows >>> cont...@isiahmeadows.com >>> www.isiahmeadows.com >>> >>> >>> On Mon, Jul 30, 2018 at 8:04 PM, Ranando King wrote: >>> > So you're wanting the ability for a 3rd-party function to be able to >>> > store >>> > data private to that library on an object it didn't create, and that >>> > only >>> > that library can access? >>> > >>> > On Mon, Jul 30, 2018 at 6:36 PM Isiah Meadows >>> > wrote: >>> >> >>> >> First, my private symbols are properly *private*. The only >>> >> "unexpected" thing that could happen is making an object larger >>> >> memory-wise, which engines already have to be equipped to handle now >>> >> (libraries aren't always well-behaved, and like to occasionally add >>> >> expando properties to builtins and DOM elements). About the only thing >>> >> most people would care about is in the debugger. >>> >> >>> >> Second, I had things like this in mind with supporting expando >>> >> properties: >>> >> >>> >> https://github.com/nodejs/node/blob/ae4fde8bc883686def5badfb324236320669e8f4/lib/internal/linkedlist.js >>> >> >>> >> In that case, the Node.js people made it a pseudo-mixin rather than an >>> >> actual type for performance reasons - there's fewer object allocations >>> >> and they needed that. >>> >> >>> >> So I've considered the expando problem, and I disagree about it being >>> >> a problem at all. >>> >> >>> >> - >>> >> >>> >> Isiah Meadows >>> >> cont...@isiahmeadows.com >>> >> www.isiahmeadows.com >>> >> >>> >> >>> >> On Mon, Jul 30, 2018 at 6:35 PM, Waldemar Horwat >>> >> wrote: >>> >> > On 07/29/2018 04:37 PM, Isiah Meadows 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. >>> >> > >>> >> > >>> >> > Aside from syntax, the main semantic difference I see between this >>> >> > alternative and the main one is that this alternative defines >>> >> > private >>> >> > fields >>> >> > as expandos, creating opportunities for mischief by attaching them >>> >> > to >>> >> > unexpected objects. Aside from privacy, one of th
Re: !Re: proposal: Object Members
I meant to say if the object passed to the 3rd party function. On Mon, Jul 30, 2018 at 7:59 PM Ranando King wrote: > Just that use case alone is problematic. If the 3rd party function is not > extensible, then the new private data should not be allowed. If the library > cannot function without storing that data, then the function will have no > choice but to fall back to WeakMaps which don't care if the key is not > extensible. So why not just stick with WeakMaps for that case? And if > that's the case, then there would be little need for so open a means of > defining private field names. The proposal I'm offering offers the room to > extend it in the future to support everything else you might look for from > your private symbols idea unless you think I missed something. > > On Mon, Jul 30, 2018 at 7:26 PM Isiah Meadows > wrote: > >> That is one supported use case, yes. But that isn't the only use case >> this supports. It can still extend to traditional private class data, >> too. >> >> - >> >> Isiah Meadows >> cont...@isiahmeadows.com >> www.isiahmeadows.com >> >> >> On Mon, Jul 30, 2018 at 8:04 PM, Ranando King wrote: >> > So you're wanting the ability for a 3rd-party function to be able to >> store >> > data private to that library on an object it didn't create, and that >> only >> > that library can access? >> > >> > On Mon, Jul 30, 2018 at 6:36 PM Isiah Meadows >> > wrote: >> >> >> >> First, my private symbols are properly *private*. The only >> >> "unexpected" thing that could happen is making an object larger >> >> memory-wise, which engines already have to be equipped to handle now >> >> (libraries aren't always well-behaved, and like to occasionally add >> >> expando properties to builtins and DOM elements). About the only thing >> >> most people would care about is in the debugger. >> >> >> >> Second, I had things like this in mind with supporting expando >> >> properties: >> >> >> https://github.com/nodejs/node/blob/ae4fde8bc883686def5badfb324236320669e8f4/lib/internal/linkedlist.js >> >> >> >> In that case, the Node.js people made it a pseudo-mixin rather than an >> >> actual type for performance reasons - there's fewer object allocations >> >> and they needed that. >> >> >> >> So I've considered the expando problem, and I disagree about it being >> >> a problem at all. >> >> >> >> - >> >> >> >> Isiah Meadows >> >> cont...@isiahmeadows.com >> >> www.isiahmeadows.com >> >> >> >> >> >> On Mon, Jul 30, 2018 at 6:35 PM, Waldemar Horwat >> >> wrote: >> >> > On 07/29/2018 04:37 PM, Isiah Meadows 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. >> >> > >> >> > >> >> > Aside from syntax, the main semantic difference I see between this >> >> > alternative and the main one is that this alternative defines private >> >> > fields >> >> > as expandos, creating opportunities for mischief by attaching them to >> >> > unexpected objects. Aside from privacy, one of the things the >> private >> >> > fields proposal gives you is consistency among multiple private >> fields >> >> > on >> >> > the same object. In the rare cases where you don't want that, you >> could >> >> > use >> >> > weak maps. >> >> > >> >> > Waldemar >> >> ___ >> >> 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: !Re: proposal: Object Members
Just that use case alone is problematic. If the 3rd party function is not extensible, then the new private data should not be allowed. If the library cannot function without storing that data, then the function will have no choice but to fall back to WeakMaps which don't care if the key is not extensible. So why not just stick with WeakMaps for that case? And if that's the case, then there would be little need for so open a means of defining private field names. The proposal I'm offering offers the room to extend it in the future to support everything else you might look for from your private symbols idea unless you think I missed something. On Mon, Jul 30, 2018 at 7:26 PM Isiah Meadows wrote: > That is one supported use case, yes. But that isn't the only use case > this supports. It can still extend to traditional private class data, > too. > > - > > Isiah Meadows > cont...@isiahmeadows.com > www.isiahmeadows.com > > > On Mon, Jul 30, 2018 at 8:04 PM, Ranando King wrote: > > So you're wanting the ability for a 3rd-party function to be able to > store > > data private to that library on an object it didn't create, and that only > > that library can access? > > > > On Mon, Jul 30, 2018 at 6:36 PM Isiah Meadows > > wrote: > >> > >> First, my private symbols are properly *private*. The only > >> "unexpected" thing that could happen is making an object larger > >> memory-wise, which engines already have to be equipped to handle now > >> (libraries aren't always well-behaved, and like to occasionally add > >> expando properties to builtins and DOM elements). About the only thing > >> most people would care about is in the debugger. > >> > >> Second, I had things like this in mind with supporting expando > >> properties: > >> > https://github.com/nodejs/node/blob/ae4fde8bc883686def5badfb324236320669e8f4/lib/internal/linkedlist.js > >> > >> In that case, the Node.js people made it a pseudo-mixin rather than an > >> actual type for performance reasons - there's fewer object allocations > >> and they needed that. > >> > >> So I've considered the expando problem, and I disagree about it being > >> a problem at all. > >> > >> - > >> > >> Isiah Meadows > >> cont...@isiahmeadows.com > >> www.isiahmeadows.com > >> > >> > >> On Mon, Jul 30, 2018 at 6:35 PM, Waldemar Horwat > >> wrote: > >> > On 07/29/2018 04:37 PM, Isiah Meadows 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. > >> > > >> > > >> > Aside from syntax, the main semantic difference I see between this > >> > alternative and the main one is that this alternative defines private > >> > fields > >> > as expandos, creating opportunities for mischief by attaching them to > >> > unexpected objects. Aside from privacy, one of the things the private > >> > fields proposal gives you is consistency among multiple private fields > >> > on > >> > the same object. In the rare cases where you don't want that, you > could > >> > use > >> > weak maps. > >> > > >> > Waldemar > >> ___ > >> 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: !Re: proposal: Object Members
That is one supported use case, yes. But that isn't the only use case this supports. It can still extend to traditional private class data, too. - Isiah Meadows cont...@isiahmeadows.com www.isiahmeadows.com On Mon, Jul 30, 2018 at 8:04 PM, Ranando King wrote: > So you're wanting the ability for a 3rd-party function to be able to store > data private to that library on an object it didn't create, and that only > that library can access? > > On Mon, Jul 30, 2018 at 6:36 PM Isiah Meadows > wrote: >> >> First, my private symbols are properly *private*. The only >> "unexpected" thing that could happen is making an object larger >> memory-wise, which engines already have to be equipped to handle now >> (libraries aren't always well-behaved, and like to occasionally add >> expando properties to builtins and DOM elements). About the only thing >> most people would care about is in the debugger. >> >> Second, I had things like this in mind with supporting expando >> properties: >> https://github.com/nodejs/node/blob/ae4fde8bc883686def5badfb324236320669e8f4/lib/internal/linkedlist.js >> >> In that case, the Node.js people made it a pseudo-mixin rather than an >> actual type for performance reasons - there's fewer object allocations >> and they needed that. >> >> So I've considered the expando problem, and I disagree about it being >> a problem at all. >> >> - >> >> Isiah Meadows >> cont...@isiahmeadows.com >> www.isiahmeadows.com >> >> >> On Mon, Jul 30, 2018 at 6:35 PM, Waldemar Horwat >> wrote: >> > On 07/29/2018 04:37 PM, Isiah Meadows 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. >> > >> > >> > Aside from syntax, the main semantic difference I see between this >> > alternative and the main one is that this alternative defines private >> > fields >> > as expandos, creating opportunities for mischief by attaching them to >> > unexpected objects. Aside from privacy, one of the things the private >> > fields proposal gives you is consistency among multiple private fields >> > on >> > the same object. In the rare cases where you don't want that, you could >> > use >> > weak maps. >> > >> > Waldemar >> ___ >> 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: !Re: proposal: Object Members
So you're wanting the ability for a 3rd-party function to be able to store data private to that library on an object it didn't create, and that only that library can access? On Mon, Jul 30, 2018 at 6:36 PM Isiah Meadows wrote: > First, my private symbols are properly *private*. The only > "unexpected" thing that could happen is making an object larger > memory-wise, which engines already have to be equipped to handle now > (libraries aren't always well-behaved, and like to occasionally add > expando properties to builtins and DOM elements). About the only thing > most people would care about is in the debugger. > > Second, I had things like this in mind with supporting expando > properties: > https://github.com/nodejs/node/blob/ae4fde8bc883686def5badfb324236320669e8f4/lib/internal/linkedlist.js > > In that case, the Node.js people made it a pseudo-mixin rather than an > actual type for performance reasons - there's fewer object allocations > and they needed that. > > So I've considered the expando problem, and I disagree about it being > a problem at all. > > - > > Isiah Meadows > cont...@isiahmeadows.com > www.isiahmeadows.com > > > On Mon, Jul 30, 2018 at 6:35 PM, Waldemar Horwat > wrote: > > On 07/29/2018 04:37 PM, Isiah Meadows 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. > > > > > > Aside from syntax, the main semantic difference I see between this > > alternative and the main one is that this alternative defines private > fields > > as expandos, creating opportunities for mischief by attaching them to > > unexpected objects. Aside from privacy, one of the things the private > > fields proposal gives you is consistency among multiple private fields on > > the same object. In the rare cases where you don't want that, you could > use > > weak maps. > > > > Waldemar > ___ > 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: !Re: proposal: Object Members
First, my private symbols are properly *private*. The only "unexpected" thing that could happen is making an object larger memory-wise, which engines already have to be equipped to handle now (libraries aren't always well-behaved, and like to occasionally add expando properties to builtins and DOM elements). About the only thing most people would care about is in the debugger. Second, I had things like this in mind with supporting expando properties: https://github.com/nodejs/node/blob/ae4fde8bc883686def5badfb324236320669e8f4/lib/internal/linkedlist.js In that case, the Node.js people made it a pseudo-mixin rather than an actual type for performance reasons - there's fewer object allocations and they needed that. So I've considered the expando problem, and I disagree about it being a problem at all. - Isiah Meadows cont...@isiahmeadows.com www.isiahmeadows.com On Mon, Jul 30, 2018 at 6:35 PM, Waldemar Horwat wrote: > On 07/29/2018 04:37 PM, Isiah Meadows 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. > > > Aside from syntax, the main semantic difference I see between this > alternative and the main one is that this alternative defines private fields > as expandos, creating opportunities for mischief by attaching them to > unexpected objects. Aside from privacy, one of the things the private > fields proposal gives you is consistency among multiple private fields on > the same object. In the rare cases where you don't want that, you could use > weak maps. > > Waldemar ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: !Re: proposal: Object Members
On 07/29/2018 04:37 PM, Isiah Meadows 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. Aside from syntax, the main semantic difference I see between this alternative and the main one is that this alternative defines private fields as expandos, creating opportunities for mischief by attaching them to unexpected objects. Aside from privacy, one of the things the private fields proposal gives you is consistency among multiple private fields on the same object. In the rare cases where you don't want that, you could use weak maps. Waldemar ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: !Re: proposal: Object Members
Isn't this just a different version of the private names idea that Kevin & Daniel were pushing before settling into "proposal-class-fields"? If not, then what's the difference? On Mon, Jul 30, 2018 at 6:01 AM Michael Theriot < michael.lee.ther...@gmail.com> wrote: > I'll just say it feels inconsistent with how every other property is > configured. That the key itself holds magic behavior-changing information. > It's not a use case or overhead concern. > > On Monday, July 30, 2018, Isiah Meadows wrote: > >> Um, no. The use case is *extremely* limited, and that ruins a few >> optimizations you could otherwise make with private symbols (like >> caching proxy forwarding without having to bail out). >> >> Besides, whether a symbol is private requires exactly one bit to >> store, so there's no real overhead with storing it on the object. >> Heck, if you want to optimize it better, you might choose to store >> that same bit on both the symbol and the object descriptor itself, and >> I'd expect engines to do just that - it saves a pointer dereference. >> - >> >> Isiah Meadows >> m...@isiahmeadows.com >> www.isiahmeadows.com >> >> >> On Mon, Jul 30, 2018 at 1:25 AM, Michael Theriot >> wrote: >> > 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 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 >> >> m...@isiahmeadows.com >> >> www.isiahmeadows.com >> >> >> >> >> >> On Sun, Jul 29, 2018 at 10:55 PM, Michael Theriot >> >> 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 >> 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 >> >> >> m...@isiahmeadows.com >> >> >> www.isiahmeadows.com >> >> >> >> >> >> >> >> >> On Sun, Jul 29, 2018 at 10:05 PM, Michael Theriot >> >> >> 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 >> >> >> > 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 >> >> >> >> m...@isiahmeadows.com >> >> >> >> www.isiahmeadows.com >> >> >> >> >> >> >> >> >> >> >> >> On Sun, Jul 29, 2018 at 12:23 AM, Darien Valentine >> >> >>
Re: !Re: proposal: Object Members
I'll just say it feels inconsistent with how every other property is configured. That the key itself holds magic behavior-changing information. It's not a use case or overhead concern. On Monday, July 30, 2018, Isiah Meadows wrote: > Um, no. The use case is *extremely* limited, and that ruins a few > optimizations you could otherwise make with private symbols (like > caching proxy forwarding without having to bail out). > > Besides, whether a symbol is private requires exactly one bit to > store, so there's no real overhead with storing it on the object. > Heck, if you want to optimize it better, you might choose to store > that same bit on both the symbol and the object descriptor itself, and > I'd expect engines to do just that - it saves a pointer dereference. > - > > Isiah Meadows > m...@isiahmeadows.com > www.isiahmeadows.com > > > On Mon, Jul 30, 2018 at 1:25 AM, Michael Theriot > wrote: > > 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 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 > >> m...@isiahmeadows.com > >> www.isiahmeadows.com > >> > >> > >> On Sun, Jul 29, 2018 at 10:55 PM, Michael Theriot > >> 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 > 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/a8494868c4b193dfbf7139589f472a > d8 > >> >> - > >> >> > >> >> Isiah Meadows > >> >> m...@isiahmeadows.com > >> >> www.isiahmeadows.com > >> >> > >> >> > >> >> On Sun, Jul 29, 2018 at 10:05 PM, Michael Theriot > >> >> 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 > >> >> > 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 > >> >> >> m...@isiahmeadows.com > >> >> >> www.isiahmeadows.com > >> >> >> > >> >> >> > >> >> >> On Sun, Jul 29, 2018 at 12:23 AM, Darien Valentine > >> >> >> 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 > >> >> >> > appe
Re: !Re: proposal: Object Members
Um, no. The use case is *extremely* limited, and that ruins a few optimizations you could otherwise make with private symbols (like caching proxy forwarding without having to bail out). Besides, whether a symbol is private requires exactly one bit to store, so there's no real overhead with storing it on the object. Heck, if you want to optimize it better, you might choose to store that same bit on both the symbol and the object descriptor itself, and I'd expect engines to do just that - it saves a pointer dereference. - Isiah Meadows m...@isiahmeadows.com www.isiahmeadows.com On Mon, Jul 30, 2018 at 1:25 AM, Michael Theriot wrote: > 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 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 >> m...@isiahmeadows.com >> www.isiahmeadows.com >> >> >> On Sun, Jul 29, 2018 at 10:55 PM, Michael Theriot >> 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 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 >> >> m...@isiahmeadows.com >> >> www.isiahmeadows.com >> >> >> >> >> >> On Sun, Jul 29, 2018 at 10:05 PM, Michael Theriot >> >> 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 >> >> > 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 >> >> >> m...@isiahmeadows.com >> >> >> www.isiahmeadows.com >> >> >> >> >> >> >> >> >> On Sun, Jul 29, 2018 at 12:23 AM, Darien Valentine >> >> >> 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 >> >>
Re: !Re: proposal: Object Members
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 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 > m...@isiahmeadows.com > www.isiahmeadows.com > > > On Sun, Jul 29, 2018 at 10:55 PM, Michael Theriot > 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 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 > >> m...@isiahmeadows.com > >> www.isiahmeadows.com > >> > >> > >> On Sun, Jul 29, 2018 at 10:05 PM, Michael Theriot > >> 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 > 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 > >> >> m...@isiahmeadows.com > >> >> www.isiahmeadows.com > >> >> > >> >> > >> >> On Sun, Jul 29, 2018 at 12:23 AM, Darien Valentine > >> >> 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 > >>
Re: !Re: proposal: Object Members
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 m...@isiahmeadows.com www.isiahmeadows.com On Sun, Jul 29, 2018 at 10:55 PM, Michael Theriot 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 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 >> m...@isiahmeadows.com >> www.isiahmeadows.com >> >> >> On Sun, Jul 29, 2018 at 10:05 PM, Michael Theriot >> 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 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 >> >> m...@isiahmeadows.com >> >> www.isiahmeadows.com >> >> >> >> >> >> On Sun, Jul 29, 2018 at 12:23 AM, Darien Valentine >> >> 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) >> >> > >> >> >
Re: !Re: proposal: Object Members
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 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 > m...@isiahmeadows.com > www.isiahmeadows.com > > > On Sun, Jul 29, 2018 at 10:05 PM, Michael Theriot > 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 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 > >> m...@isiahmeadows.com > >> www.isiahmeadows.com > >> > >> > >> On Sun, Jul 29, 2018 at 12:23 AM, Darien Valentine > >> 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. Th
Re: !Re: proposal: Object Members
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 m...@isiahmeadows.com www.isiahmeadows.com On Sun, Jul 29, 2018 at 10:05 PM, Michael Theriot 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 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 >> m...@isiahmeadows.com >> www.isiahmeadows.com >> >> >> On Sun, Jul 29, 2018 at 12:23 AM, Darien Valentine >> 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 fi
Re: !Re: proposal: Object Members
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 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 > m...@isiahmeadows.com > www.isiahmeadows.com > > > On Sun, Jul 29, 2018 at 12:23 AM, Darien Valentine > 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.c
Re: !Re: proposal: Object Members
1. I don't believe tampering is a major issue, especially considering most tampering problems occur *after* the type is instantiated. If it is, the follow-on proposal of added syntax would likely avoid it. 2. The prototype part is just for consistency and code reuse. And it's not about the object it's associated, but about the key lookup itself. - Isiah Meadows m...@isiahmeadows.com www.isiahmeadows.com On Sun, Jul 29, 2018 at 8:00 PM, Darien Valentine wrote: > Isaiah, that’s pretty similar to what I was [talking about > earlier](https://mail.mozilla.org/pipermail/es-discuss/2018-July/051410.html) > — and I think it’s awesome that multiple people have arrived there, since it > seems like soft confirmation of the idea that private symbols likely > represent the most minimal possible “surgery” to achieve the functionality. > > There are some differences; I saw `Symbol.private` as an obvious API too, > but specifically mentioned it to point out that it’s not viable if we > consider one of the goals here to be the elimination of the > “tamperability-hole” that exists for any non-syntactic solution (unless > global.Symbol is redefined as non-configurable, non-writable, etc, but this > is likely not an option). > > The proxy forwarding is _very_ interesting, but the prototype lookup doesn’t > make sense to me. Slots/fields are associated with _an_ object, not subject > to the vagaries of that object’s present prototype chain. I don’t think > changing that relationship is a good idea. > > On Sun, Jul 29, 2018 at 7:38 PM Isiah Meadows > 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 >> m...@isiahmeadows.com >> www.isiahmeadows.com >> >> >> On Sun, Jul 29, 2018 at 12:23 AM, Darien Valentine >> 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 con
Re: !Re: proposal: Object Members
Isaiah, that’s pretty similar to what I was [talking about earlier]( https://mail.mozilla.org/pipermail/es-discuss/2018-July/051410.html) — and I think it’s awesome that multiple people have arrived there, since it seems like soft confirmation of the idea that private symbols likely represent the most minimal possible “surgery” to achieve the functionality. There are some differences; I saw `Symbol.private` as an obvious API too, but specifically mentioned it to point out that it’s not viable if we consider one of the goals here to be the elimination of the “tamperability-hole” that exists for any non-syntactic solution (unless global.Symbol is redefined as non-configurable, non-writable, etc, but this is likely not an option). The proxy forwarding is _very_ interesting, but the prototype lookup doesn’t make sense to me. Slots/fields are associated with _an_ object, not subject to the vagaries of that object’s present prototype chain. I don’t think changing that relationship is a good idea. On Sun, Jul 29, 2018 at 7:38 PM Isiah Meadows 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 > m...@isiahmeadows.com > www.isiahmeadows.com > > > On Sun, Jul 29, 2018 at 12:23 AM, Darien Valentine > 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 >
Re: !Re: proposal: Object Members
Let me see if I can roll this up: you're looking for syntax support for something akin to Java and C#'s "internal" privilege level, and a means to declare a "common private name" so that something like this will work: ```js var {A, B, C} = (() => { static common = Symbol("common"); class A { internal [common] = 1; sum(...arg) { var retval = this#[common]; for (let obj of arg) { retval += obj#[common]; } return retval; } } class B { internal [common] = 2; sum(...arg) { var retval = this#[common]; for (let obj of arg) { retval += obj#[common]; } return retval; } } class C { internal [common] = 3; sum(...arg) { var retval = this#[common]; for (let obj of arg) { retval += obj#[common]; } return retval; } } return { A, B, C }; })(); (new A()).sum(new B(), new C()); //If it works, returns 6 ``` It's already the case that A, B, & C will have to include the `[[DeclarationInfo]]` of the arrow function in each of their respective methods' `__proto__` chains. That and the `Symbol` for direct use as a private name, solves the problem, and avoids the original issue without much of a change. The "internal" keyword would be trickier to implement as it would require that the corresponding declarations be added to the `[[DeclarationInfo]]` of the containing scope while the storage exists in the `[[PrivateValues]]` of the owning objects. It's not impossible, possibly not even difficult. I'll have to give it some thought. On Sat, Jul 28, 2018 at 11:24 PM Darien Valentine 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 associat
Re: !Re: proposal: Object Members
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 m...@isiahmeadows.com www.isiahmeadows.com On Sun, Jul 29, 2018 at 12:23 AM, Darien Valentine 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 thi
Re: !Re: proposal: Object Members
> 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
Re: !Re: proposal: Object Members
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 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
Re: !Re: proposal: Object Members
> 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 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 t
Re: !Re: proposal: Object Members
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 [] [extends ] [mixes [, [, ...]]] { ... } ``` 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 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 > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss >
Re: !Re: proposal: Object Members
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 es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re:!Re: proposal: Object Members
Ranando, I share your reservations about private fields being bound too tightly to class syntax. In my case it isn’t because I don’t want to use classes, but rather because in the last few years, using the WeakMap solution, a good number of times I’ve needed to do things which the private field proposal either doesn’t permit or account for: - 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 - 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 With the WeakMap solution, the privacy mechanism is one that already exists: a scope. This makes it very flexible (it handles the above three cases fine), but it has a key limitation in terms of achieving privacy, which is that `global.WeakMap` and `WeakMap.prototype` may be compromised. Given this limitation — plus the amount of boilerplate WeakMap privacy can entail — I am very happy to see private instance state being addressed syntactically. However because the model chosen for “scope of privacy” is “class declaration body” — not previously something that provided a closure/scope at all? — instead of just using existing scopes, I have found them impractical to use in some cases. If I’m understanding your alternative proposal, Ranando, I don’t think it addresses these issues either, not in the way I’m looking for anyway — I’m wishing for a syntactic solution for true private slots on objects, but where said slots are associated with a scope (almost always a module scope) rather than a class declaration. In particular, I’m not convinced that the concept of “protected” makes sense within the JS models of objects and dispatch. I’m gonna get more detailed about what I see as inadequacies in the current proposal. These are subjective, but not hypothetical: I’ve been doing WeakMap-based privacy for a few years now and I’ve tried converting existing code to use private fields since Chrome shipped it behind a flag. I found that, unfortunately, it did not meet my needs. --- Regarding exposing functions that operate on private state but which do not live on the constructor or prototype — there is a way to achieve this in the proposed spec. It’s awkward, but it is technically possible: ```js class Foo { #bar = 1; getBarOfFoo(foo) { return this.#bar; } // [[ ... other methods that may manipulate but do not expose #bar here ... ]] } const { getBarOfFoo } = Foo.prototype; delete Foo.prototype.getBarOfFoo; ``` It gets more awkward in the “multiple classes with the same semantic slot” case, since one will have to wrap each attempted access in a try-catch, as there is no other way to be certain whether the target has the slot. With WeakMap, in contrast, one will just get undefined — and one may use the same WeakMap to manage the same slot across multiple classes that are declared in the same scope as the WeakMap. Assume we have two classes with a private bar “slot” which is meant to be semantically equivalent. It holds an integer. We want to create a function that adds together two bar values from any classes that implement this slot. If an argument has no bar slot, bar defaults to zero. With WeakMaps, such a function might look like this: ```js function addBars(a, b) { return (wm.get(a).bar || 0) + (wm.get(b).bar || 0); } ``` Realizing the same logic with classes that use private field syntax is still possible (using the aforementioned “pop off a method” pattern), but now it looks like this: ```js function addBars(a, b) { let aBar, bBar; try { aBar = getBarOfFoo(a); } catch { try { aBar = getBarOfBaz(a); } catch { aBar = 0; } } try { bBar = getBarOfFoo(b); } catch { try { bBar = getBarOfBaz(b); } catch { bBar = 0; } } return aBar + bBar; } ``` ¯\_(ツ)_/¯ --- This is a more minor issue, but assuming we *can’t* have dynamic slots, I would like to take advantage of the fact that whether-a-function-may-access-a-slot is statically knowable by having immediate brand checking occur in all methods that may access private state. This is actually the main source of boilerplate in the WeakMap solution (for me, but admittedly I’m probably in a tiny minority here): ```js set foo(value) { if (!wm.has(this)) throw new TypeError(`Illegal invocation`); const str = String(value); if (VALID_FOO_VALUES.has(str)) { wm.get(this).foo = str; } else { throw new Error(`Invalid value for foo`); } } ``` The difference between the above function with and without the guard concerns guarantees about behavior. The `String(value)` call actually might throw, but it ought to be predictable that a method which requires a branded receiver always throws the same error when called on anything unbranded — even if (especially if!) private state access occurs in the
Re: Re: proposal: Object Members
> That, and that the existing builtins already impose those limitations - and only class allows you to do those things, with them. I’m surprised by that statement — it appeared to me that it currently remains possible to create classes, including classes that extend built-ins, with class syntax. ``` const test = value => { if (typeof value !== 'string') throw new TypeError('nope'); return value; }; function StringSet(init) { if (new.target === undefined) throw new TypeError('StringSet is not a constructor'); if (init !== undefined) init = Array.from(init, test); return Reflect.construct(Set, [ init ], new.target); } Reflect.defineProperty(StringSet.prototype, 'add', { configurable: true, value: Object.setPrototypeOf({ add(value) { return super.add(test(value)); } }, Set.prototype).add }); Reflect.defineProperty(StringSet.prototype, Symbol.toStringTag, { configurable: true, value: 'StringSet' }); Reflect.setPrototypeOf(StringSet, Set); Reflect.setPrototypeOf(StringSet.prototype, Set.prototype); new StringSet('abc'); ``` Not that this is something one is apt to want to do normally, though it being possible does remain useful sometimes for meta/compositiony stuff. It cannot be achieved in an <= ES5 environment, but it seems all the reflection tools needed are present in environments that actually have class syntax — even, despite the awkwardness necessitated by HomeObject stuff, what is needed to employ super in methods. I’m curious if, aside from the possibility of implementation-specific things like type error messages being different, there there is anything about the above class which ends up observably different from the ES-side from one created with class syntax instead? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss