GithubHelp home page GithubHelp logo

Comments (21)

bmeck avatar bmeck commented on August 16, 2024 2
  1. It would be useful to identify invalid private field references with static analysis. This won't be possible if decorators can create private fields at runtime.

This is still preserved since the PrivateName would be anonymous as mentioned in the paragraph. # syntax would not be able to use those anonymous fields.

from proposal-decorators.

not-an-aardvark avatar not-an-aardvark commented on August 16, 2024 2

Thanks for the responses. I've edited the original issue to remove the static analysis property.

I think this would be useful for a number of frameworks. The side effect would usually be on the setter, rather than the getter, to queue re-rendering if it is overwritten.

I'm not sure I agree about this -- it seems like if a framework is able to observe all changes to a property/field on a user-provided class, then the field is part of the class's public API. In my opinion, it's important to preserve the invariant that a class can safely change the value of its private fields without worrying about "spooky action at a distance" (side-effects from outside the class). In other words, I think the decorator shouldn't be able to modify the descriptor after it's created, although it can sometimes transform the initial value.

from proposal-decorators.

domenic avatar domenic commented on August 16, 2024 2

I must be missing something fundamental. How is it possible for decorators to break the private state encapsulation? You'd have to actual modify the source code of the class in question to add the decorator. But if you do that, you might as well just remove the # sign. "Encapsulation" doesn't mean robustness against people editing the class definition.

from proposal-decorators.

littledan avatar littledan commented on August 16, 2024

I'd be fine to say, private class elements don't get decorated the first time around. In this repo, I'm providing a "maximal" proposal, analogous to @erights' earlier orthogonal class framework; it's not to say that this all needs to happen right now, or that it will all eventually happen.

  1. This proposal doesn't let decorators mess with the lexical bindings made by private field or method declarations, only change what they point to (e.g., a private field to a private accessor).
  2. As for where I got these use cases,
    • Sometimes classes are pretty big and take time to refactor, but I agree that this case is more marginal than the other one.
    • I think this would be useful for a number of frameworks. The side effect would usually be on the setter, rather than the getter, to queue re-rendering if it is overwritten. cc @diervo @wycats
  3. The intention is to preserve this property.

from proposal-decorators.

littledan avatar littledan commented on August 16, 2024

"spooky action at a distance"

Spooky action at a distance is sort of the entire point of decorators. If it's not OK for private fields, why is it OK for public fields? Maybe it really isn't OK for either; I have heard this objection in the past with respect to public decorators.

In other words, I think the decorator shouldn't be able to modify the descriptor after it's created, although it can sometimes transform the initial value.

Even if you're explicitly annotating that particular private field declaration to a decorator?

What changes do you think should be possible to the initial value?

from proposal-decorators.

not-an-aardvark avatar not-an-aardvark commented on August 16, 2024

If it's not OK for private fields, why is it OK for public fields?

My impression of decorators on public fields is that they're roughly syntactic sugar for something that would be possible to do after the declaration anyway by mutating the prototype. On the other hand, private fields are something completely internal to the class, and (in the absence of decorators) they are completely unobservable outside of the class. So I think it makes sense to allow decorators only on public fields, because external functions can only access public state.

What changes do you think should be possible to the initial value?

Disclaimer: I haven't followed past decorator proposals very closely. My view of what a decorator would be able to do is similar to what a python decorator can do (i.e. it's just a higher-order function that gets called at declaration time on the original value, without having access to binding info).

So with code like this:

class A {
  @foo
  #bar() { baz(); }

  @foo
  set #qux(value) { baz(); return value; }
}

The private method #bar would be given a value of foo(function() { baz(); }), and the private field #qux would have a setter with the with the function foo(function(value) { baz(); return value; }).

I realize this model of decorators is less powerful than the version where they have access to the descriptor, and it's fairly different from the current decorators proposal, so feel free to ignore it. I'm more sure about the first point (that decorators shouldn't have access to private state) than I am about what they could do with the binding if they did have access.

from proposal-decorators.

littledan avatar littledan commented on August 16, 2024

My impression of decorators on public fields is that they're roughly syntactic sugar for something that would be possible to do after the declaration anyway by mutating the prototype

With fields, this is no longer true. Decorators can add fields with initializers, and there's purposely no reflection API for doing the same.

it's just a higher-order function that gets called at declaration time on the original value, without having access to binding info

This is an interesting idea. The current decorators proposal is far more general, to allow things like a "non-enumerable" decorator, but we could provide a more restricted API for private methods.

from proposal-decorators.

ljharb avatar ljharb commented on August 16, 2024

I definitely agree that private and public fields are fundamentally different, and that there are things that make sense for public fields that do not for private fields.

Since private fields do not have the same descriptor properties - eg, enumerability is irrelevant, they're always writable, etc - I wouldn't expect a decorator to be able to do anything except transform the initial value.

from proposal-decorators.

littledan avatar littledan commented on August 16, 2024

In this proposal, a decorator could create a non-writable private field.

from proposal-decorators.

ljharb avatar ljharb commented on August 16, 2024

That's surprising to me; how would I make a private field nonwritable without a decorator?

from proposal-decorators.

wycats avatar wycats commented on August 16, 2024

@ljharb how is that different from public fields. In general, we haven't added any specific modifiers to public or private fields, with the assumption that for now, people can use decorators to customize the behavior of these fields.

If particular decorators become popular, we can look into adding first-class modifiers to the language, no?

from proposal-decorators.

littledan avatar littledan commented on August 16, 2024

You could only do it with a decorator. This is just like how we only have non-enumerable fields or enumerable methods with a decorator.

function nonwritable(element) {
  element.descriptor.writable = false;
  return element;
}

from proposal-decorators.

ljharb avatar ljharb commented on August 16, 2024

@littledan That's a decorator; I'm asking how I'd do it without decorators - as far as I'm aware I can replicate everything a decorator can do on public fields without them; it's just at a different time and less elegantly.

@wycats I'm not asking for a first-class modifier; I have Object.defineProperty already - I'm saying that I expect decorators not to be strictly required for any functionality like nonwritability.

from proposal-decorators.

littledan avatar littledan commented on August 16, 2024

@ljharb By design, in this proposal, decorators are the only API for a couple things--adding fields and doing reflection on private things. I'd rather not introduce even more imperative APIs for these.

from proposal-decorators.

ljharb avatar ljharb commented on August 16, 2024

@domenic that's true I think of the field being decorated, but not necessarily as true of the decorator that I added on #x being able to access a different #y.

from proposal-decorators.

domenic avatar domenic commented on August 16, 2024

Sure it is. You still had to get access to the class body. You could remove the # from y just as easily as from x.

from proposal-decorators.

not-an-aardvark avatar not-an-aardvark commented on August 16, 2024

I'm saying that allowing decorators on private fields violates the following invariants:

  • Getting or setting a private field in a class is unobservable outside the class.
  • The value of a field cannot be modified except by using an explicit assignment in the class.
  • Refactoring a class to add private fields, remove private fields, or change the behavior of existing private fields is unobservable outside the class.

I think these invariants would be useful because they would make it easier to refactor classes. With these invariants present, the API of a class would only be defined by its public fields/methods, and the internal representation could change without affecting consumers. In my opinion, being able to define an opaque internal representation of a value is the main use case for private fields.


@domenic It's true that the invariants would still apply anyway for classes without decorators, so adding a decorator could be considered an opt-out of the invariants. However, the ability to do this seems like it would be encouraging poor class design. I suppose my argument isn't that the existence of the feature breaks encapsulation -- it's more that we shouldn't encourage users to shoot themselves in the foot by exposing internal state to external decorators.

from proposal-decorators.

ljharb avatar ljharb commented on August 16, 2024

@domenic oh totally, but if I want #y to be private, I may not realize that adding a decorator onto #x would expose #y. If only a class decorator can access all private fields, and a private field decorator can only access its own private field, then my comments indeed don't apply.

from proposal-decorators.

littledan avatar littledan commented on August 16, 2024

Any more thoughts on this issue? I still that decorator access to private class elements is very useful. For one, it seems like a better solution at least to start than any of the protected/friend modifiers I've seen proposed. For one, this allows decorators like @testable to expose the entire class to tests.

The logic for exposure is, if you decorate a class element, then you're giving that decorator access to the class element, and if you decorate the class, you're giving the decorator access to the whole class. Logically, if you decorate an element, you're in the class. I don't think decorators are a way of opting out of those invariants you're listing; it's just that decorators are considered inside for the purpose of the the invariants.

It seems that this is a big unsettled topic, and I failed to bring it up at the last TC39 meeting, so I'll have it as part of the presentation for the next one.

from proposal-decorators.

littledan avatar littledan commented on August 16, 2024

I presented on this topic at the January 2018 TC39 meeting, explaining the logic for what encapsulation means with respect to decorated private fields: That the decorator is considered "part of the class". I didn't hear any objections in the question period.

Offline, @concavelenz expressed some hesitation about exposing private names in decorators as well. He and @wycats discussed this issue further. My understanding is that the concern is not fatal; maybe one of the two can elaborate here.

from proposal-decorators.

littledan avatar littledan commented on August 16, 2024

We've discussed this question at additional TC39 meetings since January. I believe we have concluded that decorators should be able to see private class elements--that the use cases are significant enough to justify the downsides stated in this thread.

from proposal-decorators.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.