-
Notifications
You must be signed in to change notification settings - Fork 113
Summary: Objections to fields (as opposed to alternatives), especially the private field syntax #150
Comments
@Igmat (me):
|
After talks with @ljharb, I concede that "undetectability" is a reasonable desire. Whether that reaches the level of a requirement depends on whether or not achieving it causes some existing functionality to fail or work in unexpected ways. I don't remember wanting the ability to dynamically add a private field. I feel that would be counter-productive and dangerous. I've also been working with the advocates of the classes-1.1 proposal on issues of functionality and implementation. You can count me as being in favor of that proposal. |
Sorry @rdking, that must have been a bad recollection on my part. I removed that from the original post. |
Someone want it. But I can't find the comment, too many 🤣 |
|
@hax I remember that too, from when I debuted the idea behind proposal-object-members. Someone thought that would enable the possibility for dynamically adding private fields (and indeed it could), but I said that wasn't part of the plan. |
I don't mind so much that they can't be created dynamically after construction. I just think dynamic access is a staple of JS and not having it is a huge oversight. Right now private symbols seems the best approach to achieve this in my opinion. |
Summary of my feelings of this proposal
|
@nicolo-ribaudo Sure - updated. I also added @allenwb's feedback. @rdking I am trying not to add too many bullet points of closely related items or second tier concerns, but this one that you added seems particularly significant:
Can you expand on that slightly, while still keeping it a concise summary? I'd like to add it to the issue description but it doesn't say what you're specifically referring to. Or if you prefer that I completely replace your summary, you can post something for me to copy and paste. |
@mbrowne The things I listed were in addition to what you've already got.
Where this is concerned, I mean that, using the concept of a "private property", since this is just another property of an object, it is reasonable for the uninitialized to assume that access capability will be no different for public than it is for private, especially since they both take the same form. So with the existing feature being
This is even more true in the case of Proxy where the completely undetectable private properties are not being stored in a separate object that uses the identity of the owner as a lookup reference, but somehow, Proxy still throws when dealing with a method accessing private fields. While the reason it throws is directly analogous to WeakMaps (the Proxy object itself is passed as the "target" to the handler functions), there's no reason for this to be the case, especially considering that developers implementing private fields in their libraries will be flooded with feedback from their users about use cases where whatever they used a Proxy for is now breaking merely due to the presence of the private fields. Put shortly: If the proper introduction of a new feature into existing, working code bases that don't rely on the improper use of properties not intended for external use, causes the code to break, then the new feature has broken an existing feature. |
Since you asked... I believe that we are overpricing the benefit of this entire feature set while underpricing the risk. Why do I think that we're overpricing the benefit?
Why do I think that we're underpricing the risk?
Thanks for asking me to share my thoughts (I'm not particularly interested in debating though). |
@mbrowne Thanks for the summary! This helps a lot. |
Summary of my comment/issues:
Reference: #148 , #100 (comment) |
Updated. @zenparsing and @BrendanEich, I mentioned you not to encourage you to join the debate (unless you want to), but just to give you an opportunity to have your feedback included in the issue description. Thank you everyone for summarizing your feedback. |
I will summarize my own feedback as well:
|
How is it a breaking change or problem for Babel? Or do you just mean when using Babel and Flow together? I think |
This would be so much simpler and avoid many of the issues raised if redeclaring the same property in a subclass were simply illegal...you can already set different initial values if you want (or even call |
@mbrowne Since properties are either data properties or accessor properties, it might be better if redeclaration of a data property that doesn't changing the property type from data to accessor is illegal. Likewise, changing from accessor to data should also be illegal. Redefining accessor properties as new accessor properties should be allowed as this might represent some useful change to the accessors. |
...and irrelevant since even with [[Set]], the action can be immediately followed by a change to the writability of the property, leaving all side effects of setting the value in tact. |
If possible, can I suggest we keep discussion of specific points to other threads? (Anything beyond clarifications, anyway.) I'd like to keep this thread as an accessible summary. |
|
Even hard privacy is must, both classes 1.1 and Symbol.private proposal meet this requirement. Basically instance variable in classes 1.1 keep the same semantic of current private field, but use different syntax which avoid controversial |
Sorry I still want to add a small comment about "the purpose of classes" (hope I could say it clear in one time so I don't need to add more.) Whether we like or not, ES6 classes already have inheritance and accessors. Some guys don't like inheritance or assessors and advocate not use them at all, so it's understandable why they choose to ignore the [[Define]] issue. But I believe it's very wrong to force others follow your way by breaking existing features. More important, ES6 classes have very similar code to other mainstream languages, also very similar high-level OO concept model to other mainstream languages, even it's prototype based, which is very different to all other languages. So a reasonable assumption is, "the purpose of ES6 classes" is to match the developer experience of classes in other mainstream languages. Note, some parts (encapsulation, traits/mixins, etc.) were missing because TC39 do not have enough time to get consensus about them in ES6 timeline. But the purpose is clear, at least in that time. It's obvious to me current proposal not follow such purpose anymore. Whether it's ok or not, may be a separate problem. |
FYI, private fields have shipped in Chrome. |
also in node v12. |
Hi. I'm late to the party here, but I have two concerns:
Let me know if these types of concerns have been expressed and addressed elsewhere. Edit: I read this but I didn't find it very compelling. If "hard-private" is already polyfillable this feels more like an opportunity for a framework to simplify its usage, or a babel plugin if this is really that important to you. I really don't want to lose the ability to see all of the properties in an object, and I really don't think it's wise to let developers let their guard down just because they're in a private scope. |
|
@brianjenkins94 Though I have many reasons to not like the private-fields implementation, the concerns you mentioned are not among them. |
That's a relief. Thank you guys for the confirmation. |
I agree with @hax, Since javascript has a directive "use strict" defines that JavaScript code should be executed in "strict mode". Maybe javascript can add a new directive such as "use strict c#" or "use strict java" to defines that javascript class member's grammar declared respect the rule of java(c#) class. |
@tiandian A couple of problems with that.
Off Topic CommentIf any directive could still be added, I'd want a `"use sloppy"` directive to turn off strict-mode, even in cases where it was automatically turned on.
|
@rdking I don't think engine developers regret |
@mbrowne That makes sense and I agree But you've gotta admit: it is hard not to want to leave a reply like my previous one when a committee member has argued for a feature using points such as the one I disproved. (I didn't provide actual examples, but if you happen to know poor-man's OOP in C (f.e. GLib), or just pure functional languages, then you won't need examples to know how my reasoning disproves what he said.) Classes are about inheritance. Even a "non-inheriting base class" in the sense that @ljharb speaks of, is still about inheritance, because it can be inherited. (In practice next to no one will ever write @ljharb Why are you so interested in the design of class features if you don't believe in how closely Let's please take inheritance into consideration when designing new Sorry, I'll avoid commenting off-topic here now. |
"It can be used for inheritance therefore it's all about inheritance" is not any kind of a water-tight point. |
@trusktr I think there must be a lot of comments from committee members that you missed over the past few years if you think they were glossing over inheritance use cases in the design of this proposal. There are certain things like the absence of |
I think this whole line of conversation has gone too far off topic.
That being said....
@mbrowne When it comes down to it, the implementation of fields hampers the pre-existing use cases for inheritance. Where fields are present, various other inheritance features will not work as in the past or as expected. It's not as if there are not alternate possible implementations that produce semantically equivalent results without the unnecessary complications and counter-intuitive side effects. But once again, the undocumented design goals have stood as reasons why such implementations were never given much if any consideration. Like you, I want to give TC39 as much credit as they deserve for coming as far as they have with this proposal. However, I also believe they need to be open to receiving much criticism for pushing forward with such an enticing, yet feature and design pattern interfering and hampering proposal. |
only yesterday i realized that discussion moved to this new repo (8 months ago). #slowpoke is slow if anyone still cares, here is my summary:
TL;DR
|
@rdking always explains everything the best, and always makes sense!
It is breaking two decades worth of JavaScript paradigms. |
Just wait until some says
Authors of this spec seem to be fine with breaking decades worth of expectations. |
Has anyone here posted objections to class fields in the issue trackers of browsers that are implementing class fields? Maybe that could help. I started with two: |
The response on both of those was "we are not interested in deviating from what TC39 has decided". Considering that representatives of all the browsers were part of this proposal's consensus, it doesn't seem a viable course of action. |
While the may not be "interested in deviating", that does not mean that if enough issues are raised, they wouldn't be willing to consider it necessary to remove the implementation. |
All of the major vendors participate in TC39 already. Please do not spam their issue trackers and waste the time of their triage people. |
@bakkot I understand the nuisance of such developer useless spam all too well. I don't want to see that happen either. So that raises a very direct question: How does the community at large go about getting TC39 members to recognize and accept that this proposal in its current form is introducing unacceptable issues? What will it take? Or is it TC39's stance that there is no recourse for the community should it reject use of the proposal? |
@rdking The process for you to get TC39 to agree with your position is for you to convince TC39 of your position on this issue tracker. If there are issues which we have not already discussed to death, feel free to bring them up. (As I've said several times, repeating issues we've already discussed at great length is unlikely to convince anyone of anything.) If you can't convince TC39 of your position here, spamming browser vendors elsewhere is not going to help anything. |
Let's go to a different thread, because I have a few more questions.... #253 |
I agree with @hax |
As @eddyw pointed out already, until 2012 |
Continuing from #100 and other threads, here's a summary of key objections to this proposal raised by the community:
@hax's top 3 concerns:
Also, he believes another long wait for private state is acceptable if that's what it takes to get it right: the problems with the current proposal—including with public fields—are just too severe.
Regarding the substance of the proposal:
#
syntax does not fit into the mental model of JS devs and will cause a community split, and TypeScript issues will further fracture the community@rdking:
obj['property']
for public fields but no equivalent for private fields breaks existing feature by breaking expectations. Lack of dynamic access of private fields (e.g.this['#x']
) is a deal-breaker.#
is not "well-defined"—has two meanings. Context is insufficient to disambiguate declaration and access.@bdistin:
@mbrowne (me):
(NB: it's mbrowne, not mbrown)
private #x
syntax should be strongly considered because#
alone might make future native support of intermediate access levels impossible. But#
alone might be OK if we are confident we could have another way of natively sharing private fields within a module.@Igmat:
brand-checking
shouldn't be added implicitly to all private reads/writes, since it breaks metaprogramming with proxies as described in Private members break proxies #106 and [Private] Metaprogramming vs Security #134Symbol.private
+ some kind of shorthand syntax for making symbols more ergonomic, provides much cleaner mechanism for encapsulation@shannon:
#
being part of the name leads to confusion becausethis.#x !== this['#x']
, it's just too weird. The sigil is fine but the functionality is just too different.#
-based syntax #149) is by far the simplest addition to existing JS paradigms/existing JS class spec, and achieves most of what the current proposal wants with a few minor exceptions (possibility to leak private symbols for one, but I think this could actual be useful for things like protected to be implemented in userland).@aimingoo:
var
and ctx's VariableEnvironment, which is an abuse of Environment components, and it is obviously too bulky.this["#x"]
vs.this.#x
). About grammar, I recommend enabling theprivate
keyword to declare private properties (Note: that I don't support new concepts like "Fields or Private Fields"). And # as an operator, this is reasonable in boththis#data
and#data
as unary or binary operators.Reference: #148 , #100 (comment)
@RyanCavanaugh:
[[Define]]
over[[Set]]
for initializers is a bad trade-off that throws away six years of evidence from TypeScript and Babel developers' use of fields. The "natural experiment" has been performed, the results are clear, and the runtime breakage incurred here is very difficult to detect with tooling. The proposed upside of[[Define]]
(const fields later) is purely speculative; the downside of not being able to install a deprecation setter is concrete and immediate.#
sigil is something we should just ignore and take the hit for, if built-in hard privacy is really needed. People will adapt and the runtime need for it is extremely clear; all counterproposals have been ignorant of the design constraints or runtime semantics.@Jamesernator
In addition, some members of the TC39 committee also have current objections to this proposal. For example:
@allenwb:
Design Rules:
Item 2:
Item 3:
Item 4:
@zenparsing:
private x
from TypeScript) won't work. It doesn't "just work". We are taking on the risk that this feature will continue to create head-scratching across our community.#
for something else and it won't be available.I probably missed something important, and obviously I haven't included a summary for everyone who has commented. If you feel something is missing, please provide a concise summary of your feedback as your first comment on this thread (saving longer arguments for subsequent comments). Also feel free to simply say, "I agree with [username]".
The text was updated successfully, but these errors were encountered: