closure-compiler icon indicating copy to clipboard operation
closure-compiler copied to clipboard

Add Support for Public Class Fields

Open davydotcom opened this issue 7 years ago • 52 comments

It is becoming common place to use class fields and this is not yet supported from ES6 to ES5 conversion via closure compiler

https://github.com/tc39/proposal-class-fields

davydotcom avatar Nov 28 '17 23:11 davydotcom

Also Static Class Fields: https://github.com/tc39/proposal-static-class-features/

rahbari avatar Jul 21 '18 16:07 rahbari

They are stage 3 features now. https://github.com/tc39/proposals

teppeis avatar Jul 22 '18 06:07 teppeis

I wish to see this feature soon in closure compiler, having static fields helps a lot in class feature encapsulation.

class A {
    static a = 1;
}

instead of:

class A {}
A.a = 1;

rahbari avatar Jul 23 '18 00:07 rahbari

We've been looking forward to this feature making it to stage 4, also. We're not ready to implement it in closure-compiler yet, but it is on our minds.

brad4d avatar Jul 24 '18 15:07 brad4d

@brad4d does a feature have to make it to stage 4 before implementing? Browsers will generally implement before stage 4, and all the other compilers I know of support class fields.

justinfagnani avatar Aug 08 '18 16:08 justinfagnani

We've implemented features at stage 3 before. It's just a matter of priority or someone willing to contribute the work.

ChadKillingsworth avatar Aug 08 '18 17:08 ChadKillingsworth

At stage 3 now and shipping in V8.

https://github.com/tc39/proposal-class-fields https://twitter.com/_gsathya/status/1100845457876541442

arv avatar Mar 07 '19 17:03 arv

Exciting!

Created internal issue: http://b/127859638

blickly avatar Mar 08 '19 00:03 blickly

@justinfagnani I'm actively working on an official SLO for handling new features. It still requires review, but the current draft calls for us to start working on stage 3 features when we see that browsers have started adding support. (Lots of definition needed of what that means exactly.)

@arv One thing that I find discourages me from prioritizing class fields over other stage 3 features, like BigInt, is that there still are no official tests associated with the proposal according to the TC39 active proposals page. http://go/gh/tc39/proposals/blob/master/README.md

We would like to have these to base our unit tests on. Do you know why there aren't any yet? Thanks.

brad4d avatar Mar 11 '19 16:03 brad4d

@brad4d there are a ton of tests for public, private, and static fields and methods: https://github.com/tc39/test262/tree/master/src/class-elements

justinfagnani avatar Mar 11 '19 17:03 justinfagnani

@justinfagnani Thanks for pointing out those tests. I guess the page I pointed to needs to be updated.

brad4d avatar Mar 11 '19 17:03 brad4d

If/when this ships, will it require an opt-in? Perhaps via @language ECMASCRIPT_2017?

loadedsith avatar Mar 28 '19 16:03 loadedsith

The proposal is still a stage 3 proposal, i.e. not yet part of a language standard, but the current assumption (I think) is that it will become part of ES2020

blickly avatar Mar 28 '19 22:03 blickly

@blickly Stage 3 is when implementors should implement. Chrome is already shipping public and private class fields. As an implementor, the time for Closure to implement is now, you don't have to wait for Stage 4.

justinfagnani avatar Mar 28 '19 22:03 justinfagnani

Agreed, I'm just responding to the question of which language version it will be in (i.e. not ES2017)

blickly avatar Mar 28 '19 23:03 blickly

Ah, sorry then!

justinfagnani avatar Mar 28 '19 23:03 justinfagnani

@loadedsith if/when this feature ships you'll at least initially have to ask the compiler to handle it by specifying language_in to be the ES version in which it lands. (Probably ES_2020 as @blickly pointed out.)

When we feel it is safe to do so, we'll likely modify the default for language_in to be that new ES version, at which point it is no longer an "opt in" feature.

brad4d avatar Mar 29 '19 16:03 brad4d

Thank you 3 for the informative replies. I'm looking forward to it.

loadedsith avatar Mar 29 '19 17:03 loadedsith

Hello @brad4d - I am very interested in the SLO you mentioned. Is there a link to this?

The Class Fields proposal has shipped in Chrome, Node LTS, Moddable XS, QuickJS, Babel, TypeScript nightly, and Firefox (public-fields-only). The corresponding test262 tests were declared complete on 10 November 2017. Do you think it is now appropriate to ship in GCC?

robpalme avatar Dec 30 '19 15:12 robpalme

I'm afraid the SLO isn't in a publicly accessible place right now, but the gist of it is we want to have support for new JS features added to the compiler and available with --language_in=ES_20XX within 6 months of ES_20XX being officially defined.

Although they've been shipped in some form or other by several products, the TC39 committee hasn't discussed moving the relevant proposals for class fields forward to stage 4 (i.e. officially in the next version of the language) since January 2019.

See https://github.com/tc39/proposals/blob/master/README.md

It's possible that they will promote them to stage 4 in the February meeting, making them part of ES_2020, but we have other things that are definitely in ES_2020 to work on first.

We're currently working on nullish coalescing (https://github.com/tc39/proposal-nullish-coalescing) and optional chaining (https://github.com/tc39/proposal-optional-chaining), which were promoted to stage 4 in December.

brad4d avatar Jan 03 '20 01:01 brad4d

Waiting for stage 4 is really the wrong thing for tools like this. Stage 3 is when tools are expected to implement. Stage 4 is recognition that there wasn't some catastrophic failure in stage 3. Shipping is what counts, and class fields have shipped in enough implementations to not be at risk of rollback, (even with previously threatened TC39 consensus shenanigans, which aren't even a potential issue anymore).

Note the wording for stage 3:

The solution is complete and no further work is possible without implementation experience, significant usage and external feedback.

It sounds like the SLO / feature approach, if strictly applied to stage 4 features only, would leave out very widely implemented things like dynamic import(). I know there's not a readily available other label for a feature set, but the official ES year isn't great either. It doesn't indicate what's actually usable in any implementation.

justinfagnani avatar Jan 03 '20 02:01 justinfagnani

The fact that V8 has supported this for over a year yet Closure Compiler will immediately throw an error seems a little silly. Support for this would be completely non-breaking, there would be no difference in compilation output for people who did not use static public fields in their source code. Waiting for Stage 4 literally just prevents people from using this pattern at all in code that will be CC'd.

I'm having to do:

class Child extends Parent {
    static get a() {
       return 4;
   }
}

To override a static property right now, if I want my code to compile without doing a class declaration and then setting the field manually (which is horribly disorganized). Replacing with static a = 4 works in Chrome without issue, but the compiler won't take it at all.

Would a PR adding support for static class fields get approved?

ctjlewis avatar Jun 20 '20 13:06 ctjlewis

Adding a new feature like this to the compiler takes a large number of changes. There's no way to do it in a single PR.

As a sampling:

  • New AST node types must be created and AstValidator updated to ensure the correct shape of the AST is maintained for them.
  • The parser and code printer must be updated to parse and print code using the new feature.
  • Dozens of compiler passes must be updated to make sure they don't choke on the new AST nodes for the feature.
  • A transpilation pass must be written to downlevel the feature to work on older browsers.

And there's more....

Also, class fields behavior as defined by the spec is more complex than one would initially think. Doing this work requires creating a plan, getting agreement that it's a good one, then working through it with regular discussions of problems as they come up.

Sorry. If it were easy, we would have done it already.

This feature is top of my mind when it comes to things to work on after our current efforts to support BigInt and optional chaining.

brad4d avatar Jun 22 '20 18:06 brad4d

Thanks for the clarification @brad4d.

ctjlewis avatar Jun 22 '20 18:06 ctjlewis

I've resorted to transpiling class fields to get methods until native support for this is added.

ctjlewis avatar Oct 10 '20 06:10 ctjlewis

adding private fields and methods too?

d3x0r avatar Dec 29 '20 08:12 d3x0r

plzsir my #private fields

runthis avatar Apr 05 '21 20:04 runthis

Hi

Do you have contemplate include Private class fields soonly ?

Currently I get this error:

`ERROR - [JSC_PARSE_ERROR] Parse error. '}' expected #cOps ^

1 error(s), 0 warning(s)`

thanks

cristhianDt avatar May 03 '21 01:05 cristhianDt

@helenlpang is currently working on support for public fields (both static and non), but #private fields will unfortunately have to wait until after that is done.

blickly avatar Aug 04 '21 17:08 blickly

Just a note, Class Fields are now Stage 4 and included in the ECMAScript 2022 draft specification. https://tc39.es/ecma262/#sec-classfielddefinition-record-specification-type

rconnamacher avatar Feb 04 '22 16:02 rconnamacher