You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This post comes after experience using decorators with TypeScript and Babel, including the new Stage 3 decorators since day one, for years.
It seems to me that the argument for performance in not allowing class fields to be accessed with (or converted to) get/set pairs is moot, because accessor #foo = 123 is exactly equivalent to the very same idea, and yet we allow it.
The problem
In this code,
classFoo{accessor #foo =123// this creates a `get`/`set` pair *somewhere*!accessorfoo=123}
The #foo and foo properties are not the same at all. The private field is associated with the instance, while the public field is defined on the prototype.
This is a big discrepancy.
First and foremost, converting foo = 123 to accessor foo = 123 can, and will, break certain code bases.
The half-way defined accessor feature (when decorators are released, the feature will be half-way implemented, with the other half in a separate spec) does not even need to exist in this round of decorators, because if we simply fix the timing of context.addInitializer() for getter/setter elements, as described in
then, for the most part, important use cases that include reading initial values from getters/setters are covered. Please show a case where you absolutely need the getter/setter extra initializer to run before fields.
Don't get me wrong, accessor syntax is concise and more enjoyable than getters/setters, but not fundamentally enabling anything new, while decorators provide new confusing differences between auto accessor and regular accessors as in #548.
Solution
It would be more desirable, more consistent, and more breakage avoiding, to be able to provide the ability to provide get and set functions for class fields, with the same or similar semantics as private fields which we've already blessed.
Two ways to do this:
Option 1: The simplest option is perhaps to update the [[Define]] semantics of field initialization so it creates an accessor descriptor if any decorator has provided the get or set functions, otherwise continue with a value descriptor as before.
This will share the get and set functions across instances
Option 2: Keep the descriptor as a value descriptor, while mapping the get/set functions to inaccessible internal/private storage (like private fields).
If someone overrides the field with their own accessor descriptor, we could either
let the get/set functions continue to be used by any other code referencing them (silent fail)
or throw an error
Regardless of which of the previous two are picked, then if we also:
then at this point class fields would be as useful as accessor including with initial values, which would effectively be eliminate the need for accessor in this iteration of decorators.
Accessors would still be nice sugar for prototype getters/setters, but basically unnecessary for shipping decorators.
The text was updated successfully, but these errors were encountered:
@trusktr so I've been trying to tell you a few things for a while now, gunna lay it out one more time.
I know the performance concerns don't seem to make sense to you from time to time in this design. They also did not make sense to me. A lot of this I believe came from the uncertainty of dynamic class features and behaviors that engines only realized once they had started implement class fields with [[Define]] semantics and saw that they were huge performance regressions initially. So I think they basically adopted a "let's play it extremely safe" stance, which meant that they either did not want decorators at all, or would only accept a version where as much behavior as possible was statically knowable at parse time.
The changes you keep suggesting at this point in the process would require that the stage 3 spec be moved back to stage 2. At that point, it could once again be challenged by any TC39 member and potentially completely halted in progress. It could be killed, because stage 2 is a lot less certain than stage 3.
I have and the other champions have no control over 1, and we are not willing to risk the consequences of 2. I understand your frustrations, but this is the best spec we could have had given the constraints and the fact that there were a number of members who were almost ready to kill the proposal entirely. It was frankly a miracle that we got consensus to have the features and capabilities we have.
trusktr
changed the title
discrepancy: we're allowed to get/set private fields, but not public fields, and auto public auto accessors are not fields.
discrepancy: we're allowed to get/set private fields, but not public fields, and public auto accessors are not fields.
Oct 17, 2024
Note
This post comes after experience using decorators with TypeScript and Babel, including the new Stage 3 decorators since day one, for years.
It seems to me that the argument for performance in not allowing class fields to be accessed with (or converted to)
get
/set
pairs is moot, becauseaccessor #foo = 123
is exactly equivalent to the very same idea, and yet we allow it.The problem
In this code,
The
#foo
andfoo
properties are not the same at all. The private field is associated with the instance, while the public field is defined on the prototype.This is a big discrepancy.
First and foremost, converting
foo = 123
toaccessor foo = 123
can, and will, break certain code bases.The half-way defined
accessor
feature (when decorators are released, the feature will be half-way implemented, with the other half in a separate spec) does not even need to exist in this round of decorators, because if we simply fix the timing ofcontext.addInitializer()
forget
ter/set
ter elements, as described inthen, for the most part, important use cases that include reading initial values from getters/setters are covered. Please show a case where you absolutely need the getter/setter extra initializer to run before fields.
Don't get me wrong,
accessor
syntax is concise and more enjoyable thanget
ters/set
ters, but not fundamentally enabling anything new, while decorators provide new confusing differences between auto accessor and regular accessors as in #548.Solution
It would be more desirable, more consistent, and more breakage avoiding, to be able to provide the ability to provide
get
andset
functions for class fields, with the same or similar semantics as private fields which we've already blessed.Two ways to do this:
[[Define]]
semantics of field initialization so it creates an accessor descriptor if any decorator has provided theget
orset
functions, otherwise continue with a value descriptor as before.get
andset
functions across instancesget
/set
functions to inaccessible internal/private storage (like private fields).Regardless of which of the previous two are picked, then if we also:
context.addInitializer()
for getters/setters as in confusing that extra initializers for auto accessors and regular accessors do not both run after storage initializers. #548then at this point class fields would be as useful as
accessor
including with initial values, which would effectively be eliminate the need foraccessor
in this iteration of decorators.Accessors would still be nice sugar for prototype getters/setters, but basically unnecessary for shipping decorators.
The text was updated successfully, but these errors were encountered: